V3 version with backward comp
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user