Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.SetUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.activity.Activity;
import org.prebid.server.activity.ComponentType;
import org.prebid.server.activity.infrastructure.ActivityInfrastructure;
Expand Down Expand Up @@ -50,7 +49,8 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

import java.util.Collections;

public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements ProcessedAuctionRequestHook {

Expand All @@ -61,6 +61,9 @@ public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements

private static final String INSERTER = "s2s.liveintent.com";

// IdResResponse is already stamped by Ulysses, in the EID's matcher field, it has "liveintent.com"
private static final String MATCHER = "liveintent.com";

private final LiveIntentOmniChannelProperties config;
private final JacksonMapper mapper;
private final HttpClient httpClient;
Expand Down Expand Up @@ -216,19 +219,18 @@ private BidRequest updateBidRequest(BidRequest bidRequest, List<Eid> resolvedEid
}

private ExtRequest updateExtRequest(ExtRequest ext, List<Eid> resolvedEids) {
final Set<String> uniqueSources = CollectionUtils.emptyIfNull(resolvedEids).stream()
.map(Eid::getSource)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(resolvedEids)) {
return ext;
}

final ExtRequestPrebid extPrebid = ext != null ? ext.getPrebid() : null;
final ExtRequestPrebidData extPrebidData = extPrebid != null ? extPrebid.getData() : null;
final List<ExtRequestPrebidDataEidPermissions> eidPermissions =
extPrebidData != null ? extPrebidData.getEidPermissions() : null;

final List<ExtRequestPrebidDataEidPermissions> modifiedEidPermissions = CollectionUtils.isEmpty(eidPermissions)
? createEidPermissions(uniqueSources)
: modifyEidPermissions(eidPermissions, uniqueSources);
? createEidPermissions()
: modifyEidPermissions(eidPermissions);

final ExtRequestPrebid updatedExtPrebid = Optional.ofNullable(extPrebid)
.map(ExtRequestPrebid::toBuilder)
Expand Down Expand Up @@ -257,24 +259,21 @@ private static User updateUser(User user, List<Eid> resolvedEids) {
.build();
}

private List<ExtRequestPrebidDataEidPermissions> createEidPermissions(Set<String> sources) {
return sources.stream()
.map(source -> ExtRequestPrebidDataEidPermissions.builder()
.source(source)
.inserter(INSERTER)
.bidders(targetBidders.stream().toList())
.build())
.toList();
private List<ExtRequestPrebidDataEidPermissions> createEidPermissions() {
return Collections.singletonList(ExtRequestPrebidDataEidPermissions.builder()
.matcher(MATCHER)
.inserter(INSERTER)
.bidders(targetBidders.stream().toList())
.build());
}

private List<ExtRequestPrebidDataEidPermissions> modifyEidPermissions(
List<ExtRequestPrebidDataEidPermissions> eidPermissions,
Set<String> sources) {
List<ExtRequestPrebidDataEidPermissions> eidPermissions) {
final List<ExtRequestPrebidDataEidPermissions> modifiedEidPermissions = eidPermissions.stream()
.map(it -> updateEidPermission(it, sources))
.filter(Objects::nonNull)
.toList();
final List<ExtRequestPrebidDataEidPermissions> defaultEidPermissions = createEidPermissions(sources);
.map(this::updateEidPermission)
.filter(Objects::nonNull)
.toList();
final List<ExtRequestPrebidDataEidPermissions> defaultEidPermissions = createEidPermissions();
return ListUtils.union(modifiedEidPermissions, defaultEidPermissions);
}

Expand All @@ -286,9 +285,8 @@ private ExtRequestPrebidData updatePrebidData(ExtRequestPrebidData extPrebidData
return ExtRequestPrebidData.of(originalBidders, eidPermissions);
}

private ExtRequestPrebidDataEidPermissions updateEidPermission(ExtRequestPrebidDataEidPermissions eidPermission,
Set<String> sources) {
if (!sources.contains(eidPermission.getSource()) || !INSERTER.equals(eidPermission.getInserter())) {
private ExtRequestPrebidDataEidPermissions updateEidPermission(ExtRequestPrebidDataEidPermissions eidPermission) {
if (!MATCHER.equals(eidPermission.getMatcher()) || !INSERTER.equals(eidPermission.getInserter())) {
return eidPermission;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ public void setUp() {

defaultPermissions = ExtRequestPrebidDataEidPermissions.builder()
.inserter("s2s.liveintent.com")
.matcher("liveintent.com")
.bidders(configuredBidders.stream().toList())
.source("liveintent.com")
.build();

target = new LiveIntentOmniChannelIdentityProcessedAuctionRequestHook(
Expand Down Expand Up @@ -254,13 +254,13 @@ public void callShouldEnrichUserEidsWithRequestedEids() {
final User givenUser = User.builder().eids(singletonList(givenEid)).build();
final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build();

final Eid expectedEid = Eid.builder()
final Eid apiResponseEid = Eid.builder()
.source("liveintent.com")
.uids(singletonList(Uid.builder().id("id2").atype(3).build()))
.matcher("liveintent.com")
.uids(singletonList(Uid.builder().id("id2").atype(3).build()))
.build();

final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(expectedEid)));
final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(apiResponseEid)));
given(httpClient.post(any(), any(), any(), anyLong()))
.willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody)));

Expand All @@ -279,11 +279,24 @@ public void callShouldEnrichUserEidsWithRequestedEids() {
// then
assertThat(result.status()).isEqualTo(InvocationStatus.success);
assertThat(result.action()).isEqualTo(InvocationAction.update);
assertThat(result.payloadUpdate().apply(AuctionRequestPayloadImpl.of(givenBidRequest)))

final AuctionRequestPayload updatedPayload =
result.payloadUpdate().apply(AuctionRequestPayloadImpl.of(givenBidRequest));

assertThat(updatedPayload)
.extracting(AuctionRequestPayload::bidRequest)
.extracting(BidRequest::getUser)
.extracting(User::getEids)
.isEqualTo(List.of(givenEid, expectedEid.toBuilder().inserter("s2s.liveintent.com").build()));
.isEqualTo(List.of(givenEid, apiResponseEid.toBuilder()
.inserter("s2s.liveintent.com")
.build()));

assertThat(updatedPayload)
.extracting(AuctionRequestPayload::bidRequest)
.extracting(BidRequest::getExt)
.extracting(ExtRequest::getPrebid)
.extracting(ExtRequestPrebid::getData)
.isEqualTo(ExtRequestPrebidData.of(null, List.of(defaultPermissions)));

verify(httpClient).post(
eq("https://test.com/idres"),
Expand All @@ -297,13 +310,12 @@ public void callShouldCreateUserAndUseRequestedEidsWhenUserIsAbsent() {
// given
final BidRequest givenBidRequest = BidRequest.builder().id("request").user(null).build();

final Eid expectedEid = Eid.builder()
final Eid apiResponseEid = Eid.builder()
.source("liveintent.com")
.uids(singletonList(Uid.builder().id("id2").atype(3).build()))
.matcher("liveintent.com")
.build();

final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(expectedEid)));
final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(apiResponseEid)));
given(httpClient.post(any(), any(), any(), anyLong()))
.willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody)));

