209 lines
5.7 KiB
Go
209 lines
5.7 KiB
Go
package repository
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"hyapp-admin-server/internal/model"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func (s *Store) ListPermissions() ([]model.Permission, error) {
|
|
var permissions []model.Permission
|
|
err := s.db.Order("kind ASC, code ASC").Find(&permissions).Error
|
|
return permissions, err
|
|
}
|
|
|
|
func (s *Store) CreatePermission(permission *model.Permission) error {
|
|
normalized, err := normalizePermission(*permission)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*permission = normalized
|
|
return s.db.Create(permission).Error
|
|
}
|
|
|
|
func (s *Store) UpdatePermission(id uint, patch model.Permission) (*model.Permission, error) {
|
|
normalized, err := normalizePermission(patch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var permission model.Permission
|
|
if err := s.db.First(&permission, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 权限码会写入 JWT 和前端按钮判断,更新时必须整体校验后一次性落库。
|
|
updates := map[string]any{
|
|
"name": normalized.Name,
|
|
"code": normalized.Code,
|
|
"kind": normalized.Kind,
|
|
"description": normalized.Description,
|
|
}
|
|
if err := s.db.Model(&permission).Updates(updates).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
if err := s.db.First(&permission, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &permission, nil
|
|
}
|
|
|
|
func (s *Store) DeletePermission(id uint) error {
|
|
var roleCount int64
|
|
if err := s.db.Table("admin_role_permissions").Where("permission_id = ?", id).Count(&roleCount).Error; err != nil {
|
|
return err
|
|
}
|
|
if roleCount > 0 {
|
|
return errors.New("permission is bound to roles")
|
|
}
|
|
|
|
// Menus reference permission_code by string, so deletion must check the code before removing the definition.
|
|
var menuCount int64
|
|
if err := s.db.Model(&model.Menu{}).Where("permission_code = (SELECT code FROM admin_permissions WHERE id = ?)", id).Count(&menuCount).Error; err != nil {
|
|
return err
|
|
}
|
|
if menuCount > 0 {
|
|
return errors.New("permission is bound to menus")
|
|
}
|
|
|
|
return s.db.Delete(&model.Permission{}, id).Error
|
|
}
|
|
|
|
func (s *Store) SyncDefaultPermissions() error {
|
|
return s.db.Transaction(func(tx *gorm.DB) error {
|
|
if err := s.syncDefaultPermissions(tx); err != nil {
|
|
return err
|
|
}
|
|
return s.syncManagedDefaultRolePermissions(tx)
|
|
})
|
|
}
|
|
|
|
func (s *Store) syncManagedDefaultRolePermissions(tx *gorm.DB) error {
|
|
var allPermissions []model.Permission
|
|
if err := tx.Find(&allPermissions).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, definition := range managedDefaultRoles {
|
|
var role model.Role
|
|
result := tx.Where("code = ?", definition.Code).Limit(1).Find(&role)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
role = definition
|
|
if err := tx.Create(&role).Error; err != nil {
|
|
return err
|
|
}
|
|
} else if err := tx.Model(&role).Updates(map[string]any{
|
|
"name": definition.Name,
|
|
"description": definition.Description,
|
|
}).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
permissions := allPermissions
|
|
if definition.Code != roleCodePlatformAdmin {
|
|
permissions = nil
|
|
codes := defaultRolePermissionCodes(definition.Code)
|
|
if len(codes) > 0 {
|
|
if err := tx.Where("code IN ?", codes).Find(&permissions).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
// “同步权限”是恢复固定岗位模板的显式管理动作,必须删除历史跨模块授权,不能只追加缺失项。
|
|
if err := tx.Model(&role).Association("Permissions").Replace(permissions); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) ListRoles() ([]model.Role, error) {
|
|
var roles []model.Role
|
|
err := s.db.Preload("Permissions").Order("id ASC").Find(&roles).Error
|
|
return roles, err
|
|
}
|
|
|
|
func (s *Store) CreateRole(role *model.Role, permissionIDs []uint) error {
|
|
return s.db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Create(role).Error; err != nil {
|
|
return err
|
|
}
|
|
if len(permissionIDs) == 0 {
|
|
return nil
|
|
}
|
|
var permissions []model.Permission
|
|
if err := tx.Where("id IN ?", permissionIDs).Find(&permissions).Error; err != nil {
|
|
return err
|
|
}
|
|
return tx.Model(role).Association("Permissions").Replace(permissions)
|
|
})
|
|
}
|
|
|
|
func (s *Store) UpdateRole(roleID uint, patch model.Role, permissionIDs *[]uint) (*model.Role, error) {
|
|
var role model.Role
|
|
if err := s.db.First(&role, roleID).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err := s.db.Transaction(func(tx *gorm.DB) error {
|
|
updates := map[string]any{
|
|
"name": patch.Name,
|
|
"code": patch.Code,
|
|
"description": patch.Description,
|
|
}
|
|
if err := tx.Model(&role).Updates(updates).Error; err != nil {
|
|
return err
|
|
}
|
|
if permissionIDs != nil {
|
|
var permissions []model.Permission
|
|
if len(*permissionIDs) > 0 {
|
|
if err := tx.Where("id IN ?", *permissionIDs).Find(&permissions).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := tx.Model(&role).Association("Permissions").Replace(permissions); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.db.Preload("Permissions").First(&role, roleID).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &role, nil
|
|
}
|
|
|
|
func (s *Store) DeleteRole(roleID uint) error {
|
|
var users int64
|
|
if err := s.db.Table("admin_user_roles").Where("role_id = ?", roleID).Count(&users).Error; err != nil {
|
|
return err
|
|
}
|
|
if users > 0 {
|
|
return errors.New("role is bound to users")
|
|
}
|
|
return s.db.Delete(&model.Role{}, roleID).Error
|
|
}
|
|
|
|
func (s *Store) ReplaceRolePermissions(roleID uint, permissionIDs []uint) error {
|
|
var role model.Role
|
|
if err := s.db.First(&role, roleID).Error; err != nil {
|
|
return err
|
|
}
|
|
var permissions []model.Permission
|
|
if len(permissionIDs) > 0 {
|
|
if err := s.db.Where("id IN ?", permissionIDs).Find(&permissions).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return s.db.Model(&role).Association("Permissions").Replace(permissions)
|
|
}
|