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

Refactor Usersync #2830

Merged
merged 23 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from 14 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
4 changes: 3 additions & 1 deletion endpoints/cookie_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ func (c *cookieSyncEndpoint) Handle(w http.ResponseWriter, r *http.Request, _ ht
c.handleError(w, err, http.StatusBadRequest)
return
}
decoder := usersync.DecodeV1{}

cookie := usersync.ParseCookieFromRequest(r, &c.config.HostCookie)
cookie := usersync.ReadCookie(r, decoder, &c.config.HostCookie)
usersync.SyncHostCookie(r, cookie, &c.config.HostCookie)

result := c.chooser.Choose(request, cookie)
switch result.Status {
Expand Down
7 changes: 3 additions & 4 deletions endpoints/cookie_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strings"
"testing"
"testing/iotest"
"time"

"github.com/prebid/prebid-server/analytics"
"github.com/prebid/prebid-server/config"
Expand Down Expand Up @@ -106,7 +105,7 @@ func TestCookieSyncHandle(t *testing.T) {
syncer.On("GetSync", syncTypeExpected, privacy.Policies{}).Return(sync, nil).Maybe()

cookieWithSyncs := usersync.NewCookie()
cookieWithSyncs.TrySync("foo", "anyID")
cookieWithSyncs.Sync("foo", "anyID")

testCases := []struct {
description string
Expand Down Expand Up @@ -271,7 +270,7 @@ func TestCookieSyncHandle(t *testing.T) {

request := httptest.NewRequest("POST", "/cookiesync", test.givenBody)
if test.givenCookie != nil {
request.AddCookie(test.givenCookie.ToHTTPCookie(24 * time.Hour))
request.AddCookie(test.givenCookie.ToHTTPCookie())
}

writer := httptest.NewRecorder()
Expand Down Expand Up @@ -1663,7 +1662,7 @@ func TestCookieSyncHandleResponse(t *testing.T) {

cookie := usersync.NewCookie()
if test.givenCookieHasSyncs {
if err := cookie.TrySync("foo", "anyID"); err != nil {
if err := cookie.Sync("foo", "anyID"); err != nil {
assert.FailNow(t, test.description+":set_cookie")
}
}
Expand Down
6 changes: 4 additions & 2 deletions endpoints/getuids.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ type userSyncs struct {
// returns all the existing syncs for the user
func NewGetUIDsEndpoint(cfg config.HostCookie) httprouter.Handle {
return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
pc := usersync.ParseCookieFromRequest(r, &cfg)
cookie := usersync.ReadCookie(r, usersync.DecodeV1{}, &cfg)
usersync.SyncHostCookie(r, cookie, &cfg)

userSyncs := new(userSyncs)
userSyncs.BuyerUIDs = pc.GetUIDs()
userSyncs.BuyerUIDs = cookie.GetUIDs()
json.NewEncoder(w).Encode(userSyncs)
})
}
5 changes: 4 additions & 1 deletion endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,15 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
}
defer cancel()

usersyncs := usersync.ParseCookieFromRequest(r, &(deps.cfg.HostCookie))
// Read UserSyncs/Cookie from Request
usersyncs := usersync.ReadCookie(r, usersync.DecodeV1{}, &deps.cfg.HostCookie)
usersync.SyncHostCookie(r, usersyncs, &deps.cfg.HostCookie)
if usersyncs.HasAnyLiveSyncs() {
labels.CookieFlag = metrics.CookieFlagYes
} else {
labels.CookieFlag = metrics.CookieFlagNo
}

labels.PubID = getAccountID(reqWrapper.Site.Publisher)
// Look up account now that we have resolved the pubID value
account, acctIDErrs := accountService.GetAccount(ctx, deps.cfg, deps.accounts, labels.PubID, deps.metricsEngine)
Expand Down
6 changes: 5 additions & 1 deletion endpoints/openrtb2/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,11 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
defer cancel()
}

usersyncs := usersync.ParseCookieFromRequest(r, &(deps.cfg.HostCookie))
// Read Usersyncs/Cookie
decoder := usersync.DecodeV1{}
usersyncs := usersync.ReadCookie(r, decoder, &deps.cfg.HostCookie)
usersync.SyncHostCookie(r, usersyncs, &deps.cfg.HostCookie)

if req.Site != nil {
if usersyncs.HasAnyLiveSyncs() {
labels.CookieFlag = metrics.CookieFlagYes
Expand Down
6 changes: 5 additions & 1 deletion endpoints/openrtb2/video_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,11 @@ func (deps *endpointDeps) VideoAuctionEndpoint(w http.ResponseWriter, r *http.Re
defer cancel()
}

usersyncs := usersync.ParseCookieFromRequest(r, &(deps.cfg.HostCookie))
// Read Usersyncs/Cookie
decoder := usersync.DecodeV1{}
usersyncs := usersync.ReadCookie(r, decoder, &deps.cfg.HostCookie)
usersync.SyncHostCookie(r, usersyncs, &deps.cfg.HostCookie)

if bidReqWrapper.App != nil {
labels.Source = metrics.DemandApp
labels.PubID = getAccountID(bidReqWrapper.App.Publisher)
Expand Down
18 changes: 13 additions & 5 deletions endpoints/setuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ const (
chromeiOSStrLen = len(chromeiOSStr)
)

const uidCookieName = "uids"

func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]usersync.Syncer, gdprPermsBuilder gdpr.PermissionsBuilder, tcf2CfgBuilder gdpr.TCF2ConfigBuilder, pbsanalytics analytics.PBSAnalyticsModule, accountsFetcher stored_requests.AccountFetcher, metricsEngine metrics.MetricsEngine) httprouter.Handle {
cookieTTL := time.Duration(cfg.HostCookie.TTL) * 24 * time.Hour
encoder := usersync.EncoderV1{}
decoder := usersync.DecodeV1{}

// convert map of syncers by bidder to map of syncers by key
// - its safe to assume that if multiple bidders map to the same key, the syncers are interchangeable.
Expand All @@ -46,13 +50,14 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use

defer pbsanalytics.LogSetUIDObject(&so)

pc := usersync.ParseCookieFromRequest(r, &cfg.HostCookie)
if !pc.AllowSyncs() {
cookie := usersync.ReadCookie(r, decoder, &cfg.HostCookie)
if !cookie.AllowSyncs() {
w.WriteHeader(http.StatusUnauthorized)
metricsEngine.RecordSetUid(metrics.SetUidOptOut)
so.Status = http.StatusUnauthorized
return
}
usersync.SyncHostCookie(r, cookie, &cfg.HostCookie)

query := r.URL.Query()

Expand Down Expand Up @@ -121,18 +126,21 @@ func NewSetUIDEndpoint(cfg *config.Configuration, syncersByBidder map[string]use
so.UID = uid

if uid == "" {
pc.Unsync(syncer.Key())
cookie.Unsync(syncer.Key())
metricsEngine.RecordSetUid(metrics.SetUidOK)
metricsEngine.RecordSyncerSet(syncer.Key(), metrics.SyncerSetUidCleared)
so.Success = true
} else if err = pc.TrySync(syncer.Key(), uid); err == nil {
} else if err = cookie.Sync(syncer.Key(), uid); err == nil {
metricsEngine.RecordSetUid(metrics.SetUidOK)
metricsEngine.RecordSyncerSet(syncer.Key(), metrics.SyncerSetUidOK)
so.Success = true
}

setSiteCookie := siteCookieCheck(r.UserAgent())
pc.SetCookieOnResponse(w, setSiteCookie, &cfg.HostCookie, cookieTTL)

// Write Cookie
encodedCookie := cookie.PrepareCookieForWrite(&cfg.HostCookie, cookieTTL, encoder)
usersync.WriteCookie(w, encodedCookie, &cfg.HostCookie, setSiteCookie)

switch responseFormat {
case "i":
Expand Down
8 changes: 4 additions & 4 deletions endpoints/setuid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/url"
"regexp"
"testing"
"time"

"github.com/prebid/prebid-server/analytics"
"github.com/prebid/prebid-server/config"
Expand Down Expand Up @@ -697,7 +696,7 @@ func makeRequest(uri string, existingSyncs map[string]string) *http.Request {
if len(existingSyncs) > 0 {
pbsCookie := usersync.NewCookie()
for key, value := range existingSyncs {
pbsCookie.TrySync(key, value)
pbsCookie.Sync(key, value)
}
addCookie(request, pbsCookie)
}
Expand Down Expand Up @@ -749,10 +748,11 @@ func doRequest(req *http.Request, analytics analytics.PBSAnalyticsModule, metric
}

func addCookie(req *http.Request, cookie *usersync.Cookie) {
req.AddCookie(cookie.ToHTTPCookie(time.Duration(1) * time.Hour))
req.AddCookie(cookie.ToHTTPCookie())
}

func parseCookieString(t *testing.T, response *httptest.ResponseRecorder) *usersync.Cookie {
decoder := usersync.DecodeV1{}
cookieString := response.Header().Get("Set-Cookie")
parser := regexp.MustCompile("uids=(.*?);")
res := parser.FindStringSubmatch(cookieString)
Expand All @@ -761,7 +761,7 @@ func parseCookieString(t *testing.T, response *httptest.ResponseRecorder) *users
Name: "uids",
Value: res[1],
}
return usersync.ParseCookie(&httpCookie)
return decoder.Decode(httpCookie.Value)
}

type fakePermissionsBuilder struct {
Expand Down
10 changes: 8 additions & 2 deletions pbs/usersync.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func (deps *UserSyncDeps) VerifyRecaptcha(response string) error {
func (deps *UserSyncDeps) OptOut(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
optout := r.FormValue("optout")
rr := r.FormValue("g-recaptcha-response")
encoder := usersync.EncoderV1{}
decoder := usersync.DecodeV1{}

if rr == "" {
http.Redirect(w, r, fmt.Sprintf("%s/static/optout.html", deps.ExternalUrl), http.StatusMovedPermanently)
Expand All @@ -73,10 +75,14 @@ func (deps *UserSyncDeps) OptOut(w http.ResponseWriter, r *http.Request, _ httpr
return
}

pc := usersync.ParseCookieFromRequest(r, deps.HostCookieConfig)
// Read Cookie
pc := usersync.ReadCookie(r, decoder, deps.HostCookieConfig)
usersync.SyncHostCookie(r, pc, deps.HostCookieConfig)
pc.SetOptOut(optout != "")

pc.SetCookieOnResponse(w, false, deps.HostCookieConfig, deps.HostCookieConfig.TTLDuration())
// Write Cookie
encodedCookie := pc.PrepareCookieForWrite(deps.HostCookieConfig, deps.HostCookieConfig.TTLDuration(), encoder)
usersync.WriteCookie(w, encodedCookie, deps.HostCookieConfig, false)

if optout == "" {
http.Redirect(w, r, deps.HostCookieConfig.OptInURL, http.StatusMovedPermanently)
Expand Down
4 changes: 2 additions & 2 deletions usersync/chooser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ func TestChooserEvaluate(t *testing.T) {
Redirect: NewUniformBidderFilter(BidderFilterModeExclude)}

cookieNeedsSync := Cookie{}
cookieAlreadyHasSyncForA := Cookie{uids: map[string]uidWithExpiry{"keyA": {Expires: time.Now().Add(time.Duration(24) * time.Hour)}}}
cookieAlreadyHasSyncForB := Cookie{uids: map[string]uidWithExpiry{"keyB": {Expires: time.Now().Add(time.Duration(24) * time.Hour)}}}
cookieAlreadyHasSyncForA := Cookie{uids: map[string]UIDEntry{"keyA": {Expires: time.Now().Add(time.Duration(24) * time.Hour)}}}
cookieAlreadyHasSyncForB := Cookie{uids: map[string]UIDEntry{"keyB": {Expires: time.Now().Add(time.Duration(24) * time.Hour)}}}

testCases := []struct {
description string
Expand Down
Loading