graphql: add TrackerResource schema, resolvers, and IAM actions
Add the full GraphQL surface for the new tracker_resources table:
- TrackerResourceType enum (SCRIPT, IFRAME), TrackerResource node type
with connection/edge/order/filter, fields on CookieBanner
(uncategorisedTrackerResources) and CookieCategory (trackerResources).
- Mutations: createTrackerResource, updateTrackerResource,
deleteTrackerResource, moveTrackerResourceToCategory with
inputs and payloads.
- Resolvers for all mutations, connection fields, field resolvers
(cookieCategory, permission), and totalCount.
- IAM actions: core:tracker-resource:{get,list,create,update,delete}.
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -213,6 +213,42 @@ func (r *cookieBannerResolver) UncategorisedTrackerPatterns(ctx context.Context,
|
||||
return types.NewTrackerPatternConnectionWithFilter(p, r, obj.ID, filter), nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.TrackerResourceOrderField]{
|
||||
Field: coredata.TrackerResourceOrderFieldLastDetectedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.TrackerResourceOrderField]{
|
||||
Field: orderBy.Field,
|
||||
Direction: orderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
scope := coredata.NewScopeFromObjectID(obj.ID)
|
||||
|
||||
coredataFilter := coredata.NewTrackerResourceFilter(nil, nil)
|
||||
if filter != nil {
|
||||
coredataFilter = coredataFilter.WithQuery(filter.Query).WithResourceType(filter.Type)
|
||||
}
|
||||
|
||||
resources, err := r.cookieBanner.ListUncategorisedTrackerResources(ctx, scope, obj.ID, cursor, coredataFilter)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list uncategorised tracker resources", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
p := page.NewPage(resources, cursor)
|
||||
|
||||
return types.NewTrackerResourceConnectionWithFilter(p, r, obj.ID, filter), nil
|
||||
}
|
||||
|
||||
// Permission is the resolver for the permission field.
|
||||
func (r *cookieBannerResolver) Permission(ctx context.Context, obj *types.CookieBanner, action string) (bool, error) {
|
||||
return r.Resolver.Permission(ctx, obj, action)
|
||||
@@ -333,6 +369,37 @@ func (r *cookieCategoryResolver) TrackerPatterns(ctx context.Context, obj *types
|
||||
return types.NewTrackerPatternConnection(p, r, obj.ID), nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.TrackerResourceOrderField]{
|
||||
Field: coredata.TrackerResourceOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionAsc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.TrackerResourceOrderField]{
|
||||
Field: orderBy.Field,
|
||||
Direction: orderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
r.logger.ErrorCtx(ctx, "cannot list tracker resources", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
p := page.NewPage(resources, cursor)
|
||||
|
||||
return types.NewTrackerResourceConnection(p, r, obj.ID), nil
|
||||
}
|
||||
|
||||
// Permission is the resolver for the permission field.
|
||||
func (r *cookieCategoryResolver) Permission(ctx context.Context, obj *types.CookieCategory, action string) (bool, error) {
|
||||
return r.Resolver.Permission(ctx, obj, action)
|
||||
@@ -929,6 +996,177 @@ func (r *mutationResolver) MoveTrackerPatternToCategory(ctx context.Context, inp
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateTrackerResource is the resolver for the createTrackerResource field.
|
||||
func (r *mutationResolver) CreateTrackerResource(ctx context.Context, input types.CreateTrackerResourceInput) (*types.CreateTrackerResourcePayload, error) {
|
||||
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionTrackerResourceCreate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
||||
|
||||
var description string
|
||||
if input.Description != nil {
|
||||
description = *input.Description
|
||||
}
|
||||
|
||||
resource, err := r.cookieBanner.CreateTrackerResource(
|
||||
ctx,
|
||||
scope,
|
||||
cookiebanner.CreateTrackerResourceRequest{
|
||||
CookieCategoryID: input.CookieCategoryID,
|
||||
ResourceType: input.Type,
|
||||
Origin: input.Origin,
|
||||
Path: input.Path,
|
||||
DisplayName: input.DisplayName,
|
||||
Description: description,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, cookiebanner.ErrResourceAlreadyExists) {
|
||||
return nil, gqlutils.Conflictf(ctx, "a resource with this origin and path already exists in this banner")
|
||||
}
|
||||
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
||||
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot create tracker resource", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
bannerScope := coredata.NewScopeFromObjectID(resource.CookieBannerID)
|
||||
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, resource.CookieBannerID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.CreateTrackerResourcePayload{
|
||||
TrackerResourceEdge: types.NewTrackerResourceEdge(resource, coredata.TrackerResourceOrderFieldCreatedAt),
|
||||
CookieBanner: types.NewCookieBanner(banner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateTrackerResource is the resolver for the updateTrackerResource field.
|
||||
func (r *mutationResolver) UpdateTrackerResource(ctx context.Context, input types.UpdateTrackerResourceInput) (*types.UpdateTrackerResourcePayload, error) {
|
||||
if err := r.authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scope := coredata.NewScopeFromObjectID(input.TrackerResourceID)
|
||||
|
||||
resource, err := r.cookieBanner.UpdateTrackerResource(
|
||||
ctx,
|
||||
scope,
|
||||
cookiebanner.UpdateTrackerResourceRequest{
|
||||
TrackerResourceID: input.TrackerResourceID,
|
||||
DisplayName: input.DisplayName,
|
||||
Description: input.Description,
|
||||
Excluded: input.Excluded,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, cookiebanner.ErrTrackerResourceNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
||||
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot update tracker resource", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
bannerScope := coredata.NewScopeFromObjectID(resource.CookieBannerID)
|
||||
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, resource.CookieBannerID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.UpdateTrackerResourcePayload{
|
||||
TrackerResource: types.NewTrackerResourceNode(resource),
|
||||
CookieBanner: types.NewCookieBanner(banner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteTrackerResource is the resolver for the deleteTrackerResource field.
|
||||
func (r *mutationResolver) DeleteTrackerResource(ctx context.Context, input types.DeleteTrackerResourceInput) (*types.DeleteTrackerResourcePayload, error) {
|
||||
if err := r.authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceDelete); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scope := coredata.NewScopeFromObjectID(input.TrackerResourceID)
|
||||
|
||||
resource, err := r.cookieBanner.GetTrackerResource(ctx, scope, input.TrackerResourceID)
|
||||
if err != nil {
|
||||
if errors.Is(err, cookiebanner.ErrTrackerResourceNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get tracker resource", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
bannerID := resource.CookieBannerID
|
||||
|
||||
if err := r.cookieBanner.DeleteTrackerResource(ctx, scope, input.TrackerResourceID); err != nil {
|
||||
if errors.Is(err, cookiebanner.ErrTrackerResourceNotFound) {
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot delete tracker resource", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
bannerScope := coredata.NewScopeFromObjectID(bannerID)
|
||||
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, bannerID)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return &types.DeleteTrackerResourcePayload{
|
||||
DeletedTrackerResourceID: input.TrackerResourceID,
|
||||
CookieBanner: types.NewCookieBanner(banner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MoveTrackerResourceToCategory is the resolver for the moveTrackerResourceToCategory field.
|
||||
func (r *mutationResolver) MoveTrackerResourceToCategory(ctx context.Context, input types.MoveTrackerResourceToCategoryInput) (*types.MoveTrackerResourceToCategoryPayload, error) {
|
||||
if err := r.authorize(ctx, input.TrackerResourceID, probo.ActionTrackerResourceUpdate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := r.authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scope := coredata.NewScopeFromObjectID(input.TrackerResourceID)
|
||||
|
||||
result, err := r.cookieBanner.MoveTrackerResourceToCategory(
|
||||
ctx,
|
||||
scope,
|
||||
cookiebanner.MoveTrackerResourceToCategoryRequest{
|
||||
TrackerResourceID: input.TrackerResourceID,
|
||||
TargetCookieCategoryID: input.TargetCookieCategoryID,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, cookiebanner.ErrCategoryNotFound):
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
case errors.Is(err, cookiebanner.ErrTrackerResourceNotFound):
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
case errors.Is(err, cookiebanner.ErrCategoriesBannerMismatch):
|
||||
return nil, gqlutils.NotFoundf(ctx, "tracker resource or target category not found")
|
||||
default:
|
||||
r.logger.ErrorCtx(ctx, "cannot move tracker resource to category", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return &types.MoveTrackerResourceToCategoryPayload{
|
||||
TrackerResource: types.NewTrackerResourceNode(result.TrackerResource),
|
||||
CookieBanner: types.NewCookieBanner(result.Banner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CookieCategory is the resolver for the cookieCategory field.
|
||||
func (r *trackerPatternResolver) CookieCategory(ctx context.Context, obj *types.TrackerPattern) (*types.CookieCategory, error) {
|
||||
if err := r.authorize(ctx, obj.CookieCategory.ID, probo.ActionCookieCategoryGet); err != nil {
|
||||
@@ -993,6 +1231,57 @@ func (r *trackerPatternConnectionResolver) TotalCount(ctx context.Context, obj *
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// CookieCategory is the resolver for the cookieCategory field.
|
||||
func (r *trackerResourceResolver) CookieCategory(ctx context.Context, obj *types.TrackerResource) (*types.CookieCategory, error) {
|
||||
if err := r.authorize(ctx, obj.CookieCategory.ID, probo.ActionCookieCategoryGet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loaders := dataloader.FromContext(ctx)
|
||||
|
||||
category, err := loaders.CookieCategory.Load(ctx, obj.CookieCategory.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
r.logger.ErrorCtx(ctx, "cannot get cookie category", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewCookieCategory(category), nil
|
||||
}
|
||||
|
||||
// Permission is the resolver for the permission field.
|
||||
func (r *trackerResourceResolver) Permission(ctx context.Context, obj *types.TrackerResource, action string) (bool, error) {
|
||||
return r.Resolver.Permission(ctx, obj, action)
|
||||
}
|
||||
|
||||
// TotalCount is the resolver for the totalCount field.
|
||||
func (r *trackerResourceConnectionResolver) TotalCount(ctx context.Context, obj *types.TrackerResourceConnection) (int, error) {
|
||||
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
||||
|
||||
var count int
|
||||
var err error
|
||||
|
||||
switch obj.Resolver.(type) {
|
||||
case *cookieCategoryResolver:
|
||||
count, err = r.cookieBanner.CountTrackerResourcesForCategory(ctx, scope, obj.ParentID)
|
||||
default:
|
||||
filter := coredata.NewTrackerResourceFilter(nil, nil)
|
||||
if obj.Filter != nil {
|
||||
filter = filter.WithQuery(obj.Filter.Query).WithResourceType(obj.Filter.Type)
|
||||
}
|
||||
count, err = r.cookieBanner.CountUncategorisedTrackerResources(ctx, scope, obj.ParentID, filter)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot count tracker resources", log.Error(err))
|
||||
return 0, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// CookieBanner returns schema.CookieBannerResolver implementation.
|
||||
func (r *Resolver) CookieBanner() schema.CookieBannerResolver { return &cookieBannerResolver{r} }
|
||||
|
||||
@@ -1022,6 +1311,16 @@ func (r *Resolver) TrackerPatternConnection() schema.TrackerPatternConnectionRes
|
||||
return &trackerPatternConnectionResolver{r}
|
||||
}
|
||||
|
||||
// TrackerResource returns schema.TrackerResourceResolver implementation.
|
||||
func (r *Resolver) TrackerResource() schema.TrackerResourceResolver {
|
||||
return &trackerResourceResolver{r}
|
||||
}
|
||||
|
||||
// TrackerResourceConnection returns schema.TrackerResourceConnectionResolver implementation.
|
||||
func (r *Resolver) TrackerResourceConnection() schema.TrackerResourceConnectionResolver {
|
||||
return &trackerResourceConnectionResolver{r}
|
||||
}
|
||||
|
||||
type cookieBannerResolver struct{ *Resolver }
|
||||
type cookieBannerConnectionResolver struct{ *Resolver }
|
||||
type cookieBannerVersionResolver struct{ *Resolver }
|
||||
@@ -1029,3 +1328,5 @@ type cookieCategoryResolver struct{ *Resolver }
|
||||
type cookieCategoryConnectionResolver struct{ *Resolver }
|
||||
type trackerPatternResolver struct{ *Resolver }
|
||||
type trackerPatternConnectionResolver struct{ *Resolver }
|
||||
type trackerResourceResolver struct{ *Resolver }
|
||||
type trackerResourceConnectionResolver struct{ *Resolver }
|
||||
|
||||
@@ -152,6 +152,15 @@ type CookieBanner implements Node {
|
||||
filter: TrackerPatternFilter
|
||||
): TrackerPatternConnection @goField(forceResolver: true)
|
||||
|
||||
uncategorisedTrackerResources(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: TrackerResourceOrder
|
||||
filter: TrackerResourceFilter
|
||||
): TrackerResourceConnection @goField(forceResolver: true)
|
||||
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
@@ -185,6 +194,14 @@ type CookieCategory implements Node {
|
||||
orderBy: TrackerPatternOrder
|
||||
): TrackerPatternConnection @goField(forceResolver: true)
|
||||
|
||||
trackerResources(
|
||||
first: Int
|
||||
after: CursorKey
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: TrackerResourceOrder
|
||||
): TrackerResourceConnection @goField(forceResolver: true)
|
||||
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
@@ -281,6 +298,86 @@ input TrackerPatternFilter
|
||||
trackerType: TrackerType
|
||||
}
|
||||
|
||||
enum TrackerResourceType
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.TrackerResourceType") {
|
||||
SCRIPT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceTypeScript"
|
||||
)
|
||||
IFRAME
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceTypeIframe"
|
||||
)
|
||||
}
|
||||
|
||||
enum TrackerResourceOrderField
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/coredata.TrackerResourceOrderField"
|
||||
) {
|
||||
CREATED_AT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceOrderFieldCreatedAt"
|
||||
)
|
||||
LAST_DETECTED_AT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceOrderFieldLastDetectedAt"
|
||||
)
|
||||
ORIGIN
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceOrderFieldOrigin"
|
||||
)
|
||||
UPDATED_AT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.TrackerResourceOrderFieldUpdatedAt"
|
||||
)
|
||||
}
|
||||
|
||||
type TrackerResource implements Node {
|
||||
id: ID!
|
||||
cookieCategory: CookieCategory @goField(forceResolver: true)
|
||||
type: TrackerResourceType!
|
||||
origin: String!
|
||||
path: String!
|
||||
displayName: String!
|
||||
description: String!
|
||||
excluded: Boolean!
|
||||
lastDetectedAt: Datetime
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
|
||||
permission(action: String!): Boolean! @goField(forceResolver: true)
|
||||
}
|
||||
|
||||
type TrackerResourceConnection
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.TrackerResourceConnection"
|
||||
) {
|
||||
totalCount: Int! @goField(forceResolver: true)
|
||||
edges: [TrackerResourceEdge!]!
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type TrackerResourceEdge {
|
||||
cursor: CursorKey!
|
||||
node: TrackerResource!
|
||||
}
|
||||
|
||||
input TrackerResourceOrder
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.TrackerResourceOrderBy"
|
||||
) {
|
||||
direction: OrderDirection!
|
||||
field: TrackerResourceOrderField!
|
||||
}
|
||||
|
||||
input TrackerResourceFilter
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/console/v1/types.TrackerResourceFilter"
|
||||
) {
|
||||
query: String
|
||||
type: TrackerResourceType
|
||||
}
|
||||
|
||||
type CookieBannerVersion implements Node {
|
||||
id: ID!
|
||||
version: Int!
|
||||
@@ -378,6 +475,18 @@ extend type Mutation {
|
||||
moveTrackerPatternToCategory(
|
||||
input: MoveTrackerPatternToCategoryInput!
|
||||
): MoveTrackerPatternToCategoryPayload!
|
||||
createTrackerResource(
|
||||
input: CreateTrackerResourceInput!
|
||||
): CreateTrackerResourcePayload!
|
||||
updateTrackerResource(
|
||||
input: UpdateTrackerResourceInput!
|
||||
): UpdateTrackerResourcePayload!
|
||||
deleteTrackerResource(
|
||||
input: DeleteTrackerResourceInput!
|
||||
): DeleteTrackerResourcePayload!
|
||||
moveTrackerResourceToCategory(
|
||||
input: MoveTrackerResourceToCategoryInput!
|
||||
): MoveTrackerResourceToCategoryPayload!
|
||||
}
|
||||
|
||||
input CreateCookieBannerInput {
|
||||
@@ -542,3 +651,48 @@ type MoveTrackerPatternToCategoryPayload {
|
||||
trackerPattern: TrackerPattern!
|
||||
cookieBanner: CookieBanner!
|
||||
}
|
||||
|
||||
input CreateTrackerResourceInput {
|
||||
cookieCategoryId: ID!
|
||||
type: TrackerResourceType!
|
||||
origin: String!
|
||||
path: String!
|
||||
displayName: String!
|
||||
description: String
|
||||
}
|
||||
|
||||
input UpdateTrackerResourceInput {
|
||||
trackerResourceId: ID!
|
||||
displayName: String
|
||||
description: String
|
||||
excluded: Boolean
|
||||
}
|
||||
|
||||
input DeleteTrackerResourceInput {
|
||||
trackerResourceId: ID!
|
||||
}
|
||||
|
||||
input MoveTrackerResourceToCategoryInput {
|
||||
trackerResourceId: ID!
|
||||
targetCookieCategoryId: ID!
|
||||
}
|
||||
|
||||
type CreateTrackerResourcePayload {
|
||||
trackerResourceEdge: TrackerResourceEdge!
|
||||
cookieBanner: CookieBanner!
|
||||
}
|
||||
|
||||
type UpdateTrackerResourcePayload {
|
||||
trackerResource: TrackerResource!
|
||||
cookieBanner: CookieBanner!
|
||||
}
|
||||
|
||||
type DeleteTrackerResourcePayload {
|
||||
deletedTrackerResourceId: ID!
|
||||
cookieBanner: CookieBanner!
|
||||
}
|
||||
|
||||
type MoveTrackerResourceToCategoryPayload {
|
||||
trackerResource: TrackerResource!
|
||||
cookieBanner: CookieBanner!
|
||||
}
|
||||
|
||||
99
pkg/server/api/console/v1/types/tracker_resource.go
Normal file
99
pkg/server/api/console/v1/types/tracker_resource.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type (
|
||||
TrackerResourceOrderBy OrderBy[coredata.TrackerResourceOrderField]
|
||||
|
||||
TrackerResourceConnection struct {
|
||||
TotalCount int
|
||||
Edges []*TrackerResourceEdge
|
||||
PageInfo PageInfo
|
||||
|
||||
Resolver any
|
||||
ParentID gid.GID
|
||||
Filter *TrackerResourceFilter
|
||||
}
|
||||
|
||||
TrackerResourceFilter struct {
|
||||
Query *string
|
||||
Type *coredata.TrackerResourceType
|
||||
}
|
||||
)
|
||||
|
||||
func NewTrackerResourceConnection(
|
||||
p *page.Page[*coredata.TrackerResource, coredata.TrackerResourceOrderField],
|
||||
parentType any,
|
||||
parentID gid.GID,
|
||||
) *TrackerResourceConnection {
|
||||
edges := make([]*TrackerResourceEdge, len(p.Data))
|
||||
|
||||
for i := range edges {
|
||||
edges[i] = NewTrackerResourceEdge(p.Data[i], p.Cursor.OrderBy.Field)
|
||||
}
|
||||
|
||||
return &TrackerResourceConnection{
|
||||
Edges: edges,
|
||||
PageInfo: *NewPageInfo(p),
|
||||
|
||||
Resolver: parentType,
|
||||
ParentID: parentID,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTrackerResourceConnectionWithFilter(
|
||||
p *page.Page[*coredata.TrackerResource, coredata.TrackerResourceOrderField],
|
||||
parentType any,
|
||||
parentID gid.GID,
|
||||
filter *TrackerResourceFilter,
|
||||
) *TrackerResourceConnection {
|
||||
conn := NewTrackerResourceConnection(p, parentType, parentID)
|
||||
conn.Filter = filter
|
||||
return conn
|
||||
}
|
||||
|
||||
func NewTrackerResourceEdge(tr *coredata.TrackerResource, orderBy coredata.TrackerResourceOrderField) *TrackerResourceEdge {
|
||||
return &TrackerResourceEdge{
|
||||
Cursor: tr.CursorKey(orderBy),
|
||||
Node: NewTrackerResourceNode(tr),
|
||||
}
|
||||
}
|
||||
|
||||
func NewTrackerResourceNode(tr *coredata.TrackerResource) *TrackerResource {
|
||||
return &TrackerResource{
|
||||
ID: tr.ID,
|
||||
CookieCategory: &CookieCategory{
|
||||
ID: tr.CookieCategoryID,
|
||||
CookieBanner: &CookieBanner{
|
||||
ID: tr.CookieBannerID,
|
||||
},
|
||||
},
|
||||
Type: tr.ResourceType,
|
||||
Origin: tr.Origin,
|
||||
Path: tr.Path,
|
||||
DisplayName: tr.DisplayName,
|
||||
Description: tr.Description,
|
||||
Excluded: tr.Excluded,
|
||||
LastDetectedAt: tr.LastDetectedAt,
|
||||
CreatedAt: tr.CreatedAt,
|
||||
UpdatedAt: tr.UpdatedAt,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user