basicly implement acl crud ops with roles and resources
This commit is contained in:
140
internal/acl/resources.go
Normal file
140
internal/acl/resources.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// GetResources returns all resources.
|
||||
// May return [ErrNotInitialized] or db error.
|
||||
func (s *Service) GetResources() ([]Resource, error) {
|
||||
if !s.isInitialized() {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
|
||||
var resources []Resource
|
||||
if err := s.db.Order("id").Find(&resources).Error; err != nil {
|
||||
return nil, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// CreateResource creates a new resource with the given key or returns existing one.
|
||||
// Returns ID of created resource.
|
||||
// May return [ErrNotInitialized], [ErrInvalidResourceKey], [ErrResourceAlreadyExists] or db error.
|
||||
func (s *Service) CreateResource(key string) (uint, error) {
|
||||
if !s.isInitialized() {
|
||||
return 0, ErrNotInitialized
|
||||
}
|
||||
|
||||
key = strings.TrimSpace(key)
|
||||
if key == "" {
|
||||
return 0, ErrInvalidResourceKey
|
||||
}
|
||||
|
||||
var res Resource
|
||||
if err := s.db.Where("key = ?", key).First(&res).Error; err == nil {
|
||||
// already exists
|
||||
return res.ID, ErrResourceAlreadyExists
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// other db error
|
||||
return 0, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
res = Resource{Key: key}
|
||||
if err := s.db.Create(&res).Error; err != nil {
|
||||
return 0, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return res.ID, nil
|
||||
}
|
||||
|
||||
// GetResourceByID returns the resource with the given ID.
|
||||
// May return [ErrNotInitialized], [ErrResourceNotFound] or db error.
|
||||
func (s *Service) GetResourceByID(resourceID uint) (*Resource, error) {
|
||||
if !s.isInitialized() {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
|
||||
var res Resource
|
||||
if err := s.db.First(&res, resourceID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrResourceNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// UpdateResource updates the key of a resource.
|
||||
// May return [ErrNotInitialized], [ErrInvalidResourceKey], [ErrResourceNotFound], [ErrSameResourceKey] or db error.
|
||||
func (s *Service) UpdateResource(resourceID uint, newKey string) error {
|
||||
if !s.isInitialized() {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
|
||||
newKey = strings.TrimSpace(newKey)
|
||||
if newKey == "" {
|
||||
return ErrInvalidResourceKey
|
||||
}
|
||||
|
||||
var res Resource
|
||||
if err := s.db.First(&res, resourceID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
// same key?
|
||||
if res.Key == newKey {
|
||||
return ErrSameResourceKey
|
||||
}
|
||||
|
||||
// check if key used by another resource
|
||||
var count int64
|
||||
if err := s.db.Model(&Resource{}).
|
||||
Where("key = ? AND id != ?", newKey, resourceID).
|
||||
Count(&count).Error; err != nil {
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
return ErrSameResourceKey
|
||||
}
|
||||
|
||||
res.Key = newKey
|
||||
if err := s.db.Save(&res).Error; err != nil {
|
||||
return fmt.Errorf("failed to update resource: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteResource deletes a resource.
|
||||
// May return [ErrNotInitialized], [ErrResourceNotFound], [ErrResourceInUse] or db error.
|
||||
func (s *Service) DeleteResource(resourceID uint) error {
|
||||
if !s.isInitialized() {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
|
||||
result := s.db.Delete(&Resource{}, resourceID)
|
||||
|
||||
if err := result.Error; err != nil {
|
||||
if strings.Contains(err.Error(), "FOREIGN KEY constraint failed") {
|
||||
return ErrResourceInUse
|
||||
}
|
||||
return fmt.Errorf("db error: %w", err)
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return ErrResourceNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user