Repository: prebid/prebid-server
Pull request #1514 (2020-09-28 17:32:38)

Refactor EEAC map to be more in line with the nonstandard publisher map
Resolves Gus' unresolved comment in #1427 


Patch:
diff --git a/config/config.go b/config/config.go
index dd660992..d2bd5613 100755
--- a/config/config.go
+++ b/config/config.go
@@ -212,7 +212,7 @@ type GDPR struct {
 	UsersyncIfAmbiguous     bool         `mapstructure:"usersync_if_ambiguous"`
 	Timeouts                GDPRTimeouts `mapstructure:"timeouts_ms"`
 	NonStandardPublishers   []string     `mapstructure:"non_standard_publishers,flow"`
-	NonStandardPublisherMap map[string]int
+	NonStandardPublisherMap map[string]struct{}
 	TCF1                    TCF1 `mapstructure:"tcf1"`
 	TCF2                    TCF2 `mapstructure:"tcf2"`
 	AMPException            bool `mapstructure:"amp_exception"`
@@ -220,7 +220,8 @@ type GDPR struct {
 	// If the gdpr flag is unset in a request, but geo.country is set, we will assume GDPR applies if and only
 	// if the country matches one on this list. If both the GDPR flag and country are not set, we default
 	// to UsersyncIfAmbiguous
-	EEACountries []string `mapstructure:"eea_countries"`
+	EEACountries    []string `mapstructure:"eea_countries"`
+	EEACountriesMap map[string]struct{}
 }
 
 func (cfg *GDPR) validate(errs configErrors) configErrors {
@@ -608,9 +609,15 @@ func New(v *viper.Viper) (*Configuration, error) {
 
 	// To look for a request's publisher_id in the NonStandardPublishers list in
 	// O(1) time, we fill this hash table located in the NonStandardPublisherMap field of GDPR
-	c.GDPR.NonStandardPublisherMap = make(map[string]int)
+	var s struct{}
+	c.GDPR.NonStandardPublisherMap = make(map[string]struct{})
 	for i := 0; i < len(c.GDPR.NonStandardPublishers); i++ {
-		c.GDPR.NonStandardPublisherMap[c.GDPR.NonStandardPublishers[i]] = 1
+		c.GDPR.NonStandardPublisherMap[c.GDPR.NonStandardPublishers[i]] = s
+	}
+
+	c.GDPR.EEACountriesMap = make(map[string]struct{})
+	for i := 0; i < len(c.GDPR.EEACountriesMap); i++ {
+		c.GDPR.NonStandardPublisherMap[c.GDPR.EEACountries[i]] = s
 	}
 
 	// To look for a request's app_id in O(1) time, we fill this hash table located in the
@@ -966,7 +973,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.triplelift_native.disabled", true)
 	v.SetDefault("adapters.triplelift_native.extra_info", "{\"publisher_whitelist\":[]}")
 	v.SetDefault("adapters.triplelift.endpoint", "https://tlx.3lift.com/s2s/auction?sra=1&supplier_id=20")
-	v.SetDefault("adapters.ucfunnel.endpoint", "http://apac-hk-adx.aralego.com/prebid")
+	v.SetDefault("adapters.ucfunnel.endpoint", "http://pbs.aralego.com/prebid")
 	v.SetDefault("adapters.unruly.endpoint", "http://targeting.unrulymedia.com/openrtb/2.2")
 	v.SetDefault("adapters.valueimpression.endpoint", "https://rtb.valueimpression.com/endpoint")
 	v.SetDefault("adapters.verizonmedia.disabled", true)
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 11ef9a98..62fb9a2c 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -59,7 +59,6 @@ type exchange struct {
 	currencyConverter   *currencies.RateConverter
 	UsersyncIfAmbiguous bool
 	privacyConfig       config.Privacy
-	eeaCountries        map[string]struct{}
 }
 
 // Container to pass out response ext data from the GetAllBids goroutines back into the main thread
@@ -80,11 +79,6 @@ type bidResponseWrapper struct {
 func NewExchange(client *http.Client, cache prebid_cache_client.Client, cfg *config.Configuration, metricsEngine pbsmetrics.MetricsEngine, infos adapters.BidderInfos, gDPR gdpr.Permissions, currencyConverter *currencies.RateConverter) Exchange {
 	e := new(exchange)
 
-	e.eeaCountries = make(map[string]struct{}, len(cfg.GDPR.EEACountries))
-	var s struct{}
-	for _, c := range cfg.GDPR.EEACountries {
-		e.eeaCountries[c] = s
-	}
 	e.adapterMap = newAdapterMap(client, cfg, infos, metricsEngine)
 	e.cache = cache
 	e.cacheTime = time.Duration(cfg.CacheURL.ExpectedTimeMillis) * time.Millisecond
@@ -141,7 +135,7 @@ func (e *exchange) HoldAuction(ctx context.Context, bidRequest *openrtb.BidReque
 	if geo != nil {
 		// If we have a country set, and it is on the list, we assume GDPR applies if not set on the request.
 		// Otherwise we assume it does not apply as long as it appears "valid" (is 3 characters long).
-		if _, found := e.eeaCountries[strings.ToUpper(geo.Country)]; found {
+		if _, found := e.privacyConfig.GDPR.EEACountriesMap[strings.ToUpper(geo.Country)]; found {
 			usersyncIfAmbiguous = false
 		} else if len(geo.Country) == 3 {
 			// The country field is formatted properly as a three character country code


Test patch:
diff --git a/adapters/ucfunnel/ucfunneltest/exemplary/ucfunnel.json b/adapters/ucfunnel/ucfunneltest/exemplary/ucfunnel.json
index 2a7e4b2b..9a4dad9b 100644
--- a/adapters/ucfunnel/ucfunneltest/exemplary/ucfunnel.json
+++ b/adapters/ucfunnel/ucfunneltest/exemplary/ucfunnel.json
@@ -29,7 +29,8 @@
             "exp": 3600,
             "ext":{
                 "ucfunnel":{
-                    "adunitid":"ad-BE7E9EB323E9996218A733887B6E924"
+                    "adunitid": "test-ad-83444226E44368D1E32E49EEBE6D29",
+                    "partnerid": "par-2EDDB423AA24474188B843EE4842932"
                 }
             }
         }
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 820c578b..2b91f1b0 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -1282,6 +1282,12 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 		t.Fatalf("%s: Failed to parse aliases", filename)
 	}
 
+	var s struct{}
+	eeac := make(map[string]struct{})
+	for _, c := range []string{"FIN", "FRA", "GUF"} {
+		eeac[c] = s
+	}
+
 	privacyConfig := config.Privacy{
 		CCPA: config.CCPA{
 			Enforce: spec.EnforceCCPA,
@@ -1291,6 +1297,7 @@ func runSpec(t *testing.T, filename string, spec *exchangeSpec) {
 		},
 		GDPR: config.GDPR{
 			UsersyncIfAmbiguous: !spec.AssumeGDPRApplies,
+			EEACountriesMap:     eeac,
 		},
 	}
 
@@ -1409,12 +1416,6 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
 		}
 	}
 
-	var s struct{}
-	eeac := make(map[string]struct{})
-	for _, c := range []string{"FIN", "FRA", "GUF"} {
-		eeac[c] = s
-	}
-
 	return &exchange{
 		adapterMap:          adapters,
 		me:                  metricsConf.NewMetricsEngine(&config.Configuration{}, openrtb_ext.BidderList()),
@@ -1424,7 +1425,6 @@ func newExchangeForTests(t *testing.T, filename string, expectations map[string]
 		currencyConverter:   currencies.NewRateConverter(&http.Client{}, "", time.Duration(0)),
 		UsersyncIfAmbiguous: privacyConfig.GDPR.UsersyncIfAmbiguous,
 		privacyConfig:       privacyConfig,
-		eeaCountries:        eeac,
 	}
 }
 
diff --git a/gdpr/impl_test.go b/gdpr/impl_test.go
index d5114454..793eb967 100644
--- a/gdpr/impl_test.go
+++ b/gdpr/impl_test.go
@@ -212,7 +212,7 @@ func TestAllowPersonalInfo(t *testing.T) {
 	assertBoolsEqual(t, true, allowPI)
 
 	// Assert that an item that otherwise would not be allowed PI access, gets approved because it is found in the GDPR.NonStandardPublishers array
-	perms.cfg.NonStandardPublisherMap = map[string]int{"appNexusAppID": 1}
+	perms.cfg.NonStandardPublisherMap = map[string]struct{}{"appNexusAppID": {}}
 	allowPI, _, _, err = perms.PersonalInfoAllowed(context.Background(), openrtb_ext.BidderAppnexus, "appNexusAppID", "BOS2bx5OS2bx5ABABBAAABoAAAABBwAA")
 	assertNilErr(t, err)
 	assertBoolsEqual(t, true, allowPI)
@@ -343,7 +343,7 @@ func TestAllowPersonalInfoWhitelistTCF2(t *testing.T) {
 		},
 	}
 	// Assert that an item that otherwise would not be allowed PI access, gets approved because it is found in the GDPR.NonStandardPublishers array
-	perms.cfg.NonStandardPublisherMap = map[string]int{"appNexusAppID": 1}
+	perms.cfg.NonStandardPublisherMap = map[string]struct{}{"appNexusAppID": {}}
 	allowPI, allowGeo, allowID, err := perms.PersonalInfoAllowed(context.Background(), openrtb_ext.BidderAppnexus, "appNexusAppID", "COzTVhaOzTVhaGvAAAENAiCIAP_AAH_AAAAAAEEUACCKAAA")
 	assert.NoErrorf(t, err, "Error processing PersonalInfoAllowed")
 	assert.EqualValuesf(t, true, allowPI, "AllowPI failure")