From 88d7961ac65351179e4c6534412346419c36e2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Thu, 28 May 2026 14:29:02 +0200 Subject: [PATCH] Take resolver scope from authorize, not the GID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The authorize/Authorize helpers (GraphQL and MCP) already return the *coredata.Scope resolved from the resource's organization_id attribute, but several resolvers discarded it and rebuilt the scope with coredata.NewScopeFromObjectID(...) right after. NewScopeFromObjectID only reads the tenant encoded in the GID, while the authorizer derives the scope from loaded resource attributes, so the two silently drift if the resource lookup ever changes. Capture scope from authorize and feed it straight to the service/coredata layer. For the LinkX/UnlinkX MCP tools, move the per-case Authorize inside the switch and drop the shared scope so each case owns its own authorization result. Document the rule in contrib/claude/authorization.md and add a matching .cursor/rules/go-authorize-scope.mdc, including the narrow exception for global-catalog authorize calls (e.g. identity-scoped ActionCommonThirdPartyList) where downstream services take no scope. Signed-off-by: Émile Ré --- .cursor/rules/go-authorize-scope.mdc | 59 +++++ contrib/claude/authorization.md | 54 ++++- .../api/console/v1/cookie_banner_resolvers.go | 31 ++- .../api/console/v1/document_resolvers.go | 9 +- .../api/console/v1/organization_resolvers.go | 5 +- pkg/server/api/console/v1/risk_resolvers.go | 2 - pkg/server/api/mcp/v1/schema.resolvers.go | 207 +++++++++--------- 7 files changed, 230 insertions(+), 137 deletions(-) create mode 100644 .cursor/rules/go-authorize-scope.mdc 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,