Files
ai-gateway-go/internal/identity/account.go
T
LLMGuardX Dev 58535fda7b 0.11.7: 代码审查查缺补漏(安全/并发/前端三轮审查修复)
安全:
- 渠道 webhook 入站强制令牌鉴权(恒定时间比较+统一文案),企微签名官方算法;
- 报表/概览/systemInfo 端点按 usage:read/audit:read/system:manage 授权;
- sso_error 固定错误码;个人渠道令牌仅请求头;工具出站 Dialer.Control 消除
  DNS rebinding TOCTOU;新增 channel:read/manage 权限;限流倍数上限 10。

并发/一致性:
- 任务上报单条条件 UPDATE 防重放双提交;认领回收过期 claimed 任务;
- 审批改先开通后落记录(幂等,无嵌套事务);聊天消息单事务落库;
- 会话列表校验 AuthVersion;吊销先 Del 后 SRem;删工具保护调用历史;
- rejected 冷却 24h;限流被拒补偿;maintenance 清理限流窗口。

前端/菜单:
- 修复 gatewayChildren late-append 导致 reports/tenants/channels 菜单不可见;
- 聊天改名 PUT 对齐;渠道编辑清空凭据防串写+启用开关;
- 聊天响应防串扰;报表本地时区日期。
2026-08-13 15:22:19 +08:00

148 lines
5.5 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"
PermissionChannelRead = "channel:read"
PermissionChannelManage = "channel: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"
PermissionSystemManage = "system: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,
PermissionChannelRead, PermissionChannelManage,
PermissionMCPServerRead, PermissionMCPServerManage,
PermissionSkillRead, PermissionSkillManage,
PermissionDigitalEmployeeRead, PermissionDigitalEmployeeManage,
PermissionMarketplaceRead, PermissionMarketplaceManage,
PermissionFileRead, PermissionFileManage,
PermissionInboxRead, PermissionInboxManage,
PermissionScheduledTaskRead, PermissionScheduledTaskManage,
PermissionTraceRead,
PermissionAgentNodeRead, PermissionAgentNodeManage,
PermissionSystemManage,
},
"auditor": {PermissionProviderRead, PermissionAPIKeyRead, PermissionAuditRead, PermissionUsageRead, PermissionOutboxRead, PermissionContentPolicyRead, PermissionPricingRead, PermissionPromptRead, PermissionKnowledgeRead, PermissionToolRead, PermissionApplicationRead, PermissionNotificationRead, PermissionChannelRead, 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)
}