Add wsl linter and fix

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-05-19 14:51:08 +04:00
parent eedfdcecc8
commit 9156d6a16a
882 changed files with 6068 additions and 574 deletions

View File

@@ -31,5 +31,6 @@ func AnonymizeIP(raw string) string {
}
mask := net.CIDRMask(48, 128)
return ip.Mask(mask).String()
}

View File

@@ -27,6 +27,7 @@ func ptrEqual[T comparable](a, b *T) bool {
if a == nil || b == nil {
return a == b
}
return *a == *b
}
@@ -38,8 +39,10 @@ func jsonEqual(a, b json.RawMessage) (bool, error) {
if err := json.Unmarshal(a, &av); err != nil {
return false, fmt.Errorf("cannot unmarshal first json blob: %w", err)
}
if err := json.Unmarshal(b, &bv); err != nil {
return false, fmt.Errorf("cannot unmarshal second json blob: %w", err)
}
return reflect.DeepEqual(av, bv), nil
}

View File

@@ -60,9 +60,11 @@ func durationBucket(maxAge *int) int {
remaining := *maxAge
total := 0
for _, u := range durationUnits {
if remaining >= u.seconds-u.snap {
count := remaining / u.seconds
leftover := remaining - count*u.seconds
if leftover >= u.seconds-u.snap {
count++
@@ -72,9 +74,11 @@ func durationBucket(maxAge *int) int {
} else {
remaining = leftover
}
total += count * u.seconds
}
}
return total
}
@@ -120,6 +124,7 @@ func (h *patternAnalysisHandler) Claim(ctx context.Context) (coredata.CookieBann
if errors.Is(err, coredata.ErrResourceNotFound) {
return coredata.CookieBanner{}, worker.ErrNoTask
}
return coredata.CookieBanner{}, fmt.Errorf("cannot claim pattern analysis task: %w", err)
}
@@ -133,11 +138,14 @@ func (h *patternAnalysisHandler) Process(ctx context.Context, banner coredata.Co
scope := coredata.NewScopeFromObjectID(banner.ID)
var uncategorised coredata.CookieCategory
hasUncategorised := true
if err := uncategorised.LoadUncategorisedByCookieBannerID(ctx, tx, scope, banner.ID); err != nil {
if !errors.Is(err, coredata.ErrResourceNotFound) {
return fmt.Errorf("cannot load uncategorised category: %w", err)
}
hasUncategorised = false
}
@@ -156,8 +164,10 @@ func (h *patternAnalysisHandler) Process(ctx context.Context, banner coredata.Co
mergeGroups := findMergeGroups(exactPatterns, patternMergeThreshold)
consentChanged := false
for key, group := range mergeGroups {
var maxAge *int
if key.durationBucket >= 0 {
v := key.durationBucket
maxAge = &v
@@ -187,6 +197,7 @@ func (h *patternAnalysisHandler) Process(ctx context.Context, banner coredata.Co
if err != nil {
return fmt.Errorf("cannot insert glob pattern %q: %w", key.template, err)
}
if !inserted {
if err := globPattern.LoadByBannerIDTypeAndPattern(ctx, tx, scope, banner.ID, key.trackerType, key.template, maxAge); err != nil {
return fmt.Errorf("cannot load existing glob pattern %q: %w", key.template, err)
@@ -266,19 +277,24 @@ func findMergeGroups(
if tmpl, ok := heuristicTemplate(p.Pattern); ok {
key := mergeGroupKey{categoryID: p.CookieCategoryID, trackerType: p.TrackerType, template: tmpl, durationBucket: bucket}
mk := memberKey{key, p}
if !seen[mk] {
seen[mk] = true
templateCounts[key] = append(templateCounts[key], p)
}
heuristicKeys[key] = true
}
for _, tmpl := range templateCandidates(p.Pattern) {
key := mergeGroupKey{categoryID: p.CookieCategoryID, trackerType: p.TrackerType, template: tmpl, durationBucket: bucket}
mk := memberKey{key, p}
if !seen[mk] {
seen[mk] = true
templateCounts[key] = append(templateCounts[key], p)
}
}
@@ -292,12 +308,15 @@ func findMergeGroups(
}
var candidates []candidate
for key, pats := range templateCounts {
isH := heuristicKeys[key]
effectiveThreshold := threshold
if isH {
effectiveThreshold = 1
}
if len(pats) >= effectiveThreshold {
candidates = append(candidates, candidate{key, len(strings.ReplaceAll(key.template, "*", "")), isH, pats})
}
@@ -312,12 +331,15 @@ func findMergeGroups(
if candidates[i].isHeuristic != candidates[j].isHeuristic {
return candidates[i].isHeuristic
}
if candidates[i].fixedChars != candidates[j].fixedChars {
return candidates[i].fixedChars > candidates[j].fixedChars
}
if len(candidates[i].patterns) != len(candidates[j].patterns) {
return len(candidates[i].patterns) > len(candidates[j].patterns)
}
return candidates[i].key.template < candidates[j].key.template
},
)
@@ -332,6 +354,7 @@ func findMergeGroups(
}
var unassigned []*coredata.TrackerPattern
for _, p := range c.patterns {
if !assigned[p] {
unassigned = append(unassigned, p)
@@ -361,6 +384,7 @@ func heuristicTemplate(name string) (string, bool) {
var prefix strings.Builder
for len(tokens) > 1 && tokens[0] == "" {
prefix.WriteString(string(seps[0]))
tokens = tokens[1:]
seps = seps[1:]
}
@@ -378,21 +402,28 @@ func heuristicTemplate(name string) (string, bool) {
}
changed := false
var resultTokens []string
var resultSeps []byte
var (
resultTokens []string
resultSeps []byte
)
for i, t := range tokens {
if looksVariable(t) {
changed = true
if len(resultTokens) == 0 || resultTokens[len(resultTokens)-1] != "*" {
if i > 0 {
resultSeps = append(resultSeps, seps[i-1])
}
resultTokens = append(resultTokens, "*")
}
} else {
if i > 0 {
resultSeps = append(resultSeps, seps[i-1])
}
resultTokens = append(resultTokens, t)
}
}
@@ -435,6 +466,7 @@ func looksVariable(token string) bool {
hasLetter := false
allHex := true
allDigits := true
for _, ch := range token {
switch {
case ch >= '0' && ch <= '9':
@@ -478,25 +510,31 @@ func isUUIDShape(s string) bool {
if len(s) != 36 {
return false
}
for i, ch := range s {
if i == 8 || i == 13 || i == 18 || i == 23 {
if ch != '-' {
return false
}
continue
}
if (ch < '0' || ch > '9') && (ch < 'a' || ch > 'f') && (ch < 'A' || ch > 'F') {
return false
}
}
return true
}
func splitTokens(name string) ([]string, []byte) {
underscoreParts := strings.Split(name, "_")
var tokens []string
var seps []byte
var (
tokens []string
seps []byte
)
for i, part := range underscoreParts {
if i > 0 {
@@ -510,6 +548,7 @@ func splitTokens(name string) ([]string, []byte) {
if j > 0 {
seps = append(seps, '-')
}
tokens = append(tokens, sub)
}
}
@@ -524,12 +563,15 @@ func splitTokens(name string) ([]string, []byte) {
func joinTokens(tokens []string, seps []byte) string {
var b strings.Builder
for i, t := range tokens {
if i > 0 {
b.WriteByte(seps[i-1])
}
b.WriteString(t)
}
return b.String()
}
@@ -542,12 +584,14 @@ func globMatch(pattern, name string) bool {
if !strings.HasPrefix(name, parts[0]) {
return false
}
name = name[len(parts[0]):]
last := parts[len(parts)-1]
if !strings.HasSuffix(name, last) {
return false
}
name = name[:len(name)-len(last)]
for _, part := range parts[1 : len(parts)-1] {
@@ -555,6 +599,7 @@ func globMatch(pattern, name string) bool {
if idx == -1 {
return false
}
name = name[idx+len(part):]
}
@@ -567,7 +612,9 @@ func bestSource(patterns []*coredata.TrackerPattern) *coredata.CookieSource {
return p.Source
}
}
src := coredata.CookieSourcePreExisting
return &src
}
@@ -582,6 +629,7 @@ func (h *patternAnalysisHandler) adoptUncategorisedPatterns(
if errors.Is(err, coredata.ErrResourceNotFound) {
return false, nil
}
return false, fmt.Errorf("cannot load uncategorised category: %w", err)
}
@@ -609,6 +657,7 @@ func (h *patternAnalysisHandler) adoptUncategorisedPatterns(
)
exactMatchType := coredata.TrackerPatternMatchTypeExact
var uncategorisedExact coredata.TrackerPatterns
if err := uncategorisedExact.LoadAllByCookieBannerID(
ctx,
@@ -622,8 +671,10 @@ func (h *patternAnalysisHandler) adoptUncategorisedPatterns(
}
adopted := false
for _, ep := range uncategorisedExact {
var match *coredata.TrackerPattern
epBucket := durationBucket(ep.MaxAgeSeconds)
for _, gp := range globPatterns {
if ep.TrackerType == gp.TrackerType && globMatch(gp.Pattern, ep.Pattern) && durationBucket(gp.MaxAgeSeconds) == epBucket {
@@ -646,6 +697,7 @@ func (h *patternAnalysisHandler) adoptUncategorisedPatterns(
}
adopted = true
h.logger.InfoCtx(
ctx,
"adopted uncategorised exact pattern into glob pattern",

View File

@@ -245,8 +245,10 @@ func TestHeuristicTemplate(t *testing.T) {
tt.name,
func(t *testing.T) {
t.Parallel()
tmpl, changed := heuristicTemplate(tt.input)
assert.Equal(t, tt.changed, changed)
if changed {
assert.Equal(t, tt.template, tmpl)
}
@@ -329,6 +331,7 @@ func TestTemplateCandidates(t *testing.T) {
tt.name,
func(t *testing.T) {
t.Parallel()
result := templateCandidates(tt.input)
assert.Equal(t, tt.expected, result)
},
@@ -506,6 +509,7 @@ func TestSplitTokens(t *testing.T) {
tt.name,
func(t *testing.T) {
t.Parallel()
tokens, seps := splitTokens(tt.input)
assert.Equal(t, tt.tokens, tokens)
assert.Equal(t, tt.seps, seps)
@@ -988,6 +992,7 @@ func TestDurationBucket(t *testing.T) {
tt.name,
func(t *testing.T) {
t.Parallel()
result := durationBucket(tt.maxAge)
assert.Equal(t, tt.expected, result)
},

View File

@@ -51,6 +51,7 @@ func searchTrackerPatternsTool(pgClient *pg.Client) agent.Tool {
ctx,
func(ctx context.Context, conn pg.Querier) error {
var patterns coredata.CommonTrackerPatterns
results, err := patterns.FindByKeyword(ctx, conn, p.Query, 10)
if err != nil {
return err

View File

@@ -328,6 +328,7 @@ func (r *UpsertCookieBannerTranslationRequest) Validate() error {
}
}
}
continue
}
@@ -340,6 +341,7 @@ func (r *UpsertCookieBannerTranslationRequest) Validate() error {
if key == "banner_description" {
validators = append(validators, validator.ContainsSubstring("{{cookie_policy_link}}"))
}
v.Check(s, "translations."+key, validators...)
}
@@ -353,10 +355,12 @@ func (r *CreateTrackerPatternRequest) Validate() error {
v.Check(string(r.TrackerType), "tracker_type", validator.Required(), validator.OneOfSlice(
func() []string {
types := coredata.TrackerTypes()
s := make([]string, len(types))
for i, t := range types {
s[i] = string(t)
}
return s
}(),
))
@@ -364,15 +368,18 @@ func (r *CreateTrackerPatternRequest) Validate() error {
v.Check(string(r.MatchType), "match_type", validator.Required(), validator.OneOfSlice(
func() []string {
types := coredata.TrackerPatternMatchTypes()
s := make([]string, len(types))
for i, t := range types {
s[i] = string(t)
}
return s
}(),
))
v.Check(r.Pattern, "pattern", func(value any) *validator.ValidationError {
s, _ := value.(string)
switch r.MatchType {
case coredata.TrackerPatternMatchTypeGlob:
if strings.Count(s, "*") != 1 {
@@ -389,6 +396,7 @@ func (r *CreateTrackerPatternRequest) Validate() error {
}
}
}
return nil
})
v.Check(r.DisplayName, "display_name", validator.Required(), validator.SafeTextNoNewLine(255))
@@ -401,6 +409,7 @@ func (r *UpdateTrackerPatternRequest) Validate() error {
v := validator.New()
v.Check(r.TrackerPatternID, "tracker_pattern_id", validator.Required(), validator.GID(coredata.TrackerPatternEntityType))
if r.Description != nil {
v.Check(*r.Description, "description", validator.SafeText(1000))
}
@@ -415,10 +424,12 @@ func (r *CreateTrackerResourceRequest) Validate() error {
v.Check(string(r.ResourceType), "resource_type", validator.Required(), validator.OneOfSlice(
func() []string {
types := coredata.TrackerResourceTypes()
s := make([]string, len(types))
for i, t := range types {
s[i] = string(t)
}
return s
}(),
))
@@ -434,9 +445,11 @@ func (r *UpdateTrackerResourceRequest) Validate() error {
v := validator.New()
v.Check(r.TrackerResourceID, "tracker_resource_id", validator.Required(), validator.GID(coredata.TrackerResourceEntityType))
if r.DisplayName != nil {
v.Check(*r.DisplayName, "display_name", validator.SafeTextNoNewLine(255))
}
if r.Description != nil {
v.Check(*r.Description, "description", validator.SafeText(1000))
}
@@ -472,8 +485,8 @@ func (s *Service) ensureDraftVersion(
snapshot := buildSnapshot(banner, categories, allPatterns)
var latest coredata.CookieBannerVersion
err := latest.LoadLatestByCookieBannerID(ctx, tx, scope, banner.ID)
err := latest.LoadLatestByCookieBannerID(ctx, tx, scope, banner.ID)
if err == nil {
if latestSnapshot, snapErr := latest.GetSnapshot(); snapErr == nil && snapshotsEqual(snapshot, latestSnapshot) {
return &latest, nil
@@ -483,10 +496,12 @@ func (s *Service) ensureDraftVersion(
if err := latest.SetSnapshot(snapshot); err != nil {
return nil, fmt.Errorf("cannot set snapshot: %w", err)
}
latest.UpdatedAt = time.Now()
if err := latest.Update(ctx, tx, scope); err != nil {
return nil, fmt.Errorf("cannot update draft version: %w", err)
}
return &latest, nil
}
}
@@ -509,6 +524,7 @@ func (s *Service) ensureDraftVersion(
if err != nil {
return nil, fmt.Errorf("cannot determine next version: %w", err)
}
version.Version = nextVersion
if err := version.SetSnapshot(snapshot); err != nil {
@@ -588,6 +604,7 @@ func (s *Service) CreateCookieBanner(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrOriginAlreadyInUse
}
return fmt.Errorf("cannot insert cookie banner: %w", err)
}
@@ -597,6 +614,7 @@ func (s *Service) CreateCookieBanner(
if gcmConsentTypes == nil {
gcmConsentTypes = []string{}
}
category := &coredata.CookieCategory{
ID: gid.New(scope.GetTenantID(), coredata.CookieCategoryEntityType),
OrganizationID: banner.OrganizationID,
@@ -620,6 +638,7 @@ func (s *Service) CreateCookieBanner(
if dc.Kind == coredata.CookieCategoryKindNecessary {
consentMaxAge := req.ConsentExpiryDays * 86400
consentPattern := &coredata.TrackerPattern{
ID: gid.New(scope.GetTenantID(), coredata.TrackerPatternEntityType),
OrganizationID: banner.OrganizationID,
@@ -657,6 +676,7 @@ func (s *Service) CreateCookieBanner(
}
}
}
if len(catMap) > 0 {
blob["categories"] = catMap
}
@@ -710,6 +730,7 @@ func (s *Service) GetCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -760,6 +781,7 @@ func (s *Service) GetActiveCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -810,8 +832,10 @@ func (s *Service) CountCookieBannersForOrganization(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var banners coredata.CookieBanners
var err error
var (
banners coredata.CookieBanners
err error
)
count, err = banners.CountByOrganizationID(ctx, conn, scope, organizationID, filter)
if err != nil {
@@ -846,6 +870,7 @@ func (s *Service) UpdateCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -864,15 +889,19 @@ func (s *Service) UpdateCookieBanner(
if req.Name != nil {
banner.Name = *req.Name
}
if req.PrivacyPolicyURL != nil {
banner.PrivacyPolicyURL = req.PrivacyPolicyURL
}
if req.CookiePolicyURL != nil {
banner.CookiePolicyURL = *req.CookiePolicyURL
}
if req.ConsentExpiryDays != nil {
banner.ConsentExpiryDays = *req.ConsentExpiryDays
}
if req.DefaultLanguage != nil {
banner.DefaultLanguage = *req.DefaultLanguage
}
@@ -883,6 +912,7 @@ func (s *Service) UpdateCookieBanner(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrOriginAlreadyInUse
}
return fmt.Errorf("cannot update cookie banner: %w", err)
}
@@ -916,6 +946,7 @@ func (s *Service) PublishCookieBannerVersion(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrNoDraftVersion
}
return fmt.Errorf("cannot load latest version: %w", err)
}
@@ -954,6 +985,7 @@ func (s *Service) ActivateCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -968,6 +1000,7 @@ func (s *Service) ActivateCookieBanner(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrOriginAlreadyInUse
}
return fmt.Errorf("cannot update cookie banner: %w", err)
}
@@ -995,6 +1028,7 @@ func (s *Service) DeactivateCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -1032,6 +1066,7 @@ func (s *Service) DeleteCookieBanner(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -1063,6 +1098,7 @@ func (s *Service) CreateCookieCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -1086,6 +1122,7 @@ func (s *Service) CreateCookieCategory(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrCategorySlugAlreadyExists
}
return fmt.Errorf("cannot insert cookie category: %w", err)
}
@@ -1117,6 +1154,7 @@ func (s *Service) GetCookieCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -1189,8 +1227,10 @@ func (s *Service) CountCookieCategoriesForBanner(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var categories coredata.CookieCategories
var err error
var (
categories coredata.CookieCategories
err error
)
count, err = categories.CountConsentCategoriesByCookieBannerID(ctx, conn, scope, bannerID)
if err != nil {
@@ -1225,6 +1265,7 @@ func (s *Service) UpdateCookieCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -1241,25 +1282,31 @@ func (s *Service) UpdateCookieCategory(
if req.Name != nil {
category.Name = *req.Name
}
if req.Slug != nil {
category.Slug = *req.Slug
}
if req.Description != nil {
category.Description = *req.Description
}
if req.GCMConsentTypes != nil {
category.GCMConsentTypes = *req.GCMConsentTypes
}
if posthogChanged {
if *req.PostHogConsent && category.Kind != coredata.CookieCategoryKindNormal {
return ErrPostHogConsentKindInvalid
}
if *req.PostHogConsent {
var categories coredata.CookieCategories
if err := categories.ClearPostHogConsentByBannerID(ctx, tx, scope, category.CookieBannerID); err != nil {
return fmt.Errorf("cannot clear posthog consent: %w", err)
}
}
category.PostHogConsent = *req.PostHogConsent
}
@@ -1269,6 +1316,7 @@ func (s *Service) UpdateCookieCategory(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrCategorySlugAlreadyExists
}
return fmt.Errorf("cannot update cookie category: %w", err)
}
@@ -1305,6 +1353,7 @@ func (s *Service) ReorderCookieCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -1350,6 +1399,7 @@ func (s *Service) DeleteCookieCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -1396,6 +1446,7 @@ func (s *Service) GetCookieBannerVersion(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrVersionNotFound
}
return fmt.Errorf("cannot load cookie banner version: %w", err)
}
@@ -1444,8 +1495,10 @@ func (s *Service) CountCookieBannerVersionsForBanner(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var versions coredata.CookieBannerVersions
var err error
var (
versions coredata.CookieBannerVersions
err error
)
count, err = versions.CountByCookieBannerID(ctx, conn, scope, bannerID)
if err != nil {
@@ -1527,8 +1580,10 @@ func (s *Service) CountCookieConsentRecordsForBanner(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var records coredata.CookieConsentRecords
var err error
var (
records coredata.CookieConsentRecords
err error
)
count, err = records.CountByCookieBannerID(ctx, conn, scope, bannerID, filter)
if err != nil {
@@ -1562,6 +1617,7 @@ func (s *Service) GetActiveBannerConfig(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load active cookie banner: %w", err)
}
@@ -1572,6 +1628,7 @@ func (s *Service) GetActiveBannerConfig(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrNoPublishedVersion
}
return fmt.Errorf("cannot load latest published version: %w", err)
}
@@ -1601,6 +1658,7 @@ func (s *Service) GetActiveBannerConfig(
}
config.Regulation = regulation
config.ConsentMode = ConsentModeForRegulation(regulation)
if !isLegacySDK(sdkVersion) {
remapTextsForConsentMode(config.Texts, config.ConsentMode)
@@ -1622,6 +1680,7 @@ func buildBannerConfig(
}
resolvedLang := defaultLang
if lang != "" {
if _, ok := translations[lang]; ok {
resolvedLang = lang
@@ -1634,6 +1693,7 @@ func buildBannerConfig(
categories = append(categories, c)
}
}
texts := make(map[string]string)
if t, ok := translations[resolvedLang]; ok {
@@ -1642,14 +1702,17 @@ func buildBannerConfig(
if len(t.Categories) == len(categories) {
translated := make([]coredata.CookieBannerVersionSnapshotCategory, len(categories))
copy(translated, categories)
for i, ct := range t.Categories {
if ct.Name != "" {
translated[i].Name = ct.Name
}
if ct.Description != "" {
translated[i].Description = ct.Description
}
}
categories = translated
}
}
@@ -1707,6 +1770,7 @@ func isLegacySDK(version string) bool {
func parseMajorMinor(version string) (major, minor int, ok bool) {
v := strings.TrimPrefix(version, "v")
parts := strings.SplitN(v, ".", 3)
if len(parts) < 2 {
return 0, 0, false
@@ -1740,13 +1804,16 @@ func (s *Service) SetShowBranding(
ctx,
func(ctx context.Context, tx pg.Tx) error {
var banner coredata.CookieBanner
banner.ID = bannerID
if err := banner.UpdateShowBranding(ctx, tx, coredata.NewNoScope(), show); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot update show_branding: %w", err)
}
return nil
},
)
@@ -1771,14 +1838,15 @@ func (s *Service) UpsertCookieBannerTranslation(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
now := time.Now()
var existing coredata.CookieBannerTranslation
err := existing.LoadByCookieBannerIDAndLanguage(ctx, tx, scope, req.CookieBannerID, req.Language)
err := existing.LoadByCookieBannerIDAndLanguage(ctx, tx, scope, req.CookieBannerID, req.Language)
if err == nil {
same, eqErr := jsonEqual(existing.Translations, req.Translations)
if eqErr == nil && same {
@@ -1787,10 +1855,12 @@ func (s *Service) UpsertCookieBannerTranslation(
}
existing.Translations = req.Translations
existing.UpdatedAt = now
if err := existing.Update(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot update cookie banner translation: %w", err)
}
result = &existing
} else if errors.Is(err, coredata.ErrResourceNotFound) {
t := &coredata.CookieBannerTranslation{
@@ -1805,6 +1875,7 @@ func (s *Service) UpsertCookieBannerTranslation(
if err := t.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert cookie banner translation: %w", err)
}
result = t
} else {
return fmt.Errorf("cannot load cookie banner translation: %w", err)
@@ -1855,6 +1926,7 @@ func (s *Service) GetVisitorConsent(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load active cookie banner: %w", err)
}
@@ -1865,6 +1937,7 @@ func (s *Service) GetVisitorConsent(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrConsentNotFound
}
return fmt.Errorf("cannot load consent record: %w", err)
}
@@ -1915,6 +1988,7 @@ func (s *Service) RecordConsent(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load active cookie banner: %w", err)
}
@@ -1925,6 +1999,7 @@ func (s *Service) RecordConsent(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrVersionNotFound
}
return fmt.Errorf("cannot load cookie banner version: %w", err)
}
@@ -1995,6 +2070,7 @@ func (s *Service) ReportDetectedTrackers(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrBannerNotFound
}
return fmt.Errorf("cannot load cookie banner: %w", err)
}
@@ -2005,6 +2081,7 @@ func (s *Service) ReportDetectedTrackers(
inserted := 0
now := time.Now()
var matchedPatternIDs []gid.GID
for _, dc := range req.Cookies {
@@ -2063,6 +2140,7 @@ func (s *Service) ReportDetectedTrackers(
if err != nil {
return err
}
if wasInserted {
inserted++
}
@@ -2107,6 +2185,7 @@ func (s *Service) reportDetectedTracker(
matchedPatternIDs *[]gid.GID,
) error {
var matchedPattern coredata.TrackerPattern
err := matchedPattern.FindMatchingPattern(ctx, tx, scope, banner.ID, info.TrackerType, info.Identifier)
if err != nil && !errors.Is(err, coredata.ErrResourceNotFound) {
return fmt.Errorf("cannot find matching tracker pattern: %w", err)
@@ -2138,10 +2217,12 @@ func (s *Service) reportDetectedTracker(
CreatedAt: now,
UpdatedAt: now,
}
wasInserted, err := newPattern.InsertIfNotExists(ctx, tx, scope)
if err != nil {
return fmt.Errorf("cannot insert tracker pattern: %w", err)
}
if wasInserted {
patternID = &newPattern.ID
*inserted++
@@ -2150,11 +2231,13 @@ func (s *Service) reportDetectedTracker(
if err := existingPattern.FindMatchingPattern(ctx, tx, scope, banner.ID, info.TrackerType, info.Identifier); err != nil {
return fmt.Errorf("cannot load existing tracker pattern: %w", err)
}
patternID = &existingPattern.ID
}
}
var initiatorDomain *string
if info.InitiatorURL != nil {
if domain := uri.ExtractDomain(*info.InitiatorURL); domain != "" {
initiatorDomain = &domain
@@ -2199,6 +2282,7 @@ func (s *Service) reportDetectedResource(
}
origin := u.Scheme + "://" + u.Host
path := u.Path
if path == "" {
path = "/"
@@ -2246,6 +2330,7 @@ func (s *Service) CreateTrackerPattern(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -2271,6 +2356,7 @@ func (s *Service) CreateTrackerPattern(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrPatternAlreadyExists
}
return fmt.Errorf("cannot insert tracker pattern: %w", err)
}
@@ -2321,10 +2407,13 @@ func (s *Service) CountTrackerPatternsForCategory(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var patterns coredata.TrackerPatterns
var err error
var (
patterns coredata.TrackerPatterns
err error
)
count, err = patterns.CountByCookieCategoryID(ctx, conn, scope, categoryID)
return err
},
)
@@ -2349,6 +2438,7 @@ func (s *Service) GetTrackerPattern(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerPatternNotFound
}
return fmt.Errorf("cannot load tracker pattern: %w", err)
}
@@ -2380,6 +2470,7 @@ func (s *Service) UpdateTrackerPattern(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerPatternNotFound
}
return fmt.Errorf("cannot load tracker pattern: %w", err)
}
@@ -2396,9 +2487,11 @@ func (s *Service) UpdateTrackerPattern(
if req.MaxAgeSeconds != nil {
pattern.MaxAgeSeconds = *req.MaxAgeSeconds
}
if req.Description != nil {
pattern.Description = *req.Description
}
if req.Excluded != nil {
pattern.Excluded = *req.Excluded
}
@@ -2438,6 +2531,7 @@ func (s *Service) DeleteTrackerPattern(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerPatternNotFound
}
return fmt.Errorf("cannot load tracker pattern: %w", err)
}
@@ -2473,6 +2567,7 @@ func (s *Service) MoveTrackerPatternToCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerPatternNotFound
}
return fmt.Errorf("cannot load tracker pattern: %w", err)
}
@@ -2481,6 +2576,7 @@ func (s *Service) MoveTrackerPatternToCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load target cookie category: %w", err)
}
@@ -2562,8 +2658,10 @@ func (s *Service) CountUncategorisedTrackerPatterns(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var patterns coredata.TrackerPatterns
var err error
var (
patterns coredata.TrackerPatterns
err error
)
count, err = patterns.CountUncategorisedByCookieBannerID(ctx, conn, scope, bannerID, filter)
if err != nil {
@@ -2590,8 +2688,10 @@ func (s *Service) CountDetectedTrackersByPatternID(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var trackers coredata.DetectedTrackers
var err error
var (
trackers coredata.DetectedTrackers
err error
)
count, err = trackers.CountByTrackerPatternID(ctx, conn, scope, trackerPatternID)
if err != nil {
@@ -2627,6 +2727,7 @@ func (s *Service) CreateTrackerResource(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load cookie category: %w", err)
}
@@ -2650,6 +2751,7 @@ func (s *Service) CreateTrackerResource(
if errors.Is(err, coredata.ErrResourceAlreadyExists) {
return ErrResourceAlreadyExists
}
return fmt.Errorf("cannot insert tracker resource: %w", err)
}
@@ -2677,6 +2779,7 @@ func (s *Service) GetTrackerResource(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerResourceNotFound
}
return fmt.Errorf("cannot load tracker resource: %w", err)
}
@@ -2708,6 +2811,7 @@ func (s *Service) UpdateTrackerResource(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerResourceNotFound
}
return fmt.Errorf("cannot load tracker resource: %w", err)
}
@@ -2722,9 +2826,11 @@ func (s *Service) UpdateTrackerResource(
if req.DisplayName != nil {
resource.DisplayName = *req.DisplayName
}
if req.Description != nil {
resource.Description = *req.Description
}
if req.Excluded != nil {
resource.Excluded = *req.Excluded
}
@@ -2758,6 +2864,7 @@ func (s *Service) DeleteTrackerResource(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerResourceNotFound
}
return fmt.Errorf("cannot load tracker resource: %w", err)
}
@@ -2785,6 +2892,7 @@ func (s *Service) MoveTrackerResourceToCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrTrackerResourceNotFound
}
return fmt.Errorf("cannot load tracker resource: %w", err)
}
@@ -2793,6 +2901,7 @@ func (s *Service) MoveTrackerResourceToCategory(
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrCategoryNotFound
}
return fmt.Errorf("cannot load target cookie category: %w", err)
}
@@ -2860,10 +2969,13 @@ func (s *Service) CountTrackerResourcesForCategory(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var resources coredata.TrackerResources
var err error
var (
resources coredata.TrackerResources
err error
)
count, err = resources.CountByCookieCategoryID(ctx, conn, scope, categoryID)
return err
},
)
@@ -2911,8 +3023,10 @@ func (s *Service) CountUncategorisedTrackerResources(
err := s.pg.WithConn(
ctx,
func(ctx context.Context, conn pg.Querier) error {
var resources coredata.TrackerResources
var err error
var (
resources coredata.TrackerResources
err error
)
count, err = resources.CountUncategorisedByCookieBannerID(ctx, conn, scope, bannerID, filter)
if err != nil {

View File

@@ -30,6 +30,7 @@ func TestSnapshotsEqual(t *testing.T) {
baseSnapshot := func() coredata.CookieBannerVersionSnapshot {
policy := "https://example.com/privacy"
maxAge := 3600
return coredata.CookieBannerVersionSnapshot{
PrivacyPolicyURL: &policy,
CookiePolicyURL: "https://example.com/cookies",

View File

@@ -65,6 +65,7 @@ func sortConsentCategories(categories coredata.CookieCategories) {
if d := snapshotCategoryKindOrder(a.Kind) - snapshotCategoryKindOrder(b.Kind); d != 0 {
return d
}
return bytes.Compare(a.ID[:], b.ID[:])
})
}
@@ -77,10 +78,12 @@ func buildSnapshot(
sortConsentCategories(categories)
cookiesByCategory := make(map[gid.GID]coredata.CookieItems)
for _, p := range allPatterns {
if p.TrackerType != coredata.TrackerTypeCookie {
continue
}
cookiesByCategory[p.CookieCategoryID] = append(
cookiesByCategory[p.CookieCategoryID],
coredata.CookieItem{
@@ -97,10 +100,12 @@ func buildSnapshot(
if cookies == nil {
cookies = coredata.CookieItems{}
}
gcmConsentTypes := c.GCMConsentTypes
if gcmConsentTypes == nil {
gcmConsentTypes = []string{}
}
snapshotCategories[i] = coredata.CookieBannerVersionSnapshotCategory{
Name: c.Name,
Slug: c.Slug,
@@ -138,15 +143,19 @@ func buildSnapshotTranslations(
Description string `json:"description"`
} `json:"categories"`
}
_ = json.Unmarshal(t.Translations, &raw)
ui := make(map[string]string)
var flat map[string]json.RawMessage
_ = json.Unmarshal(t.Translations, &flat)
for k, v := range flat {
if k == "categories" || k == "cookies" {
continue
}
var s string
if json.Unmarshal(v, &s) == nil {
ui[k] = s
@@ -161,9 +170,11 @@ func buildSnapshotTranslations(
Name: ct.Name,
Description: ct.Description,
}
continue
}
}
catTranslations[i] = coredata.CookieBannerVersionSnapshotCategoryTranslation{
Name: c.Name,
Description: c.Description,

View File

@@ -87,6 +87,7 @@ func buildTrackerMappingAgent(
func trackerMappingInstructions(_ context.Context, _ *agent.Agent) string {
categories := coredata.ThirdPartyCategories()
parts := make([]string, len(categories))
for i, c := range categories {
parts[i] = string(c)

View File

@@ -75,6 +75,7 @@ func (h *trackerMappingHandler) Claim(ctx context.Context) (coredata.TrackerPatt
if errors.Is(err, coredata.ErrResourceNotFound) {
return coredata.TrackerPattern{}, worker.ErrNoTask
}
return coredata.TrackerPattern{}, fmt.Errorf("cannot claim tracker mapping task: %w", err)
}
@@ -85,9 +86,11 @@ func (h *trackerMappingHandler) Process(ctx context.Context, tp coredata.Tracker
return h.pg.WithTx(
ctx,
func(ctx context.Context, tx pg.Tx) error {
var commonPatternID *gid.GID
var thirdPartyID *gid.GID
var err error
var (
commonPatternID *gid.GID
thirdPartyID *gid.GID
err error
)
commonPatternID, thirdPartyID, err = h.matchByPattern(ctx, tx, tp)
if err != nil {
@@ -143,12 +146,15 @@ func (h *trackerMappingHandler) matchByPattern(
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil, nil
}
return nil, nil, fmt.Errorf("cannot load common tracker pattern: %w", err)
}
var thirdPartyID *gid.GID
if commonPattern.CommonThirdPartyID != nil {
var err error
thirdPartyID, err = h.resolveThirdParty(ctx, conn, tp, &commonPattern)
if err != nil {
return nil, nil, fmt.Errorf("cannot resolve third party from pattern match: %w", err)
@@ -164,6 +170,7 @@ func (h *trackerMappingHandler) matchByDomain(
tp coredata.TrackerPattern,
) (*gid.GID, *gid.GID, error) {
var trackers coredata.DetectedTrackers
domains, err := trackers.LoadInitiatorDomainsByTrackerPatternID(ctx, tx, tp.ID, 10)
if err != nil {
return nil, nil, fmt.Errorf("cannot load initiator domains: %w", err)
@@ -174,6 +181,7 @@ func (h *trackerMappingHandler) matchByDomain(
}
filter := coredata.NewCommonThirdPartyDomainFilter(domains)
var matchedDomains coredata.CommonThirdPartyDomains
if err := matchedDomains.Load(ctx, tx, 1, filter); err != nil {
return nil, nil, fmt.Errorf("cannot load common third party domain by domain match: %w", err)
@@ -217,6 +225,7 @@ func (h *trackerMappingHandler) identifyWithAgent(
tp coredata.TrackerPattern,
) (*gid.GID, *gid.GID, error) {
var trackers coredata.DetectedTrackers
domains, err := trackers.LoadInitiatorDomainsByTrackerPatternID(ctx, tx, tp.ID, 5)
if err != nil {
h.logger.WarnCtx(ctx, "cannot load initiator domains for agent", log.Error(err))
@@ -244,6 +253,7 @@ func (h *trackerMappingHandler) identifyWithAgent(
log.Error(err),
log.String("pattern", tp.Pattern),
)
return nil, nil, nil
}
@@ -256,6 +266,7 @@ func (h *trackerMappingHandler) identifyWithAgent(
log.String("pattern", tp.Pattern),
log.Float64("confidence", identification.Confidence),
)
return nil, nil, nil
}
@@ -420,6 +431,7 @@ func (h *trackerMappingHandler) resolveThirdParty(
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, nil
}
return nil, fmt.Errorf("cannot resolve third party: %w", err)
}