diff --git a/endpoints/cookie_sync.go b/endpoints/cookie_sync.go index c7dc23e1c84..f0299d2e306 100644 --- a/endpoints/cookie_sync.go +++ b/endpoints/cookie_sync.go @@ -528,7 +528,6 @@ func (p usersyncPrivacy) CCPAAllowsBidderSync(bidder string) bool { } func (p usersyncPrivacy) ActivityAllowsUserSync(bidder string) bool { - activityResult := p.activityControl.Evaluate(privacy.ActivitySyncUser, + return p.activityControl.Allow(privacy.ActivitySyncUser, privacy.ScopedName{Scope: privacy.ScopeTypeBidder, Name: bidder}) - return activityResult == privacy.ActivityAllow } diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go index e9d812b8baf..22ecc1faf9e 100644 --- a/endpoints/cookie_sync_test.go +++ b/endpoints/cookie_sync_test.go @@ -1909,27 +1909,32 @@ func TestCookieSyncActivityControlIntegration(t *testing.T) { testCases := []struct { name string bidderName string - allow bool + accountPrivacy *config.AccountPrivacy expectedResult bool }{ { name: "activity_is_allowed", bidderName: "bidderA", - allow: true, + accountPrivacy: getDefaultActivityConfig("bidderA", true), expectedResult: true, }, { name: "activity_is_denied", bidderName: "bidderA", - allow: false, + accountPrivacy: getDefaultActivityConfig("bidderA", false), expectedResult: false, }, + { + name: "activity_is_abstain", + bidderName: "bidderA", + accountPrivacy: nil, + expectedResult: true, + }, } for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - privacyConfig := getDefaultActivityConfig(test.bidderName, test.allow) - activities, err := privacy.NewActivityControl(privacyConfig) + activities, err := privacy.NewActivityControl(test.accountPrivacy) assert.NoError(t, err) up := usersyncPrivacy{ activityControl: activities, diff --git a/endpoints/setuid.go b/endpoints/setuid.go index 4fae58cb36c..58b6f8db41d 100644 --- a/endpoints/setuid.go +++ b/endpoints/setuid.go @@ -111,9 +111,9 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use } } - userSyncActivityAllowed := activities.Evaluate(privacy.ActivitySyncUser, + userSyncActivityAllowed := activities.Allow(privacy.ActivitySyncUser, privacy.ScopedName{Scope: privacy.ScopeTypeBidder, Name: bidderName}) - if userSyncActivityAllowed == privacy.ActivityDeny { + if !userSyncActivityAllowed { w.WriteHeader(http.StatusUnavailableForLegalReasons) return } diff --git a/exchange/utils.go b/exchange/utils.go index 8f6f00b2018..17bba334e89 100644 --- a/exchange/utils.go +++ b/exchange/utils.go @@ -153,8 +153,8 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, // fetchBids activity scopedName := privacy.ScopedName{Scope: privacy.ScopeTypeBidder, Name: bidderRequest.BidderName.String()} - fetchBidsActivityAllowed := auctionReq.Activities.Evaluate(privacy.ActivityFetchBids, scopedName) - if fetchBidsActivityAllowed == privacy.ActivityDeny { + fetchBidsActivityAllowed := auctionReq.Activities.Allow(privacy.ActivityFetchBids, scopedName) + if !fetchBidsActivityAllowed { // skip the call to a bidder if fetchBids activity is not allowed // do not add this bidder to allowedBidderRequests continue @@ -173,8 +173,8 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, } } - passIDActivityAllowed := auctionReq.Activities.Evaluate(privacy.ActivityTransmitUserFPD, scopedName) - if passIDActivityAllowed == privacy.ActivityDeny { + passIDActivityAllowed := auctionReq.Activities.Allow(privacy.ActivityTransmitUserFPD, scopedName) + if !passIDActivityAllowed { privacyEnforcement.UFPD = true } else { // run existing policies (GDPR, CCPA, COPPA, LMT) @@ -190,8 +190,8 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context, privacyEnforcement.CCPA = ccpaEnforcer.ShouldEnforce(bidderRequest.BidderName.String()) } - passGeoActivityAllowed := auctionReq.Activities.Evaluate(privacy.ActivityTransmitPreciseGeo, scopedName) - if passGeoActivityAllowed == privacy.ActivityDeny { + passGeoActivityAllowed := auctionReq.Activities.Allow(privacy.ActivityTransmitPreciseGeo, scopedName) + if !passGeoActivityAllowed { privacyEnforcement.PreciseGeo = true } else { // run existing policies (GDPR, CCPA, COPPA, LMT) diff --git a/privacy/enforcer.go b/privacy/enforcer.go index 3a360c5d8b0..aeaaab8dd27 100644 --- a/privacy/enforcer.go +++ b/privacy/enforcer.go @@ -23,6 +23,8 @@ const ( ScopeTypeGeneral = "general" ) +const defaultActivityResult = true + type ActivityControl struct { plans map[Activity]ActivityPlan } @@ -124,36 +126,34 @@ func conditionToRuleComponentNames(conditions []string) ([]ScopedName, error) { return sn, nil } -func activityDefaultToDefaultResult(activityDefault *bool) ActivityResult { +func activityDefaultToDefaultResult(activityDefault *bool) bool { if activityDefault == nil { // if default is unspecified, the hardcoded default-default is true. - return ActivityAllow - } else if *activityDefault { - return ActivityAllow + return defaultActivityResult } - return ActivityDeny + return *activityDefault } -func (e ActivityControl) Evaluate(activity Activity, target ScopedName) ActivityResult { +func (e ActivityControl) Allow(activity Activity, target ScopedName) bool { plan, planDefined := e.plans[activity] if !planDefined { - return ActivityAbstain + return defaultActivityResult } return plan.Evaluate(target) } type ActivityPlan struct { - defaultResult ActivityResult + defaultResult bool rules []ActivityRule } -func (p ActivityPlan) Evaluate(target ScopedName) ActivityResult { +func (p ActivityPlan) Evaluate(target ScopedName) bool { for _, rule := range p.rules { result := rule.Evaluate(target) if result == ActivityDeny || result == ActivityAllow { - return result + return result == ActivityAllow } } return p.defaultResult diff --git a/privacy/enforcer_test.go b/privacy/enforcer_test.go index 49f3a5076d1..864964c2a51 100644 --- a/privacy/enforcer_test.go +++ b/privacy/enforcer_test.go @@ -148,22 +148,22 @@ func TestActivityDefaultToDefaultResult(t *testing.T) { testCases := []struct { name string activityDefault *bool - expectedResult ActivityResult + expectedResult bool }{ { name: "nil", activityDefault: nil, - expectedResult: ActivityAllow, + expectedResult: true, }, { name: "true", activityDefault: ptrutil.ToPtr(true), - expectedResult: ActivityAllow, + expectedResult: true, }, { name: "false", activityDefault: ptrutil.ToPtr(false), - expectedResult: ActivityDeny, + expectedResult: false, }, } @@ -182,14 +182,14 @@ func TestAllowActivityControl(t *testing.T) { activityControl ActivityControl activity Activity target ScopedName - activityResult ActivityResult + activityResult bool }{ { name: "plans_is_nil", activityControl: ActivityControl{plans: nil}, activity: ActivityFetchBids, target: ScopedName{Scope: "bidder", Name: "bidderA"}, - activityResult: ActivityAbstain, + activityResult: true, }, { name: "activity_not_defined", @@ -197,7 +197,7 @@ func TestAllowActivityControl(t *testing.T) { ActivitySyncUser: getDefaultActivityPlan()}}, activity: ActivityFetchBids, target: ScopedName{Scope: "bidder", Name: "bidderA"}, - activityResult: ActivityAbstain, + activityResult: true, }, { name: "activity_defined_but_not_found_default_returned", @@ -205,7 +205,7 @@ func TestAllowActivityControl(t *testing.T) { ActivityFetchBids: getDefaultActivityPlan()}}, activity: ActivityFetchBids, target: ScopedName{Scope: "bidder", Name: "bidderB"}, - activityResult: ActivityAllow, + activityResult: true, }, { name: "activity_defined_and_allowed", @@ -213,13 +213,13 @@ func TestAllowActivityControl(t *testing.T) { ActivityFetchBids: getDefaultActivityPlan()}}, activity: ActivityFetchBids, target: ScopedName{Scope: "bidder", Name: "bidderA"}, - activityResult: ActivityAllow, + activityResult: true, }, } for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - actualResult := test.activityControl.Evaluate(test.activity, test.target) + actualResult := test.activityControl.Allow(test.activity, test.target) assert.Equal(t, test.activityResult, actualResult) }) @@ -404,7 +404,7 @@ func getDefaultActivityConfig() config.Activity { func getDefaultActivityPlan() ActivityPlan { return ActivityPlan{ - defaultResult: ActivityAllow, + defaultResult: true, rules: []ActivityRule{ ComponentEnforcementRule{ result: ActivityAllow,