2026-05-12 09:53:20 +08:00

194 lines
5.3 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.syncDefaultRolePermissionMigrations(tx)
})
}
func (s *Store) syncDefaultRolePermissionMigrations(tx *gorm.DB) error {
var platformAdmin model.Role
err := tx.Where("code = ?", "platform-admin").First(&platformAdmin).Error
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
if platformAdmin.ID > 0 {
var permissions []model.Permission
if err := tx.Find(&permissions).Error; err != nil {
return err
}
if err := tx.Model(&platformAdmin).Association("Permissions").Replace(permissions); err != nil {
return err
}
}
var opsAdmin model.Role
err = tx.Where("code = ?", "ops-admin").First(&opsAdmin).Error
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
if opsAdmin.ID > 0 {
return s.appendRolePermissionsByCode(tx, &opsAdmin, defaultRolePermissionMigrationCodes(opsAdmin.Code))
}
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)
}