161 lines
4.8 KiB
Go
161 lines
4.8 KiB
Go
// Package permission — 能力點(capability)與角色預設對照。
|
||
//
|
||
// 現行策略(M1~M2):
|
||
// - JWT 帶 roles[];中介層/業務用 permission.Has(roles, code) 判定
|
||
// - 尚未做 DB 動態 permission 表;擴充時只改本檔 RoleGrants 即可
|
||
//
|
||
// 命名:{domain}:{resource}:{action} 或 {domain}:{action}
|
||
package permission
|
||
|
||
// ─── 公開/系統(不需登入)────────────────────────────────
|
||
const (
|
||
// PublicPing 健康檢查(無 JWT)
|
||
PublicPing = "public:ping"
|
||
// PublicAuthLogin 登入/註冊/忘密/refresh 等公開 auth
|
||
PublicAuthLogin = "public:auth:login"
|
||
// PublicThreadsOAuthCallback OAuth 回調(state 驗證)
|
||
PublicThreadsOAuthCallback = "public:threads:oauth_callback"
|
||
)
|
||
|
||
// ─── 已登入會員(member)──────────────────────────────────
|
||
const (
|
||
AuthMe = "auth:me"
|
||
AuthProfileUpdate = "auth:profile:update"
|
||
AuthPasswordChange = "auth:password:change"
|
||
AuthEmailVerify = "auth:email:verify"
|
||
AuthLogout = "auth:logout"
|
||
AuthIdentities = "auth:identities"
|
||
AuthBind = "auth:bind"
|
||
AuthUnbind = "auth:unbind"
|
||
|
||
MediaUpload = "media:upload"
|
||
|
||
SettingsAIRead = "settings:ai:read"
|
||
SettingsAIWrite = "settings:ai:write"
|
||
SettingsPlacementRead = "settings:placement:read"
|
||
SettingsPlacementWrite = "settings:placement:write"
|
||
SettingsModelsList = "settings:models:list"
|
||
|
||
ThreadsOAuthStart = "threads:oauth:start"
|
||
ThreadsList = "threads:list"
|
||
ThreadsRefresh = "threads:refresh"
|
||
ThreadsDisconnect = "threads:disconnect"
|
||
|
||
JobsList = "jobs:list"
|
||
JobsGet = "jobs:get"
|
||
// JobsDemoCreate 僅 admin(任務頁「產生測試任務」)
|
||
JobsDemoCreate = "jobs:demo:create"
|
||
|
||
NotifList = "notifications:list"
|
||
NotifUnread = "notifications:unread"
|
||
NotifMarkRead = "notifications:mark_read"
|
||
)
|
||
|
||
// ─── 管理員(admin)───────────────────────────────────────
|
||
const (
|
||
// AdminAccess 進入管理能力的總閘(AdminAuth middleware 檢查此碼)
|
||
AdminAccess = "admin:access"
|
||
|
||
AdminMembersList = "admin:members:list"
|
||
AdminMembersGet = "admin:members:get"
|
||
AdminMembersCreate = "admin:members:create"
|
||
AdminMembersSuspend = "admin:members:suspend"
|
||
AdminMembersRoles = "admin:members:roles"
|
||
AdminMembersEmailVerified = "admin:members:email_verified"
|
||
AdminMembersResetPassword = "admin:members:reset_password"
|
||
AdminMembersIdentities = "admin:members:identities"
|
||
AdminMembersStatus = "admin:members:status"
|
||
)
|
||
|
||
// Role names(與 member.domain 一致)
|
||
const (
|
||
RoleMember = "member"
|
||
RoleAdmin = "admin"
|
||
)
|
||
|
||
// memberBase — 一般會員可做的事
|
||
var memberBase = []string{
|
||
AuthMe, AuthProfileUpdate, AuthPasswordChange, AuthEmailVerify, AuthLogout,
|
||
AuthIdentities, AuthBind, AuthUnbind,
|
||
MediaUpload,
|
||
SettingsAIRead, SettingsAIWrite, SettingsPlacementRead, SettingsPlacementWrite, SettingsModelsList,
|
||
ThreadsOAuthStart, ThreadsList, ThreadsRefresh, ThreadsDisconnect,
|
||
JobsList, JobsGet,
|
||
NotifList, NotifUnread, NotifMarkRead,
|
||
}
|
||
|
||
// adminExtra — 管理員額外能力
|
||
var adminExtra = []string{
|
||
AdminAccess,
|
||
AdminMembersList, AdminMembersGet, AdminMembersCreate,
|
||
AdminMembersSuspend, AdminMembersRoles, AdminMembersEmailVerified,
|
||
AdminMembersResetPassword, AdminMembersIdentities, AdminMembersStatus,
|
||
JobsDemoCreate,
|
||
}
|
||
|
||
// RoleGrants 角色 → 能力列表(可擴充自訂角色)
|
||
var RoleGrants = map[string][]string{
|
||
RoleMember: memberBase,
|
||
RoleAdmin: append(append([]string{}, memberBase...), adminExtra...),
|
||
}
|
||
|
||
// Expand 合併多角色能力(去重)
|
||
func Expand(roles []string) map[string]struct{} {
|
||
out := make(map[string]struct{})
|
||
for _, r := range roles {
|
||
for _, p := range RoleGrants[r] {
|
||
out[p] = struct{}{}
|
||
}
|
||
}
|
||
// admin 一定含 AdminAccess
|
||
if hasRole(roles, RoleAdmin) {
|
||
out[AdminAccess] = struct{}{}
|
||
}
|
||
return out
|
||
}
|
||
|
||
func hasRole(roles []string, want string) bool {
|
||
for _, r := range roles {
|
||
if r == want {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// Has 是否具備指定 permission
|
||
func Has(roles []string, code string) bool {
|
||
if code == "" {
|
||
return false
|
||
}
|
||
_, ok := Expand(roles)[code]
|
||
return ok
|
||
}
|
||
|
||
// HasAny 具備任一即可
|
||
func HasAny(roles []string, codes ...string) bool {
|
||
set := Expand(roles)
|
||
for _, c := range codes {
|
||
if _, ok := set[c]; ok {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// HasAll 必須全部具備
|
||
func HasAll(roles []string, codes ...string) bool {
|
||
set := Expand(roles)
|
||
for _, c := range codes {
|
||
if _, ok := set[c]; !ok {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
// IsAdmin 是否具管理總閘(相容舊呼叫)
|
||
func IsAdmin(roles []string) bool {
|
||
return Has(roles, AdminAccess)
|
||
}
|