diff --git a/.cursor/rules/go-authorize-scope.mdc b/.cursor/rules/go-authorize-scope.mdc new file mode 100644 index 000000000..9ed8a2b96 --- /dev/null +++ b/.cursor/rules/go-authorize-scope.mdc @@ -0,0 +1,59 @@ +--- +description: Go authorize — always take scope from authorize, never reconstruct it +globs: "pkg/server/api/**/*.go" +alwaysApply: false +--- + +# Authorize returns the scope — use it + +`r.authorize` (GraphQL) and `r.Authorize` (MCP) return a `*coredata.Scope` +resolved from the resource's `organization_id` attribute. **Always** pass that +scope to the downstream service or coredata call. **Never** discard it and +rebuild a scope with `coredata.NewScopeFromObjectID(...)`. + +The two are not identical: `NewScopeFromObjectID(id)` only reads the tenant +encoded in the GID, while the authorizer derives the scope from the loaded +resource attributes. Reconstructing the scope from the GID silently drifts +when the resource lookup changes. + +```go +// GOOD — scope comes from authorize, fed straight to the service +scope, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList) +if err != nil { + return nil, err +} + +thirdPartyIDs, err := r.cookieBanner.LoadDistinctThirdPartyIDsByCookieBannerID(ctx, scope, obj.ID) + +// BAD — authorize discards scope, then we rebuild it from the same GID +if _, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList); err != nil { + return nil, err +} + +scope := coredata.NewScopeFromObjectID(obj.ID) +thirdPartyIDs, err := r.cookieBanner.LoadDistinctThirdPartyIDsByCookieBannerID(ctx, scope, obj.ID) +``` + +## When discarding `scope` with `_` is acceptable + +Only when **no downstream call needs a scope** — typically authorize calls +against the caller's `identity.ID` for global / cross-tenant catalogs (e.g. +`ActionCommonThirdPartyList`, `ActionCommonThirdPartyGet`) whose service +methods are unscoped. The returned scope would be derived from the identity +(a nil-tenant principal) and is useless to the caller: + +```go +// GOOD — global catalog, downstream is unscoped +identity := authn.IdentityFromContext(ctx) +if _, err := r.authorize(ctx, identity.ID, probo.ActionCommonThirdPartyList); err != nil { + return nil, err +} + +parties, err := r.thirdParty.Search(ctx, name) // no scope argument +``` + +The same rule applies to `r.batchAuthorize` (GraphQL) and `r.AuthorizeBatch` +(MCP). + +See [`contrib/claude/authorization.md`](../../contrib/claude/authorization.md) +for the full authorization guide. diff --git a/contrib/claude/authorization.md b/contrib/claude/authorization.md index 95f145bdd..ee4468ee4 100644 --- a/contrib/claude/authorization.md +++ b/contrib/claude/authorization.md @@ -178,7 +178,7 @@ var ( **GraphQL resolvers** use `AuthorizeFunc` from `pkg/server/api/authz/`: ```go -scope, err := authorize(ctx, thirdPartyID, probo.ActionThirdPartyGet) +scope, err := r.authorize(ctx, thirdPartyID, probo.ActionThirdPartyGet) if err != nil { return nil, err } @@ -192,6 +192,58 @@ if err != nil { } ``` +### Always take `scope` from `authorize` — never reconstruct it + +`authorize` (and `Authorize` in MCP) returns a `*coredata.Scope` that has been +resolved from the resource's `organization_id` attribute. Pass that scope +straight to the service/coredata layer instead of building a new one with +`coredata.NewScopeFromObjectID(...)` after the authorize call. + +The two are not strictly identical: `NewScopeFromObjectID(id)` only reads the +tenant component of the GID, while the authorizer derives the scope from the +loaded resource attributes (and may be extended to compute it differently in +the future). Reconstructing the scope from the GID bypasses that and silently +drifts when the resource lookup changes. + +```go +// GOOD — scope comes from authorize, fed straight to the service +scope, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList) +if err != nil { + return nil, err +} + +thirdPartyIDs, err := r.cookieBanner.LoadDistinctThirdPartyIDsByCookieBannerID(ctx, scope, obj.ID) + +// BAD — authorize discards scope, then we rebuild it from the same GID +if _, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList); err != nil { + return nil, err +} + +scope := coredata.NewScopeFromObjectID(obj.ID) +thirdPartyIDs, err := r.cookieBanner.LoadDistinctThirdPartyIDsByCookieBannerID(ctx, scope, obj.ID) +``` + +The only time it is acceptable to write `if _, err := r.authorize(...)` is when +**no downstream call needs a scope** — typically authorize calls against the +caller's `identity.ID` for global / cross-tenant catalogs (e.g. +`ActionCommonThirdPartyList`, `ActionCommonThirdPartyGet`) whose service +methods are unscoped. In that case the returned scope would be derived from +the identity (a nil-tenant principal) and is useless to the caller, so +discarding it with `_` is correct: + +```go +// GOOD — global catalog, downstream is unscoped +identity := authn.IdentityFromContext(ctx) +if _, err := r.authorize(ctx, identity.ID, probo.ActionCommonThirdPartyList); err != nil { + return nil, err +} + +parties, err := r.thirdParty.Search(ctx, name) // no scope argument +``` + +For batch authorization, the same rule applies to `r.batchAuthorize` (GraphQL) +and `r.AuthorizeBatch` (MCP) — keep the returned scope and pass it down. + ## File locations | What | File | diff --git a/pkg/server/api/console/v1/cookie_banner_resolvers.go b/pkg/server/api/console/v1/cookie_banner_resolvers.go index ea9c53d00..56298c3a8 100644 --- a/pkg/server/api/console/v1/cookie_banner_resolvers.go +++ b/pkg/server/api/console/v1/cookie_banner_resolvers.go @@ -49,7 +49,8 @@ func (r *cookieBannerResolver) Organization(ctx context.Context, obj *types.Cook // Categories is the resolver for the categories field. func (r *cookieBannerResolver) Categories(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookieCategoryOrderBy, filter *types.CookieCategoryFilter) (*types.CookieCategoryConnection, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionCookieCategoryList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionCookieCategoryList) + if err != nil { return nil, err } @@ -65,7 +66,6 @@ func (r *cookieBannerResolver) Categories(ctx context.Context, obj *types.Cookie } cursor := types.NewCursor(first, after, last, before, pageOrderBy) - scope := coredata.NewScopeFromObjectID(obj.ID) var excludeKind *coredata.CookieCategoryKind if filter != nil { @@ -189,7 +189,8 @@ func (r *cookieBannerResolver) ConsentRecords(ctx context.Context, obj *types.Co // TrackerPatterns is the resolver for the trackerPatterns field. func (r *cookieBannerResolver) TrackerPatterns(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TrackerPatternOrderBy, filter *types.TrackerPatternFilter) (*types.TrackerPatternConnection, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionTrackerPatternList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionTrackerPatternList) + if err != nil { return nil, err } @@ -205,7 +206,6 @@ func (r *cookieBannerResolver) TrackerPatterns(ctx context.Context, obj *types.C } cursor := types.NewCursor(first, after, last, before, pageOrderBy) - scope := coredata.NewScopeFromObjectID(obj.ID) coredataFilter := coredata.NewTrackerPatternFilter(nil, nil, nil) if filter != nil { @@ -254,12 +254,11 @@ func (r *cookieBannerResolver) TrackerPatterns(ctx context.Context, obj *types.C // commonThirdParty resolver follows the same priority and we want the // banner-level filter to mirror it. func (r *cookieBannerResolver) LinkedThirdParties(ctx context.Context, obj *types.CookieBanner) ([]types.TrackerPatternThirdPartyLink, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionTrackerPatternList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyList) + if err != nil { return nil, err } - scope := coredata.NewScopeFromObjectID(obj.ID) - thirdPartyIDs, err := r.cookieBanner.LoadDistinctThirdPartyIDsByCookieBannerID(ctx, scope, obj.ID) if err != nil { r.logger.ErrorCtx(ctx, "cannot list banner third party links", log.Error(err)) @@ -276,10 +275,6 @@ func (r *cookieBannerResolver) LinkedThirdParties(ctx context.Context, obj *type loaders := dataloader.FromContext(ctx) if len(thirdPartyIDs) > 0 { - if _, err := r.authorize(ctx, obj.ID, probo.ActionThirdPartyGet); err != nil { - return nil, err - } - tps, loadErr := loaders.ThirdParty.LoadAll(ctx, thirdPartyIDs) var loadErrs dataloadgen.ErrorSlice if loadErr != nil && !errors.As(loadErr, &loadErrs) { @@ -300,7 +295,7 @@ func (r *cookieBannerResolver) LinkedThirdParties(ctx context.Context, obj *type if len(commonPatternIDs) > 0 { identity := authn.IdentityFromContext(ctx) - if _, err := r.authorize(ctx, identity.ID, probo.ActionCommonThirdPartyGet); err != nil { + if _, err := r.authorize(ctx, identity.ID, probo.ActionCommonThirdPartyList); err != nil { return nil, err } @@ -340,7 +335,8 @@ func (r *cookieBannerResolver) LinkedThirdParties(ctx context.Context, obj *type // UncategorisedTrackerResources is the resolver for the uncategorisedTrackerResources field. func (r *cookieBannerResolver) UncategorisedTrackerResources(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TrackerResourceOrderBy, filter *types.TrackerResourceFilter) (*types.TrackerResourceConnection, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionTrackerResourceList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionTrackerResourceList) + if err != nil { return nil, err } @@ -356,7 +352,6 @@ func (r *cookieBannerResolver) UncategorisedTrackerResources(ctx context.Context } cursor := types.NewCursor(first, after, last, before, pageOrderBy) - scope := coredata.NewScopeFromObjectID(obj.ID) coredataFilter := coredata.NewTrackerResourceFilter(nil, nil) if filter != nil { @@ -465,7 +460,8 @@ func (r *cookieCategoryResolver) CookieBanner(ctx context.Context, obj *types.Co // TrackerPatterns is the resolver for the trackerPatterns field. func (r *cookieCategoryResolver) TrackerPatterns(ctx context.Context, obj *types.CookieCategory, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TrackerPatternOrderBy) (*types.TrackerPatternConnection, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionTrackerPatternList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionTrackerPatternList) + if err != nil { return nil, err } @@ -481,7 +477,6 @@ func (r *cookieCategoryResolver) TrackerPatterns(ctx context.Context, obj *types } cursor := types.NewCursor(first, after, last, before, pageOrderBy) - scope := coredata.NewScopeFromObjectID(obj.ID) patterns, err := r.cookieBanner.ListTrackerPatternsForCategory(ctx, scope, obj.ID, cursor) if err != nil { @@ -496,7 +491,8 @@ func (r *cookieCategoryResolver) TrackerPatterns(ctx context.Context, obj *types // TrackerResources is the resolver for the trackerResources field. func (r *cookieCategoryResolver) TrackerResources(ctx context.Context, obj *types.CookieCategory, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TrackerResourceOrderBy) (*types.TrackerResourceConnection, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionTrackerResourceList); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionTrackerResourceList) + if err != nil { return nil, err } @@ -512,7 +508,6 @@ func (r *cookieCategoryResolver) TrackerResources(ctx context.Context, obj *type } cursor := types.NewCursor(first, after, last, before, pageOrderBy) - scope := coredata.NewScopeFromObjectID(obj.ID) resources, err := r.cookieBanner.ListTrackerResourcesForCategory(ctx, scope, obj.ID, cursor) if err != nil { diff --git a/pkg/server/api/console/v1/document_resolvers.go b/pkg/server/api/console/v1/document_resolvers.go index a6d9f3906..fba0dcabd 100644 --- a/pkg/server/api/console/v1/document_resolvers.go +++ b/pkg/server/api/console/v1/document_resolvers.go @@ -683,14 +683,13 @@ func (r *employeeDocumentResolver) Signed(ctx context.Context, obj *types.Employ // ApprovalState is the resolver for the approvalState field. func (r *employeeDocumentResolver) ApprovalState(ctx context.Context, obj *types.EmployeeDocument) (*coredata.DocumentVersionApprovalDecisionState, error) { - if _, err := r.authorize(ctx, obj.ID, probo.ActionEmployeeDocumentGet); err != nil { + scope, err := r.authorize(ctx, obj.ID, probo.ActionEmployeeDocumentGet) + if err != nil { return nil, err } identity := authn.IdentityFromContext(ctx) - scope := coredata.NewScopeFromObjectID(obj.ID) - state, err := r.probo.Documents.GetViewerApprovalState(ctx, scope, obj.ID, identity.ID) if err != nil { if errors.Is(err, coredata.ErrResourceNotFound) { @@ -791,12 +790,12 @@ func (r *employeeDocumentVersionResolver) Signed(ctx context.Context, obj *types // ApprovalDecision is the resolver for the approvalDecision field. func (r *employeeDocumentVersionResolver) ApprovalDecision(ctx context.Context, obj *types.EmployeeDocumentVersion) (*types.DocumentVersionApprovalDecision, error) { - if _, err := r.authorize(ctx, obj.DocumentID, probo.ActionEmployeeDocumentGet); err != nil { + scope, err := r.authorize(ctx, obj.DocumentID, probo.ActionEmployeeDocumentGet) + if err != nil { return nil, err } identity := authn.IdentityFromContext(ctx) - scope := coredata.NewScopeFromObjectID(obj.ID) decision, err := r.probo.DocumentApprovals.GetViewerDecision(ctx, scope, obj.ID, identity.ID) if err != nil { diff --git a/pkg/server/api/console/v1/organization_resolvers.go b/pkg/server/api/console/v1/organization_resolvers.go index 91380962c..cb5107fb1 100644 --- a/pkg/server/api/console/v1/organization_resolvers.go +++ b/pkg/server/api/console/v1/organization_resolvers.go @@ -1394,7 +1394,8 @@ func (r *profileResolver) Permission(ctx context.Context, obj *types.Profile, ac // TotalCount is the resolver for the totalCount field. func (r *profileConnectionResolver) TotalCount(ctx context.Context, obj *types.ProfileConnection) (int, error) { - if _, err := r.authorize(ctx, obj.ParentID, iam.ActionMembershipProfileList); err != nil { + scope, err := r.authorize(ctx, obj.ParentID, iam.ActionMembershipProfileList) + if err != nil { return 0, err } @@ -1408,8 +1409,6 @@ func (r *profileConnectionResolver) TotalCount(ctx context.Context, obj *types.P return count, nil case *documentVersionResolver: - scope := coredata.NewScopeFromObjectID(obj.ParentID) - count, err := r.probo.Documents.CountVersionApprovers(ctx, scope, obj.ParentID) if err != nil { r.logger.ErrorCtx(ctx, "cannot count document version approvers", log.Error(err)) diff --git a/pkg/server/api/console/v1/risk_resolvers.go b/pkg/server/api/console/v1/risk_resolvers.go index 2c2767e9c..fbe2218b9 100644 --- a/pkg/server/api/console/v1/risk_resolvers.go +++ b/pkg/server/api/console/v1/risk_resolvers.go @@ -500,8 +500,6 @@ func (r *riskConnectionResolver) TotalCount(ctx context.Context, obj *types.Risk return count, nil case *riskAssessmentScenarioResolver: - scope := coredata.NewScopeFromObjectID(obj.ParentID) - count, err := r.riskManagement.CountRisksForScenarioID(ctx, scope, obj.ParentID) if err != nil { r.logger.ErrorCtx(ctx, "cannot count scenario risks", log.Error(err)) diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index 5af6d709e..c04693db2 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -1670,12 +1670,12 @@ func (r *Resolver) UpdateControlTool(ctx context.Context, req *mcp.CallToolReque } func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkControlInput) (*mcp.CallToolResult, types.LinkControlOutput, error) { - scope := coredata.NewScopeFromObjectID(input.ControlID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.MeasureEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingCreate) + if err != nil { return nil, types.LinkControlOutput{}, err } @@ -1683,7 +1683,8 @@ func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to measure: %w", err) } case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingCreate) + if err != nil { return nil, types.LinkControlOutput{}, err } @@ -1691,7 +1692,8 @@ func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to document: %w", err) } case coredata.AuditEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingCreate) + if err != nil { return nil, types.LinkControlOutput{}, err } @@ -1699,7 +1701,8 @@ func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkControlOutput{}, fmt.Errorf("failed to link control to audit: %w", err) } case coredata.ObligationEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingCreate) + if err != nil { return nil, types.LinkControlOutput{}, err } @@ -1714,12 +1717,12 @@ func (r *Resolver) LinkControlTool(ctx context.Context, req *mcp.CallToolRequest } func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkControlInput) (*mcp.CallToolResult, types.UnlinkControlOutput, error) { - scope := coredata.NewScopeFromObjectID(input.ControlID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.MeasureEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlMeasureMappingDelete) + if err != nil { return nil, types.UnlinkControlOutput{}, err } @@ -1727,7 +1730,8 @@ func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from measure: %w", err) } case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlDocumentMappingDelete) + if err != nil { return nil, types.UnlinkControlOutput{}, err } @@ -1735,7 +1739,8 @@ func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from document: %w", err) } case coredata.AuditEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlAuditMappingDelete) + if err != nil { return nil, types.UnlinkControlOutput{}, err } @@ -1743,7 +1748,8 @@ func (r *Resolver) UnlinkControlTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkControlOutput{}, fmt.Errorf("failed to unlink control from audit: %w", err) } case coredata.ObligationEntityType: - if _, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.ControlID, probo.ActionControlObligationMappingDelete) + if err != nil { return nil, types.UnlinkControlOutput{}, err } @@ -1908,12 +1914,12 @@ func (r *Resolver) ListRiskObligationsTool(ctx context.Context, req *mcp.CallToo } func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkRiskInput) (*mcp.CallToolResult, types.LinkRiskOutput, error) { - scope := coredata.NewScopeFromObjectID(input.RiskID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingCreate) + if err != nil { return nil, types.LinkRiskOutput{}, err } @@ -1921,7 +1927,8 @@ func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, i return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to document: %w", err) } case coredata.MeasureEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingCreate) + if err != nil { return nil, types.LinkRiskOutput{}, err } @@ -1929,7 +1936,8 @@ func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, i return nil, types.LinkRiskOutput{}, fmt.Errorf("failed to link risk to measure: %w", err) } case coredata.ObligationEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingCreate) + if err != nil { return nil, types.LinkRiskOutput{}, err } @@ -1944,12 +1952,12 @@ func (r *Resolver) LinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, i } func (r *Resolver) UnlinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkRiskInput) (*mcp.CallToolResult, types.UnlinkRiskOutput, error) { - scope := coredata.NewScopeFromObjectID(input.RiskID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskDocumentMappingDelete) + if err != nil { return nil, types.UnlinkRiskOutput{}, err } @@ -1957,7 +1965,8 @@ func (r *Resolver) UnlinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from document: %w", err) } case coredata.MeasureEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskMeasureMappingDelete) + if err != nil { return nil, types.UnlinkRiskOutput{}, err } @@ -1965,7 +1974,8 @@ func (r *Resolver) UnlinkRiskTool(ctx context.Context, req *mcp.CallToolRequest, return nil, types.UnlinkRiskOutput{}, fmt.Errorf("failed to unlink risk from measure: %w", err) } case coredata.ObligationEntityType: - if _, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.RiskID, probo.ActionRiskObligationMappingDelete) + if err != nil { return nil, types.UnlinkRiskOutput{}, err } @@ -2305,7 +2315,8 @@ func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequ } func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionsInput) (*mcp.CallToolResult, types.ListDocumentVersionsOutput, error) { - if _, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionList); err != nil { + scope, err := r.Authorize(ctx, input.DocumentID, probo.ActionDocumentVersionList) + if err != nil { return nil, types.ListDocumentVersionsOutput{}, err } @@ -2322,7 +2333,6 @@ func (r *Resolver) ListDocumentVersionsTool(ctx context.Context, req *mcp.CallTo } cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy) - scope := coredata.NewScopeFromObjectID(input.DocumentID) svc := r.proboSvc versionFilter := coredata.NewDocumentVersionFilter() @@ -2636,12 +2646,12 @@ func (r *Resolver) ListMeasureEvidencesTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.LinkMeasureInput) (*mcp.CallToolResult, types.LinkMeasureOutput, error) { - scope := coredata.NewScopeFromObjectID(input.MeasureID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.ControlEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingCreate) + if err != nil { return nil, types.LinkMeasureOutput{}, err } @@ -2649,7 +2659,8 @@ func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to control: %w", err) } case coredata.RiskEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingCreate) + if err != nil { return nil, types.LinkMeasureOutput{}, err } @@ -2657,7 +2668,8 @@ func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to risk: %w", err) } case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingCreate) + if err != nil { return nil, types.LinkMeasureOutput{}, err } @@ -2665,7 +2677,8 @@ func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest return nil, types.LinkMeasureOutput{}, fmt.Errorf("failed to link measure to document: %w", err) } case coredata.ThirdPartyEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingCreate); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingCreate) + if err != nil { return nil, types.LinkMeasureOutput{}, err } @@ -2680,12 +2693,12 @@ func (r *Resolver) LinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest } func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UnlinkMeasureInput) (*mcp.CallToolResult, types.UnlinkMeasureOutput, error) { - scope := coredata.NewScopeFromObjectID(input.MeasureID) svc := r.proboSvc switch input.ResourceID.EntityType() { case coredata.ControlEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionControlMeasureMappingDelete) + if err != nil { return nil, types.UnlinkMeasureOutput{}, err } @@ -2693,7 +2706,8 @@ func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from control: %w", err) } case coredata.RiskEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionRiskMeasureMappingDelete) + if err != nil { return nil, types.UnlinkMeasureOutput{}, err } @@ -2701,7 +2715,8 @@ func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from risk: %w", err) } case coredata.DocumentEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureDocumentMappingDelete) + if err != nil { return nil, types.UnlinkMeasureOutput{}, err } @@ -2709,7 +2724,8 @@ func (r *Resolver) UnlinkMeasureTool(ctx context.Context, req *mcp.CallToolReque return nil, types.UnlinkMeasureOutput{}, fmt.Errorf("failed to unlink measure from document: %w", err) } case coredata.ThirdPartyEntityType: - if _, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingDelete); err != nil { + scope, err := r.Authorize(ctx, input.MeasureID, probo.ActionMeasureThirdPartyMappingDelete) + if err != nil { return nil, types.UnlinkMeasureOutput{}, err } @@ -5418,11 +5434,11 @@ func (r *Resolver) PublishThirdPartyListTool(ctx context.Context, req *mcp.CallT } func (r *Resolver) ListCookieBannersTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannersInput) (*mcp.CallToolResult, types.ListCookieBannersOutput, error) { - if _, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerList); err != nil { + scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerList) + if err != nil { return nil, types.ListCookieBannersOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.OrganizationID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerOrderField]{Field: coredata.CookieBannerOrderFieldCreatedAt, Direction: page.OrderDirectionDesc}) banners, err := r.cookieBanner.ListCookieBannersForOrganization(ctx, scope, input.OrganizationID, cursor, coredata.NewCookieBannerFilter(nil)) @@ -5436,12 +5452,11 @@ func (r *Resolver) ListCookieBannersTool(ctx context.Context, req *mcp.CallToolR } func (r *Resolver) GetCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieBannerInput) (*mcp.CallToolResult, types.GetCookieBannerOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerGet); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerGet) + if err != nil { return nil, types.GetCookieBannerOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.ID) if err != nil { return nil, types.GetCookieBannerOutput{}, fmt.Errorf("cannot get cookie banner: %w", err) @@ -5451,12 +5466,11 @@ func (r *Resolver) GetCookieBannerTool(ctx context.Context, req *mcp.CallToolReq } func (r *Resolver) AddCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieBannerInput) (*mcp.CallToolResult, types.AddCookieBannerOutput, error) { - if _, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerCreate); err != nil { + scope, err := r.Authorize(ctx, input.OrganizationID, probo.ActionCookieBannerCreate) + if err != nil { return nil, types.AddCookieBannerOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.OrganizationID) - banner, err := r.cookieBanner.CreateCookieBanner(ctx, scope, cookiebanner.CreateCookieBannerRequest{ OrganizationID: input.OrganizationID, Name: input.Name, @@ -5473,12 +5487,11 @@ func (r *Resolver) AddCookieBannerTool(ctx context.Context, req *mcp.CallToolReq } func (r *Resolver) UpdateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieBannerInput) (*mcp.CallToolResult, types.UpdateCookieBannerOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerUpdate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerUpdate) + if err != nil { return nil, types.UpdateCookieBannerOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - updateReq := cookiebanner.UpdateCookieBannerRequest{CookieBannerID: input.ID} if v := UnwrapOmittable(input.Name); v != nil && *v != nil { updateReq.Name = *v @@ -5522,12 +5535,11 @@ func (r *Resolver) DeleteCookieBannerTool(ctx context.Context, req *mcp.CallTool } func (r *Resolver) ActivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ActivateCookieBannerInput) (*mcp.CallToolResult, types.ActivateCookieBannerOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerActivate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerActivate) + if err != nil { return nil, types.ActivateCookieBannerOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - banner, err := r.cookieBanner.ActivateCookieBanner(ctx, scope, input.ID) if err != nil { return nil, types.ActivateCookieBannerOutput{}, fmt.Errorf("cannot activate cookie banner: %w", err) @@ -5537,12 +5549,11 @@ func (r *Resolver) ActivateCookieBannerTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) DeactivateCookieBannerTool(ctx context.Context, req *mcp.CallToolRequest, input *types.DeactivateCookieBannerInput) (*mcp.CallToolResult, types.DeactivateCookieBannerOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDeactivate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieBannerDeactivate) + if err != nil { return nil, types.DeactivateCookieBannerOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - banner, err := r.cookieBanner.DeactivateCookieBanner(ctx, scope, input.ID) if err != nil { return nil, types.DeactivateCookieBannerOutput{}, fmt.Errorf("cannot deactivate cookie banner: %w", err) @@ -5552,11 +5563,10 @@ func (r *Resolver) DeactivateCookieBannerTool(ctx context.Context, req *mcp.Call } func (r *Resolver) ListCookieCategoriesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieCategoriesInput) (*mcp.CallToolResult, types.ListCookieCategoriesOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryList); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryList) + if err != nil { return nil, types.ListCookieCategoriesOutput{}, err } - - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieCategoryOrderField]{Field: coredata.CookieCategoryOrderFieldRank, Direction: page.OrderDirectionAsc}) categories, err := r.cookieBanner.ListCategoriesForBanner(ctx, scope, input.CookieBannerID, cursor, coredata.NewCookieCategoryFilter(new(coredata.CookieCategoryKindUncategorised))) @@ -5570,12 +5580,11 @@ func (r *Resolver) ListCookieCategoriesTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) GetCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieCategoryInput) (*mcp.CallToolResult, types.GetCookieCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryGet); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryGet) + if err != nil { return nil, types.GetCookieCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.ID) if err != nil { return nil, types.GetCookieCategoryOutput{}, fmt.Errorf("cannot get cookie category: %w", err) @@ -5585,12 +5594,11 @@ func (r *Resolver) GetCookieCategoryTool(ctx context.Context, req *mcp.CallToolR } func (r *Resolver) AddCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddCookieCategoryInput) (*mcp.CallToolResult, types.AddCookieCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryCreate); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryCreate) + if err != nil { return nil, types.AddCookieCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) - category, err := r.cookieBanner.CreateCookieCategory(ctx, scope, cookiebanner.CreateCookieCategoryRequest{ CookieBannerID: input.CookieBannerID, Name: input.Name, @@ -5606,12 +5614,11 @@ func (r *Resolver) AddCookieCategoryTool(ctx context.Context, req *mcp.CallToolR } func (r *Resolver) UpdateCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateCookieCategoryInput) (*mcp.CallToolResult, types.UpdateCookieCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate) + if err != nil { return nil, types.UpdateCookieCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - updateReq := cookiebanner.UpdateCookieCategoryRequest{CookieCategoryID: input.ID} if v := UnwrapOmittable(input.Name); v != nil && *v != nil { updateReq.Name = *v @@ -5647,13 +5654,12 @@ func (r *Resolver) DeleteCookieCategoryTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) ReorderCookieCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ReorderCookieCategoryInput) (*mcp.CallToolResult, types.ReorderCookieCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieCategoryUpdate) + if err != nil { return nil, types.ReorderCookieCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - - _, err := r.cookieBanner.ReorderCookieCategory(ctx, scope, cookiebanner.ReorderCookieCategoryRequest{ + _, err = r.cookieBanner.ReorderCookieCategory(ctx, scope, cookiebanner.ReorderCookieCategoryRequest{ CookieCategoryID: input.ID, Rank: input.Rank, }) @@ -5670,11 +5676,10 @@ func (r *Resolver) ReorderCookieCategoryTool(ctx context.Context, req *mcp.CallT } func (r *Resolver) ListTrackerPatternsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerPatternsInput) (*mcp.CallToolResult, types.ListTrackerPatternsOutput, error) { - if _, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternList); err != nil { + scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternList) + if err != nil { return nil, types.ListTrackerPatternsOutput{}, err } - - scope := coredata.NewScopeFromObjectID(input.CookieCategoryID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerPatternOrderField]{Field: coredata.TrackerPatternOrderFieldCreatedAt, Direction: page.OrderDirectionAsc}) patterns, err := r.cookieBanner.ListTrackerPatternsForCategory(ctx, scope, input.CookieCategoryID, cursor) @@ -5688,12 +5693,11 @@ func (r *Resolver) ListTrackerPatternsTool(ctx context.Context, req *mcp.CallToo } func (r *Resolver) GetTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerPatternInput) (*mcp.CallToolResult, types.GetTrackerPatternOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternGet); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternGet) + if err != nil { return nil, types.GetTrackerPatternOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - pattern, err := r.cookieBanner.GetTrackerPattern(ctx, scope, input.ID) if err != nil { return nil, types.GetTrackerPatternOutput{}, fmt.Errorf("cannot get tracker pattern: %w", err) @@ -5703,12 +5707,11 @@ func (r *Resolver) GetTrackerPatternTool(ctx context.Context, req *mcp.CallToolR } func (r *Resolver) AddTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerPatternInput) (*mcp.CallToolResult, types.AddTrackerPatternOutput, error) { - if _, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternCreate); err != nil { + scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternCreate) + if err != nil { return nil, types.AddTrackerPatternOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.CookieCategoryID) - pattern, err := r.cookieBanner.CreateTrackerPattern(ctx, scope, cookiebanner.CreateTrackerPatternRequest{ CookieCategoryID: input.CookieCategoryID, TrackerType: coredata.TrackerType(input.TrackerType), @@ -5726,12 +5729,11 @@ func (r *Resolver) AddTrackerPatternTool(ctx context.Context, req *mcp.CallToolR } func (r *Resolver) UpdateTrackerPatternTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerPatternInput) (*mcp.CallToolResult, types.UpdateTrackerPatternOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternUpdate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerPatternUpdate) + if err != nil { return nil, types.UpdateTrackerPatternOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - updateReq := cookiebanner.UpdateTrackerPatternRequest{TrackerPatternID: input.ID} if input.MaxAgeSeconds.IsSet() { val, _ := input.MaxAgeSeconds.Value() @@ -5768,12 +5770,11 @@ func (r *Resolver) DeleteTrackerPatternTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) MoveTrackerPatternToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerPatternToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerPatternToCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate); err != nil { + scope, err := r.Authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate) + if err != nil { return nil, types.MoveTrackerPatternToCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.TrackerPatternID) - result, err := r.cookieBanner.MoveTrackerPatternToCategory(ctx, scope, cookiebanner.MoveTrackerPatternToCategoryRequest{ TrackerPatternID: input.TrackerPatternID, TargetCookieCategoryID: input.TargetCookieCategoryID, @@ -5786,12 +5787,11 @@ func (r *Resolver) MoveTrackerPatternToCategoryTool(ctx context.Context, req *mc } func (r *Resolver) PublishCookieBannerVersionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.PublishCookieBannerVersionInput) (*mcp.CallToolResult, types.PublishCookieBannerVersionOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionPublish); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionPublish) + if err != nil { return nil, types.PublishCookieBannerVersionOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) - version, err := r.cookieBanner.PublishCookieBannerVersion(ctx, scope, input.CookieBannerID) if err != nil { return nil, types.PublishCookieBannerVersionOutput{}, fmt.Errorf("cannot publish cookie banner version: %w", err) @@ -5801,11 +5801,10 @@ func (r *Resolver) PublishCookieBannerVersionTool(ctx context.Context, req *mcp. } func (r *Resolver) ListCookieBannerVersionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieBannerVersionsInput) (*mcp.CallToolResult, types.ListCookieBannerVersionsOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionList); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionList) + if err != nil { return nil, types.ListCookieBannerVersionsOutput{}, err } - - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieBannerVersionOrderField]{Field: coredata.CookieBannerVersionOrderFieldCreatedAt, Direction: page.OrderDirectionDesc}) versions, err := r.cookieBanner.ListCookieBannerVersionsForBanner(ctx, scope, input.CookieBannerID, cursor) @@ -5819,12 +5818,11 @@ func (r *Resolver) ListCookieBannerVersionsTool(ctx context.Context, req *mcp.Ca } func (r *Resolver) UpsertCookieBannerTranslationTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpsertCookieBannerTranslationInput) (*mcp.CallToolResult, types.UpsertCookieBannerTranslationOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate) + if err != nil { return nil, types.UpsertCookieBannerTranslationOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) - translation, err := r.cookieBanner.UpsertCookieBannerTranslation(ctx, scope, cookiebanner.UpsertCookieBannerTranslationRequest{ CookieBannerID: input.CookieBannerID, Language: input.Language, @@ -5838,11 +5836,10 @@ func (r *Resolver) UpsertCookieBannerTranslationTool(ctx context.Context, req *m } func (r *Resolver) ListCookieConsentRecordsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListCookieConsentRecordsInput) (*mcp.CallToolResult, types.ListCookieConsentRecordsOutput, error) { - if _, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieConsentRecordList); err != nil { + scope, err := r.Authorize(ctx, input.CookieBannerID, probo.ActionCookieConsentRecordList) + if err != nil { return nil, types.ListCookieConsentRecordsOutput{}, err } - - scope := coredata.NewScopeFromObjectID(input.CookieBannerID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.CookieConsentRecordOrderField]{Field: coredata.CookieConsentRecordOrderFieldCreatedAt, Direction: page.OrderDirectionDesc}) var action *coredata.CookieConsentAction @@ -5865,12 +5862,11 @@ func (r *Resolver) ListCookieConsentRecordsTool(ctx context.Context, req *mcp.Ca } func (r *Resolver) GetCookieConsentRecordTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetCookieConsentRecordInput) (*mcp.CallToolResult, types.GetCookieConsentRecordOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionCookieConsentRecordList); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionCookieConsentRecordList) + if err != nil { return nil, types.GetCookieConsentRecordOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - record, err := r.cookieBanner.GetCookieConsentRecord(ctx, scope, input.ID) if err != nil { return nil, types.GetCookieConsentRecordOutput{}, fmt.Errorf("cannot get cookie consent record: %w", err) @@ -6064,11 +6060,10 @@ func (r *Resolver) PublishDocumentTool(ctx context.Context, req *mcp.CallToolReq } func (r *Resolver) ListTrackerResourcesTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListTrackerResourcesInput) (*mcp.CallToolResult, types.ListTrackerResourcesOutput, error) { - if _, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceList); err != nil { + scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceList) + if err != nil { return nil, types.ListTrackerResourcesOutput{}, err } - - scope := coredata.NewScopeFromObjectID(input.CookieCategoryID) cursor := types.NewCursor(input.Size, input.Cursor, page.OrderBy[coredata.TrackerResourceOrderField]{Field: coredata.TrackerResourceOrderFieldCreatedAt, Direction: page.OrderDirectionAsc}) resources, err := r.cookieBanner.ListTrackerResourcesForCategory(ctx, scope, input.CookieCategoryID, cursor) @@ -6082,12 +6077,11 @@ func (r *Resolver) ListTrackerResourcesTool(ctx context.Context, req *mcp.CallTo } func (r *Resolver) GetTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetTrackerResourceInput) (*mcp.CallToolResult, types.GetTrackerResourceOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceGet); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceGet) + if err != nil { return nil, types.GetTrackerResourceOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - resource, err := r.cookieBanner.GetTrackerResource(ctx, scope, input.ID) if err != nil { return nil, types.GetTrackerResourceOutput{}, fmt.Errorf("cannot get tracker resource: %w", err) @@ -6097,12 +6091,11 @@ func (r *Resolver) GetTrackerResourceTool(ctx context.Context, req *mcp.CallTool } func (r *Resolver) AddTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.AddTrackerResourceInput) (*mcp.CallToolResult, types.AddTrackerResourceOutput, error) { - if _, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceCreate); err != nil { + scope, err := r.Authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceCreate) + if err != nil { return nil, types.AddTrackerResourceOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.CookieCategoryID) - description := "" if input.Description != nil { description = *input.Description @@ -6124,12 +6117,11 @@ func (r *Resolver) AddTrackerResourceTool(ctx context.Context, req *mcp.CallTool } func (r *Resolver) UpdateTrackerResourceTool(ctx context.Context, req *mcp.CallToolRequest, input *types.UpdateTrackerResourceInput) (*mcp.CallToolResult, types.UpdateTrackerResourceOutput, error) { - if _, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceUpdate); err != nil { + scope, err := r.Authorize(ctx, input.ID, probo.ActionTrackerResourceUpdate) + if err != nil { return nil, types.UpdateTrackerResourceOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.ID) - updateReq := cookiebanner.UpdateTrackerResourceRequest{TrackerResourceID: input.ID} if v := UnwrapOmittable(input.DisplayName); v != nil && *v != nil { updateReq.DisplayName = *v @@ -6165,12 +6157,11 @@ func (r *Resolver) DeleteTrackerResourceTool(ctx context.Context, req *mcp.CallT } func (r *Resolver) MoveTrackerResourceToCategoryTool(ctx context.Context, req *mcp.CallToolRequest, input *types.MoveTrackerResourceToCategoryInput) (*mcp.CallToolResult, types.MoveTrackerResourceToCategoryOutput, error) { - if _, err := r.Authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate); err != nil { + scope, err := r.Authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate) + if err != nil { return nil, types.MoveTrackerResourceToCategoryOutput{}, err } - scope := coredata.NewScopeFromObjectID(input.TrackerResourceID) - result, err := r.cookieBanner.MoveTrackerResourceToCategory(ctx, scope, cookiebanner.MoveTrackerResourceToCategoryRequest{ TrackerResourceID: input.TrackerResourceID, TargetCookieCategoryID: input.TargetCookieCategoryID,