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 }