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

TransmitUserFPD and TransmitPreciseGeo activity integration #2906

Merged
merged 11 commits into from
Jul 27, 2023
12 changes: 1 addition & 11 deletions exchange/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,6 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context,
}
// potentially block passing IDs based on CCPA
privacyEnforcement.CCPA = ccpaEnforcer.ShouldEnforce(bidderRequest.BidderName.String())
// potentially block passing IDs based on COPPA
if req.BidRequest.Regs != nil && req.BidRequest.Regs.COPPA == 1 {
privacyEnforcement.COPPA = true
}
}

passGeoActivityAllowed := auctionReq.Activities.Allow(privacy.ActivityTransmitPreciseGeo, scopedName)
Expand All @@ -207,15 +203,9 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context,
privacyEnforcement.GDPRGeo = true
}
}

// potentially block passing geo based on CCPA
privacyEnforcement.CCPA = ccpaEnforcer.ShouldEnforce(bidderRequest.BidderName.String())
// potentially block passing geo based on COPPA
if req.BidRequest.Regs != nil && req.BidRequest.Regs.COPPA == 1 {
privacyEnforcement.COPPA = true
}
// potentially block passing geo based on LMT
privacyEnforcement.LMT = lmtEnforcer.ShouldEnforce(unknownBidder)

}

