basicly implement acl crud ops with roles and resources
This commit is contained in:
136
internal/acl/roles.go
Normal file
136
internal/acl/roles.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// GetRoles returns all roles.
|
||||
// May return [ErrNotInitialized] or db error.
|
||||
func (s *Service) GetRoles() ([]Role, error) {
|
||||
if !s.isInitialized() {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
|
||||
var roles []Role
|
||||
if err := s.db.Preload("Resources").Order("id").Find(&roles).Error; err != nil {
|
||||
return nil, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// CreateRole creates a new role with the given name or returns existing one.
|
||||
// Returns the ID of the created role.
|
||||
// May return [ErrNotInitialized], [ErrInvalidRoleName], [ErrRoleAlreadyExists] or db error.
|
||||
func (s *Service) CreateRole(name string) (uint, error) {
|
||||
if !s.isInitialized() {
|
||||
return 0, ErrNotInitialized
|
||||
}
|
||||
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return 0, ErrInvalidRoleName
|
||||
}
|
||||
|
||||
var role Role
|
||||
if err := s.db.Where("name = ?", name).First(&role).Error; err == nil {
|
||||
// already exists
|
||||
return role.ID, ErrRoleAlreadyExists
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// other database error
|
||||
return 0, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
role = Role{Name: name}
|
||||
if err := s.db.Create(&role).Error; err != nil {
|
||||
return 0, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return role.ID, nil
|
||||
}
|
||||
|
||||
// GetRoleByID returns the role with the given ID or an error.
|
||||
// May return [ErrNotInitialized], [ErrRoleNotFound] or db error.
|
||||
func (s *Service) GetRoleByID(roleID uint) (*Role, error) {
|
||||
if !s.isInitialized() {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
var role Role
|
||||
err := s.db.Preload("Resources").First(&role, roleID).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrRoleNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return &role, nil
|
||||
}
|
||||
|
||||
// UpdateRole updates the name of a role.
|
||||
// May return [ErrNotInitialized], [ErrInvalidRoleName], [ErrRoleNotFound], [ErrSameRoleName], or db error.
|
||||
func (s *Service) UpdateRole(roleID uint, newName string) error {
|
||||
if !s.isInitialized() {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
|
||||
newName = strings.TrimSpace(newName)
|
||||
if newName == "" {
|
||||
return ErrInvalidRoleName
|
||||
}
|
||||
|
||||
var role Role
|
||||
err := s.db.First(&role, roleID).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrRoleNotFound
|
||||
}
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
// check for name conflicts
|
||||
if role.Name == newName {
|
||||
return ErrSameRoleName
|
||||
}
|
||||
var count int64
|
||||
err = s.db.Model(&Role{}).Where("name = ? AND id != ?", newName, roleID).Count(&count).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return ErrSameRoleName
|
||||
}
|
||||
|
||||
role.Name = newName
|
||||
if err := s.db.Save(&role).Error; err != nil {
|
||||
return fmt.Errorf("failed to update role: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteRole deletes a role.
|
||||
// May return [ErrNotInitialized], [ErrRoleNotFound], [ErrRoleInUse] or db error.
|
||||
func (s *Service) DeleteRole(roleID uint) error {
|
||||
if !s.isInitialized() {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
|
||||
result := s.db.Delete(&Role{}, roleID)
|
||||
if err := result.Error; err != nil {
|
||||
if strings.Contains(err.Error(), "FOREIGN KEY constraint failed") {
|
||||
return ErrRoleInUse
|
||||
}
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return ErrRoleNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user