-
-
Notifications
You must be signed in to change notification settings - Fork 275
feat(1199): add bulk-permission check wrapper endpoint #2657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -47,6 +47,82 @@ func (r *PermissionServer) Check(ctx context.Context, request *v1.PermissionChec | |||||||||||||||||||||||||||||||||||||
| return response, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // BulkCheck - Performs multiple authorization checks in a single request | ||||||||||||||||||||||||||||||||||||||
| func (r *PermissionServer) BulkCheck(ctx context.Context, request *v1.PermissionBulkCheckRequest) (*v1.PermissionBulkCheckResponse, error) { | ||||||||||||||||||||||||||||||||||||||
| ctx, span := internal.Tracer.Start(ctx, "permissions.bulk-check") | ||||||||||||||||||||||||||||||||||||||
| defer span.End() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Validate tenant_id | ||||||||||||||||||||||||||||||||||||||
| if request.GetTenantId() == "" { | ||||||||||||||||||||||||||||||||||||||
| err := status.Error(GetStatus(nil), "tenant_id is required") | ||||||||||||||||||||||||||||||||||||||
| span.RecordError(err) | ||||||||||||||||||||||||||||||||||||||
| span.SetStatus(otelCodes.Error, err.Error()) | ||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Validate number of requests | ||||||||||||||||||||||||||||||||||||||
| if len(request.GetItems()) == 0 { | ||||||||||||||||||||||||||||||||||||||
| err := status.Error(GetStatus(nil), "at least one item is required") | ||||||||||||||||||||||||||||||||||||||
| span.RecordError(err) | ||||||||||||||||||||||||||||||||||||||
| span.SetStatus(otelCodes.Error, err.Error()) | ||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if len(request.GetItems()) > 100 { | ||||||||||||||||||||||||||||||||||||||
| err := status.Error(GetStatus(nil), "maximum 100 items allowed") | ||||||||||||||||||||||||||||||||||||||
| span.RecordError(err) | ||||||||||||||||||||||||||||||||||||||
| span.SetStatus(otelCodes.Error, err.Error()) | ||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Process each check request | ||||||||||||||||||||||||||||||||||||||
| results := make([]*v1.PermissionCheckResponse, len(request.GetItems())) | ||||||||||||||||||||||||||||||||||||||
| for i, checkRequestItem := range request.GetItems() { | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Validate individual request | ||||||||||||||||||||||||||||||||||||||
| v := checkRequestItem.Validate() | ||||||||||||||||||||||||||||||||||||||
| if v != nil { | ||||||||||||||||||||||||||||||||||||||
| // Return error response for this check | ||||||||||||||||||||||||||||||||||||||
| results[i] = &v1.PermissionCheckResponse{ | ||||||||||||||||||||||||||||||||||||||
| Can: v1.CheckResult_CHECK_RESULT_DENIED, | ||||||||||||||||||||||||||||||||||||||
| Metadata: &v1.PermissionCheckResponseMetadata{ | ||||||||||||||||||||||||||||||||||||||
| CheckCount: 0, | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Perform the check using existing Check function | ||||||||||||||||||||||||||||||||||||||
| checkRequest := &v1.PermissionCheckRequest{ | ||||||||||||||||||||||||||||||||||||||
| TenantId: request.GetTenantId(), | ||||||||||||||||||||||||||||||||||||||
| Subject: checkRequestItem.GetSubject(), | ||||||||||||||||||||||||||||||||||||||
| Entity: checkRequestItem.GetEntity(), | ||||||||||||||||||||||||||||||||||||||
| Permission: checkRequestItem.GetPermission(), | ||||||||||||||||||||||||||||||||||||||
| Metadata: request.GetMetadata(), | ||||||||||||||||||||||||||||||||||||||
| Context: request.GetContext(), | ||||||||||||||||||||||||||||||||||||||
| Arguments: request.GetArguments(), | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+96
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix formatting inconsistency. Line 101 uses tabs for indentation while the surrounding lines use spaces. This creates inconsistent formatting. Apply this diff to fix the indentation: checkRequest := &v1.PermissionCheckRequest{
TenantId: request.GetTenantId(),
Subject: checkRequestItem.GetSubject(),
Entity: checkRequestItem.GetEntity(),
Permission: checkRequestItem.GetPermission(),
- Metadata: request.GetMetadata(),
+ Metadata: request.GetMetadata(),
Context: request.GetContext(),
Arguments: request.GetArguments(),
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| response, err := r.invoker.Check(ctx, checkRequest) | ||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||
| // Log error but don't fail the entire bulk operation | ||||||||||||||||||||||||||||||||||||||
| slog.ErrorContext(ctx, "check failed in bulk operation", "error", err.Error(), "index", i) | ||||||||||||||||||||||||||||||||||||||
| results[i] = &v1.PermissionCheckResponse{ | ||||||||||||||||||||||||||||||||||||||
| Can: v1.CheckResult_CHECK_RESULT_DENIED, | ||||||||||||||||||||||||||||||||||||||
| Metadata: &v1.PermissionCheckResponseMetadata{ | ||||||||||||||||||||||||||||||||||||||
| CheckCount: 0, | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| results[i] = response | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return &v1.PermissionBulkCheckResponse{ | ||||||||||||||||||||||||||||||||||||||
| Results: results, | ||||||||||||||||||||||||||||||||||||||
| }, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Expand - Get schema actions in a tree structure | ||||||||||||||||||||||||||||||||||||||
| func (r *PermissionServer) Expand(ctx context.Context, request *v1.PermissionExpandRequest) (*v1.PermissionExpandResponse, error) { | ||||||||||||||||||||||||||||||||||||||
| ctx, span := internal.Tracer.Start(ctx, "permissions.expand") | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider providing validation error details to callers.
When an item fails validation, the response only includes
CHECK_RESULT_DENIEDwithout any indication of what validation rule failed. This makes it difficult for API consumers to debug issues. Consider one of these approaches:PermissionCheckResponseto include validation errorsIf adding error details isn't feasible, at least add structured logging:
// Validate individual request v := checkRequestItem.Validate() if v != nil { + slog.ErrorContext(ctx, "item validation failed in bulk operation", "error", v.Error(), "index", i) // Return error response for this check results[i] = &v1.PermissionCheckResponse{📝 Committable suggestion
🤖 Prompt for AI Agents