Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Commit

Permalink
Privacy: Remove user.ext.eids (prebid#1294)
Browse files Browse the repository at this point in the history
* Privacy: Remove user.ext.eids

* Extract To A Method

* Minor Refactor + More Tests

* Performance Tweak
  • Loading branch information
SyntaxNode authored Jun 1, 2020
1 parent 5981e06 commit d5391b2
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 28 deletions.
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)
}
}

0 comments on commit d5391b2

Please sign in to comment.