From 30066237fd538b8721642272174ab6f9f7227cbf Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 10 Sep 2025 16:43:51 +0200 Subject: [PATCH 1/6] DATA-36551: Restrict LI enrichment based on allowed activity --- ...ntentOmniChannelIdentityConfiguration.java | 4 +- ...elIdentityProcessedAuctionRequestHook.java | 66 ++++++++++++++++++- ...entityProcessedAuctionRequestHookTest.java | 8 ++- 3 files changed, 72 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/config/LiveIntentOmniChannelIdentityConfiguration.java b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/config/LiveIntentOmniChannelIdentityConfiguration.java index e3f286e0120..4a75fca6caa 100644 --- a/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/config/LiveIntentOmniChannelIdentityConfiguration.java +++ b/extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/config/LiveIntentOmniChannelIdentityConfiguration.java @@ -1,5 +1,6 @@ package org.prebid.server.hooks.modules.liveintent.omni.channel.identity.config; +import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.config.LiveIntentOmniChannelProperties; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.v1.LiveIntentOmniChannelIdentityModule; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.v1.hooks.LiveIntentOmniChannelIdentityProcessedAuctionRequestHook; @@ -30,12 +31,13 @@ LiveIntentOmniChannelProperties properties() { @Bean Module liveIntentOmniChannelIdentityModule(LiveIntentOmniChannelProperties properties, JacksonMapper mapper, + UserFpdActivityMask userFpdActivityMask, HttpClient httpClient, @Value("${logging.sampling-rate:0.01}") double logSamplingRate) { final LiveIntentOmniChannelIdentityProcessedAuctionRequestHook hook = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( - properties, mapper, httpClient, logSamplingRate); + properties, userFpdActivityMask, mapper, httpClient, logSamplingRate); return new LiveIntentOmniChannelIdentityModule(Collections.singleton(hook)); } 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 5c3e43f9952..8149e2061df 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 @@ -1,15 +1,26 @@ package org.prebid.server.hooks.modules.liveintent.omni.channel.identity.v1.hooks; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Eid; +import com.iab.openrtb.request.Source; import com.iab.openrtb.request.User; import io.vertx.core.Future; import io.vertx.core.MultiMap; import org.apache.commons.collections4.ListUtils; +import org.prebid.server.activity.Activity; +import org.prebid.server.activity.ComponentType; +import org.prebid.server.activity.infrastructure.ActivityInfrastructure; +import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload; +import org.prebid.server.activity.infrastructure.payload.impl.ActivityInvocationPayloadImpl; +import org.prebid.server.activity.infrastructure.payload.impl.BidRequestActivityInvocationPayload; +import org.prebid.server.auction.model.AuctionContext; +import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; import org.prebid.server.hooks.execution.v1.InvocationResultImpl; import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.IdResResponse; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.config.LiveIntentOmniChannelProperties; +import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.v1.LiveIntentOmniChannelIdentityModule; import org.prebid.server.hooks.v1.InvocationAction; import org.prebid.server.hooks.v1.InvocationResult; import org.prebid.server.hooks.v1.InvocationStatus; @@ -39,9 +50,11 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements private final LiveIntentOmniChannelProperties config; private final JacksonMapper mapper; private final HttpClient httpClient; + private final UserFpdActivityMask userFpdActivityMask; private final double logSamplingRate; public LiveIntentOmniChannelIdentityProcessedAuctionRequestHook(LiveIntentOmniChannelProperties config, + UserFpdActivityMask userFpdActivityMask, JacksonMapper mapper, HttpClient httpClient, double logSamplingRate) { @@ -51,6 +64,7 @@ public LiveIntentOmniChannelIdentityProcessedAuctionRequestHook(LiveIntentOmniCh this.mapper = Objects.requireNonNull(mapper); this.httpClient = Objects.requireNonNull(httpClient); this.logSamplingRate = logSamplingRate; + this.userFpdActivityMask = Objects.requireNonNull(userFpdActivityMask); } @Override @@ -58,22 +72,68 @@ public Future> call(AuctionRequestPayloa AuctionInvocationContext invocationContext) { return config.getTreatmentRate() > ThreadLocalRandom.current().nextFloat() - ? requestIdentities(auctionRequestPayload.bidRequest()) + ? requestIdentities(auctionRequestPayload.bidRequest(), invocationContext.auctionContext()) .>map(this::update) .onFailure(throwable -> conditionalLogger.error( "Failed enrichment: %s".formatted(throwable.getMessage()), logSamplingRate)) : noAction(); } - private Future requestIdentities(BidRequest bidRequest) { + private Future requestIdentities(BidRequest bidRequest, AuctionContext auctionContext) { + final BidRequest restrictedBidRequest = applyActivityRestrictions(bidRequest, auctionContext); return httpClient.post( config.getIdentityResolutionEndpoint(), headers(), - mapper.encodeToString(bidRequest), + mapper.encodeToString(restrictedBidRequest), config.getRequestTimeoutMs()) .map(this::processResponse); } + private BidRequest applyActivityRestrictions(BidRequest bidRequest, AuctionContext auctionContext) { + final ActivityInvocationPayload activityInvocationPayload = BidRequestActivityInvocationPayload.of( + ActivityInvocationPayloadImpl.of(ComponentType.GENERAL_MODULE, LiveIntentOmniChannelIdentityModule.CODE), + bidRequest); + final ActivityInfrastructure activityInfrastructure = auctionContext.getActivityInfrastructure(); + + final boolean disallowTransmitUfpd = !activityInfrastructure.isAllowed( + Activity.TRANSMIT_UFPD, activityInvocationPayload); + final boolean disallowTransmitEids = !activityInfrastructure.isAllowed( + Activity.TRANSMIT_EIDS, activityInvocationPayload); + final boolean disallowTransmitGeo = !activityInfrastructure.isAllowed( + Activity.TRANSMIT_GEO, activityInvocationPayload); + final boolean disallowTransmitTid = !activityInfrastructure.isAllowed( + Activity.TRANSMIT_TID, activityInvocationPayload); + + return maskUserPersonalInfo( + bidRequest, + disallowTransmitUfpd, + disallowTransmitEids, + disallowTransmitGeo, + disallowTransmitTid); + } + + private BidRequest maskUserPersonalInfo(BidRequest bidRequest, + boolean disallowTransmitUfpd, + boolean disallowTransmitEids, + boolean disallowTransmitGeo, + boolean disallowTransmitTid) { + + final User maskedUser = userFpdActivityMask.maskUser( + bidRequest.getUser(), disallowTransmitUfpd, disallowTransmitEids); + final Device maskedDevice = userFpdActivityMask.maskDevice( + bidRequest.getDevice(), disallowTransmitUfpd, disallowTransmitGeo); + + final Source maskedSource = disallowTransmitTid + ? bidRequest.getSource().toBuilder().tid(null).build() + : bidRequest.getSource(); + + return bidRequest.toBuilder() + .user(maskedUser) + .device(maskedDevice) + .source(maskedSource) + .build(); + } + private MultiMap headers() { return MultiMap.caseInsensitiveMultiMap() .add(HttpUtil.AUTHORIZATION_HEADER, "Bearer " + config.getAuthToken()); 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 9dc53916980..9731e769283 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 @@ -10,6 +10,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; import org.prebid.server.hooks.execution.v1.auction.AuctionInvocationContextImpl; import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.IdResResponse; @@ -44,6 +45,9 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest { private static final JacksonMapper MAPPER = new JacksonMapper(ObjectMapperProvider.mapper()); + @Mock + private UserFpdActivityMask userFpdActivityMask; + @Mock private HttpClient httpClient; @@ -60,7 +64,7 @@ public void setUp() { given(properties.getTreatmentRate()).willReturn(1.0f); target = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( - properties, MAPPER, httpClient, 0.01d); + properties, userFpdActivityMask, MAPPER, httpClient, 0.01d); } @Test @@ -68,7 +72,7 @@ public void creationShouldFailOnInvalidIdentityUrl() { given(properties.getIdentityResolutionEndpoint()).willReturn("invalid_url"); assertThatIllegalArgumentException().isThrownBy(() -> new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( - properties, MAPPER, httpClient, 0.01d)); + properties, userFpdActivityMask, MAPPER, httpClient, 0.01d)); } @Test From c9444c4d40ac0469dbfd498df91ddce8d59c94af Mon Sep 17 00:00:00 2001 From: ilya Date: Thu, 11 Sep 2025 14:01:09 +0200 Subject: [PATCH 2/6] DATA-36551: PR issues fixed --- ...elIdentityProcessedAuctionRequestHook.java | 2 +- ...entityProcessedAuctionRequestHookTest.java | 175 ++++++++++++++++++ 2 files changed, 176 insertions(+), 1 deletion(-) 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 8149e2061df..b7aac03846f 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 @@ -123,7 +123,7 @@ private BidRequest maskUserPersonalInfo(BidRequest bidRequest, final Device maskedDevice = userFpdActivityMask.maskDevice( bidRequest.getDevice(), disallowTransmitUfpd, disallowTransmitGeo); - final Source maskedSource = disallowTransmitTid + final Source maskedSource = (disallowTransmitUfpd && disallowTransmitTid) ? bidRequest.getSource().toBuilder().tid(null).build() : bidRequest.getSource(); 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 9731e769283..954568ff1e2 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 @@ -1,7 +1,10 @@ package org.prebid.server.hooks.modules.liveintent.omni.channel.identity.v1; import com.iab.openrtb.request.BidRequest; +import com.iab.openrtb.request.Device; import com.iab.openrtb.request.Eid; +import com.iab.openrtb.request.Geo; +import com.iab.openrtb.request.Source; import com.iab.openrtb.request.Uid; import com.iab.openrtb.request.User; import io.vertx.core.Future; @@ -10,6 +13,11 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.prebid.server.activity.Activity; +import org.prebid.server.activity.infrastructure.ActivityController; +import org.prebid.server.activity.infrastructure.ActivityInfrastructure; +import org.prebid.server.activity.infrastructure.debug.ActivityInfrastructureDebug; +import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; import org.prebid.server.hooks.execution.v1.auction.AuctionInvocationContextImpl; import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; @@ -27,6 +35,7 @@ import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeoutException; import static java.util.Collections.singletonList; @@ -51,6 +60,9 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest { @Mock private HttpClient httpClient; + @Mock + private ActivityInfrastructureDebug activityInfrastructureDebug; + @Mock(strictness = LENIENT) private LiveIntentOmniChannelProperties properties; @@ -75,6 +87,169 @@ public void creationShouldFailOnInvalidIdentityUrl() { properties, userFpdActivityMask, MAPPER, httpClient, 0.01d)); } + @Test + public void geoPassingRestrictionShouldBeRespected() { + // given + final Geo givenGeo = Geo.builder() + .lat(52.51671856406936f) + .lon(13.377639726342583f) + .city("Berlin") + .country("Germany") + .build(); + final Device givenDevice = Device.builder() + .geo(givenGeo) + .ip("192.168.127.12") + .ifa("foo") + .macsha1("bar") + .macmd5("baz") + .dpidsha1("boo") + .dpidmd5("far") + .didsha1("zoo") + .didmd5("goo") + .build(); + final BidRequest givenBidRequest = BidRequest.builder().id("request").device(givenDevice).build(); + + final Geo expectedGeo = givenGeo.toBuilder() + .country(null) + .city(null) + .lat(52.52f) + .lon(13.38f) + .build(); + final Device expectedDevice = givenDevice.toBuilder() + .geo(expectedGeo) + .ip("192.168.127.0") + .ifa(null) + .macsha1(null) + .macmd5(null) + .dpidsha1(null) + .dpidmd5(null) + .didsha1(null) + .didmd5(null) + .build(); + final BidRequest expectedBidRequest = givenBidRequest.toBuilder().device(expectedDevice).build(); + + 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))); + + final ActivityController activityController = ActivityController.of( + false, List.of(), activityInfrastructureDebug); + + final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( + Map.of(Activity.TRANSMIT_TID, activityController, + Activity.TRANSMIT_UFPD, activityController), + activityInfrastructureDebug); + + final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( + null, + AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), + false, + null, + null); + + // when + final InvocationResult result = + target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result(); + // then + assertThat(result.status()).isEqualTo(InvocationStatus.success); + + verify(httpClient).post( + eq("https://test.com/idres"), + argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)), + eq(MAPPER.encodeToString(expectedBidRequest)), + eq(5L)); + } + + @Test + public void tidPassingRestrictionShouldBeRespected() { + // given + final Source givenSource = Source.builder().tid("tid1").build(); + final BidRequest givenBidRequest = BidRequest.builder().id("request").source(givenSource).build(); + + final Source expectedSource = givenSource.toBuilder().tid(null).build(); + final BidRequest expectedBidRequest = givenBidRequest.toBuilder().source(expectedSource).build(); + + 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))); + + final ActivityController activityController = ActivityController.of( + false, List.of(), activityInfrastructureDebug); + + final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( + Map.of(Activity.TRANSMIT_TID, activityController, + Activity.TRANSMIT_UFPD, activityController), + activityInfrastructureDebug); + + final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( + null, + AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), + false, + null, + null); + + // when + final InvocationResult result = + target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result(); + // then + assertThat(result.status()).isEqualTo(InvocationStatus.success); + + verify(httpClient).post( + eq("https://test.com/idres"), + argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)), + eq(MAPPER.encodeToString(expectedBidRequest)), + eq(5L)); + } + + @Test + public void eidPassingRestrictionShouldBeRespected() { + // 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).build(); + + final User expectedUser = givenUser.toBuilder().eids(null).build(); + final BidRequest expectedBidRequest = givenBidRequest.toBuilder().user(expectedUser).build(); + + 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))); + + final ActivityController activityController = ActivityController.of( + false, List.of(), activityInfrastructureDebug); + + final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( + Map.of(Activity.TRANSMIT_EIDS, activityController, + Activity.TRANSMIT_UFPD, activityController), + activityInfrastructureDebug); + + final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( + null, + AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), + false, + null, + null); + + // when + final InvocationResult result = + target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result(); + // then + assertThat(result.status()).isEqualTo(InvocationStatus.success); + + verify(httpClient).post( + eq("https://test.com/idres"), + argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)), + eq(MAPPER.encodeToString(expectedBidRequest)), + eq(5L)); + } + @Test public void callShouldEnrichUserEidsWithRequestedEids() { // given From 3a0d8ececb71e95faee4c47556eb4e5d4715b94e Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 17 Sep 2025 15:15:13 +0200 Subject: [PATCH 3/6] DATA-36551: PR issues fixed --- ...entityProcessedAuctionRequestHookTest.java | 67 ++++++------------- 1 file changed, 19 insertions(+), 48 deletions(-) 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 954568ff1e2..9c9d1693663 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 @@ -14,9 +14,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.prebid.server.activity.Activity; -import org.prebid.server.activity.infrastructure.ActivityController; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; -import org.prebid.server.activity.infrastructure.debug.ActivityInfrastructureDebug; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; import org.prebid.server.hooks.execution.v1.auction.AuctionInvocationContextImpl; @@ -35,7 +33,6 @@ import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.List; -import java.util.Map; import java.util.concurrent.TimeoutException; import static java.util.Collections.singletonList; @@ -60,12 +57,18 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest { @Mock private HttpClient httpClient; - @Mock - private ActivityInfrastructureDebug activityInfrastructureDebug; - @Mock(strictness = LENIENT) private LiveIntentOmniChannelProperties properties; + @Mock + private ActivityInfrastructure activityInfrastructure; + + @Mock + private AuctionInvocationContext auctionInvocationContext; + + @Mock + private AuctionContext auctionContext; + private LiveIntentOmniChannelIdentityProcessedAuctionRequestHook target; @BeforeEach @@ -75,6 +78,10 @@ public void setUp() { given(properties.getAuthToken()).willReturn("auth_token"); given(properties.getTreatmentRate()).willReturn(1.0f); + given(auctionInvocationContext.auctionContext()).willReturn(auctionContext); + given(auctionContext.getActivityInfrastructure()).willReturn(activityInfrastructure); + given(activityInfrastructure.isAllowed(any(), any())).willReturn(true); + target = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( properties, userFpdActivityMask, MAPPER, httpClient, 0.01d); } @@ -134,20 +141,8 @@ public void geoPassingRestrictionShouldBeRespected() { given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); - final ActivityController activityController = ActivityController.of( - false, List.of(), activityInfrastructureDebug); - - final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( - Map.of(Activity.TRANSMIT_TID, activityController, - Activity.TRANSMIT_UFPD, activityController), - activityInfrastructureDebug); - - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, - AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), - false, - null, - null); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_GEO), any())).willReturn(false); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); // when final InvocationResult result = @@ -177,20 +172,8 @@ public void tidPassingRestrictionShouldBeRespected() { given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); - final ActivityController activityController = ActivityController.of( - false, List.of(), activityInfrastructureDebug); - - final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( - Map.of(Activity.TRANSMIT_TID, activityController, - Activity.TRANSMIT_UFPD, activityController), - activityInfrastructureDebug); - - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, - AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), - false, - null, - null); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_TID), any())).willReturn(false); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); // when final InvocationResult result = @@ -222,20 +205,8 @@ public void eidPassingRestrictionShouldBeRespected() { given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); - final ActivityController activityController = ActivityController.of( - false, List.of(), activityInfrastructureDebug); - - final ActivityInfrastructure givenActivityInfrastructure = new ActivityInfrastructure( - Map.of(Activity.TRANSMIT_EIDS, activityController, - Activity.TRANSMIT_UFPD, activityController), - activityInfrastructureDebug); - - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, - AuctionContext.builder().activityInfrastructure(givenActivityInfrastructure).build(), - false, - null, - null); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_EIDS), any())).willReturn(false); + given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); // when final InvocationResult result = From 618a526548d45528945751a4087865c464a04a67 Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 24 Sep 2025 15:48:31 +0200 Subject: [PATCH 4/6] DATA-36551: Fixing linting --- ...eIntentOmniChannelIdentityProcessedAuctionRequestHook.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 b7aac03846f..7e46f618056 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 @@ -91,7 +91,9 @@ private Future requestIdentities(BidRequest bidRequest, AuctionCo private BidRequest applyActivityRestrictions(BidRequest bidRequest, AuctionContext auctionContext) { final ActivityInvocationPayload activityInvocationPayload = BidRequestActivityInvocationPayload.of( - ActivityInvocationPayloadImpl.of(ComponentType.GENERAL_MODULE, LiveIntentOmniChannelIdentityModule.CODE), + ActivityInvocationPayloadImpl.of( + ComponentType.GENERAL_MODULE, + LiveIntentOmniChannelIdentityModule.CODE), bidRequest); final ActivityInfrastructure activityInfrastructure = auctionContext.getActivityInfrastructure(); From c39bdef2827b272f29871e67c3fd8a65d0236f09 Mon Sep 17 00:00:00 2001 From: ilya Date: Fri, 26 Sep 2025 14:37:34 +0200 Subject: [PATCH 5/6] DATA-36551: Build fixed --- ...hannelIdentityProcessedAuctionRequestHookTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 9c9d1693663..b1213402357 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 @@ -78,10 +78,6 @@ public void setUp() { given(properties.getAuthToken()).willReturn("auth_token"); given(properties.getTreatmentRate()).willReturn(1.0f); - given(auctionInvocationContext.auctionContext()).willReturn(auctionContext); - given(auctionContext.getActivityInfrastructure()).willReturn(activityInfrastructure); - given(activityInfrastructure.isAllowed(any(), any())).willReturn(true); - target = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook( properties, userFpdActivityMask, MAPPER, httpClient, 0.01d); } @@ -172,6 +168,10 @@ public void tidPassingRestrictionShouldBeRespected() { 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(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_TID), any())).willReturn(false); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); @@ -205,6 +205,9 @@ public void eidPassingRestrictionShouldBeRespected() { 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(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_EIDS), any())).willReturn(false); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); From d7867477b2b0d392bb1b29d8f9ad86cff4309c08 Mon Sep 17 00:00:00 2001 From: ilya Date: Mon, 29 Sep 2025 17:13:34 +0200 Subject: [PATCH 6/6] DATA-36551: Fixing tests --- ...elIdentityProcessedAuctionRequestHook.java | 12 +++- ...entityProcessedAuctionRequestHookTest.java | 69 +++++++++++-------- 2 files changed, 50 insertions(+), 31 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 7e46f618056..e0025e70bbb 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 @@ -125,9 +125,7 @@ private BidRequest maskUserPersonalInfo(BidRequest bidRequest, final Device maskedDevice = userFpdActivityMask.maskDevice( bidRequest.getDevice(), disallowTransmitUfpd, disallowTransmitGeo); - final Source maskedSource = (disallowTransmitUfpd && disallowTransmitTid) - ? bidRequest.getSource().toBuilder().tid(null).build() - : bidRequest.getSource(); + final Source maskedSource = maskSource(bidRequest.getSource(), disallowTransmitUfpd, disallowTransmitTid); return bidRequest.toBuilder() .user(maskedUser) @@ -136,6 +134,14 @@ private BidRequest maskUserPersonalInfo(BidRequest bidRequest, .build(); } + private Source maskSource(Source source, boolean mastUfpd, boolean maskTid) { + if (source == null || !(mastUfpd || maskTid)) { + return source; + } + + return source.toBuilder().tid(null).build(); + } + private MultiMap headers() { return MultiMap.caseInsensitiveMultiMap() .add(HttpUtil.AUTHORIZATION_HEADER, "Bearer " + config.getAuthToken()); 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 b1213402357..0558f9126f2 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 @@ -17,7 +17,6 @@ import org.prebid.server.activity.infrastructure.ActivityInfrastructure; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask; -import org.prebid.server.hooks.execution.v1.auction.AuctionInvocationContextImpl; import org.prebid.server.hooks.execution.v1.auction.AuctionRequestPayloadImpl; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.IdResResponse; import org.prebid.server.hooks.modules.liveintent.omni.channel.identity.model.config.LiveIntentOmniChannelProperties; @@ -51,7 +50,7 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest { private static final JacksonMapper MAPPER = new JacksonMapper(ObjectMapperProvider.mapper()); - @Mock + @Mock(strictness = LENIENT) private UserFpdActivityMask userFpdActivityMask; @Mock @@ -112,22 +111,13 @@ public void geoPassingRestrictionShouldBeRespected() { .build(); final BidRequest givenBidRequest = BidRequest.builder().id("request").device(givenDevice).build(); - final Geo expectedGeo = givenGeo.toBuilder() - .country(null) - .city(null) + final Geo expectedGeo = Geo.builder() .lat(52.52f) .lon(13.38f) .build(); - final Device expectedDevice = givenDevice.toBuilder() + final Device expectedDevice = Device.builder() .geo(expectedGeo) .ip("192.168.127.0") - .ifa(null) - .macsha1(null) - .macmd5(null) - .dpidsha1(null) - .dpidmd5(null) - .didsha1(null) - .didmd5(null) .build(); final BidRequest expectedBidRequest = givenBidRequest.toBuilder().device(expectedDevice).build(); @@ -137,8 +127,15 @@ public void geoPassingRestrictionShouldBeRespected() { 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(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_GEO), any())).willReturn(false); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); + given(userFpdActivityMask.maskUser(any(), eq(true), eq(false))) + .will(invocation -> invocation.getArgument(0)); + given(userFpdActivityMask.maskDevice(any(), eq(true), eq(true))) + .will(invocation -> expectedDevice); // when final InvocationResult result = @@ -174,6 +171,10 @@ public void tidPassingRestrictionShouldBeRespected() { given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_TID), any())).willReturn(false); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); + 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 = @@ -196,8 +197,7 @@ public void eidPassingRestrictionShouldBeRespected() { final User givenUser = User.builder().eids(singletonList(givenEid)).build(); final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build(); - final User expectedUser = givenUser.toBuilder().eids(null).build(); - final BidRequest expectedBidRequest = givenBidRequest.toBuilder().user(expectedUser).build(); + final BidRequest expectedBidRequest = givenBidRequest.toBuilder().user(null).build(); final Eid expectedEid = Eid.builder().source("liveintent.com").build(); @@ -210,6 +210,10 @@ public void eidPassingRestrictionShouldBeRespected() { given(activityInfrastructure.isAllowed(any(), any())).willReturn(true); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_EIDS), any())).willReturn(false); given(activityInfrastructure.isAllowed(eq(Activity.TRANSMIT_UFPD), any())).willReturn(false); + given(userFpdActivityMask.maskUser(any(), eq(true), eq(true))) + .willReturn(null); + given(userFpdActivityMask.maskDevice(any(), eq(false), eq(false))) + .willAnswer(invocation -> invocation.getArgument(0)); // when final InvocationResult result = @@ -241,8 +245,13 @@ public void callShouldEnrichUserEidsWithRequestedEids() { given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, null, false, null, null); + 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 = @@ -278,8 +287,13 @@ public void callShouldCreateUserAndUseRequestedEidsWhenUserIsAbsent() { given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody))); - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, null, false, null, null); + 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 = @@ -304,13 +318,7 @@ public void callShouldCreateUserAndUseRequestedEidsWhenUserIsAbsent() { @Test public void callShouldReturnNoActionSuccessfullyWhenTreatmentRateIsLowerThanThreshold() { // given - final Uid givenUid = Uid.builder().id("id1").atype(2).build(); - final Eid givebEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build(); - final User givenUser = User.builder().eids(singletonList(givebEid)).build(); - final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build(); - - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, null, false, null, null); + final BidRequest givenBidRequest = BidRequest.builder().build(); given(properties.getTreatmentRate()).willReturn(0.0f); @@ -334,8 +342,13 @@ public void callShouldReturnFailureWhenRequestingEidsIsFailed() { final User givenUser = User.builder().eids(singletonList(givebEid)).build(); final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build(); - final AuctionInvocationContext auctionInvocationContext = AuctionInvocationContextImpl.of( - null, null, false, null, null); + 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)); given(httpClient.post(any(), any(), any(), anyLong())) .willReturn(Future.failedFuture(new TimeoutException("Timeout exceeded")));