225 lines
7.8 KiB
Go
225 lines
7.8 KiB
Go
package httpx
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// Permission 权限标识(对应 API 操作)。
|
|
type Permission string
|
|
|
|
// 预定义权限常量(覆盖全部 API 操作)。
|
|
const (
|
|
// 内容管理
|
|
PermContentRegister Permission = "content:register"
|
|
PermContentReview Permission = "content:review"
|
|
PermContentIssue Permission = "content:issue"
|
|
PermContentVerify Permission = "content:verify"
|
|
PermContentTranscode Permission = "content:transcode"
|
|
PermContentIngest Permission = "content:ingest"
|
|
PermContentPublish Permission = "content:publish"
|
|
PermContentInject Permission = "content:inject"
|
|
PermContentVersionChange Permission = "content:version_change"
|
|
PermContentTakedown Permission = "content:takedown"
|
|
PermContentRestore Permission = "content:restore"
|
|
PermContentMerge Permission = "content:merge"
|
|
PermContentSplit Permission = "content:split"
|
|
PermContentAddEpisodes Permission = "content:add_episodes"
|
|
// 查询
|
|
PermQueryByMA Permission = "query:by_ma"
|
|
PermQueryByHash Permission = "query:by_hash"
|
|
PermQueryByProvincial Permission = "query:by_provincial"
|
|
PermQueryByLibraryID Permission = "query:by_library_id"
|
|
PermQueryMappings Permission = "query:mappings"
|
|
PermQueryEpisodes Permission = "query:episodes"
|
|
PermQueryReviews Permission = "query:reviews"
|
|
PermQueryContents Permission = "query:contents"
|
|
PermQueryProvenance Permission = "query:provenance"
|
|
PermQueryAccountability Permission = "query:accountability"
|
|
PermQueryEvidence Permission = "query:evidence"
|
|
// 数据与分账
|
|
PermPlaybackReport Permission = "data:playback_report"
|
|
PermPlaybackSummary Permission = "data:playback_summary"
|
|
PermSettlement Permission = "data:settlement"
|
|
// 确权与侵权
|
|
PermInfringeMatch Permission = "rights:infringe_match"
|
|
PermAuthorize Permission = "rights:authorize"
|
|
PermAuthCheck Permission = "rights:auth_check"
|
|
// 跨省与终端
|
|
PermCrossProvince Permission = "cross:province_admit"
|
|
PermTerminalVerify Permission = "terminal:verify"
|
|
// 备案与监管
|
|
PermBindFiling Permission = "regulatory:bind_filing"
|
|
PermQueryFiling Permission = "regulatory:query_filing"
|
|
PermNationalStats Permission = "regulatory:national_stats"
|
|
PermDailyReport Permission = "regulatory:daily_report"
|
|
PermListSegments Permission = "admin:list_segments"
|
|
PermRegisterSegment Permission = "admin:register_segment"
|
|
// 大小屏融合
|
|
PermResolve Permission = "screen:resolve"
|
|
PermScanVerify Permission = "screen:scan_verify"
|
|
PermRecordPurchase Permission = "rights:record_purchase"
|
|
PermVerifyRights Permission = "rights:verify_rights"
|
|
// 系统管理
|
|
PermManageUsers Permission = "admin:manage_users"
|
|
PermManageOrgs Permission = "admin:manage_orgs"
|
|
)
|
|
|
|
// RBACManager 基于角色的动态权限管理器。
|
|
// 支持运行时配置角色-权限映射,替代硬编码角色检查。
|
|
type RBACManager struct {
|
|
mu sync.RWMutex
|
|
roles map[string]map[Permission]bool // role -> permission set
|
|
}
|
|
|
|
// NewRBACManager 创建权限管理器并预置默认角色权限。
|
|
func NewRBACManager() *RBACManager {
|
|
r := &RBACManager{roles: make(map[string]map[Permission]bool)}
|
|
r.loadDefaults()
|
|
return r
|
|
}
|
|
|
|
// loadDefaults 加载默认四角色权限矩阵。
|
|
func (r *RBACManager) loadDefaults() {
|
|
// 监管主体:全部权限
|
|
r.SetRolePermissions("regulator", allPermissions())
|
|
|
|
// 审核主体:审核、入库、转码、查询、验真
|
|
r.SetRolePermissions("reviewer", []Permission{
|
|
PermContentReview, PermContentTranscode, PermContentIngest,
|
|
PermContentVerify, PermContentVersionChange,
|
|
PermQueryByMA, PermQueryByHash, PermQueryByProvincial, PermQueryByLibraryID,
|
|
PermQueryMappings, PermQueryEpisodes, PermQueryReviews, PermQueryContents,
|
|
PermQueryProvenance, PermQueryAccountability, PermQueryEvidence,
|
|
PermBindFiling, PermQueryFiling,
|
|
PermResolve, PermScanVerify,
|
|
})
|
|
|
|
// 内容提供商:送审、查询、确权
|
|
r.SetRolePermissions("cp", []Permission{
|
|
PermContentRegister,
|
|
PermQueryByMA, PermQueryByHash, PermQueryByProvincial, PermQueryByLibraryID,
|
|
PermQueryMappings, PermQueryEpisodes, PermQueryReviews, PermQueryContents,
|
|
PermQueryProvenance, PermQueryEvidence,
|
|
PermInfringeMatch, PermAuthorize, PermAuthCheck,
|
|
PermResolve, PermScanVerify, PermRecordPurchase, PermVerifyRights,
|
|
})
|
|
|
|
// 运营商:注入、发布、查询、播放回传
|
|
r.SetRolePermissions("operator", []Permission{
|
|
PermContentPublish, PermContentInject,
|
|
PermContentVerify, PermTerminalVerify,
|
|
PermQueryByMA, PermQueryByHash, PermQueryMappings, PermQueryEpisodes,
|
|
PermQueryContents, PermQueryProvenance,
|
|
PermPlaybackReport, PermPlaybackSummary, PermSettlement,
|
|
PermResolve, PermScanVerify, PermVerifyRights,
|
|
})
|
|
}
|
|
|
|
// SetRolePermissions 设置某角色的权限集合(覆盖原有)。
|
|
func (r *RBACManager) SetRolePermissions(role string, perms []Permission) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
set := make(map[Permission]bool, len(perms))
|
|
for _, p := range perms {
|
|
set[p] = true
|
|
}
|
|
r.roles[role] = set
|
|
}
|
|
|
|
// GrantPermission 为角色追加单个权限。
|
|
func (r *RBACManager) GrantPermission(role string, perm Permission) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
if r.roles[role] == nil {
|
|
r.roles[role] = make(map[Permission]bool)
|
|
}
|
|
r.roles[role][perm] = true
|
|
}
|
|
|
|
// RevokePermission 移除角色的某个权限。
|
|
func (r *RBACManager) RevokePermission(role string, perm Permission) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
if r.roles[role] != nil {
|
|
delete(r.roles[role], perm)
|
|
}
|
|
}
|
|
|
|
// HasPermission 检查角色是否拥有指定权限。
|
|
func (r *RBACManager) HasPermission(role string, perm Permission) bool {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
perms, ok := r.roles[role]
|
|
if !ok {
|
|
return false
|
|
}
|
|
return perms[perm]
|
|
}
|
|
|
|
// ListPermissions 列出角色的全部权限。
|
|
func (r *RBACManager) ListPermissions(role string) []Permission {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
perms, ok := r.roles[role]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
out := make([]Permission, 0, len(perms))
|
|
for p := range perms {
|
|
out = append(out, p)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// ListRoles 列出全部已配置角色。
|
|
func (r *RBACManager) ListRoles() []string {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
out := make([]string, 0, len(r.roles))
|
|
for role := range r.roles {
|
|
out = append(out, role)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// RequirePermission 返回 Gin 中间件,校验当前角色是否拥有指定权限。
|
|
// 用法:rg.POST("/content/issue", rbac.RequirePermission(httpx.PermContentIssue), h.issue)
|
|
func (r *RBACManager) RequirePermission(perm Permission) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
role := RoleFromContext(c)
|
|
if role == "" {
|
|
Error(c, 401, "UNAUTHORIZED", "未认证")
|
|
c.Abort()
|
|
return
|
|
}
|
|
if !r.HasPermission(role, perm) {
|
|
Error(c, 403, "FORBIDDEN", "角色 "+role+" 无权限: "+string(perm))
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// allPermissions 返回全部权限列表(用于监管角色)。
|
|
func allPermissions() []Permission {
|
|
return []Permission{
|
|
PermContentRegister, PermContentReview, PermContentIssue, PermContentVerify,
|
|
PermContentTranscode, PermContentIngest, PermContentPublish, PermContentInject,
|
|
PermContentVersionChange, PermContentTakedown, PermContentRestore,
|
|
PermContentMerge, PermContentSplit, PermContentAddEpisodes,
|
|
PermQueryByMA, PermQueryByHash, PermQueryByProvincial, PermQueryByLibraryID,
|
|
PermQueryMappings, PermQueryEpisodes, PermQueryReviews, PermQueryContents,
|
|
PermQueryProvenance, PermQueryAccountability, PermQueryEvidence,
|
|
PermPlaybackReport, PermPlaybackSummary, PermSettlement,
|
|
PermInfringeMatch, PermAuthorize, PermAuthCheck,
|
|
PermCrossProvince, PermTerminalVerify,
|
|
PermBindFiling, PermQueryFiling, PermNationalStats, PermDailyReport,
|
|
PermListSegments, PermRegisterSegment,
|
|
PermResolve, PermScanVerify, PermRecordPurchase, PermVerifyRights,
|
|
PermManageUsers, PermManageOrgs,
|
|
}
|
|
}
|