package service import ( "crypto/rand" "encoding/hex" "fmt" "sync" "time" "github.com/tcs-iptv/tcs/internal/model" ) // AdminService 用户管理/组织管理服务(系统管理模块补足)。 // MVP 使用内存存储,生产环境可替换为 PostgreSQL 实现。 type AdminService struct { mu sync.RWMutex users map[string]*model.User // userID -> User orgs map[string]*model.Organization // orgID -> Organization keys map[string]*model.User // apiKey -> User(快速鉴权查找) names map[string]bool // username 唯一性校验 } // NewAdminService 创建用户/组织管理服务。 func NewAdminService() *AdminService { return &AdminService{ users: make(map[string]*model.User), orgs: make(map[string]*model.Organization), keys: make(map[string]*model.User), names: make(map[string]bool), } } // ---- 组织管理 ---- // CreateOrg 创建组织。 func (a *AdminService) CreateOrg(org model.Organization) (model.Organization, error) { if org.Name == "" { return model.Organization{}, fmt.Errorf("admin: 组织名称不能为空") } a.mu.Lock() defer a.mu.Unlock() org.ID = a.nextID("org") org.Status = model.OrgStatusActive if org.CreatedAt.IsZero() { org.CreatedAt = time.Now() } org.UpdatedAt = time.Now() a.orgs[org.ID] = &org return org, nil } // UpdateOrg 更新组织信息。 func (a *AdminService) UpdateOrg(orgID string, updates model.Organization) (model.Organization, error) { a.mu.Lock() defer a.mu.Unlock() org, ok := a.orgs[orgID] if !ok { return model.Organization{}, fmt.Errorf("admin: 组织 %s 不存在", orgID) } if updates.Name != "" { org.Name = updates.Name } if updates.OrgNode != "" { org.OrgNode = updates.OrgNode } if updates.Province != "" { org.Province = updates.Province } if updates.Type != "" { org.Type = updates.Type } if updates.Status != "" { org.Status = updates.Status } org.UpdatedAt = time.Now() return *org, nil } // GetOrg 查询组织详情。 func (a *AdminService) GetOrg(orgID string) (model.Organization, error) { a.mu.RLock() defer a.mu.RUnlock() org, ok := a.orgs[orgID] if !ok { return model.Organization{}, fmt.Errorf("admin: 组织 %s 不存在", orgID) } return *org, nil } // ListOrgs 列出全部组织(可按类型过滤)。 func (a *AdminService) ListOrgs(orgType string) []model.Organization { a.mu.RLock() defer a.mu.RUnlock() var out []model.Organization for _, org := range a.orgs { if orgType == "" || org.Type == orgType { out = append(out, *org) } } return out } // DisableOrg 禁用组织。 func (a *AdminService) DisableOrg(orgID string) error { a.mu.Lock() defer a.mu.Unlock() org, ok := a.orgs[orgID] if !ok { return fmt.Errorf("admin: 组织 %s 不存在", orgID) } org.Status = model.OrgStatusDisabled org.UpdatedAt = time.Now() return nil } // ---- 用户管理 ---- // CreateUser 创建用户并自动生成 API Key/Secret。 func (a *AdminService) CreateUser(user model.User) (model.User, error) { if user.Username == "" { return model.User{}, fmt.Errorf("admin: 用户名不能为空") } if user.OrgID == "" { return model.User{}, fmt.Errorf("admin: 所属组织不能为空") } a.mu.Lock() defer a.mu.Unlock() if a.names[user.Username] { return model.User{}, fmt.Errorf("admin: 用户名 %s 已存在", user.Username) } if _, ok := a.orgs[user.OrgID]; !ok { return model.User{}, fmt.Errorf("admin: 组织 %s 不存在", user.OrgID) } user.ID = a.nextID("user") user.APIKey = a.generateAPIKey() user.APISecret = a.generateAPISecret() user.Status = model.UserStatusActive if user.CreatedAt.IsZero() { user.CreatedAt = time.Now() } user.UpdatedAt = time.Now() a.users[user.ID] = &user a.keys[user.APIKey] = &user a.names[user.Username] = true return user, nil } // UpdateUser 更新用户信息(不支持修改用户名和 API Key)。 func (a *AdminService) UpdateUser(userID string, updates model.User) (model.User, error) { a.mu.Lock() defer a.mu.Unlock() user, ok := a.users[userID] if !ok { return model.User{}, fmt.Errorf("admin: 用户 %s 不存在", userID) } if updates.FullName != "" { user.FullName = updates.FullName } if updates.OrgID != "" { if _, ok := a.orgs[updates.OrgID]; !ok { return model.User{}, fmt.Errorf("admin: 组织 %s 不存在", updates.OrgID) } user.OrgID = updates.OrgID } if updates.Role != "" { user.Role = updates.Role } if updates.Status != "" { user.Status = updates.Status } user.UpdatedAt = time.Now() return *user, nil } // GetUser 查询用户详情。 func (a *AdminService) GetUser(userID string) (model.User, error) { a.mu.RLock() defer a.mu.RUnlock() user, ok := a.users[userID] if !ok { return model.User{}, fmt.Errorf("admin: 用户 %s 不存在", userID) } return *user, nil } // ListUsers 列出全部用户(可按组织或角色过滤)。 func (a *AdminService) ListUsers(orgID, role string) []model.User { a.mu.RLock() defer a.mu.RUnlock() var out []model.User for _, user := range a.users { if orgID != "" && user.OrgID != orgID { continue } if role != "" && user.Role != role { continue } out = append(out, *user) } return out } // DisableUser 禁用用户。 func (a *AdminService) DisableUser(userID string) error { a.mu.Lock() defer a.mu.Unlock() user, ok := a.users[userID] if !ok { return fmt.Errorf("admin: 用户 %s 不存在", userID) } user.Status = model.UserStatusDisabled user.UpdatedAt = time.Now() return nil } // ResetAPIKey 重置用户的 API Key 和 Secret。 func (a *AdminService) ResetAPIKey(userID string) (model.User, error) { a.mu.Lock() defer a.mu.Unlock() user, ok := a.users[userID] if !ok { return model.User{}, fmt.Errorf("admin: 用户 %s 不存在", userID) } // 移除旧 key delete(a.keys, user.APIKey) // 生成新 key user.APIKey = a.generateAPIKey() user.APISecret = a.generateAPISecret() user.UpdatedAt = time.Now() a.keys[user.APIKey] = user return *user, nil } // LookupByAPIKey 根据 API Key 查询用户(供 httpx.KeyStore 使用)。 func (a *AdminService) LookupByAPIKey(apiKey string) (secret string, role string, ok bool) { a.mu.RLock() defer a.mu.RUnlock() user, exists := a.keys[apiKey] if !exists || user.Status != model.UserStatusActive { return "", "", false } return user.APISecret, user.Role, true } // ---- 辅助方法 ---- func (a *AdminService) nextID(prefix string) string { // 使用时间戳+随机数生成唯一 ID ts := time.Now().Format("20060102") b := make([]byte, 4) rand.Read(b) return fmt.Sprintf("%s-%s-%s", prefix, ts, hex.EncodeToString(b)) } func (a *AdminService) generateAPIKey() string { b := make([]byte, 16) rand.Read(b) return "tcs-" + hex.EncodeToString(b) } func (a *AdminService) generateAPISecret() string { b := make([]byte, 32) rand.Read(b) return hex.EncodeToString(b) }