141 lines
3.3 KiB
Go
141 lines
3.3 KiB
Go
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
|
|
}
|