Create scope in Authorize
Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
@@ -37,7 +37,7 @@ The evaluator processes all statements against a request:
|
||||
`Authorizer` is the main orchestrator in `pkg/iam/authorizer.go`:
|
||||
|
||||
```go
|
||||
err := iamService.Authorizer.Authorize(ctx, iam.AuthorizeParams{
|
||||
scope, err := iamService.Authorizer.Authorize(ctx, iam.AuthorizeParams{
|
||||
Principal: identityID, // who
|
||||
Resource: thirdPartyID, // what
|
||||
Action: probo.ActionThirdPartyGet, // which action
|
||||
@@ -51,7 +51,8 @@ The flow:
|
||||
3. Load resource attributes via `AuthorizationAttributes()` on the entity
|
||||
4. Build policies: identity-scoped + role-specific
|
||||
5. Evaluate all policies
|
||||
6. Return `ErrInsufficientPermissions` if no allow match
|
||||
6. Return an authorization scope (`*coredata.Scope`) for downstream data access
|
||||
7. Return `ErrInsufficientPermissions` if no allow match
|
||||
|
||||
## PolicySet
|
||||
|
||||
@@ -126,14 +127,16 @@ var (
|
||||
|
||||
**GraphQL resolvers** use `AuthorizeFunc` from `pkg/server/api/authz/`:
|
||||
```go
|
||||
if err := authorize(ctx, thirdPartyID, probo.ActionThirdPartyGet); err != nil {
|
||||
scope, err := authorize(ctx, thirdPartyID, probo.ActionThirdPartyGet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
```
|
||||
|
||||
**MCP resolvers** use `Authorize` and return early on error:
|
||||
```go
|
||||
if err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyGet); err != nil {
|
||||
scope, err := r.Authorize(ctx, input.ID, probo.ActionThirdPartyGet)
|
||||
if err != nil {
|
||||
return nil, types.GetThirdPartyOutput{}, err
|
||||
}
|
||||
```
|
||||
@@ -183,7 +186,7 @@ When adding a new entity that needs authorization:
|
||||
2. **Role policies** — wire actions into the appropriate role policies in `pkg/probo/policies.go` (`OwnerPolicy`, `AdminPolicy`, `ViewerPolicy`, etc.) with `organization_id` condition
|
||||
3. **`AuthorizationAttributes`** — implement on the `coredata` entity struct, returning at minimum `{"organization_id": ...}` (use the denormalized `OrganizationID` field — see coredata doc)
|
||||
4. **Entity type registry** — register in `pkg/coredata/entity_type_reg.go` and `NewEntityFromID` so the authorizer can construct the entity from its GID
|
||||
5. **Resolver calls** — add `r.authorize(ctx, id, probo.ActionEntityGet)` in GraphQL resolvers and `if err := r.Authorize(ctx, id, probo.ActionEntityGet); err != nil { return nil, types.GetEntityOutput{}, err }` in MCP resolvers
|
||||
5. **Resolver calls** — add `scope, err := r.authorize(ctx, id, probo.ActionEntityGet)` in GraphQL resolvers and `scope, err := r.Authorize(ctx, id, probo.ActionEntityGet)` in MCP resolvers, then pass `scope` to services
|
||||
|
||||
## Key patterns
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ First return is always `nil`. Authorization errors are returned and handled like
|
||||
Use `Authorize` with an early return:
|
||||
|
||||
```go
|
||||
if err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList); err != nil {
|
||||
scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList)
|
||||
if err != nil {
|
||||
return nil, types.ListThirdPartiesOutput{}, err
|
||||
}
|
||||
```
|
||||
@@ -75,7 +76,7 @@ if err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList); er
|
||||
**List with pagination:**
|
||||
```go
|
||||
func (r *Resolver) ListThirdPartiesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListThirdPartiesInput) (*mcp.CallToolResult, types.ListThirdPartiesOutput, error) {
|
||||
if err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList); err != nil {
|
||||
if _, err := r.Authorize(ctx, input.OrganizationID, probo.ActionThirdPartyList); err != nil {
|
||||
return nil, types.ListThirdPartiesOutput{}, err
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ func (r *Resolver) ListThirdPartiesTool(ctx context.Context, req *mcp.CallToolRe
|
||||
**Get single resource:**
|
||||
```go
|
||||
func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetRiskInput) (*mcp.CallToolResult, types.GetRiskOutput, error) {
|
||||
if err := r.Authorize(ctx, input.ID, probo.ActionRiskGet); err != nil {
|
||||
if _, err := r.Authorize(ctx, input.ID, probo.ActionRiskGet); err != nil {
|
||||
return nil, types.GetRiskOutput{}, err
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ func (r *Resolver) GetRiskTool(ctx context.Context, req *mcp.CallToolRequest, in
|
||||
**Create:**
|
||||
```go
|
||||
func (r *Resolver) AddRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddRiskInput) (*mcp.CallToolResult, types.AddRiskOutput, error) {
|
||||
if err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskCreate); err != nil {
|
||||
if _, err := r.Authorize(ctx, input.OrganizationID, probo.ActionRiskCreate); err != nil {
|
||||
return nil, types.AddRiskOutput{}, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user