-
This commit is contained in:
@ -138,19 +138,170 @@ func (r *PermissionRepository) GetAvailablePermissionByScope(ctx context.Context
|
||||
|
||||
// ListAvailablePermissions retrieves available permissions with pagination and filtering
|
||||
func (r *PermissionRepository) ListAvailablePermissions(ctx context.Context, category string, includeSystem bool, limit, offset int) ([]*domain.AvailablePermission, error) {
|
||||
// TODO: Implement actual permission listing
|
||||
return []*domain.AvailablePermission{}, nil
|
||||
var args []interface{}
|
||||
var whereClauses []string
|
||||
argIndex := 1
|
||||
|
||||
// Build WHERE clause based on filters
|
||||
if category != "" {
|
||||
whereClauses = append(whereClauses, fmt.Sprintf("category = $%d", argIndex))
|
||||
args = append(args, category)
|
||||
argIndex++
|
||||
}
|
||||
|
||||
if !includeSystem {
|
||||
whereClauses = append(whereClauses, fmt.Sprintf("is_system = $%d", argIndex))
|
||||
args = append(args, false)
|
||||
argIndex++
|
||||
}
|
||||
|
||||
whereClause := ""
|
||||
if len(whereClauses) > 0 {
|
||||
whereClause = "WHERE " + fmt.Sprintf("%s", whereClauses[0])
|
||||
for i := 1; i < len(whereClauses); i++ {
|
||||
whereClause += " AND " + whereClauses[i]
|
||||
}
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT id, scope, name, description, category, parent_scope,
|
||||
is_system, created_at, created_by, updated_at, updated_by
|
||||
FROM available_permissions
|
||||
%s
|
||||
ORDER BY category, scope
|
||||
LIMIT $%d OFFSET $%d
|
||||
`, whereClause, argIndex, argIndex+1)
|
||||
|
||||
args = append(args, limit, offset)
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
rows, err := db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list available permissions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []*domain.AvailablePermission
|
||||
for rows.Next() {
|
||||
permission := &domain.AvailablePermission{}
|
||||
err := rows.Scan(
|
||||
&permission.ID,
|
||||
&permission.Scope,
|
||||
&permission.Name,
|
||||
&permission.Description,
|
||||
&permission.Category,
|
||||
&permission.ParentScope,
|
||||
&permission.IsSystem,
|
||||
&permission.CreatedAt,
|
||||
&permission.CreatedBy,
|
||||
&permission.UpdatedAt,
|
||||
&permission.UpdatedBy,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan available permission: %w", err)
|
||||
}
|
||||
permissions = append(permissions, permission)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate available permissions: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// UpdateAvailablePermission updates an available permission
|
||||
func (r *PermissionRepository) UpdateAvailablePermission(ctx context.Context, permissionID uuid.UUID, permission *domain.AvailablePermission) error {
|
||||
// TODO: Implement actual permission update
|
||||
query := `
|
||||
UPDATE available_permissions
|
||||
SET scope = $2, name = $3, description = $4, category = $5,
|
||||
parent_scope = $6, is_system = $7, updated_by = $8, updated_at = $9
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
now := time.Now()
|
||||
|
||||
result, err := db.ExecContext(ctx, query,
|
||||
permissionID,
|
||||
permission.Scope,
|
||||
permission.Name,
|
||||
permission.Description,
|
||||
permission.Category,
|
||||
permission.ParentScope,
|
||||
permission.IsSystem,
|
||||
permission.UpdatedBy,
|
||||
now,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update available permission: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get rows affected: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("permission with ID %s not found", permissionID)
|
||||
}
|
||||
|
||||
permission.UpdatedAt = now
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAvailablePermission deletes an available permission
|
||||
func (r *PermissionRepository) DeleteAvailablePermission(ctx context.Context, permissionID uuid.UUID) error {
|
||||
// TODO: Implement actual permission deletion
|
||||
// First check if the permission has any child permissions
|
||||
checkChildrenQuery := `
|
||||
SELECT COUNT(*) FROM available_permissions
|
||||
WHERE parent_scope = (SELECT scope FROM available_permissions WHERE id = $1)
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
var childCount int
|
||||
err := db.QueryRowContext(ctx, checkChildrenQuery, permissionID).Scan(&childCount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check for child permissions: %w", err)
|
||||
}
|
||||
|
||||
if childCount > 0 {
|
||||
return fmt.Errorf("cannot delete permission: it has %d child permissions", childCount)
|
||||
}
|
||||
|
||||
// Check if the permission is granted to any tokens
|
||||
checkGrantsQuery := `
|
||||
SELECT COUNT(*) FROM granted_permissions
|
||||
WHERE permission_id = $1 AND revoked = false
|
||||
`
|
||||
|
||||
var grantCount int
|
||||
err = db.QueryRowContext(ctx, checkGrantsQuery, permissionID).Scan(&grantCount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check for active grants: %w", err)
|
||||
}
|
||||
|
||||
if grantCount > 0 {
|
||||
return fmt.Errorf("cannot delete permission: it is currently granted to %d tokens", grantCount)
|
||||
}
|
||||
|
||||
// Delete the permission
|
||||
deleteQuery := `DELETE FROM available_permissions WHERE id = $1`
|
||||
result, err := db.ExecContext(ctx, deleteQuery, permissionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete available permission: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get rows affected: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("permission with ID %s not found", permissionID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -198,8 +349,75 @@ func (r *PermissionRepository) ValidatePermissionScopes(ctx context.Context, sco
|
||||
|
||||
// GetPermissionHierarchy returns all parent and child permissions for given scopes
|
||||
func (r *PermissionRepository) GetPermissionHierarchy(ctx context.Context, scopes []string) ([]*domain.AvailablePermission, error) {
|
||||
// TODO: Implement actual permission hierarchy retrieval
|
||||
return []*domain.AvailablePermission{}, nil
|
||||
if len(scopes) == 0 {
|
||||
return []*domain.AvailablePermission{}, nil
|
||||
}
|
||||
|
||||
// Use recursive CTE to get full hierarchy
|
||||
query := `
|
||||
WITH RECURSIVE permission_hierarchy AS (
|
||||
-- Base case: get permissions matching the input scopes
|
||||
SELECT id, scope, name, description, category, parent_scope,
|
||||
is_system, created_at, created_by, updated_at, updated_by, 0 as level
|
||||
FROM available_permissions
|
||||
WHERE scope = ANY($1)
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Recursive case: get all parents and children
|
||||
SELECT ap.id, ap.scope, ap.name, ap.description, ap.category, ap.parent_scope,
|
||||
ap.is_system, ap.created_at, ap.created_by, ap.updated_at, ap.updated_by,
|
||||
ph.level + 1 as level
|
||||
FROM available_permissions ap
|
||||
JOIN permission_hierarchy ph ON (
|
||||
-- Get parents (where ap.scope = ph.parent_scope)
|
||||
ap.scope = ph.parent_scope
|
||||
OR
|
||||
-- Get children (where ap.parent_scope = ph.scope)
|
||||
ap.parent_scope = ph.scope
|
||||
)
|
||||
WHERE ph.level < 5 -- Prevent infinite recursion
|
||||
)
|
||||
SELECT DISTINCT id, scope, name, description, category, parent_scope,
|
||||
is_system, created_at, created_by, updated_at, updated_by
|
||||
FROM permission_hierarchy
|
||||
ORDER BY scope
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
rows, err := db.QueryContext(ctx, query, pq.Array(scopes))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get permission hierarchy: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []*domain.AvailablePermission
|
||||
for rows.Next() {
|
||||
permission := &domain.AvailablePermission{}
|
||||
err := rows.Scan(
|
||||
&permission.ID,
|
||||
&permission.Scope,
|
||||
&permission.Name,
|
||||
&permission.Description,
|
||||
&permission.Category,
|
||||
&permission.ParentScope,
|
||||
&permission.IsSystem,
|
||||
&permission.CreatedAt,
|
||||
&permission.CreatedBy,
|
||||
&permission.UpdatedAt,
|
||||
&permission.UpdatedBy,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan permission hierarchy: %w", err)
|
||||
}
|
||||
permissions = append(permissions, permission)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate permission hierarchy: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// GrantedPermissionRepository implements the GrantedPermissionRepository interface for PostgreSQL
|
||||
@ -348,13 +566,57 @@ func (r *GrantedPermissionRepository) GetGrantedPermissionScopes(ctx context.Con
|
||||
|
||||
// RevokePermission revokes a specific permission from a token
|
||||
func (r *GrantedPermissionRepository) RevokePermission(ctx context.Context, grantID uuid.UUID, revokedBy string) error {
|
||||
// TODO: Implement actual permission revocation
|
||||
query := `
|
||||
UPDATE granted_permissions
|
||||
SET revoked = true, revoked_by = $2, revoked_at = $3
|
||||
WHERE id = $1 AND revoked = false
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
now := time.Now()
|
||||
|
||||
result, err := db.ExecContext(ctx, query, grantID, revokedBy, now)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to revoke permission: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get rows affected: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("permission grant with ID %s not found or already revoked", grantID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeAllPermissions revokes all permissions from a token
|
||||
func (r *GrantedPermissionRepository) RevokeAllPermissions(ctx context.Context, tokenType domain.TokenType, tokenID uuid.UUID, revokedBy string) error {
|
||||
// TODO: Implement actual permission revocation
|
||||
query := `
|
||||
UPDATE granted_permissions
|
||||
SET revoked = true, revoked_by = $3, revoked_at = $4
|
||||
WHERE token_type = $1 AND token_id = $2 AND revoked = false
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
now := time.Now()
|
||||
|
||||
result, err := db.ExecContext(ctx, query, tokenType, tokenID, revokedBy, now)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to revoke all permissions: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get rows affected: %w", err)
|
||||
}
|
||||
|
||||
// Note: rowsAffected being 0 is not necessarily an error here -
|
||||
// the token might not have had any active permissions
|
||||
_ = rowsAffected
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user