113 lines
3.3 KiB
Go
113 lines
3.3 KiB
Go
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
|
||
}
|