From 84632fe7953b4098af17430600f572e0131e44d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Mon, 27 Apr 2026 15:09:21 +0400 Subject: [PATCH] Filter consent records by version number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the opaque cookieBannerVersionId filter with an integer version filter. The SQL filter now resolves the version number via a subquery against cookie_banner_versions. Also fix the CookieBannerVersion resolver on consent records to load the full version from the database instead of returning a stub with only the ID set (which caused the version to always display as 0). Signed-off-by: Émile Ré --- .../CookieBannerConsentRecordsPage.tsx | 36 ++++++++++++------- .../_components/ConsentRecordRow.tsx | 1 - pkg/coredata/cookie_consent_record_filter.go | 34 +++++++++--------- .../api/console/v1/cookie_banner_resolvers.go | 11 +++--- .../v1/cookie_consent_record_resolvers.go | 29 ++++++++++++++- .../v1/graphql/cookie_consent_record.graphql | 2 +- 6 files changed, 75 insertions(+), 38 deletions(-) diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPage.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPage.tsx index 127da970a..6efff3dac 100644 --- a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPage.tsx +++ b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPage.tsx @@ -64,7 +64,7 @@ const consentRecordsFragment = graphql` last: { type: "Int", defaultValue: null } action: { type: "CookieConsentAction", defaultValue: null } visitorId: { type: "String", defaultValue: null } - cookieBannerVersionId: { type: "ID", defaultValue: null } + version: { type: "Int", defaultValue: null } ) { consentRecords( first: $first @@ -75,7 +75,7 @@ const consentRecordsFragment = graphql` filter: { action: $action visitorId: $visitorId - cookieBannerVersionId: $cookieBannerVersionId + version: $version } ) @connection( @@ -109,7 +109,8 @@ export default function CookieBannerConsentRecordsPage({ const [isPending, startTransition] = useTransition(); const [actionFilter, setActionFilter] = useState(null); const [visitorIdFilter, setVisitorIdFilter] = useState(""); - const [versionIdFilter, setVersionIdFilter] = useState(""); + const [versionFilter, setVersionFilter] = useState(""); + const [versionError, setVersionError] = useState(false); const { data: fragmentData, ...pagination } = usePaginationFragment< CookieBannerConsentRecordsPageRefetchQuery, @@ -124,7 +125,7 @@ export default function CookieBannerConsentRecordsPage({ { action: actionFilter, visitorId: visitorIdFilter || null, - cookieBannerVersionId: versionIdFilter || null, + version: versionFilter ? parseInt(versionFilter, 10) : null, ...overrides, }, { fetchPolicy: "network-only" }, @@ -142,8 +143,13 @@ export default function CookieBannerConsentRecordsPage({ refetchFilters({ visitorId: visitorIdFilter || null }); }; - const handleVersionIdSubmit = () => { - refetchFilters({ cookieBannerVersionId: versionIdFilter || null }); + const handleVersionSubmit = () => { + if (versionFilter && !/^\d+$/.test(versionFilter)) { + setVersionError(true); + return; + } + setVersionError(false); + refetchFilters({ version: versionFilter ? parseInt(versionFilter, 10) : null }); }; const refetchWithFilters: ComponentProps["refetch"] = ({ order }) => { @@ -151,7 +157,7 @@ export default function CookieBannerConsentRecordsPage({ order: { direction: order.direction, field: order.field as CookieConsentRecordOrderField }, action: actionFilter, visitorId: visitorIdFilter || null, - cookieBannerVersionId: versionIdFilter || null, + version: versionFilter ? parseInt(versionFilter, 10) : null, }); }; @@ -177,11 +183,15 @@ export default function CookieBannerConsentRecordsPage({ className="w-48" /> setVersionIdFilter(e.target.value)} - onKeyDown={e => e.key === "Enter" && handleVersionIdSubmit()} - onBlur={handleVersionIdSubmit} + placeholder={__("Banner version")} + value={versionFilter} + invalid={versionError} + onChange={(e) => { + setVersionFilter(e.target.value); + setVersionError(false); + }} + onKeyDown={e => e.key === "Enter" && handleVersionSubmit()} + onBlur={handleVersionSubmit} className="w-48" /> @@ -198,7 +208,7 @@ export default function CookieBannerConsentRecordsPage({ {__("Visitor ID")} {__("Action")} - {__("Version")} + {__("Banner Version")} {__("IP Address")} {__("SDK Version")} {__("Consent Data")} diff --git a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/_components/ConsentRecordRow.tsx b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/_components/ConsentRecordRow.tsx index 118758246..cdff4078d 100644 --- a/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/_components/ConsentRecordRow.tsx +++ b/apps/console/src/pages/organizations/cookie-banners/configuration/consent-records/_components/ConsentRecordRow.tsx @@ -86,7 +86,6 @@ export function ConsentRecordRow({ recordKey }: ConsentRecordRowProps) { {record.cookieBannerVersion ? ( - v {record.cookieBannerVersion.version} ) diff --git a/pkg/coredata/cookie_consent_record_filter.go b/pkg/coredata/cookie_consent_record_filter.go index 6ae22c1fd..01c6c761c 100644 --- a/pkg/coredata/cookie_consent_record_filter.go +++ b/pkg/coredata/cookie_consent_record_filter.go @@ -16,25 +16,23 @@ package coredata import ( "github.com/jackc/pgx/v5" - - "go.probo.inc/probo/pkg/gid" ) type CookieConsentRecordFilter struct { - action *CookieConsentAction - visitorID *string - cookieBannerVersionID *gid.GID + action *CookieConsentAction + visitorID *string + version *int } func NewCookieConsentRecordFilter( action *CookieConsentAction, visitorID *string, - cookieBannerVersionID *gid.GID, + version *int, ) *CookieConsentRecordFilter { return &CookieConsentRecordFilter{ - action: action, - visitorID: visitorID, - cookieBannerVersionID: cookieBannerVersionID, + action: action, + visitorID: visitorID, + version: version, } } @@ -58,8 +56,12 @@ AND AND ( CASE - WHEN @filter_cookie_banner_version_id::text IS NOT NULL THEN - cookie_banner_version_id = @filter_cookie_banner_version_id + WHEN @filter_version::int IS NOT NULL THEN + cookie_banner_version_id = ( + SELECT id FROM cookie_banner_versions + WHERE cookie_banner_id = cookie_consent_records.cookie_banner_id + AND version = @filter_version + ) ELSE TRUE END )` @@ -67,9 +69,9 @@ AND func (f *CookieConsentRecordFilter) SQLArguments() pgx.StrictNamedArgs { args := pgx.StrictNamedArgs{ - "filter_action": nil, - "filter_visitor_id": nil, - "filter_cookie_banner_version_id": nil, + "filter_action": nil, + "filter_visitor_id": nil, + "filter_version": nil, } if f.action != nil { @@ -80,8 +82,8 @@ func (f *CookieConsentRecordFilter) SQLArguments() pgx.StrictNamedArgs { args["filter_visitor_id"] = *f.visitorID } - if f.cookieBannerVersionID != nil { - args["filter_cookie_banner_version_id"] = f.cookieBannerVersionID.String() + if f.version != nil { + args["filter_version"] = *f.version } return args diff --git a/pkg/server/api/console/v1/cookie_banner_resolvers.go b/pkg/server/api/console/v1/cookie_banner_resolvers.go index 14ceb2dd3..2f9d9ed91 100644 --- a/pkg/server/api/console/v1/cookie_banner_resolvers.go +++ b/pkg/server/api/console/v1/cookie_banner_resolvers.go @@ -13,7 +13,6 @@ import ( "go.gearno.de/kit/log" "go.probo.inc/probo/pkg/cookiebanner" "go.probo.inc/probo/pkg/coredata" - "go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/probo" "go.probo.inc/probo/pkg/server/api/console/v1/schema" @@ -144,17 +143,17 @@ func (r *cookieBannerResolver) ConsentRecords(ctx context.Context, obj *types.Co scope := coredata.NewScopeFromObjectID(obj.ID) var ( - action *coredata.CookieConsentAction - visitorID *string - cookieBannerVersionID *gid.GID + action *coredata.CookieConsentAction + visitorID *string + version *int ) if filter != nil { action = filter.Action visitorID = filter.VisitorID - cookieBannerVersionID = filter.CookieBannerVersionID + version = filter.Version } - coredataFilter := coredata.NewCookieConsentRecordFilter(action, visitorID, cookieBannerVersionID) + coredataFilter := coredata.NewCookieConsentRecordFilter(action, visitorID, version) records, err := r.cookieBanner.ListCookieConsentRecordsForBanner(ctx, scope, obj.ID, cursor, coredataFilter) if err != nil { diff --git a/pkg/server/api/console/v1/cookie_consent_record_resolvers.go b/pkg/server/api/console/v1/cookie_consent_record_resolvers.go index 0b56b9863..ca6349c50 100644 --- a/pkg/server/api/console/v1/cookie_consent_record_resolvers.go +++ b/pkg/server/api/console/v1/cookie_consent_record_resolvers.go @@ -7,8 +7,10 @@ package console_v1 import ( "context" + "errors" "go.gearno.de/kit/log" + "go.probo.inc/probo/pkg/cookiebanner" "go.probo.inc/probo/pkg/coredata" "go.probo.inc/probo/pkg/probo" "go.probo.inc/probo/pkg/server/api/console/v1/schema" @@ -23,7 +25,32 @@ func (r *cookieConsentRecordResolver) CookieBanner(ctx context.Context, obj *typ // CookieBannerVersion is the resolver for the cookieBannerVersion field. func (r *cookieConsentRecordResolver) CookieBannerVersion(ctx context.Context, obj *types.CookieConsentRecord) (*types.CookieBannerVersion, error) { - return obj.CookieBannerVersion, nil + if obj.CookieBannerVersion == nil { + return nil, nil + } + + if err := r.authorize(ctx, obj.CookieBannerVersion.ID, probo.ActionCookieBannerVersionGet); err != nil { + return nil, err + } + + scope := coredata.NewScopeFromObjectID(obj.CookieBannerVersion.ID) + + version, err := r.cookieBanner.GetCookieBannerVersion(ctx, scope, obj.CookieBannerVersion.ID) + if err != nil { + if errors.Is(err, cookiebanner.ErrVersionNotFound) { + return nil, nil + } + r.logger.ErrorCtx(ctx, "cannot get cookie banner version", log.Error(err)) + return nil, gqlutils.Internal(ctx) + } + + return &types.CookieBannerVersion{ + ID: version.ID, + Version: version.Version, + State: string(version.State), + CreatedAt: version.CreatedAt, + UpdatedAt: version.UpdatedAt, + }, nil } // TotalCount is the resolver for the totalCount field. diff --git a/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql b/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql index 34264b37f..4cc558455 100644 --- a/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql +++ b/pkg/server/api/console/v1/graphql/cookie_consent_record.graphql @@ -53,7 +53,7 @@ input CookieConsentRecordOrder input CookieConsentRecordFilter { action: CookieConsentAction visitorId: String - cookieBannerVersionId: ID + version: Int } type CookieConsentRecord implements Node {