2026-07-22 13:55:55 +08:00

167 lines
6.6 KiB
Go

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
}
}