The trackers page now lets users filter by tracker type (Cookie, localStorage, sessionStorage, IndexedDB, Cache Storage) in addition to the existing source filter. Each tracker type and cookie source badge uses a distinct color for quick visual scanning. Signed-off-by: Émile Ré <emile@getprobo.com>
1335 lines
48 KiB
Go
1335 lines
48 KiB
Go
package console_v1
|
|
|
|
// This file will be automatically regenerated based on the schema, any resolver
|
|
// implementations
|
|
// will be copied through when generating and any unknown code will be moved to the end.
|
|
// Code generated by github.com/99designs/gqlgen version v0.17.90
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"github.com/vikstrous/dataloadgen"
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/cookiebanner"
|
|
"go.probo.inc/probo/pkg/coredata"
|
|
"go.probo.inc/probo/pkg/page"
|
|
"go.probo.inc/probo/pkg/probo"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/types"
|
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
|
"go.probo.inc/probo/pkg/validator"
|
|
)
|
|
|
|
// Organization is the resolver for the organization field.
|
|
func (r *cookieBannerResolver) Organization(ctx context.Context, obj *types.CookieBanner) (*types.Organization, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
loaders := dataloader.FromContext(ctx)
|
|
|
|
organization, err := loaders.Organization.Load(ctx, obj.Organization.ID)
|
|
if err != nil {
|
|
if errors.Is(err, coredata.ErrResourceNotFound) || errors.Is(err, dataloadgen.ErrNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot get organization", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return types.NewOrganization(organization), nil
|
|
}
|
|
|
|
// ConsentCategories is the resolver for the consentCategories field.
|
|
func (r *cookieBannerResolver) ConsentCategories(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookieCategoryOrderBy) (*types.CookieCategoryConnection, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookieCategoryList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CookieCategoryOrderField]{
|
|
Field: coredata.CookieCategoryOrderFieldRank,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CookieCategoryOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
categories, err := r.cookieBanner.ListCookieCategoriesForBanner(ctx, scope, obj.ID, cursor)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list cookie categories", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
p := page.NewPage(categories, cursor)
|
|
|
|
return types.NewCookieCategoryConnection(p, r, obj.ID), nil
|
|
}
|
|
|
|
// Translations is the resolver for the translations field.
|
|
func (r *cookieBannerResolver) Translations(ctx context.Context, obj *types.CookieBanner) ([]*types.CookieBannerTranslation, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookieBannerGet); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
translations, err := r.cookieBanner.ListCookieBannerTranslations(ctx, scope, obj.ID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list cookie banner translations", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
result := make([]*types.CookieBannerTranslation, len(translations))
|
|
for i, t := range translations {
|
|
result[i] = types.NewCookieBannerTranslation(t)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// LatestVersion is the resolver for the latestVersion field.
|
|
func (r *cookieBannerResolver) LatestVersion(ctx context.Context, obj *types.CookieBanner) (*types.CookieBannerVersion, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookieBannerVersionList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
cursor := &page.Cursor[coredata.CookieBannerVersionOrderField]{
|
|
Size: 1,
|
|
Position: page.Head,
|
|
OrderBy: page.OrderBy[coredata.CookieBannerVersionOrderField]{
|
|
Field: coredata.CookieBannerVersionOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
},
|
|
}
|
|
|
|
versions, err := r.cookieBanner.ListCookieBannerVersionsForBanner(ctx, scope, obj.ID, cursor)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot load latest cookie banner version", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
if len(versions) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
v := versions[0]
|
|
return &types.CookieBannerVersion{
|
|
ID: v.ID,
|
|
Version: v.Version,
|
|
State: string(v.State),
|
|
CreatedAt: v.CreatedAt,
|
|
UpdatedAt: v.UpdatedAt,
|
|
}, nil
|
|
}
|
|
|
|
// ConsentRecords is the resolver for the consentRecords field.
|
|
func (r *cookieBannerResolver) ConsentRecords(ctx context.Context, obj *types.CookieBanner, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookieConsentRecordOrderBy, filter *types.CookieConsentRecordFilter) (*types.CookieConsentRecordConnection, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookieConsentRecordList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CookieConsentRecordOrderField]{
|
|
Field: coredata.CookieConsentRecordOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CookieConsentRecordOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
var (
|
|
action *coredata.CookieConsentAction
|
|
visitorID *string
|
|
version *int
|
|
)
|
|
if filter != nil {
|
|
action = filter.Action
|
|
visitorID = filter.VisitorID
|
|
version = filter.Version
|
|
}
|
|
|
|
coredataFilter := coredata.NewCookieConsentRecordFilter(action, visitorID, version)
|
|
|
|
records, err := r.cookieBanner.ListCookieConsentRecordsForBanner(ctx, scope, obj.ID, cursor, coredataFilter)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list consent records", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
p := page.NewPage(records, cursor)
|
|
|
|
return types.NewCookieConsentRecordConnection(p, r, obj.ID, coredataFilter), nil
|
|
}
|
|
|
|
// UncategorisedTrackerPatterns is the resolver for the uncategorisedTrackerPatterns field.
|
|
func (r *cookieBannerResolver) UncategorisedTrackerPatterns(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 {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TrackerPatternOrderField]{
|
|
Field: coredata.TrackerPatternOrderFieldName,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TrackerPatternOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
coredataFilter := coredata.NewTrackerPatternFilter(nil, nil, nil)
|
|
if filter != nil {
|
|
coredataFilter = coredataFilter.WithQuery(filter.Query).WithSource(filter.Source).WithTrackerType(filter.TrackerType)
|
|
}
|
|
|
|
patterns, err := r.cookieBanner.ListUncategorisedTrackerPatterns(ctx, scope, obj.ID, cursor, coredataFilter)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list uncategorised tracker patterns", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
p := page.NewPage(patterns, cursor)
|
|
|
|
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)
|
|
}
|
|
|
|
// TotalCount is the resolver for the totalCount field.
|
|
func (r *cookieBannerConnectionResolver) TotalCount(ctx context.Context, obj *types.CookieBannerConnection) (int, error) {
|
|
if err := r.authorize(ctx, obj.ParentID, probo.ActionCookieBannerList); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
|
|
|
count, err := r.cookieBanner.CountCookieBannersForOrganization(ctx, scope, obj.ParentID, coredata.NewCookieBannerFilter(nil))
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count cookie banners", log.Error(err))
|
|
return 0, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// Categories is the resolver for the categories field.
|
|
func (r *cookieBannerVersionResolver) Categories(ctx context.Context, obj *types.CookieBannerVersion) ([]*types.CookieBannerVersionCategory, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookieBannerVersionGet); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
version, err := r.cookieBanner.GetCookieBannerVersion(ctx, scope, obj.ID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner version", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
snapshot, err := version.GetSnapshot()
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get version snapshot", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
categories := make([]*types.CookieBannerVersionCategory, len(snapshot.Categories))
|
|
for i, cat := range snapshot.Categories {
|
|
cookies := make([]*types.CookieBannerVersionCookie, len(cat.Cookies))
|
|
for j, c := range cat.Cookies {
|
|
cookies[j] = &types.CookieBannerVersionCookie{
|
|
Name: c.Name,
|
|
MaxAgeSeconds: c.MaxAgeSeconds,
|
|
Description: c.Description,
|
|
}
|
|
}
|
|
|
|
categories[i] = &types.CookieBannerVersionCategory{
|
|
Name: cat.Name,
|
|
Slug: cat.Slug,
|
|
Description: cat.Description,
|
|
Kind: cat.Kind,
|
|
Cookies: cookies,
|
|
}
|
|
}
|
|
|
|
return categories, nil
|
|
}
|
|
|
|
// CookieBanner is the resolver for the cookieBanner field.
|
|
func (r *cookieCategoryResolver) CookieBanner(ctx context.Context, obj *types.CookieCategory) (*types.CookieBanner, error) {
|
|
if obj.CookieBanner == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if err := r.authorize(ctx, obj.CookieBanner.ID, probo.ActionCookieBannerGet); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
loaders := dataloader.FromContext(ctx)
|
|
|
|
banner, err := loaders.CookieBanner.Load(ctx, obj.CookieBanner.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 banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return types.NewCookieBanner(banner), nil
|
|
}
|
|
|
|
// 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 {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.TrackerPatternOrderField]{
|
|
Field: coredata.TrackerPatternOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.TrackerPatternOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
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 {
|
|
r.logger.ErrorCtx(ctx, "cannot list tracker patterns", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
p := page.NewPage(patterns, cursor)
|
|
|
|
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)
|
|
}
|
|
|
|
// TotalCount is the resolver for the totalCount field.
|
|
func (r *cookieCategoryConnectionResolver) TotalCount(ctx context.Context, obj *types.CookieCategoryConnection) (int, error) {
|
|
if err := r.authorize(ctx, obj.ParentID, probo.ActionCookieCategoryList); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
|
|
|
count, err := r.cookieBanner.CountCookieCategoriesForBanner(ctx, scope, obj.ParentID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count cookie categories", log.Error(err))
|
|
return 0, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// CreateCookieBanner is the resolver for the createCookieBanner field.
|
|
func (r *mutationResolver) CreateCookieBanner(ctx context.Context, input types.CreateCookieBannerInput) (*types.CreateCookieBannerPayload, error) {
|
|
if err := r.authorize(ctx, input.OrganizationID, probo.ActionCookieBannerCreate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.OrganizationID)
|
|
|
|
banner, err := r.cookieBanner.CreateCookieBanner(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.CreateCookieBannerRequest{
|
|
OrganizationID: input.OrganizationID,
|
|
Name: input.Name,
|
|
Origin: input.Origin,
|
|
PrivacyPolicyURL: input.PrivacyPolicyURL,
|
|
CookiePolicyURL: input.CookiePolicyURL,
|
|
ConsentExpiryDays: input.ConsentExpiryDays,
|
|
ConsentMode: input.ConsentMode,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrOriginAlreadyInUse) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot create cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.CreateCookieBannerPayload{
|
|
CookieBannerEdge: types.NewCookieBannerEdge(banner, coredata.CookieBannerOrderFieldCreatedAt),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateCookieBanner is the resolver for the updateCookieBanner field.
|
|
func (r *mutationResolver) UpdateCookieBanner(ctx context.Context, input types.UpdateCookieBannerInput) (*types.UpdateCookieBannerPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
banner, err := r.cookieBanner.UpdateCookieBanner(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.UpdateCookieBannerRequest{
|
|
CookieBannerID: input.CookieBannerID,
|
|
Name: input.Name,
|
|
PrivacyPolicyURL: input.PrivacyPolicyURL,
|
|
CookiePolicyURL: input.CookiePolicyURL,
|
|
ConsentExpiryDays: input.ConsentExpiryDays,
|
|
ConsentMode: input.ConsentMode,
|
|
DefaultLanguage: input.DefaultLanguage,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
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 cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.UpdateCookieBannerPayload{
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteCookieBanner is the resolver for the deleteCookieBanner field.
|
|
func (r *mutationResolver) DeleteCookieBanner(ctx context.Context, input types.DeleteCookieBannerInput) (*types.DeleteCookieBannerPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerDelete); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
err := r.cookieBanner.DeleteCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot delete cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.DeleteCookieBannerPayload{
|
|
DeletedCookieBannerID: input.CookieBannerID,
|
|
}, nil
|
|
}
|
|
|
|
// ActivateCookieBanner is the resolver for the activateCookieBanner field.
|
|
func (r *mutationResolver) ActivateCookieBanner(ctx context.Context, input types.ActivateCookieBannerInput) (*types.ActivateCookieBannerPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerActivate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
banner, err := r.cookieBanner.ActivateCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrBannerAlreadyActive) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrOriginAlreadyInUse) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot activate cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.ActivateCookieBannerPayload{
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// DeactivateCookieBanner is the resolver for the deactivateCookieBanner field.
|
|
func (r *mutationResolver) DeactivateCookieBanner(ctx context.Context, input types.DeactivateCookieBannerInput) (*types.DeactivateCookieBannerPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerDeactivate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
banner, err := r.cookieBanner.DeactivateCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrBannerAlreadyInactive) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot deactivate cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.DeactivateCookieBannerPayload{
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// PublishCookieBannerVersion is the resolver for the publishCookieBannerVersion field.
|
|
func (r *mutationResolver) PublishCookieBannerVersion(ctx context.Context, input types.PublishCookieBannerVersionInput) (*types.PublishCookieBannerVersionPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerVersionPublish); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
version, err := r.cookieBanner.PublishCookieBannerVersion(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrNoDraftVersion) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot publish cookie banner version", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.PublishCookieBannerVersionPayload{
|
|
CookieBannerVersion: &types.CookieBannerVersion{
|
|
ID: version.ID,
|
|
Version: version.Version,
|
|
State: string(version.State),
|
|
CreatedAt: version.CreatedAt,
|
|
UpdatedAt: version.UpdatedAt,
|
|
},
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// CreateCookieCategory is the resolver for the createCookieCategory field.
|
|
func (r *mutationResolver) CreateCookieCategory(ctx context.Context, input types.CreateCookieCategoryInput) (*types.CreateCookieCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieCategoryCreate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
category, err := r.cookieBanner.CreateCookieCategory(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.CreateCookieCategoryRequest{
|
|
CookieBannerID: input.CookieBannerID,
|
|
Name: input.Name,
|
|
Slug: input.Slug,
|
|
Description: input.Description,
|
|
Rank: input.Rank,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrCategorySlugAlreadyExists) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot create cookie category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.CreateCookieCategoryPayload{
|
|
CookieCategoryEdge: types.NewCookieCategoryEdge(category, coredata.CookieCategoryOrderFieldRank),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateCookieCategory is the resolver for the updateCookieCategory field.
|
|
func (r *mutationResolver) UpdateCookieCategory(ctx context.Context, input types.UpdateCookieCategoryInput) (*types.UpdateCookieCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
|
|
|
var gcmConsentTypes *[]string
|
|
if input.GcmConsentTypes != nil {
|
|
gcmConsentTypes = &input.GcmConsentTypes
|
|
}
|
|
|
|
category, err := r.cookieBanner.UpdateCookieCategory(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.UpdateCookieCategoryRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
Name: input.Name,
|
|
Slug: input.Slug,
|
|
Description: input.Description,
|
|
GCMConsentTypes: gcmConsentTypes,
|
|
PostHogConsent: input.PosthogConsent,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCategoryNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrCategorySlugAlreadyExists) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrPostHogConsentKindInvalid) {
|
|
return nil, gqlutils.Invalid(ctx, err)
|
|
}
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot update cookie category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerScope := coredata.NewScopeFromObjectID(category.CookieBannerID)
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, category.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.UpdateCookieCategoryPayload{
|
|
CookieCategory: types.NewCookieCategory(category),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteCookieCategory is the resolver for the deleteCookieCategory field.
|
|
func (r *mutationResolver) DeleteCookieCategory(ctx context.Context, input types.DeleteCookieCategoryInput) (*types.DeleteCookieCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionCookieCategoryDelete); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
|
|
|
category, err := r.cookieBanner.GetCookieCategory(ctx, scope, input.CookieCategoryID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCategoryNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerID := category.CookieBannerID
|
|
|
|
err = r.cookieBanner.DeleteCookieCategory(ctx, scope, input.CookieCategoryID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCategoryNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
if errors.Is(err, cookiebanner.ErrCannotDeleteSystemCategory) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot delete cookie category", 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.DeleteCookieCategoryPayload{
|
|
DeletedCookieCategoryID: input.CookieCategoryID,
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// ReorderCookieCategory is the resolver for the reorderCookieCategory field.
|
|
func (r *mutationResolver) ReorderCookieCategory(ctx context.Context, input types.ReorderCookieCategoryInput) (*types.ReorderCookieCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
|
|
|
banner, err := r.cookieBanner.ReorderCookieCategory(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.ReorderCookieCategoryRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
Rank: input.Rank,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCategoryNotFound) {
|
|
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 reorder cookie category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.ReorderCookieCategoryPayload{
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// UpsertCookieBannerTranslation is the resolver for the upsertCookieBannerTranslation field.
|
|
func (r *mutationResolver) UpsertCookieBannerTranslation(ctx context.Context, input types.UpsertCookieBannerTranslationInput) (*types.UpsertCookieBannerTranslationPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieBannerID, probo.ActionCookieBannerUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieBannerID)
|
|
|
|
translation, err := r.cookieBanner.UpsertCookieBannerTranslation(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.UpsertCookieBannerTranslationRequest{
|
|
CookieBannerID: input.CookieBannerID,
|
|
Language: input.Language,
|
|
Translations: json.RawMessage(input.Translations),
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrBannerNotFound) {
|
|
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 upsert cookie banner translation", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, scope, input.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot load cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.UpsertCookieBannerTranslationPayload{
|
|
CookieBannerTranslation: types.NewCookieBannerTranslation(translation),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// CreateTrackerPattern is the resolver for the createTrackerPattern field.
|
|
func (r *mutationResolver) CreateTrackerPattern(ctx context.Context, input types.CreateTrackerPatternInput) (*types.CreateTrackerPatternPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionTrackerPatternCreate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
|
|
|
trackerType := coredata.TrackerTypeCookie
|
|
if input.TrackerType != nil {
|
|
trackerType = *input.TrackerType
|
|
}
|
|
|
|
var description string
|
|
if input.Description != nil {
|
|
description = *input.Description
|
|
}
|
|
|
|
pattern, err := r.cookieBanner.CreateTrackerPattern(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.CreateTrackerPatternRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
TrackerType: trackerType,
|
|
Pattern: input.Pattern,
|
|
MatchType: input.MatchType,
|
|
DisplayName: input.DisplayName,
|
|
MaxAgeSeconds: input.MaxAgeSeconds,
|
|
Description: description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrPatternAlreadyExists) {
|
|
return nil, gqlutils.Conflictf(ctx, "a pattern with this name 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 pattern", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerScope := coredata.NewScopeFromObjectID(pattern.CookieBannerID)
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, pattern.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.CreateTrackerPatternPayload{
|
|
TrackerPatternEdge: types.NewTrackerPatternEdge(pattern, coredata.TrackerPatternOrderFieldCreatedAt),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateTrackerPattern is the resolver for the updateTrackerPattern field.
|
|
func (r *mutationResolver) UpdateTrackerPattern(ctx context.Context, input types.UpdateTrackerPatternInput) (*types.UpdateTrackerPatternPayload, error) {
|
|
if err := r.authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.TrackerPatternID)
|
|
|
|
pattern, err := r.cookieBanner.UpdateTrackerPattern(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.UpdateTrackerPatternRequest{
|
|
TrackerPatternID: input.TrackerPatternID,
|
|
MaxAgeSeconds: gqlutils.UnwrapOmittable(input.MaxAgeSeconds),
|
|
Description: input.Description,
|
|
Excluded: input.Excluded,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrTrackerPatternNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot update tracker pattern", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerScope := coredata.NewScopeFromObjectID(pattern.CookieBannerID)
|
|
banner, err := r.cookieBanner.GetCookieBanner(ctx, bannerScope, pattern.CookieBannerID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie banner", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.UpdateTrackerPatternPayload{
|
|
TrackerPattern: types.NewTrackerPatternNode(pattern),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteTrackerPattern is the resolver for the deleteTrackerPattern field.
|
|
func (r *mutationResolver) DeleteTrackerPattern(ctx context.Context, input types.DeleteTrackerPatternInput) (*types.DeleteTrackerPatternPayload, error) {
|
|
if err := r.authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternDelete); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.TrackerPatternID)
|
|
|
|
pattern, err := r.cookieBanner.GetTrackerPattern(ctx, scope, input.TrackerPatternID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrTrackerPatternNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot get tracker pattern", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerID := pattern.CookieBannerID
|
|
|
|
if err := r.cookieBanner.DeleteTrackerPattern(ctx, scope, input.TrackerPatternID); err != nil {
|
|
if errors.Is(err, cookiebanner.ErrTrackerPatternNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot delete tracker pattern", 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.DeleteTrackerPatternPayload{
|
|
DeletedTrackerPatternID: input.TrackerPatternID,
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// MoveTrackerPatternToCategory is the resolver for the moveTrackerPatternToCategory field.
|
|
func (r *mutationResolver) MoveTrackerPatternToCategory(ctx context.Context, input types.MoveTrackerPatternToCategoryInput) (*types.MoveTrackerPatternToCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.TrackerPatternID, probo.ActionTrackerPatternUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := r.authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.TrackerPatternID)
|
|
|
|
result, err := r.cookieBanner.MoveTrackerPatternToCategory(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.MoveTrackerPatternToCategoryRequest{
|
|
TrackerPatternID: input.TrackerPatternID,
|
|
TargetCookieCategoryID: input.TargetCookieCategoryID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
switch {
|
|
case errors.Is(err, cookiebanner.ErrCategoryNotFound):
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
case errors.Is(err, cookiebanner.ErrTrackerPatternNotFound):
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
case errors.Is(err, cookiebanner.ErrCategoriesBannerMismatch):
|
|
return nil, gqlutils.NotFoundf(ctx, "tracker pattern or target category not found")
|
|
default:
|
|
r.logger.ErrorCtx(ctx, "cannot move tracker pattern to category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
}
|
|
|
|
return &types.MoveTrackerPatternToCategoryPayload{
|
|
TrackerPattern: types.NewTrackerPatternNode(result.TrackerPattern),
|
|
CookieBanner: types.NewCookieBanner(result.Banner),
|
|
}, 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")
|
|
case errors.Is(err, cookiebanner.ErrSameResourceCategoryMove):
|
|
return nil, gqlutils.Invalidf(ctx, "tracker resource is already in the target category")
|
|
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 {
|
|
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
|
|
}
|
|
|
|
// DetectedCount is the resolver for the detectedCount field.
|
|
func (r *trackerPatternResolver) DetectedCount(ctx context.Context, obj *types.TrackerPattern) (int, error) {
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
count, err := r.cookieBanner.CountDetectedTrackersByPatternID(ctx, scope, obj.ID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count detected trackers", log.Error(err))
|
|
return 0, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// Permission is the resolver for the permission field.
|
|
func (r *trackerPatternResolver) Permission(ctx context.Context, obj *types.TrackerPattern, action string) (bool, error) {
|
|
return r.Resolver.Permission(ctx, obj, action)
|
|
}
|
|
|
|
// TotalCount is the resolver for the totalCount field.
|
|
func (r *trackerPatternConnectionResolver) TotalCount(ctx context.Context, obj *types.TrackerPatternConnection) (int, error) {
|
|
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
|
|
|
var count int
|
|
var err error
|
|
|
|
switch obj.Resolver.(type) {
|
|
case *cookieCategoryResolver:
|
|
count, err = r.cookieBanner.CountTrackerPatternsForCategory(ctx, scope, obj.ParentID)
|
|
default:
|
|
filter := coredata.NewTrackerPatternFilter(nil, nil, nil)
|
|
if obj.Filter != nil {
|
|
filter = filter.WithQuery(obj.Filter.Query).WithSource(obj.Filter.Source).WithTrackerType(obj.Filter.TrackerType)
|
|
}
|
|
count, err = r.cookieBanner.CountUncategorisedTrackerPatterns(ctx, scope, obj.ParentID, filter)
|
|
}
|
|
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count tracker patterns", log.Error(err))
|
|
return 0, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
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} }
|
|
|
|
// CookieBannerConnection returns schema.CookieBannerConnectionResolver implementation.
|
|
func (r *Resolver) CookieBannerConnection() schema.CookieBannerConnectionResolver {
|
|
return &cookieBannerConnectionResolver{r}
|
|
}
|
|
|
|
// CookieBannerVersion returns schema.CookieBannerVersionResolver implementation.
|
|
func (r *Resolver) CookieBannerVersion() schema.CookieBannerVersionResolver {
|
|
return &cookieBannerVersionResolver{r}
|
|
}
|
|
|
|
// CookieCategory returns schema.CookieCategoryResolver implementation.
|
|
func (r *Resolver) CookieCategory() schema.CookieCategoryResolver { return &cookieCategoryResolver{r} }
|
|
|
|
// CookieCategoryConnection returns schema.CookieCategoryConnectionResolver implementation.
|
|
func (r *Resolver) CookieCategoryConnection() schema.CookieCategoryConnectionResolver {
|
|
return &cookieCategoryConnectionResolver{r}
|
|
}
|
|
|
|
// TrackerPattern returns schema.TrackerPatternResolver implementation.
|
|
func (r *Resolver) TrackerPattern() schema.TrackerPatternResolver { return &trackerPatternResolver{r} }
|
|
|
|
// TrackerPatternConnection returns schema.TrackerPatternConnectionResolver implementation.
|
|
func (r *Resolver) TrackerPatternConnection() schema.TrackerPatternConnectionResolver {
|
|
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 }
|
|
type cookieCategoryResolver struct{ *Resolver }
|
|
type cookieCategoryConnectionResolver struct{ *Resolver }
|
|
type trackerPatternResolver struct{ *Resolver }
|
|
type trackerPatternConnectionResolver struct{ *Resolver }
|
|
type trackerResourceResolver struct{ *Resolver }
|
|
type trackerResourceConnectionResolver struct{ *Resolver }
|