From e32018fda0687a5d6d68ef964b6d3aebb44b3067 Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 12 Nov 2025 12:30:57 +0100 Subject: [PATCH 1/3] DATA-43462: Limiting LI ids to bidders --- .../LiveIntentOmniChannelProperties.java | 4 ++ ...elIdentityProcessedAuctionRequestHook.java | 61 +++++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/model/config/LiveIntentOmniChannelProperties.java b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/model/config/LiveIntentOmniChannelProperties.java index b6a61b0ca8f..01d37eabda0 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/model/config/LiveIntentOmniChannelProperties.java +++ b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/model/config/LiveIntentOmniChannelProperties.java @@ -2,6 +2,8 @@ import lombok.Data; +import java.util.List; + @Data public final class LiveIntentOmniChannelProperties { @@ -12,4 +14,6 @@ public final class LiveIntentOmniChannelProperties { String authToken; float treatmentRate; + + List targetBidders; } diff --git a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java index 005ac13b223..d13f79cb9dd 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java +++ b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java @@ -7,6 +7,7 @@ import com.iab.openrtb.request.User; import io.vertx.core.Future; import io.vertx.core.MultiMap; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.prebid.server.activity.Activity; import org.prebid.server.activity.ComponentType; @@ -33,6 +34,10 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.log.ConditionalLogger; import org.prebid.server.log.LoggerFactory; +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.ExtRequestPrebidData; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ListUtil; import org.prebid.server.vertx.httpclient.HttpClient; @@ -42,6 +47,7 @@ import java.util.Objects; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements ProcessedAuctionRequestHook { @@ -55,6 +61,7 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements private final HttpClient httpClient; private final UserFpdActivityMask userFpdActivityMask; private final double logSamplingRate; + private final List targetBidders; public LiveIntentOmniChannelIdentityProcessedAuctionRequestHook(LiveIntentOmniChannelProperties config, UserFpdActivityMask userFpdActivityMask, @@ -68,6 +75,7 @@ public LiveIntentOmniChannelIdentityProcessedAuctionRequestHook(LiveIntentOmniCh this.httpClient = Objects.requireNonNull(httpClient); this.logSamplingRate = logSamplingRate; this.userFpdActivityMask = Objects.requireNonNull(userFpdActivityMask); + this.targetBidders = ListUtils.emptyIfNull(config.getTargetBidders()); } @Override @@ -170,17 +178,17 @@ private InvocationResultImpl update(IdResResponse resolut ActivityImpl.of( "liveintent-enriched", "success", List.of( - ResultImpl.of( - "", - mapper.mapper().createObjectNode() - .put("treatmentRate", config.getTreatmentRate()), - null)))))) + ResultImpl.of( + "", + mapper.mapper().createObjectNode() + .put("treatmentRate", config.getTreatmentRate()), + null)))))) .build(); } private AuctionRequestPayload updatedPayload(AuctionRequestPayload requestPayload, List resolvedEids) { final List eids = ListUtils.emptyIfNull(resolvedEids); - final BidRequest bidRequest = requestPayload.bidRequest(); + final BidRequest bidRequest = updateAllowedBidders(requestPayload.bidRequest(), resolvedEids); final User updatedUser = Optional.ofNullable(bidRequest.getUser()) .map(user -> user.toBuilder().eids(ListUtil.union(ListUtils.emptyIfNull(user.getEids()), eids))) .orElseGet(() -> User.builder().eids(eids)) @@ -189,6 +197,47 @@ private AuctionRequestPayload updatedPayload(AuctionRequestPayload requestPayloa return AuctionRequestPayloadImpl.of(bidRequest.toBuilder().user(updatedUser).build()); } + private BidRequest updateAllowedBidders(BidRequest bidRequest, List resolvedEids) { + if (this.targetBidders.isEmpty()) { + return bidRequest; + } + + final List resolvedSources = resolvedEids.stream().map(Eid::getSource).distinct().toList(); + final ExtRequest requestExt = bidRequest.getExt(); + final ExtRequestPrebid prebid = requestExt == null ? null : requestExt.getPrebid(); + final ExtRequestPrebidData prebidData = prebid != null + ? prebid.getData() + : null; + final List eidPermissions = prebidData == null + ? List.of() + : CollectionUtils.emptyIfNull(prebidData.getEidPermissions()).stream().toList(); + final Stream existingPermissions = eidPermissions + .stream() + .filter(e -> resolvedSources.contains(e.getSource())); + + final Stream missingSources = resolvedSources.stream() + .filter(src -> eidPermissions.stream().noneMatch(e -> e.getSource().equals(src))); + + final List updatedPermissions = CollectionUtils.union( + missingSources.map(src -> ExtRequestPrebidDataEidPermissions.of(src, this.targetBidders)) + .toList(), + existingPermissions.map(p -> ExtRequestPrebidDataEidPermissions.of( + p.getSource(), + CollectionUtils.union(p.getBidders(), this.targetBidders) + .stream().distinct().toList())).toList()) + .stream().toList(); + + final List bidders = prebidData == null ? this.targetBidders : CollectionUtils.union(this.targetBidders, + CollectionUtils.emptyIfNull(prebidData.getBidders())).stream().distinct().toList(); + + final ExtRequestPrebidData updatedPrebidData = ExtRequestPrebidData.of(bidders, updatedPermissions); + final ExtRequestPrebid updatedExtPrebid = prebid == null + ? ExtRequestPrebid.builder().data(updatedPrebidData).build() + : prebid.toBuilder().data(updatedPrebidData).build(); + + return bidRequest.toBuilder().ext(ExtRequest.of(updatedExtPrebid)).build(); + } + @Override public String code() { return CODE; From 4bf3c4dab93efde28dd1fafd0e54458b03d6d9cd Mon Sep 17 00:00:00 2001 From: ilya Date: Tue, 18 Nov 2025 13:48:45 +0100 Subject: [PATCH 2/3] DATA-43462: Limiting LI ids to bidders --- ...elIdentityProcessedAuctionRequestHook.java | 15 ++- ...entityProcessedAuctionRequestHookTest.java | 103 ++++++++++++++++++ 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java index d13f79cb9dd..fd13ee8950b 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java +++ b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java @@ -218,14 +218,17 @@ private BidRequest updateAllowedBidders(BidRequest bidRequest, List resolve final Stream missingSources = resolvedSources.stream() .filter(src -> eidPermissions.stream().noneMatch(e -> e.getSource().equals(src))); - final List updatedPermissions = CollectionUtils.union( - missingSources.map(src -> ExtRequestPrebidDataEidPermissions.of(src, this.targetBidders)) - .toList(), + final Stream additionalPermissions = eidPermissions.stream() + .filter(e -> !resolvedSources.contains(e.getSource())); + + final List updatedPermissions = Stream.of( + additionalPermissions, + missingSources.map(src -> ExtRequestPrebidDataEidPermissions.of(src, this.targetBidders)), existingPermissions.map(p -> ExtRequestPrebidDataEidPermissions.of( p.getSource(), - CollectionUtils.union(p.getBidders(), this.targetBidders) - .stream().distinct().toList())).toList()) - .stream().toList(); + Stream.concat(p.getBidders().stream(), this.targetBidders.stream()) + .distinct().toList()))) + .flatMap(s -> s).toList(); final List bidders = prebidData == null ? this.targetBidders : CollectionUtils.union(this.targetBidders, CollectionUtils.emptyIfNull(prebidData.getBidders())).stream().distinct().toList(); diff --git a/extra/modules/live-intent-omni-channel-identity/src/test/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest.java b/extra/modules/live-intent-omni-channel-identity/src/test/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest.java index 0558f9126f2..7b05ec6072d 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/test/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest.java +++ b/extra/modules/live-intent-omni-channel-identity/src/test/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest.java @@ -28,6 +28,10 @@ import org.prebid.server.hooks.v1.auction.AuctionRequestPayload; import org.prebid.server.json.JacksonMapper; import org.prebid.server.json.ObjectMapperProvider; +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.ExtRequestPrebidData; +import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.vertx.httpclient.HttpClient; import org.prebid.server.vertx.httpclient.model.HttpClientResponse; @@ -70,12 +74,16 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest { private LiveIntentOmniChannelIdentityProcessedAuctionRequestHook target; + private List configuredBidders; + @BeforeEach public void setUp() { + configuredBidders = List.of("bidder1", "bidder2"); given(properties.getRequestTimeoutMs()).willReturn(5L); given(properties.getIdentityResolutionEndpoint()).willReturn("https://test.com/idres"); given(properties.getAuthToken()).willReturn("auth_token"); given(properties.getTreatmentRate()).willReturn(1.0f); + given(properties.getTargetBidders()).willReturn(configuredBidders); target = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( properties, userFpdActivityMask, MAPPER, httpClient, 0.01d); @@ -365,4 +373,99 @@ public void callShouldReturnFailureWhenRequestingEidsIsFailed() { .isInstanceOf(TimeoutException.class) .hasMessage("Timeout exceeded"); } + + @Test + public void biddersConfiguredRestrictionShouldBeRespected() { + final Uid givenUid = Uid.builder().id("id1").atype(2).build(); + final Eid givenEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build(); + final User givenUser = User.builder().eids(singletonList(givenEid)).build(); + final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build(); + + final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(configuredBidders, List.of( + ExtRequestPrebidDataEidPermissions.of("liveintent.com", configuredBidders))); + + final Eid expectedEid = Eid.builder().source("liveintent.com").build(); + + final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(expectedEid))); + given(httpClient.post(any(), any(), any(), anyLong())) + .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); + + given(auctionInvocationContext.auctionContext()).willReturn(auctionContext); + given(auctionContext.getActivityInfrastructure()).willReturn(activityInfrastructure); + given(activityInfrastructure.isAllowed(any(), any())).willReturn(true); + given(userFpdActivityMask.maskUser(any(), eq(false), eq(false))) + .willAnswer(invocation -> invocation.getArgument(0)); + given(userFpdActivityMask.maskDevice(any(), eq(false), eq(false))) + .willAnswer(invocation -> invocation.getArgument(0)); + + // when + final InvocationResult result = + target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result(); + // then + assertThat(result.status()).isEqualTo(InvocationStatus.success); + assertThat(result.payloadUpdate().apply(AuctionRequestPayloadImpl.of(givenBidRequest))) + .extracting(AuctionRequestPayload::bidRequest) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getData) + .isEqualTo(expectedData); + + verify(httpClient).post( + eq("https://test.com/idres"), + argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)), + eq(MAPPER.encodeToString(givenBidRequest)), + eq(5L)); + } + + @Test + public void biddersConfiguredRestrictionShouldBeMergedWithProvided() { + // given + final Uid givenUid = Uid.builder().id("id1").atype(2).build(); + final Eid givenEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build(); + final User givenUser = User.builder().eids(singletonList(givenEid)).build(); + final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).ext(ExtRequest.of( + ExtRequestPrebid.builder().data(ExtRequestPrebidData.of(List.of("bidder3"), List.of( + ExtRequestPrebidDataEidPermissions.of("some.other-source.com", List.of("bidder3")), + ExtRequestPrebidDataEidPermissions.of("some.source.com", List.of("bidder3")))) + ).build())).build(); + + final List expectedBidders = List.of("bidder3", "bidder2", "bidder1"); + + final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(expectedBidders, List.of( + ExtRequestPrebidDataEidPermissions.of("some.other-source.com", List.of("bidder3")), + ExtRequestPrebidDataEidPermissions.of("some.source.com", List.of("bidder3")), + ExtRequestPrebidDataEidPermissions.of("liveintent.com", configuredBidders))); + + final Eid expectedEid = Eid.builder().source("liveintent.com").build(); + + final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(expectedEid))); + given(httpClient.post(any(), any(), any(), anyLong())) + .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); + + given(auctionInvocationContext.auctionContext()).willReturn(auctionContext); + given(auctionContext.getActivityInfrastructure()).willReturn(activityInfrastructure); + given(activityInfrastructure.isAllowed(any(), any())).willReturn(true); + given(userFpdActivityMask.maskUser(any(), eq(false), eq(false))) + .willAnswer(invocation -> invocation.getArgument(0)); + given(userFpdActivityMask.maskDevice(any(), eq(false), eq(false))) + .willAnswer(invocation -> invocation.getArgument(0)); + + // when + final InvocationResult result = + target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result(); + // then + assertThat(result.status()).isEqualTo(InvocationStatus.success); + assertThat(result.payloadUpdate().apply(AuctionRequestPayloadImpl.of(givenBidRequest))) + .extracting(AuctionRequestPayload::bidRequest) + .extracting(BidRequest::getExt) + .extracting(ExtRequest::getPrebid) + .extracting(ExtRequestPrebid::getData) + .isEqualTo(expectedData); + + verify(httpClient).post( + eq("https://test.com/idres"), + argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)), + eq(MAPPER.encodeToString(givenBidRequest)), + eq(5L)); + } } From 4fe5c189e0fef336554a20afcccc23af47b68659 Mon Sep 17 00:00:00 2001 From: ilya Date: Tue, 18 Nov 2025 15:40:14 +0100 Subject: [PATCH 3/3] DATA-43462: Fixing PR issues --- ...elIdentityProcessedAuctionRequestHook.java | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java index fd13ee8950b..32b608ce21c 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java +++ b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java @@ -40,13 +40,17 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ListUtil; +import org.prebid.server.util.StreamUtil; import org.prebid.server.vertx.httpclient.HttpClient; import org.prebid.server.vertx.httpclient.model.HttpClientResponse; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; import java.util.stream.Stream; public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements ProcessedAuctionRequestHook { @@ -198,47 +202,58 @@ private AuctionRequestPayload updatedPayload(AuctionRequestPayload requestPayloa } private BidRequest updateAllowedBidders(BidRequest bidRequest, List resolvedEids) { - if (this.targetBidders.isEmpty()) { + if (targetBidders.isEmpty()) { return bidRequest; } - final List resolvedSources = resolvedEids.stream().map(Eid::getSource).distinct().toList(); - final ExtRequest requestExt = bidRequest.getExt(); - final ExtRequestPrebid prebid = requestExt == null ? null : requestExt.getPrebid(); - final ExtRequestPrebidData prebidData = prebid != null - ? prebid.getData() - : null; - final List eidPermissions = prebidData == null - ? List.of() - : CollectionUtils.emptyIfNull(prebidData.getEidPermissions()).stream().toList(); - final Stream existingPermissions = eidPermissions - .stream() - .filter(e -> resolvedSources.contains(e.getSource())); - - final Stream missingSources = resolvedSources.stream() - .filter(src -> eidPermissions.stream().noneMatch(e -> e.getSource().equals(src))); - - final Stream additionalPermissions = eidPermissions.stream() - .filter(e -> !resolvedSources.contains(e.getSource())); - - final List updatedPermissions = Stream.of( - additionalPermissions, - missingSources.map(src -> ExtRequestPrebidDataEidPermissions.of(src, this.targetBidders)), - existingPermissions.map(p -> ExtRequestPrebidDataEidPermissions.of( - p.getSource(), - Stream.concat(p.getBidders().stream(), this.targetBidders.stream()) - .distinct().toList()))) - .flatMap(s -> s).toList(); - - final List bidders = prebidData == null ? this.targetBidders : CollectionUtils.union(this.targetBidders, - CollectionUtils.emptyIfNull(prebidData.getBidders())).stream().distinct().toList(); - - final ExtRequestPrebidData updatedPrebidData = ExtRequestPrebidData.of(bidders, updatedPermissions); - final ExtRequestPrebid updatedExtPrebid = prebid == null - ? ExtRequestPrebid.builder().data(updatedPrebidData).build() - : prebid.toBuilder().data(updatedPrebidData).build(); - - return bidRequest.toBuilder().ext(ExtRequest.of(updatedExtPrebid)).build(); + final ExtRequest ext = bidRequest.getExt(); + final ExtRequestPrebid extPrebid = ext != null ? ext.getPrebid() : null; + final ExtRequestPrebidData extPrebidData = extPrebid != null ? extPrebid.getData() : null; + + final ExtRequestPrebid updatedExtPrebid = Optional.ofNullable(extPrebid) + .map(ExtRequestPrebid::toBuilder) + .orElseGet(ExtRequestPrebid::builder) + .data(updatePrebidData(extPrebidData, resolvedEids)) + .build(); + + final ExtRequest updatedExtRequest = ExtRequest.of(updatedExtPrebid); + if (ext != null) { + mapper.fillExtension(updatedExtRequest, ext.getProperties()); + } + + return bidRequest.toBuilder().ext(updatedExtRequest).build(); + } + + private ExtRequestPrebidData updatePrebidData(ExtRequestPrebidData extPrebidData, List resolvedEids) { + final List prebidDataBidders = extPrebidData != null ? extPrebidData.getBidders() : null; + final List updatedPrebidDataBidders = prebidDataBidders != null + ? (List) CollectionUtils.union(targetBidders, prebidDataBidders) + : targetBidders; + + final Set resolvedSources = resolvedEids.stream().map(Eid::getSource).collect(Collectors.toSet()); + + final List initialPermissions = Optional.ofNullable(extPrebidData) + .map(ExtRequestPrebidData::getEidPermissions) + .orElse(Collections.emptyList()); + final List updatedPermissions = Stream.concat( + initialPermissions.stream() + .map(permission -> updateEidPermission(permission, resolvedSources)), + resolvedSources.stream() + .map(source -> ExtRequestPrebidDataEidPermissions.of(source, targetBidders))) + .filter(StreamUtil.distinctBy(ExtRequestPrebidDataEidPermissions::getSource)) + .toList(); + + return ExtRequestPrebidData.of(updatedPrebidDataBidders, updatedPermissions); + } + + private ExtRequestPrebidDataEidPermissions updateEidPermission(ExtRequestPrebidDataEidPermissions permission, + Set resolvedSources) { + + return resolvedSources.contains(permission.getSource()) + ? ExtRequestPrebidDataEidPermissions.of( + permission.getSource(), + (List) CollectionUtils.union(permission.getBidders(), targetBidders)) + : permission; } @Override