Replace the free-form duration TEXT column with a nullable max_age_seconds INTEGER on both cookies and cookie_patterns tables. The SDK detector now sends raw seconds instead of humanized strings, eliminating locale-dependent comparisons in the pattern merge worker. Humanization happens at display time in the widget and console UI. Signed-off-by: Émile Ré <emile@getprobo.com>
990 lines
35 KiB
Go
990 lines
35 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.87
|
|
|
|
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
|
|
}
|
|
|
|
// 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) (*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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// CookiePatterns is the resolver for the cookiePatterns field.
|
|
func (r *cookieCategoryResolver) CookiePatterns(ctx context.Context, obj *types.CookieCategory, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.CookiePatternOrderBy) (*types.CookiePatternConnection, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookiePatternList); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.CookiePatternOrderField]{
|
|
Field: coredata.CookiePatternOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionAsc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.CookiePatternOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
patterns, err := r.cookieBanner.ListCookiePatternsForCategory(ctx, scope, obj.ID, cursor)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list cookie patterns", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
p := page.NewPage(patterns, cursor)
|
|
|
|
return types.NewCookiePatternConnection(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
|
|
}
|
|
|
|
// CookieCategory is the resolver for the cookieCategory field.
|
|
func (r *cookiePatternResolver) CookieCategory(ctx context.Context, obj *types.CookiePattern) (*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
|
|
}
|
|
|
|
// CookieCount is the resolver for the cookieCount field.
|
|
func (r *cookiePatternResolver) CookieCount(ctx context.Context, obj *types.CookiePattern) (int, error) {
|
|
if err := r.authorize(ctx, obj.ID, probo.ActionCookiePatternGet); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ID)
|
|
|
|
count, err := r.cookieBanner.CountCookiesForPattern(ctx, scope, obj.ID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count cookies for pattern", log.Error(err))
|
|
return 0, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// Permission is the resolver for the permission field.
|
|
func (r *cookiePatternResolver) Permission(ctx context.Context, obj *types.CookiePattern, action string) (bool, error) {
|
|
return r.Resolver.Permission(ctx, obj, action)
|
|
}
|
|
|
|
// TotalCount is the resolver for the totalCount field.
|
|
func (r *cookiePatternConnectionResolver) TotalCount(ctx context.Context, obj *types.CookiePatternConnection) (int, error) {
|
|
if err := r.authorize(ctx, obj.ParentID, probo.ActionCookiePatternList); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(obj.ParentID)
|
|
|
|
count, err := r.cookieBanner.CountCookiePatternsForCategory(ctx, scope, obj.ParentID)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot count cookie patterns", 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
|
|
}
|
|
|
|
// CreateCookiePattern is the resolver for the createCookiePattern field.
|
|
func (r *mutationResolver) CreateCookiePattern(ctx context.Context, input types.CreateCookiePatternInput) (*types.CreateCookiePatternPayload, error) {
|
|
if err := r.authorize(ctx, input.CookieCategoryID, probo.ActionCookiePatternCreate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookieCategoryID)
|
|
|
|
pattern, err := r.cookieBanner.CreateCookiePattern(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.CreateCookiePatternRequest{
|
|
CookieCategoryID: input.CookieCategoryID,
|
|
Pattern: input.Pattern,
|
|
MatchType: input.MatchType,
|
|
DisplayName: input.DisplayName,
|
|
MaxAgeSeconds: input.MaxAgeSeconds,
|
|
Description: input.Description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrPatternAlreadyExists) {
|
|
return nil, gqlutils.Conflict(ctx, err)
|
|
}
|
|
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 create cookie 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.CreateCookiePatternPayload{
|
|
CookiePatternEdge: types.NewCookiePatternEdge(pattern, coredata.CookiePatternOrderFieldCreatedAt),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateCookiePattern is the resolver for the updateCookiePattern field.
|
|
func (r *mutationResolver) UpdateCookiePattern(ctx context.Context, input types.UpdateCookiePatternInput) (*types.UpdateCookiePatternPayload, error) {
|
|
if err := r.authorize(ctx, input.CookiePatternID, probo.ActionCookiePatternUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookiePatternID)
|
|
|
|
pattern, err := r.cookieBanner.UpdateCookiePattern(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.UpdateCookiePatternRequest{
|
|
CookiePatternID: input.CookiePatternID,
|
|
DisplayName: input.DisplayName,
|
|
MaxAgeSeconds: gqlutils.UnwrapOmittable(input.MaxAgeSeconds),
|
|
Description: input.Description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCookiePatternNotFound) {
|
|
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 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.UpdateCookiePatternPayload{
|
|
CookiePattern: types.NewCookiePattern(pattern),
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteCookiePattern is the resolver for the deleteCookiePattern field.
|
|
func (r *mutationResolver) DeleteCookiePattern(ctx context.Context, input types.DeleteCookiePatternInput) (*types.DeleteCookiePatternPayload, error) {
|
|
if err := r.authorize(ctx, input.CookiePatternID, probo.ActionCookiePatternDelete); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookiePatternID)
|
|
|
|
pattern, err := r.cookieBanner.GetCookiePattern(ctx, scope, input.CookiePatternID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCookieNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot get cookie pattern", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
bannerID := pattern.CookieBannerID
|
|
|
|
err = r.cookieBanner.DeleteCookiePattern(ctx, scope, input.CookiePatternID)
|
|
if err != nil {
|
|
if errors.Is(err, cookiebanner.ErrCookiePatternNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot delete cookie 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.DeleteCookiePatternPayload{
|
|
DeletedCookiePatternID: input.CookiePatternID,
|
|
CookieBanner: types.NewCookieBanner(banner),
|
|
}, nil
|
|
}
|
|
|
|
// MoveCookiePatternToCategory is the resolver for the moveCookiePatternToCategory field.
|
|
func (r *mutationResolver) MoveCookiePatternToCategory(ctx context.Context, input types.MoveCookiePatternToCategoryInput) (*types.MoveCookiePatternToCategoryPayload, error) {
|
|
if err := r.authorize(ctx, input.CookiePatternID, probo.ActionCookiePatternUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := r.authorize(ctx, input.TargetCookieCategoryID, probo.ActionCookieCategoryUpdate); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scope := coredata.NewScopeFromObjectID(input.CookiePatternID)
|
|
|
|
result, err := r.cookieBanner.MoveCookiePatternToCategory(
|
|
ctx,
|
|
scope,
|
|
cookiebanner.MoveCookiePatternToCategoryRequest{
|
|
CookiePatternID: input.CookiePatternID,
|
|
TargetCookieCategoryID: input.TargetCookieCategoryID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
switch {
|
|
case errors.Is(err, cookiebanner.ErrCategoryNotFound):
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
case errors.Is(err, cookiebanner.ErrCookiePatternNotFound):
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
case errors.Is(err, cookiebanner.ErrCategoriesBannerMismatch):
|
|
return nil, gqlutils.NotFoundf(ctx, "cookie pattern or target category not found")
|
|
default:
|
|
if validationErrors, ok := errors.AsType[validator.ValidationErrors](err); ok {
|
|
return nil, gqlutils.InvalidValidationErrors(ctx, validationErrors)
|
|
}
|
|
r.logger.ErrorCtx(ctx, "cannot move cookie pattern to category", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
}
|
|
|
|
return &types.MoveCookiePatternToCategoryPayload{
|
|
CookiePattern: types.NewCookiePattern(result.CookiePattern),
|
|
CookieBanner: types.NewCookieBanner(result.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
|
|
}
|
|
|
|
// 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}
|
|
}
|
|
|
|
// CookiePattern returns schema.CookiePatternResolver implementation.
|
|
func (r *Resolver) CookiePattern() schema.CookiePatternResolver { return &cookiePatternResolver{r} }
|
|
|
|
// CookiePatternConnection returns schema.CookiePatternConnectionResolver implementation.
|
|
func (r *Resolver) CookiePatternConnection() schema.CookiePatternConnectionResolver {
|
|
return &cookiePatternConnectionResolver{r}
|
|
}
|
|
|
|
type cookieBannerResolver struct{ *Resolver }
|
|
type cookieBannerConnectionResolver struct{ *Resolver }
|
|
type cookieBannerVersionResolver struct{ *Resolver }
|
|
type cookieCategoryResolver struct{ *Resolver }
|
|
type cookieCategoryConnectionResolver struct{ *Resolver }
|
|
type cookiePatternResolver struct{ *Resolver }
|
|
type cookiePatternConnectionResolver struct{ *Resolver }
|