Files
triggerssmith/internal/acl/service.go

144 lines
3.7 KiB
Go

package acl
import (
"fmt"
"gorm.io/gorm"
)
type Service struct {
initialized bool
db *gorm.DB
}
func NewService(db *gorm.DB) (*Service, error) {
if db == nil {
return nil, fmt.Errorf("db is required")
}
return &Service{
db: db,
}, nil
}
func (s *Service) isInitialized() bool {
return s.initialized
}
func (s *Service) Init() error {
if s.isInitialized() {
return nil
}
// AutoMigrate models
err := s.db.AutoMigrate(&UserRole{}, &Resource{}, &Role{}, &RoleResource{})
if err != nil {
return fmt.Errorf("failed to migrate ACL models: %w", err)
}
s.initialized = true
return nil
}
// Admin crud functions
// CreateRole creates a new role with the given name
func (s *Service) CreateRole(name string) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
role := Role{Name: name}
return s.db.FirstOrCreate(&role, &Role{Name: name}).Error
}
// CreateResource creates a new resource with the given key
func (s *Service) CreateResource(key string) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
res := Resource{Key: key}
return s.db.FirstOrCreate(&res, &Resource{Key: key}).Error
}
// AssignResourceToRole assigns a resource to a role
func (s *Service) AssignResourceToRole(roleID, resourceID uint) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
rr := RoleResource{
RoleID: roleID,
ResourceID: resourceID,
}
return s.db.FirstOrCreate(&rr, RoleResource{RoleID: roleID, ResourceID: resourceID}).Error
}
// AssignRoleToUser assigns a role to a user
func (s *Service) AssignRoleToUser(roleID, userID uint) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
ur := UserRole{
UserID: userID,
RoleID: roleID,
}
return s.db.FirstOrCreate(&ur, UserRole{UserID: userID, RoleID: roleID}).Error
}
// RemoveResourceFromRole removes a resource from a role
func (s *Service) RemoveResourceFromRole(roleID, resourceID uint) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
return s.db.Where("role_id = ? AND resource_id = ?", roleID, resourceID).Delete(&RoleResource{}).Error
}
// RemoveRoleFromUser removes a role from a user
func (s *Service) RemoveRoleFromUser(roleID, userID uint) error {
if !s.isInitialized() {
return fmt.Errorf("acl service is not initialized")
}
return s.db.Where("role_id = ? AND user_id = ?", roleID, userID).Delete(&UserRole{}).Error
}
// GetRoles returns all roles
func (s *Service) GetRoles() ([]Role, error) {
if !s.isInitialized() {
return nil, fmt.Errorf("acl service is not initialized")
}
var roles []Role
err := s.db.Preload("Resources").Order("id").Find(&roles).Error
return roles, err
}
// GetPermissions returns all permissions
func (s *Service) GetPermissions() ([]Resource, error) {
if !s.isInitialized() {
return nil, fmt.Errorf("acl service is not initialized")
}
var resources []Resource
err := s.db.Order("id").Find(&resources).Error
return resources, err
}
// GetRoleResources returns all resources for a given role
func (s *Service) GetRoleResources(roleID uint) ([]Resource, error) {
if !s.isInitialized() {
return nil, fmt.Errorf("acl service is not initialized")
}
var resources []Resource
err := s.db.Joins("JOIN role_resources rr ON rr.resource_id = resources.id").
Where("rr.role_id = ?", roleID).Find(&resources).Error
return resources, err
}
// GetUserRoles returns all roles for a given user
func (s *Service) GetUserRoles(userID uint) ([]Role, error) {
if !s.isInitialized() {
return nil, fmt.Errorf("acl service is not initialized")
}
var roles []Role
err := s.db.Joins("JOIN user_roles ur ON ur.role_id = roles.id").
Where("ur.user_id = ?", userID).Find(&roles).Error
return roles, err
}