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 Sandbox: support testing label header #3381

Merged
merged 32 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ef67df2
Privacy Sandbox: support testing label header #3297
pm-nilesh-chate Jan 3, 2024
6305606
udpate device.ext.cdep
pm-nilesh-chate Jan 3, 2024
187d6a3
move config auction to root lvl
pm-nilesh-chate Jan 18, 2024
dd3244e
refactor + new ut
pm-nilesh-chate Jan 19, 2024
067330a
add ut for secCookieDeprecation
pm-nilesh-chate Jan 19, 2024
2894864
refactor as per review
pm-nilesh-chate Jan 22, 2024
0ecfdec
cookie sync refactor as per review comments
pm-nilesh-chate Jan 22, 2024
96141e7
prc
pm-nilesh-chate Jan 22, 2024
94e020c
add cdep len validation tests
pm-nilesh-chate Jan 25, 2024
fcf8b00
fix: use warning for cdep len check
pm-nilesh-chate Jan 25, 2024
644f484
refactor as per review
pm-nilesh-chate Jan 30, 2024
445bb75
typo fix
pm-nilesh-chate Jan 30, 2024
cf2b466
revert typo
pm-nilesh-chate Jan 30, 2024
2a844f6
address nitpick pr reviews
pm-nilesh-chate Feb 5, 2024
1b1ca06
add Partitioned cookie type
pm-nilesh-chate Feb 8, 2024
e443ea5
refactor: validateOrFillCDep
pm-nilesh-chate Feb 13, 2024
3625a9b
pr comments
pm-nilesh-chate Feb 16, 2024
05cdf32
pr comment
pm-nilesh-chate Feb 16, 2024
344de67
seperate setCookieDeprecationHeader tests
pm-nilesh-chate Feb 16, 2024
7767c3d
Merge remote-tracking branch 'upstream-vanilla/master'
pm-nilesh-chate Feb 20, 2024
f9969ab
prc
pm-nilesh-chate Feb 22, 2024
cb5ff78
Merge remote-tracking branch 'upstream-vanilla/master'
pm-nilesh-chate Feb 22, 2024
dabc8bb
prc
pm-nilesh-chate Feb 22, 2024
fdc2829
prc
pm-nilesh-chate Feb 22, 2024
829c797
typo
pm-nilesh-chate Feb 22, 2024
990faea
fix TestAmpBadRequests
pm-nilesh-chate Feb 26, 2024
5d5cf55
Revert "fix TestAmpBadRequests"
pm-nilesh-chate Feb 26, 2024
0d83607
prc test case names
pm-nilesh-chate Feb 26, 2024
b6068d4
update testname validateOrFillCDep
pm-nilesh-chate Feb 26, 2024
c7bee8e
tn
pm-nilesh-chate Feb 26, 2024
a09ead0
prc
pm-nilesh-chate Feb 28, 2024
b4e1d3c
prc
pm-nilesh-chate Feb 29, 2024
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
10 changes: 10 additions & 0 deletions config/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,16 @@ type AccountPrivacy struct {
AllowActivities *AllowActivities `mapstructure:"allowactivities" json:"allowactivities"`
IPv6Config IPv6 `mapstructure:"ipv6" json:"ipv6"`
IPv4Config IPv4 `mapstructure:"ipv4" json:"ipv4"`
PrivacySandbox PrivacySandbox `mapstructure:"privacysandbox" json:"privacysandbox"`
}

type PrivacySandbox struct {
CookieDeprecation CookieDeprecation `mapstructure:"cookiedeprecation"`
}

type CookieDeprecation struct {
Enabled bool `mapstructure:"enabled"`
TTLSec int `mapstructure:"ttl_sec"`
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved
}

