Skip to content

Commit

Permalink
Fix comments
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoxaAntoxic committed Jan 24, 2025
1 parent 74ac069 commit 361605a
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 336 deletions.
8 changes: 7 additions & 1 deletion src/main/java/org/prebid/server/cookie/UidsCookie.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ public UidsCookie updateUid(String familyName, String uid) {
return new UidsCookie(uids.toBuilder().uids(uidsMap).build(), mapper);
}

public UidsCookie updateUid(String familyName, UidWithExpiry uid) {
final Map<String, UidWithExpiry> uidsMap = new HashMap<>(uids.getUids());
uidsMap.put(familyName, uid);
return new UidsCookie(uids.toBuilder().uids(uidsMap).build(), mapper);
}

/**
* Performs updates of {@link UidsCookie}'s optout flag and returns newly constructed {@link UidsCookie}
* to avoid mutation of the current {@link UidsCookie}.
Expand All @@ -102,7 +108,7 @@ public UidsCookie updateOptout(boolean optout) {
/**
* Converts {@link Uids} to JSON string.
*/
String toJson() {
public String toJson() {
return mapper.encodeToString(uids);
}

Expand Down
92 changes: 52 additions & 40 deletions src/main/java/org/prebid/server/cookie/UidsCookieService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
import io.vertx.ext.web.RoutingContext;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.cookie.model.UidWithExpiry;
import org.prebid.server.cookie.model.UidsCookieUpdateResult;
import org.prebid.server.cookie.proto.Uids;
import org.prebid.server.json.DecodeException;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.log.Logger;
import org.prebid.server.log.LoggerFactory;
import org.prebid.server.metric.Metrics;
import org.prebid.server.model.HttpRequestContext;
import org.prebid.server.model.UpdateResult;
import org.prebid.server.util.HttpUtil;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -137,17 +139,19 @@ private Uids parseUids(Map<String, String> cookies) {

for (Map.Entry<String, String> cookie : cookies.entrySet()) {
final String cookieKey = cookie.getKey();
if (cookieKey.startsWith(COOKIE_NAME)) {
try {
final Uids parsedUids = mapper.decodeValue(
Buffer.buffer(Base64.getUrlDecoder().decode(cookie.getValue())), Uids.class);
if (parsedUids != null && parsedUids.getUids() != null) {
parsedUids.getUids().forEach((key, value) -> uids.merge(key, value, (newValue, oldValue) ->
newValue.getExpires().compareTo(oldValue.getExpires()) > 0 ? newValue : oldValue));
}
} catch (IllegalArgumentException | DecodeException e) {
logger.debug("Could not decode or parse {} cookie value {}", e, COOKIE_NAME, cookie.getValue());
if (!cookieKey.startsWith(COOKIE_NAME)) {
continue;
}

try {
final Uids parsedUids = mapper.decodeValue(
Buffer.buffer(Base64.getUrlDecoder().decode(cookie.getValue())), Uids.class);
if (parsedUids != null && parsedUids.getUids() != null) {
parsedUids.getUids().forEach((key, value) -> uids.merge(key, value, (newValue, oldValue) ->
newValue.getExpires().compareTo(oldValue.getExpires()) > 0 ? newValue : oldValue));
}
} catch (IllegalArgumentException | DecodeException e) {
logger.debug("Could not decode or parse {} cookie value {}", e, COOKIE_NAME, cookie.getValue());
}
}

Expand All @@ -158,7 +162,7 @@ private Uids parseUids(Map<String, String> cookies) {
* Creates a {@link Cookie} with 'uids' as a name and encoded JSON string representing supplied {@link UidsCookie}
* as a value.
*/
public Cookie makeCookie(String cookieName, UidsCookie uidsCookie) {
public Cookie aliveCookie(String cookieName, UidsCookie uidsCookie) {
return Cookie
.cookie(cookieName, Base64.getUrlEncoder().encodeToString(uidsCookie.toJson().getBytes()))
.setPath("/")
Expand All @@ -168,11 +172,11 @@ public Cookie makeCookie(String cookieName, UidsCookie uidsCookie) {
.setDomain(hostCookieDomain);
}

public Cookie makeCookie(UidsCookie uidsCookie) {
return makeCookie(COOKIE_NAME, uidsCookie);
public Cookie aliveCookie(UidsCookie uidsCookie) {
return aliveCookie(COOKIE_NAME, uidsCookie);
}

public Cookie removeCookie(String cookieName) {
public Cookie expiredCookie(String cookieName) {
return Cookie
.cookie(cookieName, StringUtils.EMPTY)
.setPath("/")
Expand Down Expand Up @@ -245,17 +249,17 @@ private static boolean facebookSentinelOrEmpty(Map.Entry<String, UidWithExpiry>
/***
* Removes expired {@link Uids}, updates {@link UidsCookie} with new uid for family name according to priority
*/
public UidsCookieUpdateResult updateUidsCookie(UidsCookie uidsCookie, String familyName, String uid) {
public UpdateResult<UidsCookie> updateUidsCookie(UidsCookie uidsCookie, String familyName, String uid) {
final UidsCookie initialCookie = removeExpiredUids(uidsCookie);

// At the moment, Facebook calls /setuid with a UID of 0 if the user isn't logged into Facebook.
// They shouldn't be sending us a sentinel value... but since they are, we're refusing to save that ID.
if (StringUtils.isBlank(uid) || UidsCookie.isFacebookSentinel(familyName, uid)) {
return UidsCookieUpdateResult.failure(splitUids(initialCookie));
return UpdateResult.unaltered(initialCookie);
}

final UidsCookie updatedCookie = initialCookie.updateUid(familyName, uid);
return UidsCookieUpdateResult.success(splitUids(updatedCookie));
return UpdateResult.updated(updatedCookie);
}

private static UidsCookie removeExpiredUids(UidsCookie uidsCookie) {
Expand All @@ -271,49 +275,49 @@ private static UidsCookie removeExpiredUids(UidsCookie uidsCookie) {
return updatedCookie;
}

public Map<String, UidsCookie> splitUids(UidsCookie uidsCookie) {
public List<Cookie> splitUidsIntoCookies(UidsCookie uidsCookie) {
final Uids cookieUids = uidsCookie.getCookieUids();
final Map<String, UidWithExpiry> uids = cookieUids.getUids();
final boolean hasOptout = !uidsCookie.allowsSync();

final Iterator<String> cookieFamilyIterator = cookieFamilyNamesByDescPriorityAndExpiration(uidsCookie);
final Map<String, UidsCookie> splitCookies = new HashMap<>();
final Iterator<String> cookieFamilies = cookieFamilyNamesByDescPriorityAndExpiration(uidsCookie);
final List<Cookie> splitCookies = new ArrayList<>();

int uidsIndex = 0;
String nextCookieFamily = null;

while (uidsIndex < numberOfUidCookies) {
final String uidsName = uidsIndex == 0 ? COOKIE_NAME : COOKIE_NAME_FORMAT.formatted(uidsIndex + 1);
final UidsCookie tempUidsCookie = splitCookies.computeIfAbsent(
uidsName,
key -> new UidsCookie(Uids.builder().uids(new HashMap<>()).optout(hasOptout).build(), mapper));
final Map<String, UidWithExpiry> tempUids = tempUidsCookie.getCookieUids().getUids();

while (nextCookieFamily != null || cookieFamilyIterator.hasNext()) {
nextCookieFamily = nextCookieFamily == null ? cookieFamilyIterator.next() : nextCookieFamily;
tempUids.put(nextCookieFamily, uids.get(nextCookieFamily));
UidsCookie tempUidsCookie = new UidsCookie(
Uids.builder().uids(new HashMap<>()).optout(hasOptout).build(),
mapper);

while (nextCookieFamily != null || cookieFamilies.hasNext()) {
nextCookieFamily = nextCookieFamily == null ? cookieFamilies.next() : nextCookieFamily;
tempUidsCookie = tempUidsCookie.updateUid(nextCookieFamily, uids.get(nextCookieFamily));
if (cookieExceededMaxLength(uidsName, tempUidsCookie)) {
tempUids.remove(nextCookieFamily);
tempUidsCookie = tempUidsCookie.deleteUid(nextCookieFamily);
break;
}

nextCookieFamily = null;
}

uidsIndex++;
}

while (nextCookieFamily != null || cookieFamilyIterator.hasNext()) {
nextCookieFamily = nextCookieFamily == null ? cookieFamilyIterator.next() : nextCookieFamily;
if (prioritizedCoopSyncProvider.isPrioritizedFamily(nextCookieFamily)) {
metrics.updateUserSyncSizedOutMetric(nextCookieFamily);
if (tempUidsCookie.getCookieUids().getUids().isEmpty()) {
splitCookies.add(expiredCookie(uidsName));
} else {
metrics.updateUserSyncSizeBlockedMetric(nextCookieFamily);
splitCookies.add(aliveCookie(uidsName, tempUidsCookie));
}

nextCookieFamily = null;
uidsIndex++;
}

if (nextCookieFamily != null) {
updateSyncSizeMetrics(nextCookieFamily);
}

cookieFamilies.forEachRemaining(this::updateSyncSizeMetrics);

return splitCookies;
}

Expand All @@ -340,12 +344,20 @@ private int compareCookieFamilyNames(Map.Entry<String, UidWithExpiry> left,
}
}

private void updateSyncSizeMetrics(String nextCookieFamily) {
if (prioritizedCoopSyncProvider.isPrioritizedFamily(nextCookieFamily)) {
metrics.updateUserSyncSizedOutMetric(nextCookieFamily);
} else {
metrics.updateUserSyncSizeBlockedMetric(nextCookieFamily);
}
}

private boolean cookieExceededMaxLength(String name, UidsCookie uidsCookie) {
return maxCookieSizeBytes > 0 && cookieBytesLength(name, uidsCookie) > maxCookieSizeBytes;
}

private int cookieBytesLength(String cookieName, UidsCookie uidsCookie) {
return makeCookie(cookieName, uidsCookie).encode().getBytes().length;
return aliveCookie(cookieName, uidsCookie).encode().getBytes().length;
}

public String hostCookieUidToSync(RoutingContext routingContext, String cookieFamilyName) {
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/java/org/prebid/server/handler/OptoutHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private Cookie optCookie(boolean optout, RoutingContext routingContext) {
.parseFromRequest(routingContext)
.updateOptout(optout);

return uidsCookieService.makeCookie(uidsCookie);
return uidsCookieService.aliveCookie(uidsCookie);
}

private String optUrl(boolean optout) {
Expand Down
19 changes: 6 additions & 13 deletions src/main/java/org/prebid/server/handler/SetuidHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.prebid.server.cookie.UidsCookieService;
import org.prebid.server.cookie.exception.UnauthorizedUidsException;
import org.prebid.server.cookie.exception.UnavailableForLegalReasonsException;
import org.prebid.server.cookie.model.UidsCookieUpdateResult;
import org.prebid.server.exception.InvalidAccountConfigException;
import org.prebid.server.exception.InvalidRequestException;
import org.prebid.server.execution.timeout.Timeout;
Expand All @@ -44,6 +43,7 @@
import org.prebid.server.log.LoggerFactory;
import org.prebid.server.metric.Metrics;
import org.prebid.server.model.Endpoint;
import org.prebid.server.model.UpdateResult;
import org.prebid.server.privacy.HostVendorTcfDefinerService;
import org.prebid.server.privacy.gdpr.model.HostVendorTcfResponse;
import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction;
Expand Down Expand Up @@ -328,14 +328,13 @@ private void respondWithCookie(SetuidContext setuidContext) {
final String uid = routingContext.request().getParam(UID_PARAM);
final String bidder = setuidContext.getCookieName();

final UidsCookieUpdateResult uidsCookieUpdateResult = uidsCookieService.updateUidsCookie(
final UpdateResult<UidsCookie> uidsCookieUpdateResult = uidsCookieService.updateUidsCookie(
setuidContext.getUidsCookie(), bidder, uid);

uidsCookieUpdateResult.getUidsCookies().entrySet().stream()
.map(entry -> toCookie(entry.getKey(), entry.getValue()))
.forEach(uidsCookie -> addCookie(routingContext, uidsCookie));
uidsCookieService.splitUidsIntoCookies(uidsCookieUpdateResult.getValue())
.forEach(cookie -> addCookie(routingContext, cookie));

if (uidsCookieUpdateResult.isSuccessfullyUpdated()) {
if (uidsCookieUpdateResult.isUpdated()) {
metrics.updateUserSyncSetsMetric(bidder);
}
final int statusCode = HttpResponseStatus.OK.code();
Expand All @@ -346,17 +345,11 @@ private void respondWithCookie(SetuidContext setuidContext) {
.status(statusCode)
.bidder(bidder)
.uid(uid)
.success(uidsCookieUpdateResult.isSuccessfullyUpdated())
.success(uidsCookieUpdateResult.isUpdated())
.build();
analyticsDelegator.processEvent(setuidEvent, tcfContext);
}

private Cookie toCookie(String cookieName, UidsCookie uidsCookie) {
return uidsCookie.getCookieUids().getUids().isEmpty()
? uidsCookieService.removeCookie(cookieName)
: uidsCookieService.makeCookie(cookieName, uidsCookie);
}

private Consumer<HttpServerResponse> buildCookieResponseConsumer(SetuidContext setuidContext,
int responseStatusCode) {

Expand Down
Loading

0 comments on commit 361605a

Please sign in to comment.