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

Privacy: Remove user.ext.eids #1294

Merged
merged 5 commits into from
Jun 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions privacy/scrubber.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package privacy

import (
"encoding/json"
"strings"

"github.com/mxmCherry/openrtb"
Expand Down Expand Up @@ -104,11 +105,13 @@ func (scrubber) ScrubUser(user *openrtb.User, strategy ScrubStrategyUser, geo Sc
case ScrubStrategyUserIDAndDemographic:
userCopy.BuyerUID = ""
userCopy.ID = ""
userCopy.Ext = scrubUserExtIDs(userCopy.Ext)
userCopy.Yob = 0
userCopy.Gender = ""
case ScrubStrategyUserID:
userCopy.BuyerUID = ""
userCopy.ID = ""
userCopy.Ext = scrubUserExtIDs(userCopy.Ext)
}

switch geo {
Expand Down Expand Up @@ -179,3 +182,29 @@ func scrubGeoPrecision(geo *openrtb.Geo) *openrtb.Geo {
geoCopy.Lon = float64(int(geo.Lon*100.0+0.5)) / 100.0 // Round Longitude
return &geoCopy
}

func scrubUserExtIDs(userExt json.RawMessage) json.RawMessage {
if len(userExt) == 0 {
return userExt
}

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

_, hasEids := userExtParsed["eids"]
_, hasDigitrust := userExtParsed["digitrust"]
if hasEids || hasDigitrust {
delete(userExtParsed, "eids")
delete(userExtParsed, "digitrust")

result, err := json.Marshal(userExtParsed)
if err == nil {
return result
}
}

return userExt
}
186 changes: 158 additions & 28 deletions privacy/scrubber_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package privacy

import (
"encoding/json"
"testing"

"github.com/mxmCherry/openrtb"
Expand Down Expand Up @@ -241,6 +242,7 @@ func TestScrubUser(t *testing.T) {
BuyerUID: "anyBuyerUID",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
Geo: &openrtb.Geo{
Lat: 123.456,
Lon: 678.89,
Expand All @@ -251,30 +253,32 @@ func TestScrubUser(t *testing.T) {
}

testCases := []struct {
expected *openrtb.User
user ScrubStrategyUser
geo ScrubStrategyGeo
description string
expected *openrtb.User
scrubUser ScrubStrategyUser
scrubGeo ScrubStrategyGeo
}{
{
description: "Demographic Age And Gender & Geo Full",
description: "User ID And Demographic & Geo Full",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 0,
Gender: "",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{},
},
user: ScrubStrategyUserIDAndDemographic,
geo: ScrubStrategyGeoFull,
scrubUser: ScrubStrategyUserIDAndDemographic,
scrubGeo: ScrubStrategyGeoFull,
},
{
description: "Demographic Age And Gender & Geo Reduced",
description: "User ID And Demographic & Geo Reduced",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 0,
Gender: "",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{
Lat: 123.46,
Lon: 678.89,
Expand All @@ -283,16 +287,17 @@ func TestScrubUser(t *testing.T) {
ZIP: "some zip",
},
},
user: ScrubStrategyUserIDAndDemographic,
geo: ScrubStrategyGeoReducedPrecision,
scrubUser: ScrubStrategyUserIDAndDemographic,
scrubGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "Demographic Full & Geo None",
description: "User ID And Demographic & Geo None",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 0,
Gender: "",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{
Lat: 123.456,
Lon: 678.89,
Expand All @@ -301,28 +306,30 @@ func TestScrubUser(t *testing.T) {
ZIP: "some zip",
},
},
user: ScrubStrategyUserIDAndDemographic,
geo: ScrubStrategyGeoNone,
scrubUser: ScrubStrategyUserIDAndDemographic,
scrubGeo: ScrubStrategyGeoNone,
},
{
description: "Demographic Buyer ID & Geo Full",
description: "User ID & Geo Full",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{},
},
user: ScrubStrategyUserID,
geo: ScrubStrategyGeoFull,
scrubUser: ScrubStrategyUserID,
scrubGeo: ScrubStrategyGeoFull,
},
{
description: "Demographic Buyer ID & Geo Reduced",
description: "User ID & Geo Reduced",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{
Lat: 123.46,
Lon: 678.89,
Expand All @@ -331,34 +338,68 @@ func TestScrubUser(t *testing.T) {
ZIP: "some zip",
},
},
user: ScrubStrategyUserID,
geo: ScrubStrategyGeoReducedPrecision,
scrubUser: ScrubStrategyUserID,
scrubGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "User ID & Geo None",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{}`),
Geo: &openrtb.Geo{
Lat: 123.456,
Lon: 678.89,
Metro: "some metro",
City: "some city",
ZIP: "some zip",
},
},
scrubUser: ScrubStrategyUserID,
scrubGeo: ScrubStrategyGeoNone,
},
{
description: "User None & Geo Full",
expected: &openrtb.User{
ID: "anyID",
BuyerUID: "anyBuyerUID",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
Geo: &openrtb.Geo{},
},
scrubUser: ScrubStrategyUserNone,
scrubGeo: ScrubStrategyGeoFull,
},
{
description: "Demographic None & Geo None",
description: "User None & Geo Reduced",
expected: &openrtb.User{
ID: "anyID",
BuyerUID: "anyBuyerUID",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
Geo: &openrtb.Geo{
Lat: 123.456,
Lat: 123.46,
Lon: 678.89,
Metro: "some metro",
City: "some city",
ZIP: "some zip",
},
},
user: ScrubStrategyUserNone,
geo: ScrubStrategyGeoNone,
scrubUser: ScrubStrategyUserNone,
scrubGeo: ScrubStrategyGeoReducedPrecision,
},
{
description: "Demographic BuyerIDOnly & Geo None",
description: "User None & Geo None",
expected: &openrtb.User{
ID: "",
BuyerUID: "",
ID: "anyID",
BuyerUID: "anyBuyerUID",
Yob: 42,
Gender: "anyGender",
Ext: json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
Geo: &openrtb.Geo{
Lat: 123.456,
Lon: 678.89,
Expand All @@ -367,13 +408,13 @@ func TestScrubUser(t *testing.T) {
ZIP: "some zip",
},
},
user: ScrubStrategyUserID,
geo: ScrubStrategyGeoNone,
scrubUser: ScrubStrategyUserNone,
scrubGeo: ScrubStrategyGeoNone,
},
}

for _, test := range testCases {
result := NewScrubber().ScrubUser(user, test.user, test.geo)
result := NewScrubber().ScrubUser(user, test.scrubUser, test.scrubGeo)
assert.Equal(t, test.expected, result, test.description)
}
}
Expand Down Expand Up @@ -552,3 +593,92 @@ func TestScrubGeoPrecisionWhenNil(t *testing.T) {
result := scrubGeoPrecision(nil)
assert.Nil(t, result)
}

func TestScrubUserExtIDs(t *testing.T) {
testCases := []struct {
description string
userExt json.RawMessage
expected json.RawMessage
}{
{
description: "Nil",
userExt: nil,
expected: nil,
},
{
description: "Empty String",
userExt: json.RawMessage(``),
expected: json.RawMessage(``),
},
{
description: "Empty Object",
userExt: json.RawMessage(`{}`),
expected: json.RawMessage(`{}`),
},
{
description: "Do Nothing When Malformed",
userExt: json.RawMessage(`malformed`),
expected: json.RawMessage(`malformed`),
},
{
description: "Do Nothing When No IDs Present",
userExt: json.RawMessage(`{"anyExisting":42}}`),
expected: json.RawMessage(`{"anyExisting":42}}`),
},
{
description: "Remove eids + digitrust",
userExt: json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{}`),
},
{
description: "Remove eids + digitrust - With Other Data",
userExt: json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{"anyExisting":42}`),
},
{
description: "Remove eids + digitrust - With Other Nested Data",
userExt: json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}],"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{"anyExisting":{"existing":42}}`),
},
{
description: "Remove eids Only",
userExt: json.RawMessage(`{"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
expected: json.RawMessage(`{}`),
},
{
description: "Remove eids Only - Empty Array",
userExt: json.RawMessage(`{"eids":[]}`),
expected: json.RawMessage(`{}`),
},
{
description: "Remove eids Only - With Other Data",
userExt: json.RawMessage(`{"anyExisting":42,"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
expected: json.RawMessage(`{"anyExisting":42}`),
},
{
description: "Remove eids Only - With Other Nested Data",
userExt: json.RawMessage(`{"anyExisting":{"existing":42},"eids":[{"source":"anySource","id":"anyId","uids":[{"id":"anyId","ext":{"id":42}}],"ext":{"id":42}}]}`),
expected: json.RawMessage(`{"anyExisting":{"existing":42}}`),
},
{
description: "Remove digitrust Only",
userExt: json.RawMessage(`{"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{}`),
},
{
description: "Remove digitrust Only - With Other Data",
userExt: json.RawMessage(`{"anyExisting":42,"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{"anyExisting":42}`),
},
{
description: "Remove digitrust Only - With Other Nested Data",
userExt: json.RawMessage(`{"anyExisting":{"existing":42},"digitrust":{"id":"anyId","keyv":4,"pref":8}}`),
expected: json.RawMessage(`{"anyExisting":{"existing":42}}`),
},
}

for _, test := range testCases {
result := scrubUserExtIDs(test.userExt)
assert.Equal(t, test.expected, result, test.description)
}
}