6708c226a5
- 迁移 000023 gateway.file_objects(personal/system 归属隔离 + 部分索引) - internal/platform/storage:minio-go 适配(端点 scheme 剥离、流式 PutObject/Open/Delete) - internal/workbench/files.go:FileService(sha256 校验、PutObject-then-insert 回滚、delete 先删行再删对象) - admin /api/v1/admin/files + portal /api/v1/portal/files 处理器(流式上传下载、Content-Disposition) - RBAC file:read/file:manage;菜单加文件管理 + 门户文件仓库 - compose 增 minio 服务(S3_* anchor、不暴露端口);nginx client_max_body_size 32m→256m - 管理端文件管理页 + 门户个人文件仓;集成测试 TestFileObjectLifecycle 连真 MinIO 通过 - healthz object_storage:true;README/PRODUCTION/进展文档同步 Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
4.6 KiB
Go
132 lines
4.6 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"
|
|
)
|
|
|
|
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,
|
|
},
|
|
"auditor": {PermissionProviderRead, PermissionAPIKeyRead, PermissionAuditRead, PermissionUsageRead, PermissionOutboxRead, PermissionContentPolicyRead, PermissionPricingRead, PermissionPromptRead, PermissionKnowledgeRead, PermissionToolRead, PermissionApplicationRead, PermissionNotificationRead, PermissionMCPServerRead, PermissionSkillRead, PermissionDigitalEmployeeRead, PermissionMarketplaceRead, PermissionFileRead},
|
|
"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)
|
|
}
|