Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove GDPR TCF1 #1854

Merged
merged 6 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ type GDPR struct {
Timeouts GDPRTimeouts `mapstructure:"timeouts_ms"`
NonStandardPublishers []string `mapstructure:"non_standard_publishers,flow"`
NonStandardPublisherMap map[string]struct{}
TCF1 TCF1 `mapstructure:"tcf1"`
TCF2 TCF2 `mapstructure:"tcf2"`
AMPException bool `mapstructure:"amp_exception"` // Deprecated: Use account-level GDPR settings (gdpr.integration_enabled.amp) instead
// EEACountries (EEA = European Economic Area) are a list of countries where we should assume GDPR applies.
Expand All @@ -218,9 +217,6 @@ func (cfg *GDPR) validate(errs []error) []error {
if cfg.AMPException == true {
errs = append(errs, fmt.Errorf("gdpr.amp_exception has been discontinued and must be removed from your config. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp)"))
}
if cfg.TCF1.FetchGVL == true {
errs = append(errs, fmt.Errorf("gdpr.tcf1.fetch_gvl has been discontinued and must be removed from your config. TCF1 will always use the fallback GVL going forward"))
}
return errs
}

Expand All @@ -237,12 +233,6 @@ func (t *GDPRTimeouts) ActiveTimeout() time.Duration {
return time.Duration(t.ActiveVendorlistFetch) * time.Millisecond
}

// TCF1 defines the TCF1 specific configurations for GDPR
type TCF1 struct {
FetchGVL bool `mapstructure:"fetch_gvl"` // Deprecated: In a future version TCF1 will always use the fallback GVL
FallbackGVLPath string `mapstructure:"fallback_gvl_path"`
}

// TCF2 defines the TCF2 specific configurations for GDPR
type TCF2 struct {
Enabled bool `mapstructure:"enabled"`
Expand Down Expand Up @@ -947,8 +937,6 @@ func SetupViper(v *viper.Viper, filename string) {
v.SetDefault("gdpr.timeouts_ms.init_vendorlist_fetches", 0)
v.SetDefault("gdpr.timeouts_ms.active_vendorlist_fetch", 0)
v.SetDefault("gdpr.non_standard_publishers", []string{""})
v.SetDefault("gdpr.tcf1.fetch_gvl", false)
v.SetDefault("gdpr.tcf1.fallback_gvl_path", "./static/tcf1/fallback_gvl.json")
v.SetDefault("gdpr.tcf2.enabled", true)
v.SetDefault("gdpr.tcf2.purpose1.enabled", true)
v.SetDefault("gdpr.tcf2.purpose2.enabled", true)
Expand Down
6 changes: 0 additions & 6 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,12 +568,6 @@ func TestInvalidHostVendorID(t *testing.T) {
}
}

func TestInvalidFetchGVL(t *testing.T) {
cfg := newDefaultConfig(t)
cfg.GDPR.TCF1.FetchGVL = true
assertOneError(t, cfg.validate(), "gdpr.tcf1.fetch_gvl has been discontinued and must be removed from your config. TCF1 will always use the fallback GVL going forward")
}

func TestInvalidAMPException(t *testing.T) {
cfg := newDefaultConfig(t)
cfg.GDPR.AMPException = true
Expand Down
57 changes: 22 additions & 35 deletions exchange/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1447,8 +1447,7 @@ func TestCleanOpenRTBRequestsLMT(t *testing.T) {
}
}

func TestCleanOpenRTBRequestsGDPRScrub(t *testing.T) {
tcf1Consent := "BONV8oqONXwgmADACHENAO7pqzAAppY"
func TestCleanOpenRTBRequestsGDPR(t *testing.T) {
tcf2Consent := "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA"
trueValue, falseValue := true, false

Expand Down Expand Up @@ -1477,19 +1476,7 @@ func TestCleanOpenRTBRequestsGDPRScrub(t *testing.T) {
},
},
{
description: "Enforce - TCF 1",
gdprAccountEnabled: &trueValue,
gdprHostEnabled: true,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprScrub: true,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
},
},
{
description: "Enforce - TCF 2",
description: "Enforce",
gdprAccountEnabled: &trueValue,
gdprHostEnabled: true,
gdpr: "1",
Expand All @@ -1501,72 +1488,72 @@ func TestCleanOpenRTBRequestsGDPRScrub(t *testing.T) {
},
},
{
description: "Not Enforce - TCF 1",
description: "Not Enforce",
gdprAccountEnabled: &trueValue,
gdprHostEnabled: true,
gdpr: "0",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: false,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: false,
GDPRTCFVersion: "",
},
},
{
description: "Enforce - TCF 1; GDPR signal extraction error",
description: "Enforce; GDPR signal extraction error",
gdprAccountEnabled: &trueValue,
gdprHostEnabled: true,
gdpr: "0{",
gdprConsent: "BONV8oqONXwgmADACHENAO7pqzAAppY",
gdprConsent: tcf2Consent,
gdprScrub: true,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
GDPRTCFVersion: metrics.TCFVersionV2,
},
expectError: true,
},
{
description: "Enforce - TCF 1; account GDPR enabled, host GDPR setting disregarded",
description: "Enforce; account GDPR enabled, host GDPR setting disregarded",
gdprAccountEnabled: &trueValue,
gdprHostEnabled: false,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: true,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
GDPRTCFVersion: metrics.TCFVersionV2,
},
},
{
description: "Not Enforce - TCF 1; account GDPR disabled, host GDPR setting disregarded",
description: "Not Enforce; account GDPR disabled, host GDPR setting disregarded",
gdprAccountEnabled: &falseValue,
gdprHostEnabled: true,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: false,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: false,
GDPRTCFVersion: "",
},
},
{
description: "Enforce - TCF 1; account GDPR not specified, host GDPR enabled",
description: "Enforce; account GDPR not specified, host GDPR enabled",
gdprAccountEnabled: nil,
gdprHostEnabled: true,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: true,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
GDPRTCFVersion: metrics.TCFVersionV2,
},
},
{
description: "Not Enforce - TCF 1; account GDPR not specified, host GDPR disabled",
description: "Not Enforce; account GDPR not specified, host GDPR disabled",
gdprAccountEnabled: nil,
gdprHostEnabled: false,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: false,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: false,
Expand All @@ -1578,20 +1565,20 @@ func TestCleanOpenRTBRequestsGDPRScrub(t *testing.T) {
gdprAccountEnabled: nil,
gdprHostEnabled: true,
gdpr: "null",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: true,
userSyncIfAmbiguous: false,
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
GDPRTCFVersion: metrics.TCFVersionV2,
},
},
{
description: "Not Enforce - Ambiguous signal, sync user if ambiguous",
gdprAccountEnabled: nil,
gdprHostEnabled: true,
gdpr: "null",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: false,
userSyncIfAmbiguous: true,
expectPrivacyLabels: metrics.PrivacyLabels{
Expand All @@ -1604,12 +1591,12 @@ func TestCleanOpenRTBRequestsGDPRScrub(t *testing.T) {
gdprAccountEnabled: nil,
gdprHostEnabled: true,
gdpr: "1",
gdprConsent: tcf1Consent,
gdprConsent: tcf2Consent,
gdprScrub: true,
permissionsError: errors.New("Some error"),
expectPrivacyLabels: metrics.PrivacyLabels{
GDPREnforced: true,
GDPRTCFVersion: metrics.TCFVersionV1,
GDPRTCFVersion: metrics.TCFVersionV2,
},
},
}
Expand Down
4 changes: 1 addition & 3 deletions gdpr/gdpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ type Permissions interface {

// Versions of the GDPR TCF technical specification.
const (
tcf1SpecVersion uint8 = 1
tcf2SpecVersion uint8 = 2
)

Expand All @@ -44,8 +43,7 @@ func NewPermissions(ctx context.Context, cfg config.GDPR, vendorIDs map[openrtb_
cfg: cfg,
vendorIDs: vendorIDs,
fetchVendorList: map[uint8]func(ctx context.Context, id uint16) (vendorlist.VendorList, error){
tcf1SpecVersion: newVendorListFetcherTCF1(cfg),
tcf2SpecVersion: newVendorListFetcherTCF2(ctx, cfg, client, vendorListURLMaker)},
tcf2SpecVersion: newVendorListFetcher(ctx, cfg, client, vendorListURLMaker)},
}

if cfg.HostVendorID == 0 {
Expand Down
59 changes: 22 additions & 37 deletions gdpr/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"fmt"

"github.com/prebid/go-gdpr/api"
tcf1constants "github.com/prebid/go-gdpr/consentconstants"
consentconstants "github.com/prebid/go-gdpr/consentconstants/tcf2"
"github.com/prebid/go-gdpr/consentconstants"
tcf2ConsentConstants "github.com/prebid/go-gdpr/consentconstants/tcf2"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for changing this name to tcf2 specific?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to maintain the differentiation between the consentconstants and consentconstants/tcf2 packages while removing any reference to tcf1 so I renamed both of these.

"github.com/prebid/go-gdpr/vendorconsent"
tcf2 "github.com/prebid/go-gdpr/vendorconsent/tcf2"
"github.com/prebid/go-gdpr/vendorlist"
Expand Down Expand Up @@ -116,23 +116,20 @@ func (p *permissionsImpl) allowSync(ctx context.Context, vendorID uint16, consen
return false, nil
}

// InfoStorageAccess is the same across TCF 1 and TCF 2
if parsedConsent.Version() == 2 {
if !p.cfg.TCF2.Purpose1.Enabled {
// We are not enforcing purpose 1
return true, nil
}
consent, ok := parsedConsent.(tcf2.ConsentMetadata)
if !ok {
err := fmt.Errorf("Unable to access TCF2 parsed consent")
return false, err
}
return p.checkPurpose(consent, vendor, vendorID, consentconstants.InfoStorageAccess, false), nil
if parsedConsent.Version() != 2 {
return false, nil
}
if vendor.Purpose(consentconstants.InfoStorageAccess) && parsedConsent.PurposeAllowed(consentconstants.InfoStorageAccess) && parsedConsent.VendorConsent(vendorID) {

if !p.cfg.TCF2.Purpose1.Enabled {
// We are not enforcing purpose 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO the code is clear enough such that the comment isn't necessary.

return true, nil
}
return false, nil
consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
if !ok {
err := fmt.Errorf("Unable to access TCF2 parsed consent")
return false, err
}
return p.checkPurpose(consentMeta, vendor, vendorID, tcf2ConsentConstants.InfoStorageAccess, false), nil
}

func (p *permissionsImpl) allowActivities(ctx context.Context, vendorID uint16, consent string, weakVendorEnforcement bool) (allowBidRequest bool, passGeo bool, passID bool, err error) {
Expand All @@ -145,40 +142,28 @@ func (p *permissionsImpl) allowActivities(ctx context.Context, vendorID uint16,
return false, false, false, nil
}

if parsedConsent.Version() == 2 {
if p.cfg.TCF2.Enabled {
return p.allowActivitiesTCF2(parsedConsent, vendor, vendorID, weakVendorEnforcement)
}
if (vendor.Purpose(consentconstants.InfoStorageAccess) || vendor.LegitimateInterest(consentconstants.InfoStorageAccess) || weakVendorEnforcement) && parsedConsent.PurposeAllowed(consentconstants.InfoStorageAccess) && (vendor.Purpose(consentconstants.PersonalizationProfile) || vendor.LegitimateInterest(consentconstants.PersonalizationProfile) || weakVendorEnforcement) && parsedConsent.PurposeAllowed(consentconstants.PersonalizationProfile) && (parsedConsent.VendorConsent(vendorID) || weakVendorEnforcement) {
return true, true, true, nil
}
} else {
if (vendor.Purpose(tcf1constants.InfoStorageAccess) || vendor.LegitimateInterest(tcf1constants.InfoStorageAccess)) && parsedConsent.PurposeAllowed(tcf1constants.InfoStorageAccess) && (vendor.Purpose(tcf1constants.AdSelectionDeliveryReporting) || vendor.LegitimateInterest(tcf1constants.AdSelectionDeliveryReporting)) && parsedConsent.PurposeAllowed(tcf1constants.AdSelectionDeliveryReporting) && parsedConsent.VendorConsent(vendorID) {
return true, true, true, nil
}
if parsedConsent.Version() != 2 || !p.cfg.TCF2.Enabled {
return true, false, false, nil
}
return true, false, false, nil
}

func (p *permissionsImpl) allowActivitiesTCF2(parsedConsent api.VendorConsents, vendor api.Vendor, vendorID uint16, weakVendorEnforcement bool) (allowBidRequest bool, passGeo bool, passID bool, err error) {
consent, ok := parsedConsent.(tcf2.ConsentMetadata)
consentMeta, ok := parsedConsent.(tcf2.ConsentMetadata)
if !ok {
err = fmt.Errorf("Unable to access TCF2 parsed consent")
return
}

if p.cfg.TCF2.SpecialPurpose1.Enabled {
passGeo = consent.SpecialFeatureOptIn(1) && (vendor.SpecialPurpose(1) || weakVendorEnforcement)
passGeo = consentMeta.SpecialFeatureOptIn(1) && (vendor.SpecialPurpose(1) || weakVendorEnforcement)
} else {
passGeo = true
}
if p.cfg.TCF2.Purpose2.Enabled {
allowBidRequest = p.checkPurpose(consent, vendor, vendorID, tcf1constants.Purpose(2), weakVendorEnforcement)
allowBidRequest = p.checkPurpose(consentMeta, vendor, vendorID, consentconstants.Purpose(2), weakVendorEnforcement)
} else {
allowBidRequest = true
}
for i := 2; i <= 10; i++ {
if p.checkPurpose(consent, vendor, vendorID, tcf1constants.Purpose(i), weakVendorEnforcement) {
if p.checkPurpose(consentMeta, vendor, vendorID, consentconstants.Purpose(i), weakVendorEnforcement) {
passID = true
break
}
Expand All @@ -191,8 +176,8 @@ const pubRestrictNotAllowed = 0
const pubRestrictRequireConsent = 1
const pubRestrictRequireLegitInterest = 2

func (p *permissionsImpl) checkPurpose(consent tcf2.ConsentMetadata, vendor api.Vendor, vendorID uint16, purpose tcf1constants.Purpose, weakVendorEnforcement bool) bool {
if purpose == consentconstants.InfoStorageAccess && p.cfg.TCF2.PurposeOneTreatment.Enabled && consent.PurposeOneTreatment() {
func (p *permissionsImpl) checkPurpose(consent tcf2.ConsentMetadata, vendor api.Vendor, vendorID uint16, purpose consentconstants.Purpose, weakVendorEnforcement bool) bool {
if purpose == tcf2ConsentConstants.InfoStorageAccess && p.cfg.TCF2.PurposeOneTreatment.Enabled && consent.PurposeOneTreatment() {
return p.cfg.TCF2.PurposeOneTreatment.AccessAllowed
}
if consent.CheckPubRestriction(uint8(purpose), pubRestrictNotAllowed, vendorID) {
Expand Down Expand Up @@ -224,7 +209,7 @@ func (p *permissionsImpl) parseVendor(ctx context.Context, vendorID uint16, cons
}

version := parsedConsent.Version()
if version < 1 || version > 2 {
if version != 2 {
return
}
vendorList, err := p.fetchVendorList[version](ctx, parsedConsent.VendorListVersion())
Expand Down
Loading