Surface regulation and user agent across consent record API layers
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -147,7 +147,7 @@ export default function CookieBannerConsentRecordPage({
|
|||||||
</span>
|
</span>
|
||||||
</PropertyRow>
|
</PropertyRow>
|
||||||
<PropertyRow label={__("User Agent")}>
|
<PropertyRow label={__("User Agent")}>
|
||||||
<span className="font-mono text-sm truncate max-w-md" title={record.userAgent ?? undefined}>
|
<span className="font-mono text-sm break-all">
|
||||||
{record.userAgent ?? "-"}
|
{record.userAgent ?? "-"}
|
||||||
</span>
|
</span>
|
||||||
</PropertyRow>
|
</PropertyRow>
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ type consentRecord struct {
|
|||||||
VisitorID string `json:"visitorId"`
|
VisitorID string `json:"visitorId"`
|
||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
SDKVersion string `json:"sdkVersion"`
|
SDKVersion string `json:"sdkVersion"`
|
||||||
Regulation string `json:"regulation"`
|
Regulation *string `json:"regulation"`
|
||||||
CountryCode string `json:"countryCode"`
|
CountryCode *string `json:"countryCode"`
|
||||||
CreatedAt string `json:"createdAt"`
|
CreatedAt string `json:"createdAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,15 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
|
|||||||
|
|
||||||
rows := make([][]string, 0, len(records))
|
rows := make([][]string, 0, len(records))
|
||||||
for _, r := range records {
|
for _, r := range records {
|
||||||
rows = append(rows, []string{r.ID, r.VisitorID, r.Action, r.SDKVersion, r.Regulation, r.CountryCode, r.CreatedAt})
|
regulation := "-"
|
||||||
|
if r.Regulation != nil {
|
||||||
|
regulation = *r.Regulation
|
||||||
|
}
|
||||||
|
countryCode := "-"
|
||||||
|
if r.CountryCode != nil {
|
||||||
|
countryCode = *r.CountryCode
|
||||||
|
}
|
||||||
|
rows = append(rows, []string{r.ID, r.VisitorID, r.Action, r.SDKVersion, regulation, countryCode, r.CreatedAt})
|
||||||
}
|
}
|
||||||
|
|
||||||
t := cmdutil.NewTable("ID", "VISITOR ID", "ACTION", "SDK VERSION", "REGULATION", "COUNTRY", "CREATED AT").Rows(rows...)
|
t := cmdutil.NewTable("ID", "VISITOR ID", "ACTION", "SDK VERSION", "REGULATION", "COUNTRY", "CREATED AT").Rows(rows...)
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ type viewResponse struct {
|
|||||||
ConsentData string `json:"consentData"`
|
ConsentData string `json:"consentData"`
|
||||||
Action string `json:"action"`
|
Action string `json:"action"`
|
||||||
SdkVersion string `json:"sdkVersion"`
|
SdkVersion string `json:"sdkVersion"`
|
||||||
Regulation string `json:"regulation"`
|
Regulation *string `json:"regulation"`
|
||||||
CountryCode string `json:"countryCode"`
|
CountryCode *string `json:"countryCode"`
|
||||||
CreatedAt string `json:"createdAt"`
|
CreatedAt string `json:"createdAt"`
|
||||||
} `json:"node"`
|
} `json:"node"`
|
||||||
}
|
}
|
||||||
@@ -119,8 +119,12 @@ func NewCmdView(f *cmdutil.Factory) *cobra.Command {
|
|||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Visitor ID:"), v.VisitorID)
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Visitor ID:"), v.VisitorID)
|
||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Action:"), v.Action)
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Action:"), v.Action)
|
||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("SDK Version:"), v.SdkVersion)
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("SDK Version:"), v.SdkVersion)
|
||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Regulation:"), v.Regulation)
|
if v.Regulation != nil {
|
||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Country Code:"), v.CountryCode)
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Regulation:"), *v.Regulation)
|
||||||
|
}
|
||||||
|
if v.CountryCode != nil {
|
||||||
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("Country Code:"), *v.CountryCode)
|
||||||
|
}
|
||||||
if v.IPAddress != nil && *v.IPAddress != "" {
|
if v.IPAddress != nil && *v.IPAddress != "" {
|
||||||
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("IP Address:"), *v.IPAddress)
|
_, _ = fmt.Fprintf(out, "%s%s\n", label.Render("IP Address:"), *v.IPAddress)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ type (
|
|||||||
ConsentData json.RawMessage
|
ConsentData json.RawMessage
|
||||||
Action coredata.CookieConsentAction
|
Action coredata.CookieConsentAction
|
||||||
SdkVersion string
|
SdkVersion string
|
||||||
Regulation Regulation
|
Regulation *Regulation
|
||||||
CountryCode coredata.CountryCode
|
CountryCode *coredata.CountryCode
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectedCookie struct {
|
DetectedCookie struct {
|
||||||
@@ -1847,6 +1847,10 @@ func (s *Service) RecordConsent(
|
|||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if record.Regulation != nil && *record.Regulation == coredata.RegulationNone {
|
||||||
|
record.Regulation = nil
|
||||||
|
}
|
||||||
|
|
||||||
if err := record.Insert(ctx, tx, scope); err != nil {
|
if err := record.Insert(ctx, tx, scope); err != nil {
|
||||||
return fmt.Errorf("cannot insert consent record: %w", err)
|
return fmt.Errorf("cannot insert consent record: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ type (
|
|||||||
ConsentData json.RawMessage `db:"consent_data"`
|
ConsentData json.RawMessage `db:"consent_data"`
|
||||||
Action CookieConsentAction `db:"action"`
|
Action CookieConsentAction `db:"action"`
|
||||||
SdkVersion string `db:"sdk_version"`
|
SdkVersion string `db:"sdk_version"`
|
||||||
Regulation Regulation `db:"regulation"`
|
Regulation *Regulation `db:"regulation"`
|
||||||
CountryCode CountryCode `db:"country_code"`
|
CountryCode *CountryCode `db:"country_code"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
pkg/coredata/migrations/20260507T143000Z.sql
Normal file
22
pkg/coredata/migrations/20260507T143000Z.sql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
-- Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||||
|
--
|
||||||
|
-- Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
-- purpose with or without fee is hereby granted, provided that the above
|
||||||
|
-- copyright notice and this permission notice appear in all copies.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
-- PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
ALTER TABLE cookie_consent_records
|
||||||
|
ALTER COLUMN regulation DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE cookie_consent_records
|
||||||
|
ALTER COLUMN country_code DROP NOT NULL;
|
||||||
|
|
||||||
|
UPDATE cookie_consent_records SET regulation = NULL WHERE regulation = '';
|
||||||
|
UPDATE cookie_consent_records SET country_code = NULL WHERE country_code = '';
|
||||||
@@ -130,8 +130,8 @@ type CookieConsentRecord implements Node {
|
|||||||
consentData: String!
|
consentData: String!
|
||||||
action: CookieConsentAction!
|
action: CookieConsentAction!
|
||||||
sdkVersion: String!
|
sdkVersion: String!
|
||||||
regulation: Regulation!
|
regulation: Regulation
|
||||||
countryCode: CountryCode!
|
countryCode: CountryCode
|
||||||
createdAt: Datetime!
|
createdAt: Datetime!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ func (h *Handler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
lang := r.URL.Query().Get("lang")
|
lang := r.URL.Query().Get("lang")
|
||||||
cc := h.resolveCountryCode(r)
|
cc := h.resolveCountryCode(r)
|
||||||
regulation := cookiebanner.RegulationForCountry(cc)
|
|
||||||
|
var regulation cookiebanner.Regulation
|
||||||
|
if cc != nil {
|
||||||
|
regulation = cookiebanner.RegulationForCountry(*cc)
|
||||||
|
}
|
||||||
|
|
||||||
config, err := h.cookieBannerSvc.GetActiveBannerConfig(r.Context(), bannerID, lang, regulation)
|
config, err := h.cookieBannerSvc.GetActiveBannerConfig(r.Context(), bannerID, lang, regulation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -92,16 +96,16 @@ func (h *Handler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
httpserver.RenderJSON(w, http.StatusOK, config)
|
httpserver.RenderJSON(w, http.StatusOK, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) resolveCountryCode(r *http.Request) coredata.CountryCode {
|
func (h *Handler) resolveCountryCode(r *http.Request) *coredata.CountryCode {
|
||||||
ip := clientip.Extract(r)
|
ip := clientip.Extract(r)
|
||||||
|
|
||||||
cc, err := h.geolocSvc.LookupCountry(r.Context(), ip)
|
cc, err := h.geolocSvc.LookupCountry(r.Context(), ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logger.ErrorCtx(r.Context(), "cannot resolve country for IP", log.Error(err))
|
h.logger.ErrorCtx(r.Context(), "cannot resolve country for IP", log.Error(err))
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc
|
return &cc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) handleGetConsent(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) handleGetConsent(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -169,6 +173,12 @@ func (h *Handler) handlePostConsent(w http.ResponseWriter, r *http.Request) {
|
|||||||
sdkVersion := r.Header.Get("X-SDK-Version")
|
sdkVersion := r.Header.Get("X-SDK-Version")
|
||||||
cc := h.resolveCountryCode(r)
|
cc := h.resolveCountryCode(r)
|
||||||
|
|
||||||
|
var regulation *cookiebanner.Regulation
|
||||||
|
if cc != nil {
|
||||||
|
r := cookiebanner.RegulationForCountry(*cc)
|
||||||
|
regulation = &r
|
||||||
|
}
|
||||||
|
|
||||||
req := cookiebanner.RecordConsentRequest{
|
req := cookiebanner.RecordConsentRequest{
|
||||||
Version: body.Version,
|
Version: body.Version,
|
||||||
VisitorID: body.VisitorID,
|
VisitorID: body.VisitorID,
|
||||||
@@ -177,7 +187,7 @@ func (h *Handler) handlePostConsent(w http.ResponseWriter, r *http.Request) {
|
|||||||
ConsentData: body.ConsentData,
|
ConsentData: body.ConsentData,
|
||||||
Action: body.Action,
|
Action: body.Action,
|
||||||
SdkVersion: sdkVersion,
|
SdkVersion: sdkVersion,
|
||||||
Regulation: cookiebanner.RegulationForCountry(cc),
|
Regulation: regulation,
|
||||||
CountryCode: cc,
|
CountryCode: cc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9565,8 +9565,6 @@ components:
|
|||||||
- consent_data
|
- consent_data
|
||||||
- action
|
- action
|
||||||
- sdk_version
|
- sdk_version
|
||||||
- regulation
|
|
||||||
- country_code
|
|
||||||
- created_at
|
- created_at
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
@@ -9604,9 +9602,11 @@ components:
|
|||||||
regulation:
|
regulation:
|
||||||
$ref: "#/components/schemas/Regulation"
|
$ref: "#/components/schemas/Regulation"
|
||||||
description: Applicable regulation
|
description: Applicable regulation
|
||||||
|
nullable: true
|
||||||
country_code:
|
country_code:
|
||||||
$ref: "#/components/schemas/CountryCode"
|
$ref: "#/components/schemas/CountryCode"
|
||||||
description: Visitor country code (ISO 3166-1 alpha-2)
|
description: Visitor country code (ISO 3166-1 alpha-2)
|
||||||
|
nullable: true
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
|||||||
Reference in New Issue
Block a user