From 36dba898114fcba7d2871601167072f8ed2a87ba Mon Sep 17 00:00:00 2001 From: pkaczmarek Date: Fri, 20 Dec 2024 14:12:54 +0100 Subject: [PATCH] task 3678 --- config/account.go | 10 ++++++++++ exchange/exchange.go | 15 ++++++++++++--- exchange/gdpr.go | 12 ++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/config/account.go b/config/account.go index a54da82d21..9f2880c369 100644 --- a/config/account.go +++ b/config/account.go @@ -42,6 +42,7 @@ type Account struct { DefaultBidLimit int `mapstructure:"default_bid_limit" json:"default_bid_limit"` BidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments `mapstructure:"bidadjustments" json:"bidadjustments"` Privacy AccountPrivacy `mapstructure:"privacy" json:"privacy"` + EEACountries []string `mapstructure:"eea_countries" json:"eea_countries"` } // CookieSync represents the account-level defaults for the cookie sync endpoint. @@ -381,3 +382,12 @@ func (ip *IPv4) Validate(errs []error) []error { } return errs } + +func (a *Account) ValidateEEACountries(errs []error) []error { + for _, country := range a.EEACountries { + if len(country) != 2 { // Check if country code is valid + errs = append(errs, fmt.Errorf("invalid EEA country code: %s", country)) + } + } + return errs +} diff --git a/exchange/exchange.go b/exchange/exchange.go index 9ab91ee9ea..72c83fad2d 100644 --- a/exchange/exchange.go +++ b/exchange/exchange.go @@ -316,8 +316,17 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog recordImpMetrics(r.BidRequestWrapper, e.me) + // Retrieve host and account-level EEA countries config + eeaCountries := SelectEEACountries(e.privacyConfig.GDPR.EEACountries, r.Account.EEACountries) + + // Create a map for efficient lookup + eeaCountriesMap := make(map[string]struct{}) + for _, country := range eeaCountries { + eeaCountriesMap[strings.ToUpper(country)] = struct{}{} + } + // Make our best guess if GDPR applies - gdprDefaultValue := e.parseGDPRDefaultValue(r.BidRequestWrapper) + gdprDefaultValue := e.parseGDPRDefaultValue(r.BidRequestWrapper, eeaCountriesMap) gdprSignal, err := getGDPR(r.BidRequestWrapper) if err != nil { return nil, err @@ -571,7 +580,7 @@ func buildMultiBidMap(prebid *openrtb_ext.ExtRequestPrebid) map[string]openrtb_e return multiBidMap } -func (e *exchange) parseGDPRDefaultValue(r *openrtb_ext.RequestWrapper) gdpr.Signal { +func (e *exchange) parseGDPRDefaultValue(r *openrtb_ext.RequestWrapper, eeaCountriesMap map[string]struct{}) gdpr.Signal { gdprDefaultValue := e.gdprDefaultValue var geo *openrtb2.Geo @@ -584,7 +593,7 @@ func (e *exchange) parseGDPRDefaultValue(r *openrtb_ext.RequestWrapper) gdpr.Sig 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.privacyConfig.GDPR.EEACountriesMap[strings.ToUpper(geo.Country)]; found { + if _, found := eeaCountriesMap[strings.ToUpper(geo.Country)]; found { gdprDefaultValue = gdpr.SignalYes } else if len(geo.Country) == 3 { // The country field is formatted properly as a three character country code diff --git a/exchange/gdpr.go b/exchange/gdpr.go index 866f33baed..781b27bb3f 100644 --- a/exchange/gdpr.go +++ b/exchange/gdpr.go @@ -40,3 +40,15 @@ func enforceGDPR(signal gdpr.Signal, defaultValue gdpr.Signal, channelEnabled bo gdprApplies := signal == gdpr.SignalYes || (signal == gdpr.SignalAmbiguous && defaultValue == gdpr.SignalYes) return gdprApplies && channelEnabled } + +// SelectEEACountries selects the EEA countries based on host and account configurations. +// Account-level configuration takes precedence over the host-level configuration. +func SelectEEACountries(hostEEACountries []string, accountEEACountries []string) []string { + // If account-level configuration is provided, it takes precedence. + if len(accountEEACountries) > 0 { + return accountEEACountries + } + + // Otherwise, return the host-level configuration. + return hostEEACountries +}