package appconfig import ( "context" "fmt" "strings" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/integration/userclient" ) const ( organizationExpansionScene = "organization_role_expansion" managerOperationsScene = "manager_operations" roleScopeCountry = "country" roleScopeRegion = "region" roleScopeGlobal = "global" ) // RoleScopePolicyClient 是 Admin 到 user-service owner 的最小边界;后台不能直接写 user DB 配置表。 type RoleScopePolicyClient interface { GetRoleScopePolicy(ctx context.Context, req userclient.GetRoleScopePolicyRequest) (*userclient.RoleScopePolicy, error) UpdateRoleScopePolicies(ctx context.Context, req userclient.UpdateRoleScopePoliciesRequest) ([]userclient.RoleScopePolicy, error) } type RoleScopePoliciesConfig struct { AppCode string `json:"appCode"` OrganizationScope string `json:"organizationScope"` ManagerBaseScope string `json:"managerBaseScope"` ManagerExpandedScope string `json:"managerExpandedScope"` ManagerRegionExpansionConfigurable bool `json:"managerRegionExpansionConfigurable"` UpdatedAtMS int64 `json:"updatedAtMs"` } func (s *AppConfigService) GetRoleScopePoliciesConfig(ctx context.Context, appCode string, requestID string) (RoleScopePoliciesConfig, error) { if s == nil || s.roleScopePolicies == nil { return RoleScopePoliciesConfig{}, fmt.Errorf("role scope policy client is not configured") } organization, err := s.roleScopePolicies.GetRoleScopePolicy(ctx, userclient.GetRoleScopePolicyRequest{ RequestID: requestID, Caller: "hyapp-admin-server", Scene: organizationExpansionScene, }) if err != nil { return RoleScopePoliciesConfig{}, err } manager, err := s.roleScopePolicies.GetRoleScopePolicy(ctx, userclient.GetRoleScopePolicyRequest{ RequestID: requestID, Caller: "hyapp-admin-server", Scene: managerOperationsScene, }) if err != nil { return RoleScopePoliciesConfig{}, err } return roleScopePoliciesConfigFromPolicies(appCode, []userclient.RoleScopePolicy{*organization, *manager}) } func (s *AppConfigService) UpdateRoleScopePoliciesConfig(ctx context.Context, appCode string, requestID string, request roleScopePoliciesConfigRequest) (RoleScopePoliciesConfig, error) { if s == nil || s.roleScopePolicies == nil { return RoleScopePoliciesConfig{}, fmt.Errorf("role scope policy client is not configured") } policies, err := roleScopePoliciesFromRequest(request) if err != nil { return RoleScopePoliciesConfig{}, err } stored, err := s.roleScopePolicies.UpdateRoleScopePolicies(ctx, userclient.UpdateRoleScopePoliciesRequest{ RequestID: requestID, Caller: "hyapp-admin-server", Policies: policies, }) if err != nil { return RoleScopePoliciesConfig{}, err } return roleScopePoliciesConfigFromPolicies(appCode, stored) } func roleScopePoliciesFromRequest(request roleScopePoliciesConfigRequest) ([]userclient.RoleScopePolicy, error) { organizationScope := normalizeRoleScope(request.OrganizationScope) if organizationScope != roleScopeRegion && organizationScope != roleScopeGlobal { return nil, fmt.Errorf("组织角色范围不正确") } managerBase := normalizeRoleScope(request.ManagerBaseScope) managerExpanded := normalizeRoleScope(request.ManagerExpandedScope) if !validManagerRoleScope(managerBase) || !validManagerRoleScope(managerExpanded) { return nil, fmt.Errorf("经理操作范围不正确") } if !request.ManagerRegionExpansionConfigurable && managerExpanded != managerBase { return nil, fmt.Errorf("关闭经理扩区开关时两个范围必须一致") } if request.ManagerRegionExpansionConfigurable && roleScopeRank(managerExpanded) < roleScopeRank(managerBase) { return nil, fmt.Errorf("经理扩展范围不能小于基础范围") } return []userclient.RoleScopePolicy{ { Scene: organizationExpansionScene, BaseScope: organizationScope, ExpandedScope: organizationScope, }, { Scene: managerOperationsScene, BaseScope: managerBase, ExpandedScope: managerExpanded, RegionExpansionConfigurable: request.ManagerRegionExpansionConfigurable, }, }, nil } func roleScopePoliciesConfigFromPolicies(appCode string, policies []userclient.RoleScopePolicy) (RoleScopePoliciesConfig, error) { config := RoleScopePoliciesConfig{AppCode: appctx.Normalize(appCode)} seen := make(map[string]struct{}, len(policies)) for _, policy := range policies { scene := strings.ToLower(strings.TrimSpace(policy.Scene)) switch scene { case organizationExpansionScene: config.OrganizationScope = normalizeRoleScope(policy.BaseScope) if (config.OrganizationScope != roleScopeRegion && config.OrganizationScope != roleScopeGlobal) || normalizeRoleScope(policy.ExpandedScope) != config.OrganizationScope || policy.RegionExpansionConfigurable { return RoleScopePoliciesConfig{}, fmt.Errorf("组织角色范围配置无效") } case managerOperationsScene: config.ManagerBaseScope = normalizeRoleScope(policy.BaseScope) config.ManagerExpandedScope = normalizeRoleScope(policy.ExpandedScope) config.ManagerRegionExpansionConfigurable = policy.RegionExpansionConfigurable if !validManagerRoleScope(config.ManagerBaseScope) || !validManagerRoleScope(config.ManagerExpandedScope) { return RoleScopePoliciesConfig{}, fmt.Errorf("经理操作范围配置无效") } if (!config.ManagerRegionExpansionConfigurable && config.ManagerExpandedScope != config.ManagerBaseScope) || (config.ManagerRegionExpansionConfigurable && roleScopeRank(config.ManagerExpandedScope) < roleScopeRank(config.ManagerBaseScope)) { return RoleScopePoliciesConfig{}, fmt.Errorf("经理扩展范围配置无效") } default: continue } seen[scene] = struct{}{} if policy.UpdatedAtMS > config.UpdatedAtMS { config.UpdatedAtMS = policy.UpdatedAtMS } } if _, ok := seen[organizationExpansionScene]; !ok { return RoleScopePoliciesConfig{}, fmt.Errorf("组织角色范围配置缺失") } if _, ok := seen[managerOperationsScene]; !ok { return RoleScopePoliciesConfig{}, fmt.Errorf("经理操作范围配置缺失") } return config, nil } func normalizeRoleScope(value string) string { return strings.ToLower(strings.TrimSpace(value)) } func validManagerRoleScope(value string) bool { return value == roleScopeCountry || value == roleScopeRegion || value == roleScopeGlobal } func roleScopeRank(value string) int { switch value { case roleScopeCountry: return 1 case roleScopeRegion: return 2 case roleScopeGlobal: return 3 default: return 0 } }