Files
ai-gateway-go/internal/identity/account.go
T
superidou 9501751792 0.10.1: 安全与业务逻辑加固、新品牌与部署加固
三轮审查修复(60+ 项),相对远端 main(b536672)的关键变更:
- 安全: 数据面 SSRF 拨号防护(防 DNS rebinding)/上游凭据剥离/登录防枚举
  与锁定态统一/可信代理(X-Forwarded-For)限流加固/会话版本失效机制/
  撤销即时传播/弱密钥拒绝启动/脱敏字节级重写(保签名契约)
- 业务逻辑: 裸 body 上传 panic/bootstrap 审计管线卡死/定价通配符优先级/
  全局工具可见性/调度器停机补跑/TOTP 挑战令牌消费顺序/熔断探针语义/
  >4MB 响应 token 计量/管理员重置密码作废会话 等
- 前端: 新 logo(语枢 AI 网关主题)/Provider 凭据异常警示/删除入口/
  后端错误消息透传/localStorage 敏感数据收敛
- 部署: CREDENTIAL_MASTER_KEY 持久化与弱值拒绝/Provider DELETE 接口/
  nginx 安全头/worker 内存限制
- 新增迁移 000029(key_hash 索引)/000030(usage_daily 币种维度)
2026-08-13 10:50:51 +08:00

143 lines
5.2 KiB
Go

package identity
import (
"errors"
"sort"
"time"
)
var (
ErrNotFound = errors.New("identity not found")
ErrUnavailable = errors.New("identity service unavailable")
)
type Kind string
const (
KindAdmin Kind = "admin"
KindPortal Kind = "portal"
)
type Account struct {
ID string
Kind Kind
Login string
DisplayName string
Role string
Permissions []string
PasswordHash string
AuthSource string
Active bool
FailedLogins int
LockedUntil *time.Time
TOTPEnabled bool
EncryptedTOTPSecret []byte
TOTPKekVersion *int
TOTPLastStep *int64
TOTPBackupCodes []byte
DepartmentID *string
DepartmentName string
CreatedAt time.Time
UpdatedAt time.Time
}
const (
PermissionIdentityManage = "identity:manage"
PermissionProviderRead = "provider:read"
PermissionProviderManage = "provider:manage"
PermissionAPIKeyRead = "api_key:read"
PermissionAPIKeyManage = "api_key:manage"
PermissionAuditRead = "audit:read"
PermissionUsageRead = "usage:read"
PermissionOutboxRead = "outbox:read"
PermissionOutboxManage = "outbox:manage"
PermissionContentPolicyRead = "content_policy:read"
PermissionContentPolicyManage = "content_policy:manage"
PermissionPricingRead = "pricing:read"
PermissionPricingManage = "pricing:manage"
PermissionPromptRead = "prompt:read"
PermissionPromptManage = "prompt:manage"
PermissionKnowledgeRead = "knowledge:read"
PermissionKnowledgeManage = "knowledge:manage"
PermissionToolRead = "tool:read"
PermissionToolManage = "tool:manage"
PermissionApplicationRead = "application:read"
PermissionApplicationManage = "application:manage"
PermissionNotificationRead = "notification:read"
PermissionNotificationManage = "notification:manage"
PermissionMCPServerRead = "mcp_server:read"
PermissionMCPServerManage = "mcp_server:manage"
PermissionSkillRead = "skill:read"
PermissionSkillManage = "skill:manage"
PermissionDigitalEmployeeRead = "digital_employee:read"
PermissionDigitalEmployeeManage = "digital_employee:manage"
PermissionMarketplaceRead = "marketplace:read"
PermissionMarketplaceManage = "marketplace:manage"
PermissionFileRead = "file:read"
PermissionFileManage = "file:manage"
PermissionInboxRead = "inbox:read"
PermissionInboxManage = "inbox:manage"
PermissionScheduledTaskRead = "scheduled_task:read"
PermissionScheduledTaskManage = "scheduled_task:manage"
PermissionTraceRead = "trace:read"
PermissionAgentNodeRead = "agent_node:read"
PermissionAgentNodeManage = "agent_node:manage"
)
var rolePermissions = map[string][]string{
"superadmin": {"*"},
"operator": {
PermissionProviderRead, PermissionProviderManage,
PermissionAPIKeyRead, PermissionAPIKeyManage,
PermissionUsageRead,
PermissionOutboxRead, PermissionOutboxManage,
PermissionContentPolicyRead, PermissionContentPolicyManage,
PermissionPricingRead, PermissionPricingManage,
PermissionPromptRead, PermissionPromptManage,
PermissionKnowledgeRead, PermissionKnowledgeManage,
PermissionToolRead, PermissionToolManage,
PermissionApplicationRead, PermissionApplicationManage,
PermissionNotificationRead, PermissionNotificationManage,
PermissionMCPServerRead, PermissionMCPServerManage,
PermissionSkillRead, PermissionSkillManage,
PermissionDigitalEmployeeRead, PermissionDigitalEmployeeManage,
PermissionMarketplaceRead, PermissionMarketplaceManage,
PermissionFileRead, PermissionFileManage,
PermissionInboxRead, PermissionInboxManage,
PermissionScheduledTaskRead, PermissionScheduledTaskManage,
PermissionTraceRead,
PermissionAgentNodeRead, PermissionAgentNodeManage,
},
"auditor": {PermissionProviderRead, PermissionAPIKeyRead, PermissionAuditRead, PermissionUsageRead, PermissionOutboxRead, PermissionContentPolicyRead, PermissionPricingRead, PermissionPromptRead, PermissionKnowledgeRead, PermissionToolRead, PermissionApplicationRead, PermissionNotificationRead, PermissionMCPServerRead, PermissionSkillRead, PermissionDigitalEmployeeRead, PermissionMarketplaceRead, PermissionFileRead, PermissionInboxRead, PermissionScheduledTaskRead, PermissionTraceRead, PermissionAgentNodeRead},
"member": {},
}
func EffectivePermissions(account Account) []string {
seen := make(map[string]struct{})
result := make([]string, 0, len(account.Permissions)+4)
for _, permissions := range [][]string{rolePermissions[account.Role], account.Permissions} {
for _, permission := range permissions {
if _, exists := seen[permission]; exists {
continue
}
seen[permission] = struct{}{}
result = append(result, permission)
}
}
sort.Strings(result)
return result
}
func HasPermission(account Account, required string) bool {
for _, permission := range EffectivePermissions(account) {
if permission == "*" || permission == required {
return true
}
}
return false
}
func (a Account) Locked(now time.Time) bool {
return a.LockedUntil != nil && a.LockedUntil.After(now)
}