Files
lijiaoqiao/supply-api/internal/iam/scope.go
Your Name 8ac23bf7d4 test: improve coverage and fix sanitizer bug
- Fix MaskMap to properly handle []string sensitive fields
- Add missing slice handling in sanitizer
- Add comprehensive tests for GetMetrics and CreateEventsBatch
- Improve audit/handler coverage from 49.8% to 68.8%
- Fix test expectations to match actual sanitizer behavior
- All tests pass
2026-04-08 07:44:58 +08:00

277 lines
6.5 KiB
Go
Raw 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 iam
import (
"strings"
)
// ==================== P1-02 Token Scope授权模型 ====================
// Scope命名空间定义
// 格式: {domain}:{resource}:{action}
// 示例: supply:accounts:read, supply:packages:write
const (
// Domain 域
ScopeDomainSupply = "supply" // 供应域
ScopeDomainBilling = "billing" // 结算域
ScopeDomainIAM = "iam" // 身份域
ScopeDomainAudit = "audit" // 审计域
ScopeDomainAdmin = "admin" // 管理域
// Action 动作
ScopeActionRead = "read" // 读取
ScopeActionWrite = "write" // 写入
ScopeActionDelete = "delete" // 删除
ScopeActionManage = "manage" // 管理read+write+delete
ScopeActionExecute = "execute" // 执行
)
// Scope定义
type Scope struct {
Domain string // 域: supply, billing, iam, audit, admin
Resource string // 资源: accounts, packages, orders, etc.
Action string // 动作: read, write, delete, manage, execute
}
// ParseScope 解析scope字符串
func ParseScope(scopeStr string) (*Scope, error) {
parts := strings.Split(scopeStr, ":")
if len(parts) != 3 {
return nil, &InvalidScopeError{Scope: scopeStr, Reason: "must be in format domain:resource:action"}
}
domain := parts[0]
resource := parts[1]
action := parts[2]
// 验证域
if !isValidDomain(domain) {
return nil, &InvalidScopeError{Scope: scopeStr, Reason: "invalid domain: " + domain}
}
// 验证动作
if !isValidAction(action) {
return nil, &InvalidScopeError{Scope: scopeStr, Reason: "invalid action: " + action}
}
return &Scope{
Domain: domain,
Resource: resource,
Action: action,
}, nil
}
// isValidDomain 验证域
func isValidDomain(domain string) bool {
validDomains := []string{
ScopeDomainSupply,
ScopeDomainBilling,
ScopeDomainIAM,
ScopeDomainAudit,
ScopeDomainAdmin,
}
for _, d := range validDomains {
if d == domain {
return true
}
}
return false
}
// isValidAction 验证动作
func isValidAction(action string) bool {
validActions := []string{
ScopeActionRead,
ScopeActionWrite,
ScopeActionDelete,
ScopeActionManage,
ScopeActionExecute,
}
for _, a := range validActions {
if a == action {
return true
}
}
return false
}
// HasScope 检查是否包含指定scope
func HasScope(userScopes []string, requiredScope *Scope) bool {
for _, userScopeStr := range userScopes {
userScope, err := ParseScope(userScopeStr)
if err != nil {
continue
}
// 完全匹配
if userScope.Domain == requiredScope.Domain &&
userScope.Resource == requiredScope.Resource &&
userScope.Action == requiredScope.Action {
return true
}
// manage权限包含所有其他权限
if userScope.Domain == requiredScope.Domain &&
userScope.Resource == requiredScope.Resource &&
userScope.Action == ScopeActionManage {
return true
}
// admin:admin:manage 包含所有
if userScope.Domain == ScopeDomainAdmin &&
userScope.Resource == "admin" &&
userScope.Action == ScopeActionManage {
return true
}
}
return false
}
// HasAnyScope 检查是否包含任一指定scope
func HasAnyScope(userScopes []string, requiredScopes []*Scope) bool {
for _, rs := range requiredScopes {
if HasScope(userScopes, rs) {
return true
}
}
return false
}
// HasAllScopes 检查是否包含所有指定scope
func HasAllScopes(userScopes []string, requiredScopes []*Scope) bool {
for _, rs := range requiredScopes {
if !HasScope(userScopes, rs) {
return false
}
}
return true
}
// InvalidScopeError 无效scope错误
type InvalidScopeError struct {
Scope string
Reason string
}
func (e *InvalidScopeError) Error() string {
return "invalid scope '" + e.Scope + "': " + e.Reason
}
// CommonScopes 常用scope定义
var CommonScopes = struct {
// Supply域
SupplyAccountsRead string
SupplyAccountsWrite string
SupplyAccountsDelete string
SupplyAccountsManage string
SupplyPackagesRead string
SupplyPackagesWrite string
SupplyPackagesDelete string
SupplyPackagesManage string
SupplyOrdersRead string
SupplyOrdersWrite string
SupplyOrdersManage string
SupplyUsageRead string
// Billing域
BillingAccountsRead string
BillingLedgersRead string
BillingSettlementsRead string
BillingSettlementsWrite string
// IAM域
IAMUsersRead string
IAMUsersWrite string
IAMUsersManage string
// Audit域
AuditEventsRead string
// Admin域
AdminAll string
}{
// Supply域
SupplyAccountsRead: "supply:accounts:read",
SupplyAccountsWrite: "supply:accounts:write",
SupplyAccountsDelete: "supply:accounts:delete",
SupplyAccountsManage: "supply:accounts:manage",
SupplyPackagesRead: "supply:packages:read",
SupplyPackagesWrite: "supply:packages:write",
SupplyPackagesDelete: "supply:packages:delete",
SupplyPackagesManage: "supply:packages:manage",
SupplyOrdersRead: "supply:orders:read",
SupplyOrdersWrite: "supply:orders:write",
SupplyOrdersManage: "supply:orders:manage",
SupplyUsageRead: "supply:usage:read",
// Billing域
BillingAccountsRead: "billing:accounts:read",
BillingLedgersRead: "billing:ledgers:read",
BillingSettlementsRead: "billing:settlements:read",
BillingSettlementsWrite: "billing:settlements:write",
// IAM域
IAMUsersRead: "iam:users:read",
IAMUsersWrite: "iam:users:write",
IAMUsersManage: "iam:users:manage",
// Audit域
AuditEventsRead: "audit:events:read",
// Admin域
AdminAll: "admin:admin:manage",
}
// RoleScopes 角色默认scope映射
var RoleScopes = map[string][]string{
"viewer": {
CommonScopes.SupplyAccountsRead,
CommonScopes.SupplyPackagesRead,
CommonScopes.SupplyOrdersRead,
CommonScopes.SupplyUsageRead,
CommonScopes.BillingAccountsRead,
CommonScopes.BillingLedgersRead,
CommonScopes.AuditEventsRead,
},
"operator": {
CommonScopes.SupplyAccountsRead,
CommonScopes.SupplyAccountsWrite,
CommonScopes.SupplyPackagesRead,
CommonScopes.SupplyPackagesWrite,
CommonScopes.SupplyOrdersRead,
CommonScopes.SupplyOrdersWrite,
CommonScopes.SupplyUsageRead,
CommonScopes.BillingAccountsRead,
CommonScopes.BillingSettlementsRead,
},
"admin": {
CommonScopes.SupplyAccountsManage,
CommonScopes.SupplyPackagesManage,
CommonScopes.SupplyOrdersManage,
CommonScopes.BillingAccountsRead,
CommonScopes.BillingSettlementsRead,
CommonScopes.BillingSettlementsWrite,
CommonScopes.IAMUsersRead,
CommonScopes.IAMUsersWrite,
CommonScopes.AuditEventsRead,
},
"owner": {
// Owner拥有所有权限
CommonScopes.AdminAll,
},
}
// GetScopesForRole 获取角色默认scope列表
func GetScopesForRole(role string) []string {
if scopes, ok := RoleScopes[role]; ok {
return scopes
}
return []string{}
}