if auctionReq.FirstPartyData != nil && auctionReq.FirstPartyData[bidderRequest.BidderName] != nil {
Expand Down
39 changes: 31 additions & 8 deletions privacy/scrubber.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ func NewScrubber() Scrubber {
}

func (scrubber) ScrubRequest(bidRequest *openrtb2.BidRequest, enforcement Enforcement) *openrtb2.BidRequest {
var userExtParsed map[string]json.RawMessage
userExtModified := false

if enforcement.UFPD || enforcement.Eids {
if len(bidRequest.User.Ext) != 0 {
json.Unmarshal(bidRequest.User.Ext, &userExtParsed)
}
}

if enforcement.UFPD {
// transmitUfpd covers user.ext.data, user.data, user.id, user.buyeruid, user.yob, user.gender, user.keywords, user.kwarray
// and device.{ifa, macsha1, macmd5, dpidsha1, dpidmd5, didsha1, didmd5}
Expand All @@ -97,23 +106,37 @@ func (scrubber) ScrubRequest(bidRequest *openrtb2.BidRequest, enforcement Enforc
}
if bidRequest.User != nil {
bidRequest.User.Data = nil
bidRequest.User.Ext = scrubExtIDs(bidRequest.User.Ext, "data")
bidRequest.User.ID = ""
bidRequest.User.BuyerUID = ""
bidRequest.User.Yob = 0
bidRequest.User.Gender = ""
bidRequest.User.Keywords = ""
bidRequest.User.KwArray = nil

_, hasField := userExtParsed["data"]
if hasField {
delete(userExtParsed, "data")
userExtModified = true
}
}
}
if enforcement.Eids {
//transmitEids covers user.eids and user.ext.eids
if bidRequest.User != nil {
bidRequest.User.EIDs = nil
bidRequest.User.Ext = scrubExtIDs(bidRequest.User.Ext, "eids")
_, hasField := userExtParsed["eids"]
if hasField {
delete(userExtParsed, "eids")
userExtModified = true
}
}
}

if userExtModified {
userExt, _ := json.Marshal(userExtParsed)
bidRequest.User.Ext = userExt
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we sure that User is not a shared object at this point?

Copy link
Contributor

Choose a reason for hiding this comment

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

The bidRequest is absolutely at least a shallow copy at this point. I'm good with adding a shallow clone here to be certain if it's not otherwise proven. We'll replace it in the near future with the RequestWrapper and the cost of cloning the User object doesn't seem too concerning.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added clones.

}

if enforcement.TID {
//remove source.tid and imp.ext.tid
if bidRequest.Source != nil {
Expand Down Expand Up @@ -268,15 +291,15 @@ func scrubGeoPrecision(geo *openrtb2.Geo) *openrtb2.Geo {
return &geoCopy
}

func scrubExtIDs(userExt json.RawMessage, fieldName string) json.RawMessage {
if len(userExt) == 0 {
return userExt
func scrubExtIDs(ext json.RawMessage, fieldName string) json.RawMessage {
if len(ext) == 0 {
return ext
}

var userExtParsed map[string]json.RawMessage
err := json.Unmarshal(userExt, &userExtParsed)
err := json.Unmarshal(ext, &userExtParsed)
if err != nil {
return userExt
return ext
}

_, hasField := userExtParsed[fieldName]
Expand All @@ -288,5 +311,5 @@ func scrubExtIDs(userExt json.RawMessage, fieldName string) json.RawMessage {
}
}

return userExt
return ext
}
51 changes: 39 additions & 12 deletions privacy/scrubber_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,15 @@ func TestScrubRequest(t *testing.T) {
user.EIDs = []openrtb2.EID{{Source: "test"}}

testCases := []struct {
description string
enforcement Enforcement
expected *openrtb2.BidRequest
description string
enforcement Enforcement
userExtPresent bool
expected *openrtb2.BidRequest
}{
{
description: "enforce transmitUFPD",
enforcement: Enforcement{UFPD: true},
description: "enforce transmitUFPD with user.ext",
enforcement: Enforcement{UFPD: true},
userExtPresent: true,
expected: &openrtb2.BidRequest{
Imp: imps,
Source: source,
Expand All @@ -340,8 +342,27 @@ func TestScrubRequest(t *testing.T) {
},
},
{
description: "enforce transmitEids",
enforcement: Enforcement{Eids: true},
description: "enforce transmitUFPD without user.ext",
enforcement: Enforcement{UFPD: true},
userExtPresent: false,
expected: &openrtb2.BidRequest{
Imp: imps,
Source: source,
User: &openrtb2.User{
EIDs: []openrtb2.EID{{Source: "test"}},
Geo: user.Geo,
},
Device: &openrtb2.Device{
IP: "1.2.3.4",
IPv6: "2001:0db8:0000:0000:0000:ff00:0042:8329",
Geo: device.Geo,
},
},
},
{
description: "enforce transmitEids",
enforcement: Enforcement{Eids: true},
userExtPresent: true,
expected: &openrtb2.BidRequest{
Imp: imps,
Source: source,
Expand All @@ -358,8 +379,9 @@ func TestScrubRequest(t *testing.T) {
},
},
{
description: "enforce transmitTid",
enforcement: Enforcement{TID: true},
description: "enforce transmitTid",
enforcement: Enforcement{TID: true},
userExtPresent: true,
expected: &openrtb2.BidRequest{
Imp: []openrtb2.Imp{
{ID: "testId", Ext: json.RawMessage(`{"test":1}`)},
Expand All @@ -380,8 +402,9 @@ func TestScrubRequest(t *testing.T) {
},
},
{
description: "enforce precise Geo",
enforcement: Enforcement{PreciseGeo: true},
description: "enforce precise Geo",
enforcement: Enforcement{PreciseGeo: true},
userExtPresent: true,
expected: &openrtb2.BidRequest{
Imp: imps,
Source: source,
Expand Down Expand Up @@ -432,7 +455,11 @@ func TestScrubRequest(t *testing.T) {
User: getTestUser(),
Device: getTestDevice(),
}
bidRequest.User.Ext = json.RawMessage(`{"data": 1, "eids": 2}`)
if test.userExtPresent {
bidRequest.User.Ext = json.RawMessage(`{"data": 1, "eids": 2}`)
} else {
bidRequest.User.Ext = nil
}
bidRequest.User.EIDs = []openrtb2.EID{{Source: "test"}}

result := NewScrubber().ScrubRequest(bidRequest, test.enforcement)
Expand Down