package roomadmin import ( "context" "encoding/json" "errors" "fmt" "slices" "strconv" "strings" "gorm.io/gorm" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/model" ) const roomRegionWhitelistGroup = "room-region-whitelist" type RoomWhitelistConfig struct { UserIDs []string `json:"userIds"` UpdatedAtMS int64 `json:"updatedAtMs"` } type roomRegionWhitelistValue struct { UserIDs []string `json:"user_ids"` } // GetRoomWhitelistConfig 读取当前 app 的房间区域白名单;缺行时返回空集合,表示所有用户仍受区域限制。 func (s *Service) GetRoomWhitelistConfig(ctx context.Context) (RoomWhitelistConfig, error) { if s.store == nil { return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured") } item, err := s.store.GetAppConfig(roomRegionWhitelistGroup, appctx.FromContext(ctx)) if errors.Is(err, gorm.ErrRecordNotFound) { return RoomWhitelistConfig{UserIDs: []string{}}, nil } if err != nil { return RoomWhitelistConfig{}, err } userIDs, err := roomWhitelistIDsFromValue(item.Value) if err != nil { return RoomWhitelistConfig{}, err } return RoomWhitelistConfig{UserIDs: userIDs, UpdatedAtMS: item.UpdatedAtMS}, nil } // UpdateRoomWhitelistConfig 覆盖当前 app 的房间区域白名单;gateway 会在最多五分钟内通过 Redis 缓存刷新结果。 func (s *Service) UpdateRoomWhitelistConfig(ctx context.Context, req updateRoomWhitelistRequest) (RoomWhitelistConfig, error) { if s.store == nil { return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured") } userIDs, err := normalizeRoomWhitelistUserIDs(req.UserIDs) if err != nil { return RoomWhitelistConfig{}, err } payload, err := json.Marshal(roomRegionWhitelistValue{UserIDs: userIDs}) if err != nil { return RoomWhitelistConfig{}, err } item := model.AppConfig{ Group: roomRegionWhitelistGroup, Key: appctx.FromContext(ctx), Value: string(payload), Description: "房间区域白名单用户,命中后 App 房间列表不按用户 region_id 过滤", } if err := s.store.UpsertAppConfigs([]model.AppConfig{item}); err != nil { return RoomWhitelistConfig{}, err } return s.GetRoomWhitelistConfig(ctx) } func roomWhitelistIDsFromValue(raw string) ([]string, error) { raw = strings.TrimSpace(raw) if raw == "" { return []string{}, nil } var payload roomRegionWhitelistValue if strings.HasPrefix(raw, "[") { if err := json.Unmarshal([]byte(raw), &payload.UserIDs); err != nil { return nil, err } } else if err := json.Unmarshal([]byte(raw), &payload); err != nil { return nil, err } return normalizeRoomWhitelistUserIDs(payload.UserIDs) } func normalizeRoomWhitelistUserIDs(values []string) ([]string, error) { seen := make(map[int64]struct{}, len(values)) out := make([]int64, 0, len(values)) for _, value := range values { value = strings.TrimSpace(value) if value == "" { continue } id, err := strconv.ParseInt(value, 10, 64) if err != nil || id <= 0 { return nil, fmt.Errorf("%w: 用户 ID 不正确", ErrInvalidArgument) } if _, ok := seen[id]; ok { continue } seen[id] = struct{}{} out = append(out, id) } slices.Sort(out) result := make([]string, 0, len(out)) for _, id := range out { result = append(result, strconv.FormatInt(id, 10)) } return result, nil }