194 lines
5.3 KiB
Go
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)
|
|
}
|