加固后台管理安全

This commit is contained in:
yml2213
2026-06-11 07:23:00 +08:00
parent 5255b21141
commit 88b1df64e7
41 changed files with 1276 additions and 293 deletions
@@ -3,19 +3,22 @@ package adminrole
import (
"context"
"errors"
"fmt"
"hfb_sys/backend/internal/model"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Repository struct {
db *gorm.DB
db *gorm.DB
redis *redis.Client
}
func NewRepository(db *gorm.DB) *Repository {
return &Repository{db: db}
func NewRepository(db *gorm.DB, redis *redis.Client) *Repository {
return &Repository{db: db, redis: redis}
}
func (r *Repository) List(ctx context.Context) ([]RoleDTO, error) {
@@ -108,15 +111,27 @@ func (r *Repository) Delete(ctx context.Context, id uint64) error {
if role.Code == "super_admin" {
return ErrProtectedRole
}
return db.Transaction(func(tx *gorm.DB) error {
adminIDs, err := r.adminIDsByRole(ctx, id)
if err != nil {
return err
}
err = db.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("role_id = ?", id).Delete(&model.RolePermission{}).Error; err != nil {
return err
}
if err := tx.Where("role_id = ?", id).Delete(&model.AdminUserRole{}).Error; err != nil {
return err
}
return tx.Delete(&model.Role{}, id).Error
if err := tx.Delete(&model.Role{}, id).Error; err != nil {
return err
}
return r.bumpAdminTokenVersions(tx, adminIDs)
})
if err != nil {
return err
}
r.invalidateAdminPermCaches(ctx, adminIDs)
return nil
}
func (r *Repository) AssignPermissions(ctx context.Context, roleID uint64, permIDs []uint64) error {
@@ -125,7 +140,11 @@ func (r *Repository) AssignPermissions(ctx context.Context, roleID uint64, permI
if err := db.First(&role, roleID).Error; err != nil {
return err
}
return db.Transaction(func(tx *gorm.DB) error {
adminIDs, err := r.adminIDsByRole(ctx, roleID)
if err != nil {
return err
}
err = db.Transaction(func(tx *gorm.DB) error {
if role.Code == "super_admin" {
var allPermIDs []uint64
if err := tx.Model(&model.Permission{}).Pluck("id", &allPermIDs).Error; err != nil {
@@ -142,8 +161,13 @@ func (r *Repository) AssignPermissions(ctx context.Context, roleID uint64, permI
return err
}
}
return nil
return r.bumpAdminTokenVersions(tx, adminIDs)
})
if err != nil {
return err
}
r.invalidateAdminPermCaches(ctx, adminIDs)
return nil
}
func (r *Repository) ListPermissions(ctx context.Context) ([]PermissionDTO, error) {
@@ -186,6 +210,34 @@ func (r *Repository) getRolePermissions(ctx context.Context, roleID uint64) ([]P
return result, nil
}
func (r *Repository) adminIDsByRole(ctx context.Context, roleID uint64) ([]uint64, error) {
var ids []uint64
err := r.db.WithContext(ctx).Model(&model.AdminUserRole{}).
Where("role_id = ?", roleID).
Pluck("admin_user_id", &ids).Error
return ids, err
}
func (r *Repository) bumpAdminTokenVersions(tx *gorm.DB, adminIDs []uint64) error {
if len(adminIDs) == 0 {
return nil
}
return tx.Model(&model.AdminUser{}).
Where("id IN ?", adminIDs).
UpdateColumn("token_version", gorm.Expr("token_version + 1")).Error
}
func (r *Repository) invalidateAdminPermCaches(ctx context.Context, adminIDs []uint64) {
if r.redis == nil || len(adminIDs) == 0 {
return
}
keys := make([]string, 0, len(adminIDs))
for _, id := range adminIDs {
keys = append(keys, fmt.Sprintf("admin:perms:%d", id))
}
_ = r.redis.Del(ctx, keys...).Err()
}
var ErrProtectedRole = errors.New("protected role")
func IsNotFound(err error) bool {