All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 8m15s
- FamilyMemberItem 新增 auth_type、device_type 字段 - FamilySummary 新增 owner_auth_type 字段 - findUserIdentifiers 返回 identifierInfo(含 auth_type) - 新增 parseDeviceType() 从 UserAgent 解析设备类型 Co-Authored-By: claude-flow <ruv@ruv.net>
128 lines
2.7 KiB
Go
128 lines
2.7 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/perfect-panel/server/internal/model/user"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func mapFamilyStatus(status uint8) string {
|
|
if status == user.FamilyStatusActive {
|
|
return "active"
|
|
}
|
|
return "disabled"
|
|
}
|
|
|
|
func mapFamilyRoleName(role uint8) string {
|
|
switch role {
|
|
case user.FamilyRoleOwner:
|
|
return "owner"
|
|
case user.FamilyRoleMember:
|
|
return "member"
|
|
default:
|
|
return fmt.Sprintf("role_%d", role)
|
|
}
|
|
}
|
|
|
|
func mapFamilyMemberStatusName(status uint8) string {
|
|
switch status {
|
|
case user.FamilyMemberActive:
|
|
return "active"
|
|
case user.FamilyMemberLeft:
|
|
return "left"
|
|
case user.FamilyMemberRemoved:
|
|
return "removed"
|
|
default:
|
|
return fmt.Sprintf("status_%d", status)
|
|
}
|
|
}
|
|
|
|
func normalizeFamilyStatusInput(status string) (uint8, bool) {
|
|
switch strings.ToLower(strings.TrimSpace(status)) {
|
|
case "", "all":
|
|
return 0, false
|
|
case "active", "1":
|
|
return user.FamilyStatusActive, true
|
|
case "disabled", "0":
|
|
return 0, true
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
type identifierInfo struct {
|
|
Identifier string
|
|
AuthType string
|
|
}
|
|
|
|
func findUserIdentifiers(ctx context.Context, db *gorm.DB, userIDs []int64) (map[int64]identifierInfo, error) {
|
|
identifierMap := make(map[int64]identifierInfo)
|
|
if len(userIDs) == 0 {
|
|
return identifierMap, nil
|
|
}
|
|
|
|
type authRow struct {
|
|
UserId int64
|
|
AuthType string
|
|
AuthIdentifier string
|
|
}
|
|
|
|
var rows []authRow
|
|
err := db.WithContext(ctx).
|
|
Table("user_auth_methods").
|
|
Select("user_id, auth_type, auth_identifier").
|
|
Where("user_id IN ? AND deleted_at IS NULL", userIDs).
|
|
Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
priority := map[string]int{
|
|
"email": 1,
|
|
"mobile": 2,
|
|
"telegram": 3,
|
|
"device": 4,
|
|
}
|
|
selectedPriority := make(map[int64]int, len(userIDs))
|
|
|
|
for _, row := range rows {
|
|
currentPriority := priority[row.AuthType]
|
|
if currentPriority == 0 {
|
|
currentPriority = 100
|
|
}
|
|
if previous, exists := selectedPriority[row.UserId]; exists && previous <= currentPriority {
|
|
continue
|
|
}
|
|
selectedPriority[row.UserId] = currentPriority
|
|
identifierMap[row.UserId] = identifierInfo{
|
|
Identifier: row.AuthIdentifier,
|
|
AuthType: row.AuthType,
|
|
}
|
|
}
|
|
|
|
return identifierMap, nil
|
|
}
|
|
|
|
func parseDeviceType(userAgent string) string {
|
|
ua := strings.ToLower(userAgent)
|
|
switch {
|
|
case strings.Contains(ua, "iphone"):
|
|
return "iPhone"
|
|
case strings.Contains(ua, "ipad"):
|
|
return "iPad"
|
|
case strings.Contains(ua, "android"):
|
|
return "Android"
|
|
case strings.Contains(ua, "windows"):
|
|
return "Windows"
|
|
case strings.Contains(ua, "macintosh"), strings.Contains(ua, "mac os"):
|
|
return "Mac"
|
|
case strings.Contains(ua, "linux"):
|
|
return "Linux"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|