> bidErrors) {
final Bid bid = bidderBid.getBid();
@@ -629,7 +649,7 @@ private Bid toBid(BidderBid bidderBid, String bidder, ExtRequestTargeting target
keywordsCreatorByBidType(targeting, isApp);
final boolean isWinningBid = winningBids.contains(bid);
final String winUrl = eventsEnabled && bidType != BidType.video
- ? HttpUtil.encodeUrl(eventsService.winUrlTargeting(account.getId()))
+ ? HttpUtil.encodeUrl(eventsService.winUrlTargeting(bidder, account.getId(), auctionTimestamp))
: null;
targetingKeywords = keywordsCreatorByBidType.getOrDefault(bidType, keywordsCreator)
.makeFor(bid, bidder, isWinningBid, cacheId, videoCacheId, cacheHost, cachePath, winUrl);
@@ -645,7 +665,9 @@ private Bid toBid(BidderBid bidderBid, String bidder, ExtRequestTargeting target
final String extBidPrebidId = BooleanUtils.toBoolean(this.generateBidId) ? UUID.randomUUID().toString() : null;
final String eventId = BooleanUtils.toBoolean(this.generateBidId) ? extBidPrebidId : bid.getId();
final Video storedVideo = impIdToStoredVideo.get(bid.getImpid());
- final Events events = eventsEnabled ? eventsService.createEvent(eventId, account.getId()) : null;
+ final Events events = eventsEnabled && eventsAllowedByRequest
+ ? eventsService.createEvent(eventId, bidder, account.getId(), auctionTimestamp)
+ : null;
final ExtBidPrebid prebidExt = ExtBidPrebid.of(
extBidPrebidId, bidType, targetingKeywords, cache, storedVideo, events, null
@@ -713,13 +735,12 @@ private static com.iab.openrtb.request.Asset getAssetById(int assetId,
/**
* Extracts targeting keywords settings from the bid request and creates {@link TargetingKeywordsCreator}
* instance if it is present.
- *
*/
private TargetingKeywordsCreator keywordsCreator(ExtRequestTargeting targeting, boolean isApp) {
- final JsonNode pricegranularity = targeting.getPricegranularity();
- return pricegranularity == null || pricegranularity.isNull()
+ final JsonNode priceGranularityNode = targeting.getPricegranularity();
+ return priceGranularityNode == null || priceGranularityNode.isNull()
? null
- : TargetingKeywordsCreator.create(parsePriceGranularity(pricegranularity),
+ : TargetingKeywordsCreator.create(parsePriceGranularity(priceGranularityNode),
targeting.getIncludewinners(), targeting.getIncludebidderkeys(), isApp);
}
@@ -762,8 +783,9 @@ private Map keywordsCreatorByBidType(ExtReque
}
/**
- * Parse {@link JsonNode} to {@link List} of {@link ExtPriceGranularity}. Throws {@link PreBidException} in
- * case of errors during decoding pricegranularity.
+ * Parse {@link JsonNode} to {@link List} of {@link ExtPriceGranularity}.
+ *
+ * Throws {@link PreBidException} in case of errors during decoding price granularity.
*/
private ExtPriceGranularity parsePriceGranularity(JsonNode priceGranularity) {
try {
diff --git a/src/main/java/org/prebid/server/auction/BidderAliases.java b/src/main/java/org/prebid/server/auction/BidderAliases.java
new file mode 100644
index 00000000000..378946b2ca2
--- /dev/null
+++ b/src/main/java/org/prebid/server/auction/BidderAliases.java
@@ -0,0 +1,37 @@
+package org.prebid.server.auction;
+
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Represents aliases configured for bidders - configuration might come in OpenRTB request but not limited to it.
+ */
+public class BidderAliases {
+
+ private Map aliasToBidder;
+
+ private Map aliasToVendorId;
+
+ private BidderAliases(Map aliasToBidder, Map aliasToVendorId) {
+ this.aliasToBidder = ObjectUtils.firstNonNull(aliasToBidder, Collections.emptyMap());
+ this.aliasToVendorId = ObjectUtils.firstNonNull(aliasToVendorId, Collections.emptyMap());
+ }
+
+ public static BidderAliases of(Map aliasToBidder, Map aliasToVendorId) {
+ return new BidderAliases(aliasToBidder, aliasToVendorId);
+ }
+
+ public boolean isAliasDefined(String alias) {
+ return aliasToBidder.containsKey(alias);
+ }
+
+ public String resolveBidder(String aliasOrBidder) {
+ return aliasToBidder.getOrDefault(aliasOrBidder, aliasOrBidder);
+ }
+
+ public Integer resolveAliasVendorId(String alias) {
+ return aliasToVendorId.get(alias);
+ }
+}
diff --git a/src/main/java/org/prebid/server/auction/CpmRange.java b/src/main/java/org/prebid/server/auction/CpmRange.java
index 009cf0fb1b1..d847fc93fe9 100644
--- a/src/main/java/org/prebid/server/auction/CpmRange.java
+++ b/src/main/java/org/prebid/server/auction/CpmRange.java
@@ -25,7 +25,7 @@ private CpmRange() {
public static String fromCpm(BigDecimal cpm, PriceGranularity priceGranularity) {
final BigDecimal value = fromCpmAsNumber(cpm, priceGranularity);
return value != null
- ? format(value, ObjectUtils.firstNonNull(priceGranularity.getPrecision(), 2))
+ ? format(value, ObjectUtils.defaultIfNull(priceGranularity.getPrecision(), 2))
: StringUtils.EMPTY;
}
diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java
index 5853e65ce2b..5794190c5be 100644
--- a/src/main/java/org/prebid/server/auction/ExchangeService.java
+++ b/src/main/java/org/prebid/server/auction/ExchangeService.java
@@ -20,9 +20,9 @@
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.BidRequestCacheInfo;
+import org.prebid.server.auction.model.BidderPrivacyResult;
import org.prebid.server.auction.model.BidderRequest;
import org.prebid.server.auction.model.BidderResponse;
-import org.prebid.server.auction.model.PrivacyEnforcementResult;
import org.prebid.server.auction.model.StoredResponseResult;
import org.prebid.server.bidder.Bidder;
import org.prebid.server.bidder.BidderCatalog;
@@ -42,6 +42,7 @@
import org.prebid.server.proto.openrtb.ext.ExtPrebidBidders;
import org.prebid.server.proto.openrtb.ext.request.ExtApp;
import org.prebid.server.proto.openrtb.ext.request.ExtBidRequest;
+import org.prebid.server.proto.openrtb.ext.request.ExtRequestCurrency;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidCache;
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidData;
@@ -142,24 +143,22 @@ public Future holdAuction(AuctionContext context) {
final List imps = bidRequest.getImp();
final List storedResponse = new ArrayList<>();
- final Map aliases = aliases(requestExt);
+ final BidderAliases aliases = aliases(requestExt);
final String publisherId = account.getId();
final ExtRequestTargeting targeting = targeting(requestExt);
final BidRequestCacheInfo cacheInfo = bidRequestCacheInfo(targeting, requestExt);
- final Boolean isGdprEnforced = account.getEnforceGdpr();
final boolean debugEnabled = isDebugEnabled(bidRequest, requestExt);
return storedResponseProcessor.getStoredResponseResult(imps, aliases, timeout)
.map(storedResponseResult -> populateStoredResponse(storedResponseResult, storedResponse))
- .compose(impsRequiredRequest -> extractBidderRequests(context, impsRequiredRequest, requestExt,
- aliases, isGdprEnforced))
+ .compose(impsRequiredRequest ->
+ extractBidderRequests(context, impsRequiredRequest, requestExt, aliases))
.map(bidderRequests ->
- updateRequestMetric(bidderRequests, uidsCookie, aliases, publisherId,
- requestTypeMetric))
+ updateRequestMetric(bidderRequests, uidsCookie, aliases, publisherId, requestTypeMetric))
.compose(bidderRequests -> CompositeFuture.join(bidderRequests.stream()
.map(bidderRequest -> requestBids(bidderRequest,
auctionTimeout(timeout, cacheInfo.isDoCaching()), debugEnabled, aliases,
- bidAdjustments(requestExt), currencyRates(targeting)))
+ bidAdjustments(requestExt), currencyRates(requestExt)))
.collect(Collectors.toList())))
// send all the requests to the bidders and gathers results
.map(CompositeFuture::list)
@@ -168,29 +167,22 @@ public Future holdAuction(AuctionContext context) {
.map(bidderResponses ->
storedResponseProcessor.mergeWithBidderResponses(bidderResponses, storedResponse, imps))
.compose(bidderResponses ->
- bidResponseCreator.create(bidderResponses, bidRequest, targeting, cacheInfo, account, timeout,
- debugEnabled))
+ bidResponseCreator.create(bidderResponses, bidRequest, targeting, cacheInfo, account,
+ eventsAllowedByRequest(requestExt), auctionTimestamp(requestExt), debugEnabled,
+ timeout))
.compose(bidResponse ->
bidResponsePostProcessor.postProcess(routingContext, uidsCookie, bidRequest, bidResponse,
account));
}
- /**
- * Populates storedResponse parameter with stored {@link List} and returns {@link List} for which
- * request to bidders should be performed.
- */
- private List populateStoredResponse(StoredResponseResult storedResponseResult, List storedResponse) {
- storedResponse.addAll(storedResponseResult.getStoredResponse());
- return storedResponseResult.getRequiredRequestImps();
- }
-
/**
* Extracts {@link ExtBidRequest} from {@link BidRequest}.
*/
private ExtBidRequest requestExt(BidRequest bidRequest) {
try {
return bidRequest.getExt() != null
- ? mapper.mapper().treeToValue(bidRequest.getExt(), ExtBidRequest.class) : null;
+ ? mapper.mapper().treeToValue(bidRequest.getExt(), ExtBidRequest.class)
+ : null;
} catch (JsonProcessingException e) {
throw new PreBidException(String.format("Error decoding bidRequest.ext: %s", e.getMessage()), e);
}
@@ -199,10 +191,87 @@ private ExtBidRequest requestExt(BidRequest bidRequest) {
/**
* Extracts aliases from {@link ExtBidRequest}.
*/
- private static Map aliases(ExtBidRequest requestExt) {
+ private static BidderAliases aliases(ExtBidRequest requestExt) {
final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
final Map aliases = prebid != null ? prebid.getAliases() : null;
- return aliases != null ? aliases : Collections.emptyMap();
+ final Map aliasgvlids = prebid != null ? prebid.getAliasgvlids() : null;
+ return BidderAliases.of(aliases, aliasgvlids);
+ }
+
+ /**
+ * Extracts {@link ExtRequestTargeting} from {@link ExtBidRequest} model.
+ */
+ private static ExtRequestTargeting targeting(ExtBidRequest requestExt) {
+ final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
+ return prebid != null ? prebid.getTargeting() : null;
+ }
+
+ /**
+ * Extracts currency rates from {@link ExtBidRequest}.
+ */
+ private static Map> currencyRates(ExtBidRequest requestExt) {
+ final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
+ final ExtRequestCurrency currency = prebid != null ? prebid.getCurrency() : null;
+ return currency != null ? currency.getRates() : null;
+ }
+
+ /**
+ * Returns true if {@link ExtBidRequest} is present, otherwise - false.
+ */
+ private static boolean eventsAllowedByRequest(ExtBidRequest requestExt) {
+ final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
+ final ObjectNode eventsFromRequest = prebid != null ? prebid.getEvents() : null;
+ return eventsFromRequest != null;
+ }
+
+ /**
+ * Extracts auction timestamp from {@link ExtBidRequest} or get it from {@link Clock} if it is null.
+ */
+ private long auctionTimestamp(ExtBidRequest requestExt) {
+ final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
+ final Long auctionTimestamp = prebid != null ? prebid.getAuctiontimestamp() : null;
+ return auctionTimestamp != null ? auctionTimestamp : clock.millis();
+ }
+
+ /**
+ * Creates {@link BidRequestCacheInfo} based on {@link ExtBidRequest} model.
+ */
+ private static BidRequestCacheInfo bidRequestCacheInfo(ExtRequestTargeting targeting, ExtBidRequest requestExt) {
+ final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
+ final ExtRequestPrebidCache cache = prebid != null ? prebid.getCache() : null;
+
+ if (targeting != null && cache != null) {
+ final boolean shouldCacheBids = cache.getBids() != null;
+ final boolean shouldCacheVideoBids = cache.getVastxml() != null;
+ final boolean shouldCacheWinningBidsOnly = targeting.getIncludebidderkeys()
+ ? false // ext.prebid.targeting.includebidderkeys takes precedence
+ : ObjectUtils.defaultIfNull(cache.getWinningonly(), false);
+
+ if (shouldCacheBids || shouldCacheVideoBids || shouldCacheWinningBidsOnly) {
+ final Integer cacheBidsTtl = shouldCacheBids ? cache.getBids().getTtlseconds() : null;
+ final Integer cacheVideoBidsTtl = shouldCacheVideoBids ? cache.getVastxml().getTtlseconds() : null;
+
+ final boolean returnCreativeBid = shouldCacheBids
+ ? ObjectUtils.defaultIfNull(cache.getBids().getReturnCreative(), true)
+ : false;
+ final boolean returnCreativeVideoBid = shouldCacheVideoBids
+ ? ObjectUtils.defaultIfNull(cache.getVastxml().getReturnCreative(), true)
+ : false;
+
+ return BidRequestCacheInfo.builder()
+ .doCaching(true)
+ .shouldCacheBids(shouldCacheBids)
+ .cacheBidsTtl(cacheBidsTtl)
+ .shouldCacheVideoBids(shouldCacheVideoBids)
+ .cacheVideoBidsTtl(cacheVideoBidsTtl)
+ .returnCreativeBids(returnCreativeBid)
+ .returnCreativeVideoBids(returnCreativeVideoBid)
+ .shouldCacheWinningBidsOnly(shouldCacheWinningBidsOnly)
+ .build();
+ }
+ }
+
+ return BidRequestCacheInfo.noCache();
}
/**
@@ -217,19 +286,13 @@ private static boolean isDebugEnabled(BidRequest bidRequest, ExtBidRequest extBi
}
/**
- * Extracts bidAdjustments from {@link ExtBidRequest}.
- */
- private static Map bidAdjustments(ExtBidRequest requestExt) {
- final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
- final Map bidAdjustmentFactors = prebid != null ? prebid.getBidadjustmentfactors() : null;
- return bidAdjustmentFactors != null ? bidAdjustmentFactors : Collections.emptyMap();
- }
-
- /**
- * Extracts currency rates from {@link ExtRequestTargeting}.
+ * Populates storedResponse parameter with stored {@link List} and returns {@link List} for which
+ * request to bidders should be performed.
*/
- private static Map> currencyRates(ExtRequestTargeting targeting) {
- return targeting != null && targeting.getCurrency() != null ? targeting.getCurrency().getRates() : null;
+ private static List populateStoredResponse(StoredResponseResult storedResponseResult,
+ List storedResponse) {
+ storedResponse.addAll(storedResponseResult.getStoredResponse());
+ return storedResponseResult.getRequiredRequestImps();
}
/**
@@ -260,9 +323,10 @@ private static Map> currencyRates(ExtRequestTarg
* NOTE: the return list will only contain entries for bidders that both have the extension field in at least one
* {@link Imp}, and are known to {@link BidderCatalog} or aliases from bidRequest.ext.prebid.aliases.
*/
- private Future> extractBidderRequests(AuctionContext context, List requestedImps,
- ExtBidRequest requestExt, Map aliases,
- Boolean isGdprEnforced) {
+ private Future> extractBidderRequests(AuctionContext context,
+ List requestedImps,
+ ExtBidRequest requestExt,
+ BidderAliases aliases) {
// sanity check: discard imps without extension
final List imps = requestedImps.stream()
.filter(imp -> imp.getExt() != null)
@@ -276,7 +340,7 @@ private Future> extractBidderRequests(AuctionContext context
.distinct()
.collect(Collectors.toList());
- return makeBidderRequests(bidders, context, aliases, requestExt, imps, isGdprEnforced);
+ return makeBidderRequests(bidders, context, aliases, requestExt, imps);
}
private static Stream asStream(Iterator iterator) {
@@ -287,8 +351,8 @@ private static Stream asStream(Iterator iterator) {
/**
* Checks if bidder name is valid in case when bidder can also be alias name.
*/
- private boolean isValidBidder(String bidder, Map aliases) {
- return bidderCatalog.isValidName(bidder) || aliases.containsKey(bidder);
+ private boolean isValidBidder(String bidder, BidderAliases aliases) {
+ return bidderCatalog.isValidName(bidder) || aliases.isAliasDefined(bidder);
}
/**
@@ -306,9 +370,11 @@ private boolean isValidBidder(String bidder, Map aliases) {
* - bidrequest.user.ext.data, bidrequest.app.ext.data and bidrequest.site.ext.data will be removed for bidders
* that don't have first party data allowed.
*/
- private Future> makeBidderRequests(
- List bidders, AuctionContext context, Map aliases,
- ExtBidRequest requestExt, List imps, Boolean isGdprEnforced) {
+ private Future> makeBidderRequests(List bidders,
+ AuctionContext context,
+ BidderAliases aliases,
+ ExtBidRequest requestExt,
+ List imps) {
final BidRequest bidRequest = context.getBidRequest();
final ExtUser extUser = extUser(bidRequest.getUser());
@@ -323,9 +389,9 @@ private Future> makeBidderRequests(
}
return privacyEnforcementService
- .mask(bidderToUser, extUser, bidders, aliases, bidRequest, isGdprEnforced, context.getTimeout())
- .map(bidderToPrivacyEnforcementResult -> getBidderRequests(bidderToPrivacyEnforcementResult,
- bidRequest, requestExt, imps, firstPartyDataBidders));
+ .mask(context, bidderToUser, extUser, bidders, aliases)
+ .map(bidderToPrivacyResult -> getBidderRequests(bidderToPrivacyResult, bidRequest, requestExt, imps,
+ firstPartyDataBidders));
}
/**
@@ -367,7 +433,7 @@ private static List firstPartyDataBidders(ExtBidRequest requestExt) {
* Returns original {@link User} if user.buyeruid already contains uid value for bidder.
* Otherwise, returns new {@link User} containing updated {@link ExtUser} and user.buyeruid.
*/
- private User prepareUser(User user, ExtUser extUser, String bidder, Map aliases,
+ private User prepareUser(User user, ExtUser extUser, String bidder, BidderAliases aliases,
Map uidsBody, UidsCookie uidsCookie, boolean useFirstPartyData) {
final ObjectNode updatedExt = updateUserExt(extUser, useFirstPartyData);
final String updatedBuyerUid = updateUserBuyerUid(user, bidder, aliases, uidsBody, uidsCookie);
@@ -401,16 +467,16 @@ private ObjectNode updateUserExt(ExtUser extUser, boolean useFirstPartyData) {
final boolean removeFirstPartyData = !useFirstPartyData && extUser.getData() != null;
if (removePrebid || removeFirstPartyData) {
- final ExtUser.ExtUserBuilder builder = extUser.toBuilder();
+ final ExtUser.ExtUserBuilder extUserBuilder = extUser.toBuilder();
if (removePrebid) {
- builder.prebid(null);
+ extUserBuilder.prebid(null);
}
if (removeFirstPartyData) {
- builder.data(null);
+ extUserBuilder.data(null);
}
- return mapper.mapper().valueToTree(builder.build());
+ return mapper.mapper().valueToTree(extUserBuilder.build());
}
}
return null;
@@ -419,9 +485,9 @@ private ObjectNode updateUserExt(ExtUser extUser, boolean useFirstPartyData) {
/**
* Returns updated buyerUid or null if it doesn't need to be updated.
*/
- private String updateUserBuyerUid(User user, String bidder, Map aliases,
+ private String updateUserBuyerUid(User user, String bidder, BidderAliases aliases,
Map uidsBody, UidsCookie uidsCookie) {
- final String buyerUidFromBodyOrCookie = extractUid(uidsBody, uidsCookie, resolveBidder(bidder, aliases));
+ final String buyerUidFromBodyOrCookie = extractUid(uidsBody, uidsCookie, aliases.resolveBidder(bidder));
final String buyerUidFromUser = user != null ? user.getBuyeruid() : null;
return StringUtils.isBlank(buyerUidFromUser) && StringUtils.isNotBlank(buyerUidFromBodyOrCookie)
@@ -429,14 +495,6 @@ private String updateUserBuyerUid(User user, String bidder, Map
: null;
}
- /**
- * Returns the name associated with bidder if bidder is an alias.
- * If it's not an alias, the bidder is returned.
- */
- private static String resolveBidder(String bidder, Map aliases) {
- return aliases.getOrDefault(bidder, bidder);
- }
-
/**
* Extracts UID from uids from body or {@link UidsCookie}.
*/
@@ -453,22 +511,27 @@ private String resolveCookieFamilyName(String bidder) {
}
/**
- * Returns Shuffled List of {@link BidderRequest}
+ * Returns shuffled list of {@link BidderRequest}.
*/
- private List getBidderRequests(
- Map bidderToPrivacyEnforcementResult, BidRequest bidRequest,
- ExtBidRequest requestExt, List imps, List firstPartyDataBidders) {
+ private List getBidderRequests(List bidderPrivacyResults,
+ BidRequest bidRequest,
+ ExtBidRequest requestExt,
+ List imps,
+ List firstPartyDataBidders) {
final Map bidderToPrebidBidders = bidderToPrebidBidders(requestExt);
final Map bidderToPrebidSchains = bidderToPrebidSchains(requestExt);
- final List bidderRequests = bidderToPrivacyEnforcementResult.entrySet().stream()
+ final List bidderRequests = bidderPrivacyResults.stream()
// for each bidder create a new request that is a copy of original request except buyerid, imp
// extensions, ext.prebid.data.bidders and ext.prebid.bidders.
// Also, check whether to pass user.ext.data, app.ext.data and site.ext.data or not.
- .map(entry -> createBidderRequest(entry.getKey(), bidRequest, requestExt, imps, entry.getValue(),
+ .map(bidderPrivacyResult -> createBidderRequest(bidderPrivacyResult, bidRequest, requestExt, imps,
firstPartyDataBidders, bidderToPrebidBidders, bidderToPrebidSchains))
+ .filter(Objects::nonNull)
.collect(Collectors.toList());
+
Collections.shuffle(bidderRequests);
+
return bidderRequests;
}
@@ -514,24 +577,29 @@ private static Map bidderToPrebidSchains(ExtBidRequest reque
}
/**
- * Returns created {@link BidderRequest}
+ * Returns {@link BidderRequest} for the given bidder.
*/
- private BidderRequest createBidderRequest(String bidder, BidRequest bidRequest, ExtBidRequest requestExt,
- List imps, PrivacyEnforcementResult privacyEnforcementResult,
+ private BidderRequest createBidderRequest(BidderPrivacyResult bidderPrivacyResult,
+ BidRequest bidRequest,
+ ExtBidRequest requestExt,
+ List imps,
List firstPartyDataBidders,
Map bidderToPrebidBidders,
Map bidderToPrebidSchains) {
+ final String bidder = bidderPrivacyResult.getRequestBidder();
+ if (bidderPrivacyResult.isBlockedRequestByTcf()) {
+ return null;
+ }
+
final App app = bidRequest.getApp();
- final ExtApp extApp = extApp(app);
final Site site = bidRequest.getSite();
- final ExtSite extSite = extSite(site);
return BidderRequest.of(bidder, bidRequest.toBuilder()
- .user(privacyEnforcementResult.getUser())
- .device(privacyEnforcementResult.getDevice())
+ .user(bidderPrivacyResult.getUser())
+ .device(bidderPrivacyResult.getDevice())
.imp(prepareImps(bidder, imps, firstPartyDataBidders.contains(bidder)))
- .app(prepareApp(app, extApp, firstPartyDataBidders.contains(bidder)))
- .site(prepareSite(site, extSite, firstPartyDataBidders.contains(bidder)))
+ .app(prepareApp(app, extApp(app), firstPartyDataBidders.contains(bidder)))
+ .site(prepareSite(site, extSite(site), firstPartyDataBidders.contains(bidder)))
.source(prepareSource(bidder, bidderToPrebidSchains, bidRequest.getSource()))
.ext(prepareExt(bidder, firstPartyDataBidders, bidderToPrebidBidders, requestExt, bidRequest.getExt()))
.build());
@@ -623,7 +691,7 @@ private Site prepareSite(Site site, ExtSite extSite, boolean useFirstPartyData)
}
/**
- * Make Source with corresponding request.ext.prebid.schains
+ * Returns {@link Source} with corresponding request.ext.prebid.schains.
*/
private Source prepareSource(String bidder, Map bidderToSchain, Source receivedSource) {
final ObjectNode defaultSchain = bidderToSchain.get(GENERIC_SCHAIN_KEY);
@@ -633,19 +701,17 @@ private Source prepareSource(String bidder, Map bidderToScha
return receivedSource;
}
- final ObjectNode jsonExtSource = mapper.mapper().valueToTree(ExtSource.of(bidderSchain));
+ final ObjectNode extSourceNode = mapper.mapper().valueToTree(ExtSource.of(bidderSchain));
- if (receivedSource == null) {
- return Source.builder().ext(jsonExtSource).build();
- } else {
- return receivedSource.toBuilder().ext(jsonExtSource).build();
- }
+ return receivedSource == null
+ ? Source.builder().ext(extSourceNode).build()
+ : receivedSource.toBuilder().ext(extSourceNode).build();
}
/**
* Removes all bidders except the given bidder from bidrequest.ext.prebid.data.bidders and
* bidrequest.ext.prebid.bidders to hide list of allowed bidders from initial request.
- * Also mask bidrequest.ext.prebid.schains.
+ * Also masks bidrequest.ext.prebid.schains.
*/
private ObjectNode prepareExt(String bidder, List firstPartyDataBidders,
Map bidderToPrebidBidders, ExtBidRequest requestExt,
@@ -682,12 +748,12 @@ private ObjectNode prepareExt(String bidder, List firstPartyDataBidders,
* Updates 'account.*.request', 'request' and 'no_cookie_requests' metrics for each {@link BidderRequest}.
*/
private List updateRequestMetric(List bidderRequests, UidsCookie uidsCookie,
- Map aliases, String publisherId,
+ BidderAliases aliases, String publisherId,
MetricName requestTypeMetric) {
metrics.updateAccountRequestMetrics(publisherId, requestTypeMetric);
for (BidderRequest bidderRequest : bidderRequests) {
- final String bidder = resolveBidder(bidderRequest.getBidder(), aliases);
+ final String bidder = aliases.resolveBidder(bidderRequest.getBidder());
final boolean isApp = bidderRequest.getBidRequest().getApp() != null;
final boolean noBuyerId = !bidderCatalog.isActive(bidder) || StringUtils.isBlank(
uidsCookie.uidFrom(bidderCatalog.usersyncerByName(bidder).getCookieFamilyName()));
@@ -698,52 +764,12 @@ private List updateRequestMetric(List bidderReques
}
/**
- * Extracts {@link ExtRequestTargeting} from {@link ExtBidRequest} model.
- */
- private static ExtRequestTargeting targeting(ExtBidRequest requestExt) {
- final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
- return prebid != null ? prebid.getTargeting() : null;
- }
-
- /**
- * Creates {@link BidRequestCacheInfo} based on {@link ExtBidRequest} model.
+ * Extracts bidAdjustments from {@link ExtBidRequest}.
*/
- private BidRequestCacheInfo bidRequestCacheInfo(ExtRequestTargeting targeting, ExtBidRequest requestExt) {
+ private static Map bidAdjustments(ExtBidRequest requestExt) {
final ExtRequestPrebid prebid = requestExt != null ? requestExt.getPrebid() : null;
- final ExtRequestPrebidCache cache = prebid != null ? prebid.getCache() : null;
-
- if (targeting != null && cache != null) {
- final boolean shouldCacheBids = cache.getBids() != null;
- final boolean shouldCacheVideoBids = cache.getVastxml() != null;
- final boolean shouldCacheWinningBidsOnly = targeting.getIncludebidderkeys()
- ? false // ext.prebid.targeting.includebidderkeys takes precedence
- : ObjectUtils.defaultIfNull(cache.getWinningonly(), false);
-
- if (shouldCacheBids || shouldCacheVideoBids || shouldCacheWinningBidsOnly) {
- final Integer cacheBidsTtl = shouldCacheBids ? cache.getBids().getTtlseconds() : null;
- final Integer cacheVideoBidsTtl = shouldCacheVideoBids ? cache.getVastxml().getTtlseconds() : null;
-
- final boolean returnCreativeBid = shouldCacheBids
- ? ObjectUtils.defaultIfNull(cache.getBids().getReturnCreative(), true)
- : false;
- final boolean returnCreativeVideoBid = shouldCacheVideoBids
- ? ObjectUtils.defaultIfNull(cache.getVastxml().getReturnCreative(), true)
- : false;
-
- return BidRequestCacheInfo.builder()
- .doCaching(true)
- .shouldCacheBids(shouldCacheBids)
- .cacheBidsTtl(cacheBidsTtl)
- .shouldCacheVideoBids(shouldCacheVideoBids)
- .cacheVideoBidsTtl(cacheVideoBidsTtl)
- .returnCreativeBids(returnCreativeBid)
- .returnCreativeVideoBids(returnCreativeVideoBid)
- .shouldCacheWinningBidsOnly(shouldCacheWinningBidsOnly)
- .build();
- }
- }
-
- return BidRequestCacheInfo.noCache();
+ final Map bidAdjustmentFactors = prebid != null ? prebid.getBidadjustmentfactors() : null;
+ return bidAdjustmentFactors != null ? bidAdjustmentFactors : Collections.emptyMap();
}
/**
@@ -751,14 +777,14 @@ private BidRequestCacheInfo bidRequestCacheInfo(ExtRequestTargeting targeting, E
* recorded response time.
*/
private Future requestBids(BidderRequest bidderRequest, Timeout timeout,
- boolean debugEnabled, Map aliases,
+ boolean debugEnabled, BidderAliases aliases,
Map bidAdjustments,
Map> currencyConversionRates) {
final String bidderName = bidderRequest.getBidder();
final BigDecimal bidPriceAdjustmentFactor = bidAdjustments.get(bidderName);
final List cur = bidderRequest.getBidRequest().getCur();
final String adServerCurrency = cur.get(0);
- final Bidder> bidder = bidderCatalog.bidderByName(resolveBidder(bidderName, aliases));
+ final Bidder> bidder = bidderCatalog.bidderByName(aliases.resolveBidder(bidderName));
final long startTime = clock.millis();
return httpBidderRequester.requestBids(bidder, bidderRequest.getBidRequest(), timeout, debugEnabled)
diff --git a/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java b/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java
index 83471be0f6d..0fb3bebe38b 100644
--- a/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java
+++ b/src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java
@@ -9,30 +9,33 @@
import com.iab.openrtb.request.User;
import io.vertx.core.Future;
import org.apache.commons.lang3.StringUtils;
-import org.prebid.server.auction.model.PrivacyEnforcementResult;
+import org.prebid.server.auction.model.AuctionContext;
+import org.prebid.server.auction.model.BidderPrivacyResult;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.exception.PreBidException;
import org.prebid.server.execution.Timeout;
import org.prebid.server.json.JacksonMapper;
+import org.prebid.server.metric.MetricName;
import org.prebid.server.metric.Metrics;
import org.prebid.server.privacy.PrivacyExtractor;
import org.prebid.server.privacy.ccpa.Ccpa;
-import org.prebid.server.privacy.gdpr.GdprService;
-import org.prebid.server.privacy.gdpr.model.GdprResponse;
+import org.prebid.server.privacy.gdpr.TcfDefinerService;
+import org.prebid.server.privacy.gdpr.VendorIdResolver;
+import org.prebid.server.privacy.gdpr.model.PrivacyEnforcementAction;
+import org.prebid.server.privacy.gdpr.model.TcfResponse;
import org.prebid.server.privacy.model.Privacy;
import org.prebid.server.proto.openrtb.ext.request.ExtRegs;
import org.prebid.server.proto.openrtb.ext.request.ExtUser;
-import org.prebid.server.proto.response.BidderInfo;
+import org.prebid.server.settings.model.AccountGdprConfig;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
-import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
-import java.util.function.UnaryOperator;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -45,23 +48,26 @@ public class PrivacyEnforcementService {
new DecimalFormat("###.##", DecimalFormatSymbols.getInstance(Locale.US));
private static final User EMPTY_USER = User.builder().build();
+ private static final ExtUser EMPTY_USER_EXT = ExtUser.builder().build();
private final boolean useGeoLocation;
- private final GdprService gdprService;
private final BidderCatalog bidderCatalog;
+ private final TcfDefinerService tcfDefinerService;
private final Metrics metrics;
private final JacksonMapper mapper;
private final boolean ccpaEnforce;
private final PrivacyExtractor privacyExtractor;
- public PrivacyEnforcementService(GdprService gdprService,
- BidderCatalog bidderCatalog,
+ public PrivacyEnforcementService(BidderCatalog bidderCatalog,
+ TcfDefinerService tcfDefinerService,
Metrics metrics,
- JacksonMapper mapper, boolean useGeoLocation,
+ JacksonMapper mapper,
+ boolean useGeoLocation,
boolean ccpaEnforce) {
- this.gdprService = Objects.requireNonNull(gdprService);
+
this.bidderCatalog = Objects.requireNonNull(bidderCatalog);
+ this.tcfDefinerService = Objects.requireNonNull(tcfDefinerService);
this.metrics = Objects.requireNonNull(metrics);
this.mapper = Objects.requireNonNull(mapper);
this.useGeoLocation = useGeoLocation;
@@ -70,58 +76,72 @@ public PrivacyEnforcementService(GdprService gdprService,
privacyExtractor = new PrivacyExtractor(mapper);
}
- /**
- * Returns {@link Future <{@link Map}<{@link String}, {@link PrivacyEnforcementResult }>>}, where
- * bidders name mapped to masked {@link PrivacyEnforcementResult}.
- */
- Future