2026-06-17 23:13:08 +08:00

113 lines
3.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}