Files
Kazier/backend/internal/service/rebac.go
T
2026-07-28 18:12:56 +02:00

90 lines
2.5 KiB
Go

package service
import (
"context"
"fmt"
"github.com/google/uuid"
"github.com/vaultdrop/backend/internal/db"
)
type RebacService struct {
queries *db.Queries
}
func NewRebacService(queries *db.Queries) *RebacService {
return &RebacService{queries: queries}
}
func (s *RebacService) ResolveEffectiveRole(userID, resourceID string) (string, error) {
userUUID, _ := uuid.Parse(userID)
resourceUUID, _ := uuid.Parse(resourceID)
role, err := s.queries.ResolveEffectiveRole(context.Background(), db.ResolveEffectiveRoleParams{
PUserID: userUUID,
PResourceID: resourceUUID,
})
if err != nil {
return "", fmt.Errorf("resolve effective role: %w", err)
}
return role, nil
}
func (s *RebacService) HasRole(userID, resourceID, requiredRole string) (bool, error) {
role, err := s.ResolveEffectiveRole(userID, resourceID)
if err != nil {
return false, err
}
return role == requiredRole, nil
}
func (s *RebacService) canGrant(granterRole string) bool {
return granterRole == "owner" || granterRole == "admin"
}
func (s *RebacService) GrantRole(granterID, resourceID, subjectID, role string) error {
granterUUID, _ := uuid.Parse(granterID)
resourceUUID, _ := uuid.Parse(resourceID)
subjectUUID, _ := uuid.Parse(subjectID)
granterRole, err := s.ResolveEffectiveRole(granterID, resourceID)
if err != nil {
return fmt.Errorf("resolve granter role: %w", err)
}
if !s.canGrant(granterRole) {
return fmt.Errorf("granter does not have permission to grant roles")
}
_, err = s.queries.CreateRebacRelation(context.Background(), db.CreateRebacRelationParams{
ResourceID: resourceUUID,
SubjectUserID: subjectUUID,
Role: role,
GrantedBy: granterUUID,
})
if err != nil {
return fmt.Errorf("create rebac relation: %w", err)
}
return nil
}
func (s *RebacService) RevokeRole(granterID, resourceID, subjectID string) error {
granterRole, err := s.ResolveEffectiveRole(granterID, resourceID)
if err != nil {
return fmt.Errorf("resolve granter role: %w", err)
}
if !s.canGrant(granterRole) {
return fmt.Errorf("granter does not have permission to revoke roles")
}
resourceUUID, _ := uuid.Parse(resourceID)
subjectUUID, _ := uuid.Parse(subjectID)
return s.queries.DeleteRebacRelation(context.Background(), db.DeleteRebacRelationParams{
ResourceID: resourceUUID,
SubjectUserID: subjectUUID,
})
}
func (s *RebacService) ListShares(resourceID string) ([]db.RebacRelation, error) {
resourceUUID, _ := uuid.Parse(resourceID)
return s.queries.ListRebacRelationsByResource(context.Background(), resourceUUID)
}