chore: 初始化仓库基线(AGENTS.md、git 规范、敏感文件排除)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"silk-server-go/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// rolePermCache 角色-权限码缓存,避免每次请求查库
|
||||
var (
|
||||
rolePermCache = make(map[string]map[string]bool)
|
||||
rolePermCacheMu sync.RWMutex
|
||||
rolePermCacheTime time.Time
|
||||
)
|
||||
|
||||
const rolePermCacheTTL = 5 * time.Minute
|
||||
|
||||
// loadRolePermissions 从数据库加载所有角色-权限映射到缓存
|
||||
func loadRolePermissions(db *gorm.DB) map[string]map[string]bool {
|
||||
result := make(map[string]map[string]bool)
|
||||
|
||||
var rows []struct {
|
||||
Role string `gorm:"column:role"`
|
||||
Code string `gorm:"column:code"`
|
||||
}
|
||||
db.Table("role_permissions").
|
||||
Select("role_permissions.role AS role, permissions.code AS code").
|
||||
Joins("JOIN permissions ON permissions.id = role_permissions.permission_id").
|
||||
Scan(&rows)
|
||||
|
||||
for _, r := range rows {
|
||||
if result[r.Role] == nil {
|
||||
result[r.Role] = make(map[string]bool)
|
||||
}
|
||||
result[r.Role][r.Code] = true
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// getRolePermissions 获取缓存的角色权限映射(TTL 5 分钟)
|
||||
func getRolePermissions(db *gorm.DB) map[string]map[string]bool {
|
||||
rolePermCacheMu.RLock()
|
||||
if time.Since(rolePermCacheTime) < rolePermCacheTTL && len(rolePermCache) > 0 {
|
||||
cached := rolePermCache
|
||||
rolePermCacheMu.RUnlock()
|
||||
return cached
|
||||
}
|
||||
rolePermCacheMu.RUnlock()
|
||||
|
||||
rolePermCacheMu.Lock()
|
||||
defer rolePermCacheMu.Unlock()
|
||||
// 双重检查
|
||||
if time.Since(rolePermCacheTime) < rolePermCacheTTL && len(rolePermCache) > 0 {
|
||||
return rolePermCache
|
||||
}
|
||||
rolePermCache = loadRolePermissions(db)
|
||||
rolePermCacheTime = time.Now()
|
||||
return rolePermCache
|
||||
}
|
||||
|
||||
// InvalidateRolePermCache 使角色权限缓存失效(角色权限变更时调用)
|
||||
func InvalidateRolePermCache() {
|
||||
rolePermCacheMu.Lock()
|
||||
defer rolePermCacheMu.Unlock()
|
||||
rolePermCache = make(map[string]map[string]bool)
|
||||
rolePermCacheTime = time.Time{}
|
||||
}
|
||||
|
||||
// hasPermission 检查角色是否拥有指定权限码
|
||||
func hasPermission(db *gorm.DB, role, code string) bool {
|
||||
perms := getRolePermissions(db)
|
||||
rolePerms, ok := perms[role]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return rolePerms[code]
|
||||
}
|
||||
|
||||
// RequirePermission 返回一个校验指定权限码的中间件
|
||||
func RequirePermission(db *gorm.DB, code string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
userVal, exists := c.Get("user")
|
||||
if !exists {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
|
||||
return
|
||||
}
|
||||
userMap, ok := userVal.(map[string]interface{})
|
||||
if !ok {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "权限不足"})
|
||||
return
|
||||
}
|
||||
role, _ := userMap["role"].(string)
|
||||
if role == model.RoleAdmin {
|
||||
// admin 拥有全部权限,直接放行
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
if !hasPermission(db, role, code) {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "权限不足,需要:" + code})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user