Skip to content

Commit

Permalink
Fixed TCF2 Geo Only Enforcement (#1492)
Browse files Browse the repository at this point in the history
  • Loading branch information
SyntaxNode authored Sep 15, 2020
1 parent 65c6c36 commit e7d0bab
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 222 deletions.
4 changes: 1 addition & 3 deletions exchange/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,10 @@ func cleanOpenRTBRequests(ctx context.Context,
coreBidder := resolveBidder(bidder.String(), aliases)

var publisherID = labels.PubID
ok, geo, id, err := gDPR.PersonalInfoAllowed(ctx, coreBidder, publisherID, consent)
privacyEnforcement.GDPR = !ok && err == nil
_, geo, id, err := gDPR.PersonalInfoAllowed(ctx, coreBidder, publisherID, consent)
privacyEnforcement.GDPRGeo = !geo && err == nil
privacyEnforcement.GDPRID = !id && err == nil
} else {
privacyEnforcement.GDPR = false
privacyEnforcement.GDPRGeo = false
privacyEnforcement.GDPRID = false
}
Expand Down
30 changes: 22 additions & 8 deletions privacy/enforcement.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import (
type Enforcement struct {
CCPA bool
COPPA bool
GDPR bool
GDPRGeo bool
GDPRID bool
LMT bool
}

// Any returns true if at least one privacy policy requires enforcement.
func (e Enforcement) Any() bool {
return e.CCPA || e.COPPA || e.GDPR || e.GDPRGeo || e.GDPRID || e.LMT
return e.CCPA || e.COPPA || e.GDPRGeo || e.GDPRID || e.LMT
}

// Apply cleans personally identifiable information from an OpenRTB bid request.
Expand All @@ -26,17 +25,33 @@ func (e Enforcement) Apply(bidRequest *openrtb.BidRequest, ampGDPRException bool

func (e Enforcement) apply(bidRequest *openrtb.BidRequest, ampGDPRException bool, scrubber Scrubber) {
if bidRequest != nil && e.Any() {
bidRequest.Device = scrubber.ScrubDevice(bidRequest.Device, e.getIPv6ScrubStrategy(), e.getGeoScrubStrategy())
bidRequest.Device = scrubber.ScrubDevice(bidRequest.Device, e.getDeviceIDScrubStrategy(), e.getIPv4ScrubStrategy(), e.getIPv6ScrubStrategy(), e.getGeoScrubStrategy())
bidRequest.User = scrubber.ScrubUser(bidRequest.User, e.getUserScrubStrategy(ampGDPRException), e.getGeoScrubStrategy())
}
}

func (e Enforcement) getDeviceIDScrubStrategy() ScrubStrategyDeviceID {
if e.COPPA || e.GDPRID || e.CCPA || e.LMT {
return ScrubStrategyDeviceIDAll
}

return ScrubStrategyDeviceIDNone
}

func (e Enforcement) getIPv4ScrubStrategy() ScrubStrategyIPV4 {
if e.COPPA || e.GDPRGeo || e.CCPA || e.LMT {
return ScrubStrategyIPV4Lowest8
}

return ScrubStrategyIPV4None
}

func (e Enforcement) getIPv6ScrubStrategy() ScrubStrategyIPV6 {
if e.COPPA {
return ScrubStrategyIPV6Lowest32
}

if e.GDPR || e.CCPA || e.LMT {
if e.GDPRGeo || e.CCPA || e.LMT {
return ScrubStrategyIPV6Lowest16
}

Expand All @@ -60,12 +75,11 @@ func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUs
return ScrubStrategyUserIDAndDemographic
}

if e.GDPR && ampGDPRException {
return ScrubStrategyUserNone
if e.CCPA || e.LMT {
return ScrubStrategyUserID
}

// If no user scrubbing is needed, then return none, else scrub ID (COPPA checked above)
if e.CCPA || e.GDPRID || e.LMT {
if e.GDPRID && !ampGDPRException {
return ScrubStrategyUserID
}

Expand Down
131 changes: 60 additions & 71 deletions privacy/enforcement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func TestAny(t *testing.T) {
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: false,
Expand All @@ -31,7 +30,6 @@ func TestAny(t *testing.T) {
enforcement: Enforcement{
CCPA: true,
COPPA: true,
GDPR: true,
GDPRGeo: true,
GDPRID: true,
LMT: true,
Expand All @@ -43,7 +41,6 @@ func TestAny(t *testing.T) {
enforcement: Enforcement{
CCPA: false,
COPPA: true,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: true,
Expand All @@ -63,6 +60,8 @@ func TestApply(t *testing.T) {
description string
enforcement Enforcement
ampGDPRException bool
expectedDeviceID ScrubStrategyDeviceID
expectedDeviceIPv4 ScrubStrategyIPV4
expectedDeviceIPv6 ScrubStrategyIPV6
expectedDeviceGeo ScrubStrategyGeo
expectedUser ScrubStrategyUser
Expand All @@ -73,12 +72,12 @@ func TestApply(t *testing.T) {
enforcement: Enforcement{
CCPA: true,
COPPA: true,
GDPR: true,
GDPRGeo: true,
GDPRID: true,
LMT: true,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
expectedDeviceGeo: ScrubStrategyGeoFull,
expectedUser: ScrubStrategyUserIDAndDemographic,
Expand All @@ -89,12 +88,12 @@ func TestApply(t *testing.T) {
enforcement: Enforcement{
CCPA: true,
COPPA: false,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: false,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserID,
Expand All @@ -105,124 +104,97 @@ func TestApply(t *testing.T) {
enforcement: Enforcement{
CCPA: false,
COPPA: true,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: false,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
expectedDeviceGeo: ScrubStrategyGeoFull,
expectedUser: ScrubStrategyUserIDAndDemographic,
expectedUserGeo: ScrubStrategyGeoFull,
},
{
description: "GDPR Only",
description: "GDPR Only - Full",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: true,
GDPRGeo: true,
GDPRID: true,
LMT: false,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserID,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "GDPR Only, ampGDPRException",
description: "GDPR Only - Full - AMP Exception",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: true,
GDPRGeo: true,
GDPRID: true,
LMT: false,
},
ampGDPRException: true,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserNone,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "CCPA Only, ampGDPRException",
enforcement: Enforcement{
CCPA: true,
COPPA: false,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: false,
},
ampGDPRException: true,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserID,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "COPPA and GDPR, ampGDPRException",
enforcement: Enforcement{
CCPA: false,
COPPA: true,
GDPR: true,
GDPRGeo: true,
GDPRID: true,
LMT: false,
},
ampGDPRException: true,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
expectedDeviceGeo: ScrubStrategyGeoFull,
expectedUser: ScrubStrategyUserIDAndDemographic,
expectedUserGeo: ScrubStrategyGeoFull,
},
{
description: "GDPR Only, no Geo",
description: "GDPR Only - ID Only",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: true,
GDPRGeo: false,
GDPRID: true,
LMT: false,
},
ampGDPRException: false,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4None,
expectedDeviceIPv6: ScrubStrategyIPV6None,
expectedDeviceGeo: ScrubStrategyGeoNone,
expectedUser: ScrubStrategyUserID,
expectedUserGeo: ScrubStrategyGeoNone,
},
{
description: "GDPR Only, Geo only",
description: "GDPR Only - ID Only - AMP Exception",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: false,
GDPRGeo: true,
GDPRID: false,
GDPRGeo: false,
GDPRID: true,
LMT: false,
},
ampGDPRException: false,
ampGDPRException: true,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4None,
expectedDeviceIPv6: ScrubStrategyIPV6None,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedDeviceGeo: ScrubStrategyGeoNone,
expectedUser: ScrubStrategyUserNone,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
expectedUserGeo: ScrubStrategyGeoNone,
},
{
description: "GDPR Only, ID exception",
description: "GDPR Only - Geo Only",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: true,
GDPRGeo: true,
GDPRID: false,
LMT: false,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDNone,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserNone,
Expand All @@ -233,32 +205,50 @@ func TestApply(t *testing.T) {
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: true,
},
ampGDPRException: false,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserID,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "LMT Only, ampGDPRException",
description: "Interactions: COPPA Only + AMP Exception",
enforcement: Enforcement{
CCPA: false,
COPPA: false,
GDPR: false,
COPPA: true,
GDPRGeo: false,
GDPRID: false,
LMT: true,
LMT: false,
},
ampGDPRException: true,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
expectedDeviceGeo: ScrubStrategyGeoReducedPrecision,
expectedUser: ScrubStrategyUserID,
expectedUserGeo: ScrubStrategyGeoReducedPrecision,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
expectedDeviceGeo: ScrubStrategyGeoFull,
expectedUser: ScrubStrategyUserIDAndDemographic,
expectedUserGeo: ScrubStrategyGeoFull,
},
{
description: "Interactions: COPPA + GDPR Full + AMP Exception",
enforcement: Enforcement{
CCPA: false,
COPPA: true,
GDPRGeo: true,
GDPRID: true,
LMT: false,
},
ampGDPRException: true,
expectedDeviceID: ScrubStrategyDeviceIDAll,
expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
expectedDeviceGeo: ScrubStrategyGeoFull,
expectedUser: ScrubStrategyUserIDAndDemographic,
expectedUserGeo: ScrubStrategyGeoFull,
},
}

Expand All @@ -271,7 +261,7 @@ func TestApply(t *testing.T) {
replacedUser := &openrtb.User{}

m := &mockScrubber{}
m.On("ScrubDevice", req.Device, test.expectedDeviceIPv6, test.expectedDeviceGeo).Return(replacedDevice).Once()
m.On("ScrubDevice", req.Device, test.expectedDeviceID, test.expectedDeviceIPv4, test.expectedDeviceIPv6, test.expectedDeviceGeo).Return(replacedDevice).Once()
m.On("ScrubUser", req.User, test.expectedUser, test.expectedUserGeo).Return(replacedUser).Once()

test.enforcement.apply(req, test.ampGDPRException, m)
Expand All @@ -290,7 +280,6 @@ func TestApplyNoneApplicable(t *testing.T) {
enforcement := Enforcement{
CCPA: false,
COPPA: false,
GDPR: false,
GDPRGeo: false,
GDPRID: false,
LMT: false,
Expand All @@ -315,8 +304,8 @@ type mockScrubber struct {
mock.Mock
}

func (m *mockScrubber) ScrubDevice(device *openrtb.Device, ipv6 ScrubStrategyIPV6, geo ScrubStrategyGeo) *openrtb.Device {
args := m.Called(device, ipv6, geo)
func (m *mockScrubber) ScrubDevice(device *openrtb.Device, id ScrubStrategyDeviceID, ipv4 ScrubStrategyIPV4, ipv6 ScrubStrategyIPV6, geo ScrubStrategyGeo) *openrtb.Device {
args := m.Called(device, id, ipv4, ipv6, geo)
return args.Get(0).(*openrtb.Device)
}

Expand Down
Loading

0 comments on commit e7d0bab

Please sign in to comment.