Expand All @@ -326,7 +338,10 @@ public void callShouldCreateUserAndUseRequestedEidsWhenUserIsAbsent() {
.extracting(AuctionRequestPayload::bidRequest)
.extracting(BidRequest::getUser)
.extracting(User::getEids)
.isEqualTo(List.of(expectedEid.toBuilder().inserter("s2s.liveintent.com").build()));
.isEqualTo(List.of(apiResponseEid.toBuilder()
.inserter("s2s.liveintent.com")
.matcher("liveintent.com")
.build()));

verify(httpClient).post(
eq("https://test.com/idres"),
Expand Down Expand Up @@ -400,12 +415,12 @@ public void shouldRestrictExistingEidPermissionsByIntersectionAndKeepGlobalBidde
.build();

final ExtRequestPrebidDataEidPermissions liBidder2 = ExtRequestPrebidDataEidPermissions.builder()
.source("liveintent.com")
.matcher("liveintent.com")
.inserter("s2s.liveintent.com")
.bidders(singletonList("bidder2"))
.build();
final ExtRequestPrebidDataEidPermissions liBidder23 = ExtRequestPrebidDataEidPermissions.builder()
.source("liveintent.com")
.matcher("liveintent.com")
.inserter("s2s.liveintent.com")
.bidders(List.of("bidder2", "bidder3"))
.build();
Expand Down Expand Up @@ -456,69 +471,6 @@ public void shouldRestrictExistingEidPermissionsByIntersectionAndKeepGlobalBidde
eq(5L));
}

@Test
public void shouldNotAddNewEidPermissionsOrModifyGlobalBiddersWhenSourceNotPresent() {
// 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 ExtRequestPrebidDataEidPermissions bidder1 = ExtRequestPrebidDataEidPermissions.builder()
.source("some.other-source.com")
.inserter("some.other-inserter.com")
.bidders(singletonList("bidder3"))
.build();
final ExtRequestPrebidDataEidPermissions bidder2 = ExtRequestPrebidDataEidPermissions.builder()
.source("some.source.com")
.inserter("s2s.liveintent.com")
.bidders(singletonList("bidder3"))
.build();

final List<ExtRequestPrebidDataEidPermissions> bidders = List.of(bidder1, bidder2);

final BidRequest givenBidRequest = BidRequest.builder()
.id("request")
.user(givenUser)
.ext(ExtRequest.of(ExtRequestPrebid.builder()
.data(ExtRequestPrebidData.of(singletonList("bidder3"), bidders))
.build()))
.build();

final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(List.of("bidder3"),
ListUtil.union(bidders, List.of(defaultPermissions)));

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<AuctionRequestPayload> 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 shouldRemovePermissionWhenIntersectionIsEmpty() {
// given
Expand All @@ -530,7 +482,7 @@ public void shouldRemovePermissionWhenIntersectionIsEmpty() {
List.of("bidderGlobal"),
List.of(
ExtRequestPrebidDataEidPermissions.builder()
.source("liveintent.com")
.matcher("liveintent.com")
.inserter("s2s.liveintent.com")
.bidders(singletonList("not-allowed"))
.build(),
Expand Down