type IPv6 struct {
Expand Down
51 changes: 43 additions & 8 deletions endpoints/cookie_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"strconv"
"strings"
"time"

"github.com/golang/glog"
"github.com/julienschmidt/httprouter"
Expand All @@ -29,8 +30,11 @@ import (
"github.com/prebid/prebid-server/v2/usersync"
"github.com/prebid/prebid-server/v2/util/jsonutil"
stringutil "github.com/prebid/prebid-server/v2/util/stringutil"
"github.com/prebid/prebid-server/v2/util/timeutil"
)

const receiveCookieDeprecation = "receive-cookie-deprecation"

var (
errCookieSyncOptOut = errors.New("User has opted out")
errCookieSyncBody = errors.New("Failed to read request body")
Expand Down Expand Up @@ -73,6 +77,7 @@ func NewCookieSyncEndpoint(
metrics: metrics,
pbsAnalytics: analyticsRunner,
accountsFetcher: accountsFetcher,
time: &timeutil.RealTime{},
}
}

Expand All @@ -83,10 +88,12 @@ type cookieSyncEndpoint struct {
metrics metrics.MetricsEngine
pbsAnalytics analytics.Runner
accountsFetcher stored_requests.AccountFetcher
time timeutil.Time
}

func (c *cookieSyncEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
request, privacyMacros, err := c.parseRequest(r)
request, privacyMacros, account, err := c.parseRequest(r)
c.setCookieDeprecationHeader(w, r, account)
if err != nil {
c.writeParseRequestErrorMetrics(err)
c.handleError(w, err, http.StatusBadRequest)
Expand All @@ -113,32 +120,32 @@ func (c *cookieSyncEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ ht
}
}

func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, macros.UserSyncPrivacy, error) {
func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, macros.UserSyncPrivacy, *config.Account, error) {
defer r.Body.Close()
body, err := io.ReadAll(r.Body)
if err != nil {
return usersync.Request{}, macros.UserSyncPrivacy{}, errCookieSyncBody
return usersync.Request{}, macros.UserSyncPrivacy{}, nil, errCookieSyncBody
}

request := cookieSyncRequest{}
if err := jsonutil.UnmarshalValid(body, &request); err != nil {
return usersync.Request{}, macros.UserSyncPrivacy{}, fmt.Errorf("JSON parsing failed: %s", err.Error())
return usersync.Request{}, macros.UserSyncPrivacy{}, nil, fmt.Errorf("JSON parsing failed: %s", err.Error())
}

if request.Account == "" {
request.Account = metrics.PublisherUnknown
}
account, fetchErrs := accountService.GetAccount(context.Background(), c.config, c.accountsFetcher, request.Account, c.metrics)
if len(fetchErrs) > 0 {
return usersync.Request{}, macros.UserSyncPrivacy{}, combineErrors(fetchErrs)
return usersync.Request{}, macros.UserSyncPrivacy{}, nil, combineErrors(fetchErrs)
}

request = c.setLimit(request, account.CookieSync)
request = c.setCooperativeSync(request, account.CookieSync)

privacyMacros, gdprSignal, privacyPolicies, err := extractPrivacyPolicies(request, c.privacyConfig.gdprConfig.DefaultValue)
if err != nil {
return usersync.Request{}, macros.UserSyncPrivacy{}, err
return usersync.Request{}, macros.UserSyncPrivacy{}, account, err
}

ccpaParsedPolicy := ccpa.ParsedPolicy{}
Expand All @@ -156,7 +163,7 @@ func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, ma

syncTypeFilter, err := parseTypeFilter(request.FilterSettings)
if err != nil {
return usersync.Request{}, macros.UserSyncPrivacy{}, err
return usersync.Request{}, macros.UserSyncPrivacy{}, account, err
}

gdprRequestInfo := gdpr.RequestInfo{
Expand Down Expand Up @@ -185,7 +192,7 @@ func (c *cookieSyncEndpoint) parseRequest(r *http.Request) (usersync.Request, ma
SyncTypeFilter: syncTypeFilter,
GPPSID: request.GPPSID,
}
return rx, privacyMacros, nil
return rx, privacyMacros, account, nil
}

func extractPrivacyPolicies(request cookieSyncRequest, usersyncDefaultGDPRValue string) (macros.UserSyncPrivacy, gdpr.Signal, privacy.Policies, error) {
Expand Down Expand Up @@ -455,11 +462,39 @@ func (c *cookieSyncEndpoint) handleResponse(w http.ResponseWriter, tf usersync.S
})

w.Header().Set("Content-Type", "application/json; charset=utf-8")

enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
enc.Encode(response)
}

func (c *cookieSyncEndpoint) setCookieDeprecationHeader(w http.ResponseWriter, r *http.Request, account *config.Account) {
if rcd, err := r.Cookie(receiveCookieDeprecation); err == nil && rcd != nil {
return
}
if account == nil || !account.Privacy.PrivacySandbox.CookieDeprecation.Enabled {
return
}
cookie := &http.Cookie{
Name: receiveCookieDeprecation,
Value: "1",
Secure: true,
HttpOnly: true,
Path: "/",
SameSite: http.SameSiteNoneMode,
// Partition: true,
pm-nilesh-chate marked this conversation as resolved.
Show resolved Hide resolved
Expires: c.time.Now().Add(time.Second * time.Duration(account.Privacy.PrivacySandbox.CookieDeprecation.TTLSec)),
pm-nilesh-chate marked this conversation as resolved.
Show resolved Hide resolved
}
setCookie(w, cookie)
}

// setCookie temporary substitute for http.SetCookie(w, cookie) until it supports Partitioned cookie type. Refer https://github.com/golang/go/issues/62490
func setCookie(w http.ResponseWriter, cookie *http.Cookie) {
SyntaxNode marked this conversation as resolved.
Show resolved Hide resolved
if v := cookie.String(); v != "" {
w.Header().Add("Set-Cookie", v+"; Partitioned;")
}
}

func mapBidderStatusToAnalytics(from []cookieSyncResponseBidder) []*analytics.CookieSyncBidder {
to := make([]*analytics.CookieSyncBidder, len(from))
for i, b := range from {
Expand Down
Loading
Loading