Add consent record operations and rename ConsentRecord to CookieConsentRecord

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-10 17:31:59 +04:00
parent 327652163f
commit c594b10e9f
3 changed files with 125 additions and 11 deletions

View File

@@ -16,6 +16,7 @@ package cookiebanner
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
@@ -82,6 +83,15 @@ type (
Rank *int
Cookies *coredata.CookieItems
}
CreateCookieConsentRecordRequest struct {
CookieBannerID gid.GID
VisitorID string
IPAddress *string
UserAgent *string
ConsentData json.RawMessage
Action coredata.CookieConsentAction
}
)
func (r *CreateCookieBannerRequest) Validate() error {
@@ -132,6 +142,16 @@ func (r *UpdateCookieCategoryRequest) Validate() error {
return v.Error()
}
func (r *CreateCookieConsentRecordRequest) Validate() error {
v := validator.New()
v.Check(r.CookieBannerID, "cookie_banner_id", validator.Required(), validator.GID(coredata.CookieBannerEntityType))
v.Check(r.VisitorID, "visitor_id", validator.Required(), validator.NotEmpty())
v.Check(r.Action, "action", validator.Required(), validator.OneOfSlice(coredata.CookieConsentActions()))
return v.Error()
}
func (c *Client) CreateCookieBanner(
ctx context.Context,
scope coredata.Scoper,
@@ -643,3 +663,97 @@ func (c *Client) DeleteCookieCategory(
},
)
}
func (c *Client) CreateCookieConsentRecord(
ctx context.Context,
scope coredata.Scoper,
req CreateCookieConsentRecordRequest,
) (*coredata.CookieConsentRecord, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
var record *coredata.CookieConsentRecord
err := c.pg.WithTx(
ctx,
func(ctx context.Context, tx pg.Tx) error {
record = &coredata.CookieConsentRecord{
ID: gid.New(scope.GetTenantID(), coredata.CookieConsentRecordEntityType),
CookieBannerID: req.CookieBannerID,
VisitorID: req.VisitorID,
IPAddress: req.IPAddress,
UserAgent: req.UserAgent,
ConsentData: req.ConsentData,
Action: req.Action,
CreatedAt: time.Now(),
}
if err := record.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert consent record: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return record, nil
}
func (c *Client) ListCookieConsentRecordsForBanner(
ctx context.Context,
scope coredata.Scoper,
bannerID gid.GID,
cursor *page.Cursor[coredata.CookieConsentRecordOrderField],
filter *coredata.CookieConsentRecordFilter,
) (coredata.CookieConsentRecords, error) {
var records coredata.CookieConsentRecords
err := c.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
if err := records.LoadByCookieBannerID(ctx, conn, scope, bannerID, cursor, filter); err != nil {
return fmt.Errorf("cannot list consent records: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return records, nil
}
func (c *Client) CountCookieConsentRecordsForBanner(
ctx context.Context,
scope coredata.Scoper,
bannerID gid.GID,
filter *coredata.CookieConsentRecordFilter,
) (int, error) {
var count int
err := c.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var records coredata.CookieConsentRecords
var err error
count, err = records.CountByCookieBannerID(ctx, conn, scope, bannerID, filter)
if err != nil {
return fmt.Errorf("cannot count consent records: %w", err)
}
return nil
},
)
if err != nil {
return 0, err
}
return count, nil
}

View File

@@ -29,7 +29,7 @@ import (
)
type (
ConsentRecord struct {
CookieConsentRecord struct {
ID gid.GID `db:"id"`
CookieBannerID gid.GID `db:"cookie_banner_id"`
VisitorID string `db:"visitor_id"`
@@ -40,10 +40,10 @@ type (
CreatedAt time.Time `db:"created_at"`
}
ConsentRecords []*ConsentRecord
CookieConsentRecords []*CookieConsentRecord
)
func (r *ConsentRecord) CursorKey(field CookieConsentRecordOrderField) page.CursorKey {
func (r *CookieConsentRecord) CursorKey(field CookieConsentRecordOrderField) page.CursorKey {
switch field {
case CookieConsentRecordOrderFieldCreatedAt:
return page.NewCursorKey(r.ID, r.CreatedAt)
@@ -52,7 +52,7 @@ func (r *ConsentRecord) CursorKey(field CookieConsentRecordOrderField) page.Curs
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (r *ConsentRecord) AuthorizationAttributes(ctx context.Context, conn pg.Querier) (map[string]string, error) {
func (r *CookieConsentRecord) AuthorizationAttributes(ctx context.Context, conn pg.Querier) (map[string]string, error) {
q := `
SELECT cb.organization_id
FROM cookie_consent_records cr
@@ -72,7 +72,7 @@ LIMIT 1;
return map[string]string{"organization_id": organizationID.String()}, nil
}
func (r *ConsentRecords) LoadByCookieBannerID(
func (r *CookieConsentRecords) LoadByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
@@ -111,7 +111,7 @@ WHERE
return fmt.Errorf("cannot query consent records: %w", err)
}
records, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ConsentRecord])
records, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[CookieConsentRecord])
if err != nil {
return fmt.Errorf("cannot collect consent records: %w", err)
}
@@ -121,7 +121,7 @@ WHERE
return nil
}
func (r *ConsentRecords) CountByCookieBannerID(
func (r *CookieConsentRecords) CountByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
@@ -155,7 +155,7 @@ WHERE
return count, nil
}
func (r *ConsentRecord) Insert(
func (r *CookieConsentRecord) Insert(
ctx context.Context,
tx pg.Tx,
scope Scoper,

View File

@@ -100,7 +100,7 @@ const (
AccessEntryDecisionHistoryEntityType uint16 = 74
CookieBannerEntityType uint16 = 75
CookieCategoryEntityType uint16 = 76
ConsentRecordEntityType uint16 = 77
CookieConsentRecordEntityType uint16 = 77
)
func NewEntityFromID(id gid.GID) (any, bool) {
@@ -251,8 +251,8 @@ func NewEntityFromID(id gid.GID) (any, bool) {
return &CookieBanner{ID: id}, true
case CookieCategoryEntityType:
return &CookieCategory{ID: id}, true
case ConsentRecordEntityType:
return &ConsentRecord{ID: id}, true
case CookieConsentRecordEntityType:
return &CookieConsentRecord{ID: id}, true
default:
return nil, false
}