package persistence import ( "RenewCMS/internal/domain/role" "RenewCMS/internal/infrastructure/persistence/mappers" entity "RenewCMS/internal/infrastructure/persistence/models" "gorm.io/gorm" ) type RoleRepository struct { db *gorm.DB } func NewRoleRepository(db *gorm.DB) *RoleRepository { return &RoleRepository{db} } func (r *RoleRepository) grantRows(roleID uint32) ([]entity.RolePermission, error) { var rows []entity.RolePermission if err := r.db.Where("role_id = ?", roleID).Order("id asc").Find(&rows).Error; err != nil { return nil, err } return rows, nil } func (r *RoleRepository) withGrants(found entity.Role) (role.Role, error) { rows, err := r.grantRows(found.ID) if err != nil { return role.Role{}, err } return mappers.RoleToDomain(found, rows), nil } func (r *RoleRepository) List() ([]role.Role, error) { var found []entity.Role if err := r.db.Order("id asc").Find(&found).Error; err != nil { return nil, err } roles := make([]role.Role, 0, len(found)) for _, row := range found { roles = append(roles, mappers.RoleToDomain(row, nil)) } return roles, nil } func (r *RoleRepository) Get(id uint32) (role.Role, error) { var found entity.Role if err := r.db.First(&found, id).Error; err != nil { return role.Role{}, mapNotFoundErr(err, role.ErrRoleNotFound) } return r.withGrants(found) } func (r *RoleRepository) GetByName(name string) (role.Role, error) { var found entity.Role if err := r.db.Where("name = ?", name).Order("built_in DESC, id ASC").First(&found).Error; err != nil { return role.Role{}, mapNotFoundErr(err, role.ErrRoleNotFound) } return r.withGrants(found) } func (r *RoleRepository) ListGrants(roleID uint32) ([]role.Grant, error) { rows, err := r.grantRows(roleID) if err != nil { return nil, err } return mappers.GrantsToDomain(rows), nil } func (r *RoleRepository) Create(created role.Role) (role.Role, error) { model := mappers.RoleToModel(created) model.ID = 0 err := r.db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(&model).Error; err != nil { return err } rows := mappers.GrantsToModel(model.ID, created.Grants) if len(rows) == 0 { return nil } return tx.Create(&rows).Error }) if err != nil { return role.Role{}, err } return r.withGrants(model) } func (r *RoleRepository) Save(saved role.Role) (role.Role, error) { err := r.db.Transaction(func(tx *gorm.DB) error { if err := tx.First(&entity.Role{}, saved.ID).Error; err != nil { return mapNotFoundErr(err, role.ErrRoleNotFound) } update := tx.Model(&entity.Role{}). Where("id = ? AND version = ?", saved.ID, saved.Version). Updates(map[string]any{"name": saved.Name, "description": saved.Description, "version": saved.Version + 1}) if update.Error != nil { return update.Error } if update.RowsAffected == 0 { return role.ErrRoleConflict } if err := tx.Where("role_id = ?", saved.ID).Delete(&entity.RolePermission{}).Error; err != nil { return err } rows := mappers.GrantsToModel(saved.ID, saved.Grants) if len(rows) == 0 { return nil } return tx.Create(&rows).Error }) if err != nil { return role.Role{}, err } return r.Get(saved.ID) } var _ role.Repository = &RoleRepository{}