diff --git a/src/main/java/com/iab/openrtb/request/Eid.java b/src/main/java/com/iab/openrtb/request/Eid.java index f8a728e93cb..04892b57cc6 100644 --- a/src/main/java/com/iab/openrtb/request/Eid.java +++ b/src/main/java/com/iab/openrtb/request/Eid.java @@ -1,33 +1,24 @@ package com.iab.openrtb.request; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Builder; import lombok.Value; import java.util.List; -/** - * Extended identifiers support in the OpenRTB specification allows buyers - * to use audience data in real-time bidding. This object can contain one - * or more {@link Uid}s from a single source or a technology provider. The - * exchange should ensure that business agreements allow for the sending - * of this data. - */ -@Value(staticConstructor = "of") +@Value +@Builder(toBuilder = true) public class Eid { - /** - * Source or technology provider responsible for the set of included IDs. Expressed as a top-level domain. - */ String source; - /** - * Array of extended ID {@link Uid} objects from the given source. - * Refer to 3.2.28 Extended Identifier UIDs - */ List uids; - /** - * Placeholder for vendor specific extensions to this object - */ + String inserter; + + String matcher; + + Integer mm; + ObjectNode ext; } diff --git a/src/main/java/com/iab/openrtb/request/Uid.java b/src/main/java/com/iab/openrtb/request/Uid.java index 536d5a1e02b..c90e563b9d5 100644 --- a/src/main/java/com/iab/openrtb/request/Uid.java +++ b/src/main/java/com/iab/openrtb/request/Uid.java @@ -1,6 +1,7 @@ package com.iab.openrtb.request; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Builder; import lombok.Value; /** @@ -8,7 +9,8 @@ * extended identifiers. The exchange should ensure that business * agreements allow for the sending of this data. */ -@Value(staticConstructor = "of") +@Value +@Builder(toBuilder = true) public class Uid { /** diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java index b5ac7cb4705..0084afc7aca 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java @@ -410,6 +410,7 @@ private Future updateBidRequest(AuctionContext auctionContext) { .map(this::fillExplicitParameters) .map(bidRequest -> overrideParameters(bidRequest, httpRequest, auctionContext.getPrebidErrors())) .map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, true)) + .map(bidRequest -> ortb2RequestFactory.removeEmptyEids(bidRequest, auctionContext.getDebugWarnings())) .compose(resolvedBidRequest -> ortb2RequestFactory.validateRequest( resolvedBidRequest, auctionContext.getHttpRequest(), diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java index 516205a2af0..bd720a25f2b 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java @@ -248,7 +248,8 @@ private Future updateBidRequest(AuctionStoredResult auctionStoredRes .map(ortbVersionConversionManager::convertToAuctionSupportedVersion) .map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext)) .map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, hasStoredBidRequest)) - .map(bidRequest -> cookieDeprecationService.updateBidRequestDevice(bidRequest, auctionContext)); + .map(bidRequest -> cookieDeprecationService.updateBidRequestDevice(bidRequest, auctionContext)) + .map(bidRequest -> ortb2RequestFactory.removeEmptyEids(bidRequest, auctionContext.getDebugWarnings())); } private static MetricName requestTypeMetric(BidRequest bidRequest) { diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java index bd7411f24d7..336f2b5f8f1 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java @@ -4,10 +4,13 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Dooh; +import com.iab.openrtb.request.Eid; import com.iab.openrtb.request.Geo; import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Regs; import com.iab.openrtb.request.Site; +import com.iab.openrtb.request.Uid; +import com.iab.openrtb.request.User; import io.vertx.core.Future; import io.vertx.core.MultiMap; import io.vertx.ext.web.RoutingContext; @@ -32,7 +35,6 @@ import org.prebid.server.exception.UnauthorizedAccountException; import org.prebid.server.execution.Timeout; import org.prebid.server.execution.TimeoutFactory; -import org.prebid.server.floors.PriceFloorProcessor; import org.prebid.server.geolocation.CountryCodeMapper; import org.prebid.server.geolocation.model.GeoInfo; import org.prebid.server.hooks.execution.HookStageExecutor; @@ -51,11 +53,11 @@ import org.prebid.server.model.UpdateResult; import org.prebid.server.privacy.model.PrivacyContext; import org.prebid.server.proto.openrtb.ext.FlexibleExtension; +import org.prebid.server.proto.openrtb.ext.request.DsaTransparency; import org.prebid.server.proto.openrtb.ext.request.ExtPublisher; import org.prebid.server.proto.openrtb.ext.request.ExtPublisherPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRegs; import org.prebid.server.proto.openrtb.ext.request.ExtRegsDsa; -import org.prebid.server.proto.openrtb.ext.request.DsaTransparency; import org.prebid.server.proto.openrtb.ext.request.ExtRequest; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtRequestTargeting; @@ -73,12 +75,14 @@ import org.prebid.server.validation.model.ValidationResult; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.TreeMap; import java.util.function.Function; +import java.util.stream.Stream; public class Ortb2RequestFactory { @@ -99,7 +103,6 @@ public class Ortb2RequestFactory { private final ApplicationSettings applicationSettings; private final IpAddressHelper ipAddressHelper; private final HookStageExecutor hookStageExecutor; - private final PriceFloorProcessor priceFloorProcessor; private final CountryCodeMapper countryCodeMapper; private final Metrics metrics; @@ -115,7 +118,6 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor, ApplicationSettings applicationSettings, IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, - PriceFloorProcessor priceFloorProcessor, CountryCodeMapper countryCodeMapper, Metrics metrics) { @@ -135,7 +137,6 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor, this.applicationSettings = Objects.requireNonNull(applicationSettings); this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor); - this.priceFloorProcessor = Objects.requireNonNull(priceFloorProcessor); this.countryCodeMapper = Objects.requireNonNull(countryCodeMapper); this.metrics = Objects.requireNonNull(metrics); } @@ -206,6 +207,40 @@ public Future validateRequest(BidRequest bidRequest, : Future.succeededFuture(bidRequest); } + public BidRequest removeEmptyEids(BidRequest bidRequest, List warnings) { + final User user = bidRequest.getUser(); + + if (user == null) { + return bidRequest; + } + + final List eids = Stream.ofNullable(user.getEids()) + .flatMap(Collection::stream) + .map(eid -> eid.toBuilder().uids(removeEmptyUids(eid, warnings)).build()) + .filter(eid -> CollectionUtils.isNotEmpty(eid.getUids())) + .toList(); + + if (CollectionUtils.isEmpty(eids) && CollectionUtils.isNotEmpty(user.getEids())) { + warnings.add("removed empty EID array"); + } + + final User modifiedUser = user.toBuilder().eids(CollectionUtils.isEmpty(eids) ? null : eids).build(); + return bidRequest.toBuilder().user(modifiedUser).build(); + } + + private List removeEmptyUids(Eid eid, List warnings) { + return CollectionUtils.emptyIfNull(eid.getUids()).stream() + .filter(uid -> { + if (StringUtils.isBlank(uid.getId())) { + warnings.add("removed EID %s due to empty ID".formatted(eid.getSource())); + return false; + } + + return true; + }) + .toList(); + } + public Future enrichBidRequestWithGeolocationData(AuctionContext auctionContext) { final BidRequest bidRequest = auctionContext.getBidRequest(); final Device device = bidRequest.getDevice(); diff --git a/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java index 8b2533da606..8c4d5de8614 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java @@ -108,19 +108,18 @@ public Future> fromRequest(RoutingContext routingC Endpoint.openrtb2_video, MetricName.video); return ortb2RequestFactory.executeEntrypointHooks(routingContext, body, initialAuctionContext) - .compose(httpRequest -> - createBidRequest(httpRequest) + .compose(httpRequest -> createBidRequest(httpRequest) + .map(bidRequest -> removeEmptyEids(bidRequest, initialAuctionContext.getDebugWarnings())) + .compose(bidRequest -> validateRequest( + bidRequest, + httpRequest, + initialAuctionContext.getDebugWarnings())) - .compose(bidRequest -> validateRequest( - bidRequest, - httpRequest, - initialAuctionContext.getDebugWarnings())) + .map(bidRequestWithErrors -> populatePodErrors( + bidRequestWithErrors.getPodErrors(), podErrors, bidRequestWithErrors)) - .map(bidRequestWithErrors -> populatePodErrors( - bidRequestWithErrors.getPodErrors(), podErrors, bidRequestWithErrors)) - - .map(bidRequestWithErrors -> ortb2RequestFactory.enrichAuctionContext( - initialAuctionContext, httpRequest, bidRequestWithErrors.getData(), startTime))) + .map(bidRequestWithErrors -> ortb2RequestFactory.enrichAuctionContext( + initialAuctionContext, httpRequest, bidRequestWithErrors.getData(), startTime))) .compose(auctionContext -> ortb2RequestFactory.fetchAccountWithoutStoredRequestLookup(auctionContext) .map(auctionContext::with)) @@ -154,6 +153,14 @@ public Future> fromRequest(RoutingContext routingC .map(auctionContext -> WithPodErrors.of(auctionContext, podErrors)); } + private WithPodErrors removeEmptyEids(WithPodErrors requestWithPodErrors, + List debugWarnings) { + + return WithPodErrors.of( + ortb2RequestFactory.removeEmptyEids(requestWithPodErrors.getData(), debugWarnings), + requestWithPodErrors.getPodErrors()); + } + private String extractAndValidateBody(RoutingContext routingContext) { final String body = routingContext.getBodyAsString(); if (body == null) { diff --git a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java index dd54fc864d8..031f7590475 100644 --- a/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java +++ b/src/main/java/org/prebid/server/bidder/rubicon/RubiconBidder.java @@ -1230,7 +1230,7 @@ private static Eid prepareExtUserEid(Eid extUserEid) { .filter(Objects::nonNull) .map(RubiconBidder::cleanExtUserEidUidStype) .toList(); - return Eid.of(extUserEid.getSource(), extUserEidUids, extUserEid.getExt()); + return extUserEid.toBuilder().uids(extUserEidUids).build(); } private static Uid cleanExtUserEidUidStype(Uid extUserEidUid) { @@ -1242,10 +1242,7 @@ private static Uid cleanExtUserEidUidStype(Uid extUserEidUid) { final ObjectNode extUserEidUidExtCopy = extUserEidUidExt.deepCopy(); extUserEidUidExtCopy.remove(STYPE_FIELD); - return Uid.of( - extUserEidUid.getId(), - extUserEidUid.getAtype(), - extUserEidUidExtCopy); + return extUserEidUid.toBuilder().ext(extUserEidUidExtCopy).build(); } private RubiconUserExtRp rubiconUserExtRp(User user, ExtImpRubicon rubiconImpExt) { diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index d248264a59d..5676d7fd43e 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -385,7 +385,6 @@ Ortb2RequestFactory openRtb2RequestFactory( IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, CountryCodeMapper countryCodeMapper, - PriceFloorProcessor priceFloorProcessor, Metrics metrics) { final List blocklistedAccounts = splitToList(blocklistedAccountsString); @@ -403,7 +402,6 @@ Ortb2RequestFactory openRtb2RequestFactory( applicationSettings, ipAddressHelper, hookStageExecutor, - priceFloorProcessor, countryCodeMapper, metrics); } diff --git a/src/main/java/org/prebid/server/validation/RequestValidator.java b/src/main/java/org/prebid/server/validation/RequestValidator.java index bece88c27ac..f596850955d 100644 --- a/src/main/java/org/prebid/server/validation/RequestValidator.java +++ b/src/main/java/org/prebid/server/validation/RequestValidator.java @@ -10,7 +10,6 @@ import com.iab.openrtb.request.Imp; import com.iab.openrtb.request.Regs; import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.Uid; import com.iab.openrtb.request.User; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; @@ -572,19 +571,6 @@ private void validateUser(User user, Map aliases) throws Validat throw new ValidationException( "request.user.eids[%d] missing required field: \"source\"", index); } - final List eidUids = eid.getUids(); - if (CollectionUtils.isEmpty(eidUids)) { - throw new ValidationException( - "request.user.eids[%d].uids must contain at least one element", index); - } - for (int uidsIndex = 0; uidsIndex < eidUids.size(); uidsIndex++) { - final Uid uid = eidUids.get(uidsIndex); - if (StringUtils.isBlank(uid.getId())) { - throw new ValidationException( - "request.user.eids[%d].uids[%d] missing required field: \"id\"", index, - uidsIndex); - } - } } } } diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Eid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Eid.groovy index 1b70bd08799..2cb344f6967 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Eid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Eid.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import org.prebid.server.functional.util.PBSUtils @@ -10,11 +11,18 @@ class Eid { String source List uids + String inserter + String matcher + @JsonProperty("mm") + Integer matchMethod static Eid getDefaultEid(String source = PBSUtils.randomString) { new Eid().tap { it.source = source it.uids = [Uid.defaultUid] + it.inserter = PBSUtils.randomString + it.matcher = PBSUtils.randomString + it.matchMethod = PBSUtils.randomNumber } } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy index 339a2637472..529f9c9c961 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy @@ -17,10 +17,13 @@ import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer class EidsSpec extends BaseSpec { + private static final String EMPTY_STRING = "" + def "PBS shouldn't populate user.id from user.ext data"() { given: "Default basic BidRequest with generic bidder" def bidRequest = BidRequest.defaultBidRequest.tap { @@ -197,4 +200,76 @@ class EidsSpec extends BaseSpec { and: "Alias bidder should contain one eids" assert sortedEids[1].eids == [eid] } + + def "PBS should populate warning for one removed UID when invalid uidId"() { + given: "BidRequest with eids" + def sourceId = PBSUtils.randomString + def validUidId = PBSUtils.randomString + def bidRequest = BidRequest.defaultBidRequest.tap { + user = new User(ext: new UserExt(eids: [new Eid(source: sourceId, + uids: [new Uid(id: invalidUidId), + new Uid(id: validUidId)])])) + } + + when: "PBS processes auction" + def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Bidder request should contain eids" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.user.eids.uids.id.flatten() == [validUidId] + + and: "Bid response should contain warning" + assert bidResponse.ext.warnings[PREBID]?.code == [999] + assert bidResponse.ext.warnings[PREBID]?.message == + ["removed EID ${sourceId} due to empty ID" as String] + + where: + invalidUidId << [EMPTY_STRING, null] + } + + def "PBS should populate warnings for removed UIDs and entire eids when requested invalid uidIds"() { + given: "BidRequest with eids" + def sourceId = PBSUtils.randomString + def bidRequest = BidRequest.defaultBidRequest.tap { + user = new User(ext: new UserExt(eids: [new Eid(source: sourceId, + uids: [new Uid(id: invalidUidId), + new Uid(id: invalidUidId)])])) + } + + when: "PBS processes auction" + def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Bidder request shouldn't contain eids" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert !bidderRequest.user.eids + + and: "Bid response should contain warnings" + assert bidResponse.ext.warnings[PREBID]?.code == [999, 999, 999] + assert bidResponse.ext.warnings[PREBID]?.message == + ["removed EID ${sourceId} due to empty ID" as String, + "removed EID ${sourceId} due to empty ID" as String, + "removed empty EID array" as String] + + where: + invalidUidId << [EMPTY_STRING, null] + } + + def "PBS shouldn't populate warning for UID when Uid id is valid"() { + given: "BidRequest with eids" + def validUidId = PBSUtils.randomString + def bidRequest = BidRequest.defaultBidRequest.tap { + user = new User(ext: new UserExt(eids: [new Eid(source: PBSUtils.randomString, + uids: [new Uid(id: validUidId)])])) + } + + when: "PBS processes auction" + def bidResponse = defaultPbsService.sendAuctionRequest(bidRequest) + + then: "Bidder request should contain eids" + def bidderRequest = bidder.getBidderRequest(bidRequest.id) + assert bidderRequest.user.eids.uids.id.flatten() == [validUidId] + + and: "Bid response shouldn't contain warning" + assert !bidResponse.ext.warnings + } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/OrtbConverterSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/OrtbConverterSpec.groovy index 7eb388cf202..21bb80df135 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/OrtbConverterSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/OrtbConverterSpec.groovy @@ -180,7 +180,7 @@ class OrtbConverterSpec extends BaseSpec { } } - def "PBS should move eids to o user.ext.eids when adapter doesn't support ortb 2.6"() { + def "PBS should move eids to user.ext.eids when adapter doesn't support ortb 2.6"() { given: "Default bid request with user.eids" def defaultEids = [Eid.defaultEid] def bidRequest = BidRequest.defaultBidRequest.tap { diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index e058d43b0df..7eb1a351531 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -2063,7 +2063,7 @@ public void shouldPassUserDataAndExtDataOnlyForAllowedBidder() { final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); - final List eids = singletonList(Eid.of("eId", emptyList(), null)); + final List eids = singletonList(Eid.builder().source("eId").uids(emptyList()).build()); final ExtUser extUser = ExtUser.builder().data(dataNode).build(); final List data = singletonList(Data.builder().build()); @@ -2112,50 +2112,44 @@ public void shouldPassUserDataAndExtDataOnlyForAllowedBidder() { public void shouldFilterUserExtEidsWhenBidderIsNotAllowedForSourceIgnoringCase() { testUserEidsPermissionFiltering( // given - asList( - Eid.of("source1", null, null), - Eid.of("source2", null, null)), + asList(Eid.builder().source("source1").build(), Eid.builder().source("source2").build()), singletonList(ExtRequestPrebidDataEidPermissions.of("source1", singletonList("OtHeRbIdDeR"))), emptyMap(), // expected - singletonList(Eid.of("source2", null, null)) - ); + singletonList(Eid.builder().source("source2").build())); } @Test public void shouldNotFilterUserExtEidsWhenEidsPermissionDoesNotContainSourceIgnoringCase() { testUserEidsPermissionFiltering( // given - singletonList(Eid.of("source1", null, null)), + singletonList(Eid.builder().source("source1").build()), singletonList(ExtRequestPrebidDataEidPermissions.of("source2", singletonList("OtHeRbIdDeR"))), emptyMap(), // expected - singletonList(Eid.of("source1", null, null)) - ); + singletonList(Eid.builder().source("source1").build())); } @Test public void shouldNotFilterUserExtEidsWhenSourceAllowedForAllBiddersIgnoringCase() { testUserEidsPermissionFiltering( // given - singletonList(Eid.of("source1", null, null)), + singletonList(Eid.builder().source("source1").build()), singletonList(ExtRequestPrebidDataEidPermissions.of("source1", singletonList("*"))), emptyMap(), // expected - singletonList(Eid.of("source1", null, null)) - ); + singletonList(Eid.builder().source("source1").build())); } @Test public void shouldNotFilterUserExtEidsWhenSourceAllowedForBidderIgnoringCase() { testUserEidsPermissionFiltering( // given - singletonList(Eid.of("source1", null, null)), + singletonList(Eid.builder().source("source1").build()), singletonList(ExtRequestPrebidDataEidPermissions.of("source1", singletonList("SoMeBiDdEr"))), emptyMap(), // expected - singletonList(Eid.of("source1", null, null)) - ); + singletonList(Eid.builder().source("source1").build())); } @Test @@ -2173,7 +2167,7 @@ public void shouldFilterUserExtEidsWhenBidderIsNotAllowedForSourceAndSetNullIfNo singletonList("otherBidder"))))) .build())) .user(User.builder() - .eids(singletonList(Eid.of("source1", null, null))) + .eids(singletonList(Eid.builder().source("source1").build())) .ext(ExtUser.builder().data(mapper.createObjectNode()).build()) .build())); @@ -2209,7 +2203,7 @@ public void shouldFilterUserExtEidsWhenBidderPermissionsGivenToBidderAliasOnly() singletonList("someBidderAlias"))))) .build())) .user(User.builder() - .eids(singletonList(Eid.of("source1", null, null))) + .eids(singletonList(Eid.builder().source("source1").build())) .ext(ExtUser.builder().data(mapper.createObjectNode()).build()) .build())); @@ -2245,7 +2239,7 @@ public void shouldFilterUserExtEidsWhenPermissionsGivenToBidderButNotForAlias() singletonList("someBidder"))))) .build())) .user(User.builder() - .eids(singletonList(Eid.of("source1", null, null))) + .eids(singletonList(Eid.builder().source("source1").build())) .ext(ExtUser.builder().data(mapper.createObjectNode()).build()) .build())); @@ -2309,7 +2303,7 @@ public void shouldMaskUserExtIfDataBiddersListIsEmpty() { final ObjectNode dataNode = mapper.createObjectNode().put("data", "value"); final Map bidderToGdpr = doubleMap("someBidder", 1, "missingBidder", 0); - final List eids = singletonList(Eid.of("eId", emptyList(), null)); + final List eids = singletonList(Eid.builder().source("eId").uids(emptyList()).build()); final ExtUser extUser = ExtUser.builder().data(dataNode).build(); final BidRequest bidRequest = givenBidRequest(givenSingleImp(bidderToGdpr), diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java index e8222accf25..0dad839fc87 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/TcfEnforcementTest.java @@ -394,7 +394,7 @@ private static Device givenDeviceWithNoPrivacyData() { private static User givenUserWithPrivacyData() { return User.builder() .id("originalUser") - .eids(singletonList(Eid.of(null, null, null))) + .eids(singletonList(Eid.builder().build())) .geo(Geo.builder().build()) .build(); } diff --git a/src/test/java/org/prebid/server/auction/privacy/enforcement/mask/UserFpdTcfMaskTest.java b/src/test/java/org/prebid/server/auction/privacy/enforcement/mask/UserFpdTcfMaskTest.java index 14be79446d5..850c362e0d8 100644 --- a/src/test/java/org/prebid/server/auction/privacy/enforcement/mask/UserFpdTcfMaskTest.java +++ b/src/test/java/org/prebid/server/auction/privacy/enforcement/mask/UserFpdTcfMaskTest.java @@ -72,9 +72,9 @@ public void maskUserShouldReturnExpectedResultWhenEidsMasked() { .kwarray(emptyList()) .data(emptyList()) .eids(asList( - Eid.of("1", null, null), - Eid.of("2", null, null), - Eid.of("3", null, null))) + Eid.builder().source("1").build(), + Eid.builder().source("2").build(), + Eid.builder().source("3").build())) .geo(Geo.builder().lon(-85.34321F).lat(189.342323F).build()) .ext(ExtUser.builder().data(mapper.createObjectNode()).build()) .build(); @@ -92,7 +92,7 @@ public void maskUserShouldReturnExpectedResultWhenEidsMasked() { .keywords("keywords") .kwarray(emptyList()) .data(emptyList()) - .eids(singletonList(Eid.of("2", null, null))) + .eids(singletonList(Eid.builder().source("2").build())) .geo(Geo.builder().lon(-85.34321F).lat(189.342323F).build()) .ext(ExtUser.builder().data(mapper.createObjectNode()).build()) .build()); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java index bad5e98fe8d..7318d7906c2 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java @@ -154,6 +154,8 @@ public void setUp() { given(ortb2RequestFactory.restoreResultFromRejection(any())) .willAnswer(invocation -> Future.failedFuture((Throwable) invocation.getArgument(0))); given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); + given(ortb2RequestFactory.removeEmptyEids(any(), any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); given(fpdResolver.resolveApp(any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java index ab3fa774e0c..dedb325e241 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java @@ -158,6 +158,8 @@ public void setUp() { ((AuctionContext) invocation.getArgument(0)).getBidRequest())); given(ortb2RequestFactory.validateRequest(any(), any(), any())) .willAnswer(invocationOnMock -> Future.succeededFuture((BidRequest) invocationOnMock.getArgument(0))); + given(ortb2RequestFactory.removeEmptyEids(any(), any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); given(paramsResolver.resolve(any(), any(), any(), anyBoolean())) diff --git a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java index 6da1084c895..b38c305cd2b 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java @@ -5,10 +5,13 @@ import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Dooh; +import com.iab.openrtb.request.Eid; import com.iab.openrtb.request.Geo; import com.iab.openrtb.request.Publisher; import com.iab.openrtb.request.Regs; import com.iab.openrtb.request.Site; +import com.iab.openrtb.request.Uid; +import com.iab.openrtb.request.User; import io.vertx.core.Future; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpServerRequest; @@ -38,7 +41,6 @@ import org.prebid.server.exception.UnauthorizedAccountException; import org.prebid.server.execution.Timeout; import org.prebid.server.execution.TimeoutFactory; -import org.prebid.server.floors.PriceFloorProcessor; import org.prebid.server.geolocation.CountryCodeMapper; import org.prebid.server.geolocation.model.GeoInfo; import org.prebid.server.hooks.execution.HookStageExecutor; @@ -121,8 +123,6 @@ public class Ortb2RequestFactoryTest extends VertxTest { @Mock(strictness = LENIENT) private HookStageExecutor hookStageExecutor; @Mock - private PriceFloorProcessor priceFloorProcessor; - @Mock private CountryCodeMapper countryCodeMapper; @Mock private Metrics metrics; @@ -1639,6 +1639,67 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldNotSetDsaFromAccountW .isSameAs(regs); } + @Test + public void removeEmptyEidsShouldNotAddWarningWhenEidsAreEmpty() { + final User givenUser = User.builder().eids(emptyList()).build(); + final BidRequest givenBidRequest = givenBidRequest(request -> request.user(givenUser)); + final List warnings = new ArrayList<>(); + + final BidRequest actualBidRequest = target.removeEmptyEids(givenBidRequest, warnings); + + assertThat(actualBidRequest.getUser().getEids()).isNull(); + assertThat(warnings).isEmpty(); + } + + @Test + public void removeEmptyEidsShouldRemoveEidsWhenNoValidEidsLeft() { + final User givenUser = User.builder() + .eids(List.of( + Eid.builder().source("source1").uids(List.of( + Uid.builder().id("").build(), + Uid.builder().id("").build())).build(), + Eid.builder().source("source2").uids(List.of(Uid.builder().id("").build())).build(), + Eid.builder().source("source3").uids(emptyList()).build())) + .build(); + + final BidRequest givenBidRequest = givenBidRequest(request -> request.user(givenUser)); + final List warnings = new ArrayList<>(); + + final BidRequest actualBidRequest = target.removeEmptyEids(givenBidRequest, warnings); + + assertThat(actualBidRequest.getUser().getEids()).isNull(); + assertThat(warnings).containsExactlyInAnyOrder( + "removed EID source1 due to empty ID", + "removed EID source1 due to empty ID", + "removed EID source2 due to empty ID", + "removed empty EID array"); + } + + @Test + public void removeEmptyEidsShouldRemoveEmptyUidsOnly() { + final User givenUser = User.builder() + .eids(List.of( + Eid.builder().source("source1").uids(List.of( + Uid.builder().id("id1").build(), + Uid.builder().id("").build())).build(), + Eid.builder().source("source2").uids(List.of(Uid.builder().id("id2").build())).build(), + Eid.builder().source("source3").uids(List.of(Uid.builder().id("").build())).build())) + .build(); + + final BidRequest givenBidRequest = givenBidRequest(request -> request.user(givenUser)); + final List warnings = new ArrayList<>(); + + final BidRequest actualBidRequest = target.removeEmptyEids(givenBidRequest, warnings); + + assertThat(actualBidRequest.getUser().getEids()).containsExactlyInAnyOrder( + Eid.builder().source("source1").uids(List.of(Uid.builder().id("id1").build())).build(), + Eid.builder().source("source2").uids(List.of(Uid.builder().id("id2").build())).build()); + + assertThat(warnings).containsExactlyInAnyOrder( + "removed EID source1 due to empty ID", + "removed EID source3 due to empty ID"); + } + private void givenTarget(int timeoutAdjustmentFactor) { target = new Ortb2RequestFactory( timeoutAdjustmentFactor, @@ -1653,7 +1714,6 @@ private void givenTarget(int timeoutAdjustmentFactor) { applicationSettings, ipAddressHelper, hookStageExecutor, - priceFloorProcessor, countryCodeMapper, metrics); } diff --git a/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java index 5764566ea17..475b22a5d5b 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java @@ -105,6 +105,8 @@ public void setUp() { given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); given(ortb2RequestFactory.activityInfrastructureFrom(any())) .willReturn(Future.succeededFuture()); + given(ortb2RequestFactory.removeEmptyEids(any(), any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); given(ortbVersionConversionManager.convertToAuctionSupportedVersion(any())) .willAnswer(invocation -> invocation.getArgument(0)); diff --git a/src/test/java/org/prebid/server/auction/versionconverter/down/BidRequestOrtb26To25ConverterTest.java b/src/test/java/org/prebid/server/auction/versionconverter/down/BidRequestOrtb26To25ConverterTest.java index bad068fcea4..4d0aca65fa5 100644 --- a/src/test/java/org/prebid/server/auction/versionconverter/down/BidRequestOrtb26To25ConverterTest.java +++ b/src/test/java/org/prebid/server/auction/versionconverter/down/BidRequestOrtb26To25ConverterTest.java @@ -131,7 +131,7 @@ public void convertShouldMoveUserData() { final BidRequest bidRequest = givenBidRequest(request -> request.user( User.builder() .consent("consent") - .eids(singletonList(Eid.of("source", emptyList(), null))) + .eids(singletonList(Eid.builder().source("source").uids(emptyList()).build())) .ext(mapper.convertValue(Map.of("someField", "someValue"), ExtUser.class)) .build())); @@ -148,7 +148,7 @@ public void convertShouldMoveUserData() { final ExtUser expectedUserExt = ExtUser.builder() .consent("consent") - .eids(singletonList(Eid.of("source", emptyList(), null))) + .eids(singletonList(Eid.builder().source("source").uids(emptyList()).build())) .build(); expectedUserExt.addProperty("someField", TextNode.valueOf("someValue")); assertThat(user) diff --git a/src/test/java/org/prebid/server/auction/versionconverter/up/BidRequestOrtb25To26ConverterTest.java b/src/test/java/org/prebid/server/auction/versionconverter/up/BidRequestOrtb25To26ConverterTest.java index 2f52722be16..db1fc112be7 100644 --- a/src/test/java/org/prebid/server/auction/versionconverter/up/BidRequestOrtb25To26ConverterTest.java +++ b/src/test/java/org/prebid/server/auction/versionconverter/up/BidRequestOrtb25To26ConverterTest.java @@ -242,7 +242,7 @@ public void convertShouldNotChangeUserConsentIfPresent() { @Test public void convertShouldMoveUserExtEidsToUserEidsIfNotPresent() { // given - final List eids = singletonList(Eid.of("source", emptyList(), null)); + final List eids = singletonList(Eid.builder().source("source").uids(emptyList()).build()); final BidRequest bidRequest = givenBidRequest(request -> request.user( User.builder().ext(ExtUser.builder().eids(eids).build()).build())); @@ -265,7 +265,7 @@ public void convertShouldMoveUserExtEidsToUserEidsIfNotPresent() { @Test public void convertShouldNotChangeUserEidsIfPresent() { // given - final List eids = singletonList(Eid.of("source", emptyList(), null)); + final List eids = singletonList(Eid.builder().source("source").uids(emptyList()).build()); final BidRequest bidRequest = givenBidRequest(request -> request.user( User.builder().eids(eids).ext(ExtUser.builder().eids(emptyList()).build()).build())); diff --git a/src/test/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidderTest.java b/src/test/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidderTest.java index ac80138bbc0..c911aed14c5 100644 --- a/src/test/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/adnuntius/AdnuntiusBidderTest.java @@ -268,8 +268,7 @@ public void makeHttpRequestsShouldPopulateMetaDataUsiFromUserIdWhenBothUidIdAndU request -> request.user(User.builder() .id("userId") .ext(ExtUser.builder() - .eids(List.of(Eid.of(null, - List.of(Uid.of("eidsId", null, null)), null))) + .eids(List.of(Eid.builder().uids(List.of(Uid.builder().id("eidsId").build())).build())) .build()) .build()), givenImp(ExtImpAdnuntius.builder().network("network").build(), identity()), @@ -294,8 +293,7 @@ public void makeHttpRequestsShouldPopulateMetaDataUsiWhenUserExtEidsUidIdPresent request -> request.user(User.builder() .id(null) .ext(ExtUser.builder() - .eids(List.of(Eid.of(null, - List.of(Uid.of("eidsId", null, null)), null))) + .eids(List.of(Eid.builder().uids(List.of(Uid.builder().id("eidsId").build())).build())) .build()) .build()), givenImp(ExtImpAdnuntius.builder().network("network").build(), identity()), diff --git a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java index 24db88e46fc..7658e5be17a 100644 --- a/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/rubicon/RubiconBidderTest.java @@ -1962,10 +1962,10 @@ public void makeHttpRequestsShouldNotCreateUserIfVisitorAndConsentNotPresent() { public void makeHttpRequestsShouldUseGivenUserIdIfOtherExtUserFieldsPassed() { // given final ExtUser extUser = ExtUser.builder() - .eids(singletonList(Eid.of( - "liveramp.com", - singletonList(Uid.of("firstId", null, null)), - null))) + .eids(singletonList(Eid.builder() + .source("liveramp.com") + .uids(singletonList(Uid.builder().id("firstId").build())) + .build())) .build(); final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .id("userId") @@ -1989,13 +1989,21 @@ public void makeHttpRequestsShouldUseGivenUserIdIfOtherExtUserFieldsPassed() { public void makeHttpRequestsShouldCreateUserIdIfMissingFromFirstUidStypePpuid() { // given final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() - .eids(singletonList(Eid.of( - null, - asList( - Uid.of("id1", null, mapper.valueToTree(Map.of("stype", "other"))), - Uid.of("id2", null, mapper.valueToTree(Map.of("stype", "ppuid"))), - Uid.of("id3", null, mapper.valueToTree(Map.of("stype", "ppuid")))), - null))) + .eids(singletonList(Eid.builder() + .uids(asList( + Uid.builder() + .id("id1") + .ext(mapper.valueToTree(Map.of("stype", "other"))) + .build(), + Uid.builder() + .id("id2") + .ext(mapper.valueToTree(Map.of("stype", "ppuid"))) + .build(), + Uid.builder() + .id("id3") + .ext(mapper.valueToTree(Map.of("stype", "ppuid"))) + .build())) + .build())) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2015,12 +2023,16 @@ public void makeHttpRequestsShouldNotCreateUserIdIfMissingWhenNoUidWithPpuidType // given final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() - .eids(singletonList(Eid.of( - null, - asList( - Uid.of("id1", null, mapper.valueToTree(Map.of("stype", "other"))), - Uid.of("id2", null, mapper.valueToTree(Map.of("stype", "other")))), - null))) + .eids(singletonList(Eid.builder().uids(asList( + Uid.builder() + .id("id1") + .ext(mapper.valueToTree(Map.of("stype", "other"))) + .build(), + Uid.builder() + .id("id2") + .ext(mapper.valueToTree(Map.of("stype", "other"))) + .build())) + .build())) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2038,15 +2050,28 @@ public void makeHttpRequestsShouldNotCreateUserIdIfMissingWhenNoUidWithPpuidType @Test public void makeHttpRequestsShouldRemoveStypesPpuidSha256emailDmp() { // given - final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() - .eids(singletonList(Eid.of( - "source", - asList( - Uid.of("id1", null, mapper.valueToTree(Map.of("stype", "other"))), - Uid.of("id2", null, mapper.valueToTree(Map.of("stype", "ppuid"))), - Uid.of("id3", null, mapper.valueToTree(Map.of("stype", "sha256email"))), - Uid.of("id4", null, mapper.valueToTree(Map.of("stype", "dmp")))), - null))) + final BidRequest bidRequest = givenBidRequest( + builder -> builder.user(User.builder() + .eids(singletonList(Eid.builder() + .source("source") + .uids(asList( + Uid.builder() + .id("id1") + .ext(mapper.valueToTree(Map.of("stype", "other"))) + .build(), + Uid.builder() + .id("id2") + .ext(mapper.valueToTree(Map.of("stype", "ppuid"))) + .build(), + Uid.builder() + .id("id3") + .ext(mapper.valueToTree(Map.of("stype", "sha256email"))) + .build(), + Uid.builder() + .id("id4") + .ext(mapper.valueToTree(Map.of("stype", "dmp"))) + .build())) + .build())) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2059,14 +2084,15 @@ public void makeHttpRequestsShouldRemoveStypesPpuidSha256emailDmp() { .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .extracting(request -> request.getUser().getExt()).hasSize(1).element(0) .isEqualTo(ExtUser.builder() - .eids(singletonList(Eid.of( - "source", - asList( - Uid.of("id1", null, mapper.valueToTree(Map.of("stype", "other"))), - Uid.of("id2", null, mapper.createObjectNode()), - Uid.of("id3", null, mapper.createObjectNode()), - Uid.of("id4", null, mapper.createObjectNode())), - null))) + .eids(singletonList(Eid.builder() + .source("source") + .uids(asList( + Uid.builder().id("id1") + .ext(mapper.valueToTree(Map.of("stype", "other"))).build(), + Uid.builder().id("id2").ext(mapper.createObjectNode()).build(), + Uid.builder().id("id3").ext(mapper.createObjectNode()).build(), + Uid.builder().id("id4").ext(mapper.createObjectNode()).build())) + .build())) .build()); } @@ -2075,10 +2101,10 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfExt // given final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() - .eids(singletonList(Eid.of( - "adserver.org", - singletonList(Uid.of("id", null, null)), - null))) + .eids(singletonList(Eid.builder() + .source("adserver.org") + .uids(singletonList(Uid.builder().id("id").build())) + .build())) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2092,10 +2118,10 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithAdServerEidSourceIfExt .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .extracting(request -> request.getUser().getExt()) .containsOnly(ExtUser.builder() - .eids(singletonList(Eid.of( - "adserver.org", - singletonList(Uid.of("id", null, null)), - null))) + .eids(singletonList(Eid.builder() + .source("adserver.org") + .uids(singletonList(Uid.builder().id("id").build())) + .build())) .build()); } @@ -2104,13 +2130,13 @@ public void makeHttpRequestsShouldCreateUserExtEidsWithAdServerEidSource() { // given final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() - .eids(singletonList(Eid.of( - "adserver.org", - singletonList(Uid.of( - "adServerUid", - null, - mapper.valueToTree(Map.of("rtiPartner", "TDID")))), - null))) + .eids(singletonList(Eid.builder() + .source("adserver.org") + .uids(singletonList(Uid.builder() + .id("adServerUid") + .ext(mapper.valueToTree(Map.of("rtiPartner", "TDID"))) + .build())) + .build())) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2125,13 +2151,13 @@ public void makeHttpRequestsShouldCreateUserExtEidsWithAdServerEidSource() { .extracting(request -> request.getUser().getExt()) .containsOnly(jacksonMapper.fillExtension( ExtUser.builder() - .eids(singletonList(Eid.of( - "adserver.org", - singletonList(Uid.of( - "adServerUid", - null, - mapper.valueToTree(Map.of("rtiPartner", "TDID")))), - null))) + .eids(singletonList(Eid.builder() + .source("adserver.org") + .uids(singletonList(Uid.builder() + .id("adServerUid") + .ext(mapper.valueToTree(Map.of("rtiPartner", "TDID"))) + .build())) + .build())) .build(), RubiconUserExt.builder().build())); } @@ -2141,8 +2167,8 @@ public void makeHttpRequestsShouldIgnoreLiverampIdIfMissingEidUidId() { // given final ExtUser extUser = ExtUser.builder() .eids(asList( - Eid.of("liveramp.com", null, null), - Eid.of("liveramp.com", emptyList(), null))) + Eid.builder().source("liveramp.com").build(), + Eid.builder().source("liveramp.com").uids(emptyList()).build())) .build(); final BidRequest bidRequest = givenBidRequest( builder -> builder.user(User.builder().ext(extUser).build()), @@ -2165,13 +2191,13 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithUnknownEidSource() { // given final BidRequest bidRequest = givenBidRequest(builder -> builder.user(User.builder() .ext(ExtUser.builder() - .eids(singletonList(Eid.of( - "unknownSource", - singletonList(Uid.of( - "id", - null, - mapper.valueToTree(Map.of("rtiPartner", "eidUidId")))), - null))) + .eids(singletonList(Eid.builder() + .source("unknownSource") + .uids(singletonList(Uid.builder() + .id("id") + .ext(mapper.valueToTree(Map.of("rtiPartner", "eidUidId"))) + .build())) + .build())) .build()) .build()), builder -> builder.video(Video.builder().build()), identity()); @@ -2185,10 +2211,13 @@ public void makeHttpRequestsShouldNotCreateUserExtTpIdWithUnknownEidSource() { .extracting(httpRequest -> mapper.readValue(httpRequest.getBody(), BidRequest.class)) .extracting(request -> request.getUser().getExt()) .containsOnly(ExtUser.builder() - .eids(singletonList(Eid.of( - "unknownSource", - singletonList(Uid.of("id", null, mapper.valueToTree(Map.of("rtiPartner", "eidUidId")))), - null))) + .eids(singletonList(Eid.builder() + .source("unknownSource") + .uids(singletonList(Uid.builder() + .id("id") + .ext(mapper.valueToTree(Map.of("rtiPartner", "eidUidId"))) + .build())) + .build())) .build()); } diff --git a/src/test/java/org/prebid/server/bidder/siverpush/SilverPushBidderTest.java b/src/test/java/org/prebid/server/bidder/siverpush/SilverPushBidderTest.java index 2197850e023..f734090592c 100644 --- a/src/test/java/org/prebid/server/bidder/siverpush/SilverPushBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/siverpush/SilverPushBidderTest.java @@ -79,8 +79,10 @@ public void makeHttpRequestsShouldFailOnMissingPublisherId() { @Test public void makeHttpRequestsShouldPassEidsFromDataToExtEids() { // given - final List givenEids = - List.of(Eid.of("testSource", List.of(Uid.of("testUidId", 2, null)), null)); + final List givenEids = List.of(Eid.builder() + .source("testSource") + .uids(List.of(Uid.builder().id("testUidId").atype(2).build())) + .build()); final ObjectNode givenDataNode = mapper.createObjectNode(); givenDataNode.set("eids", mapper.valueToTree(givenEids)); final BidRequest bidRequest = givenBidRequest(requestBuilder -> requestBuilder diff --git a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java index a195514fa70..29e12ea6b66 100644 --- a/src/test/java/org/prebid/server/validation/RequestValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/RequestValidatorTest.java @@ -13,11 +13,10 @@ import com.iab.openrtb.request.Pmp; import com.iab.openrtb.request.Regs; import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.Uid; import com.iab.openrtb.request.User; import com.iab.openrtb.request.Video; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -1126,7 +1125,7 @@ public void validateShouldReturnValidationMessageWhenEidHasEmptySource() { // given final BidRequest bidRequest = validBidRequestBuilder() .user(User.builder() - .eids(singletonList(Eid.of(null, null, null))) + .eids(singletonList(Eid.builder().build())) .build()) .build(); @@ -1138,60 +1137,6 @@ public void validateShouldReturnValidationMessageWhenEidHasEmptySource() { .containsOnly("request.user.eids[0] missing required field: \"source\""); } - @Test - public void validateShouldReturnValidationMessageWhenEidHasNoUids() { - // given - final BidRequest bidRequest = validBidRequestBuilder() - .user(User.builder() - .eids(singletonList(Eid.of("source", null, null))) - .build()) - .build(); - - // when - final ValidationResult result = target.validate(bidRequest, null); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly("request.user.eids[0].uids must contain at least one element"); - } - - @Test - public void validateShouldReturnValidationMessageWhenEidUidsIsEmpty() { - // given - final BidRequest bidRequest = validBidRequestBuilder() - .user(User.builder() - .eids(singletonList(Eid.of("source", emptyList(), null))) - .build()) - .build(); - - // when - final ValidationResult result = target.validate(bidRequest, null); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly("request.user.eids[0].uids must contain at least one element"); - } - - @Test - public void validateShouldReturnValidationMessageWhenEidUidIdIsMissing() { - // given - final BidRequest bidRequest = validBidRequestBuilder() - .user(User.builder() - .eids(singletonList(Eid.of( - "source", - singletonList(Uid.of(null, null, null)), - null))) - .build()) - .build(); - - // when - final ValidationResult result = target.validate(bidRequest, null); - - // then - assertThat(result.getErrors()).hasSize(1) - .containsOnly("request.user.eids[0].uids[0] missing required field: \"id\""); - } - @Test public void validateShouldReturnValidationMessageWhenAliasNameEqualsToBidderItPointsOn() { // given