package database import ( "RenewCMS/internal/domain/role" entity "RenewCMS/internal/infrastructure/persistence/models" "gorm.io/gorm" "gorm.io/gorm/clause" ) const ( usersTable = "users" legacyRoleColumn = "role" legacyOwnerValue = "owner" legacyAdminValue = "admin" legacyUnsetValue = "" unassignedRoleCond = "(role_id IS NULL OR role_id = 0)" ) func legacyRoleColumnExists(db *gorm.DB) bool { return db.Migrator().HasColumn(usersTable, legacyRoleColumn) } func requireBuiltInRoleID(tx *gorm.DB, name string) (uint32, error) { id, found, err := builtInRoleID(tx, name) if err != nil { return 0, err } if !found { return 0, role.ErrRoleNotFound } return id, nil } func BackfillLegacyUserRoles(db *gorm.DB) error { if !legacyRoleColumnExists(db) { return nil } return db.Transaction(func(tx *gorm.DB) error { done, err := markerApplied(tx, legacyUserRolesMarker) if err != nil || done { return err } ownerID, err := requireBuiltInRoleID(tx, role.OwnerName) if err != nil { return err } adminID, err := requireBuiltInRoleID(tx, role.AdminName) if err != nil { return err } writerID, err := requireBuiltInRoleID(tx, role.WriterName) if err != nil { return err } legacy := clause.Column{Name: legacyRoleColumn} assign := func(roleID uint32, condition string, args ...any) error { return tx.Table(usersTable).Where(unassignedRoleCond).Where(condition, args...).UpdateColumn("role_id", roleID).Error } var owners []uint32 if err := tx.Table(usersTable).Where(unassignedRoleCond).Where("? = ?", legacy, legacyOwnerValue).Order("id asc").Pluck("id", &owners).Error; err != nil { return err } if len(owners) > 0 { if err := assign(ownerID, "id = ?", owners[0]); err != nil { return err } } if err := assign(adminID, "? = ?", legacy, legacyOwnerValue); err != nil { return err } if err := assign(adminID, "? = ?", legacy, legacyAdminValue); err != nil { return err } if len(owners) == 0 { var lowest []uint32 if err := tx.Model(&entity.User{}).Order("id asc").Limit(1).Pluck("id", &lowest).Error; err != nil { return err } if len(lowest) > 0 { if err := assign(ownerID, "? = ? AND id = ?", legacy, legacyUnsetValue, lowest[0]); err != nil { return err } } } if err := assign(adminID, "? = ?", legacy, legacyUnsetValue); err != nil { return err } if err := assign(writerID, "1 = 1"); err != nil { return err } return applyMarker(tx, legacyUserRolesMarker) }) }