71 lines
1.7 KiB
Go
71 lines
1.7 KiB
Go
package database
|
|
|
|
import (
|
|
"slices"
|
|
|
|
"RenewCMS/internal/domain/role"
|
|
"RenewCMS/internal/infrastructure/persistence/mappers"
|
|
entity "RenewCMS/internal/infrastructure/persistence/models"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func SeedBuiltInRoles(db *gorm.DB) error {
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
for _, builtIn := range role.BuiltInRoles() {
|
|
if err := seedBuiltInRole(tx, builtIn); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func seedBuiltInRole(tx *gorm.DB, builtIn role.Role) error {
|
|
id, found, err := builtInRoleID(tx, builtIn.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if found {
|
|
return reconcileBuiltInRole(tx, id, builtIn)
|
|
}
|
|
model := mappers.RoleToModel(builtIn)
|
|
if err := tx.Create(&model).Error; err != nil {
|
|
return err
|
|
}
|
|
return tx.Create(mappers.GrantsToModel(model.ID, builtIn.Grants)).Error
|
|
}
|
|
|
|
func builtInRoleID(tx *gorm.DB, name string) (uint32, bool, error) {
|
|
var found entity.Role
|
|
result := tx.Where("name = ? AND built_in = ?", name, true).Order("id asc").Limit(1).Find(&found)
|
|
if result.Error != nil {
|
|
return 0, false, result.Error
|
|
}
|
|
return found.ID, result.RowsAffected > 0, nil
|
|
}
|
|
|
|
func reconcileBuiltInRole(tx *gorm.DB, id uint32, builtIn role.Role) error {
|
|
var stored entity.Role
|
|
if err := tx.First(&stored, id).Error; err != nil {
|
|
return err
|
|
}
|
|
if !builtIn.Locked && stored.Version != 1 {
|
|
return nil
|
|
}
|
|
var present []string
|
|
if err := tx.Model(&entity.RolePermission{}).Where("role_id = ?", id).Pluck("permission_key", &present).Error; err != nil {
|
|
return err
|
|
}
|
|
missing := []role.Grant{}
|
|
for _, grant := range builtIn.Grants {
|
|
if !slices.Contains(present, grant.Key) {
|
|
missing = append(missing, grant)
|
|
}
|
|
}
|
|
if len(missing) == 0 {
|
|
return nil
|
|
}
|
|
return tx.Create(mappers.GrantsToModel(id, missing)).Error
|
|
}
|