Skip to content

Commit 71b639a

Browse files
author
ilya
committed
DATA-46374: LI EID permissions
1 parent 24e7a29 commit 71b639a

2 files changed

Lines changed: 118 additions & 35 deletions

File tree

extra/modules/live-intent-omni-channel-identity/src/main/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/hooks/LiveIntentOmniChannelIdentityProcessedAuctionRequestHook.java

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.iab.openrtb.request.User;
88
import io.vertx.core.Future;
99
import io.vertx.core.MultiMap;
10-
import org.apache.commons.collections4.CollectionUtils;
1110
import org.apache.commons.collections4.ListUtils;
1211
import org.prebid.server.activity.Activity;
1312
import org.prebid.server.activity.ComponentType;
@@ -40,18 +39,15 @@
4039
import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebidDataEidPermissions;
4140
import org.prebid.server.util.HttpUtil;
4241
import org.prebid.server.util.ListUtil;
43-
import org.prebid.server.util.StreamUtil;
4442
import org.prebid.server.vertx.httpclient.HttpClient;
4543
import org.prebid.server.vertx.httpclient.model.HttpClientResponse;
4644

47-
import java.util.Collections;
4845
import java.util.List;
4946
import java.util.Objects;
5047
import java.util.Optional;
5148
import java.util.Set;
5249
import java.util.concurrent.ThreadLocalRandom;
5350
import java.util.stream.Collectors;
54-
import java.util.stream.Stream;
5551

5652
public class LiveIntentOmniChannelIdentityProcessedAuctionRequestHook implements ProcessedAuctionRequestHook {
5753

@@ -202,14 +198,22 @@ private AuctionRequestPayload updatedPayload(AuctionRequestPayload requestPayloa
202198
}
203199

204200
private BidRequest updateAllowedBidders(BidRequest bidRequest, List<Eid> resolvedEids) {
205-
if (targetBidders.isEmpty()) {
201+
if (targetBidders.isEmpty() || resolvedEids == null || resolvedEids.isEmpty()) {
206202
return bidRequest;
207203
}
208204

209205
final ExtRequest ext = bidRequest.getExt();
210206
final ExtRequestPrebid extPrebid = ext != null ? ext.getPrebid() : null;
211207
final ExtRequestPrebidData extPrebidData = extPrebid != null ? extPrebid.getData() : null;
212208

209+
final List<ExtRequestPrebidDataEidPermissions> existingPerms = extPrebidData != null
210+
? ListUtils.emptyIfNull(extPrebidData.getEidPermissions())
211+
: List.of();
212+
213+
if (existingPerms.isEmpty()) {
214+
return bidRequest;
215+
}
216+
213217
final ExtRequestPrebid updatedExtPrebid = Optional.ofNullable(extPrebid)
214218
.map(ExtRequestPrebid::toBuilder)
215219
.orElseGet(ExtRequestPrebid::builder)
@@ -225,35 +229,37 @@ private BidRequest updateAllowedBidders(BidRequest bidRequest, List<Eid> resolve
225229
}
226230

227231
private ExtRequestPrebidData updatePrebidData(ExtRequestPrebidData extPrebidData, List<Eid> resolvedEids) {
228-
final List<String> prebidDataBidders = extPrebidData != null ? extPrebidData.getBidders() : null;
229-
final List<String> updatedPrebidDataBidders = prebidDataBidders != null
230-
? (List<String>) CollectionUtils.union(targetBidders, prebidDataBidders)
231-
: targetBidders;
232+
final List<String> originalBidders = extPrebidData != null ? extPrebidData.getBidders() : null;
232233

233-
final Set<String> resolvedSources = resolvedEids.stream().map(Eid::getSource).collect(Collectors.toSet());
234+
final Set<String> resolvedSources = resolvedEids.stream()
235+
.map(Eid::getSource)
236+
.collect(Collectors.toSet());
234237

235238
final List<ExtRequestPrebidDataEidPermissions> initialPermissions = Optional.ofNullable(extPrebidData)
236239
.map(ExtRequestPrebidData::getEidPermissions)
237-
.orElse(Collections.emptyList());
238-
final List<ExtRequestPrebidDataEidPermissions> updatedPermissions = Stream.concat(
239-
initialPermissions.stream()
240-
.map(permission -> updateEidPermission(permission, resolvedSources)),
241-
resolvedSources.stream()
242-
.map(source -> ExtRequestPrebidDataEidPermissions.of(source, targetBidders)))
243-
.filter(StreamUtil.distinctBy(ExtRequestPrebidDataEidPermissions::getSource))
240+
.orElse(List.of());
241+
242+
final List<ExtRequestPrebidDataEidPermissions> updatedPermissions = initialPermissions.stream()
243+
.map(permission -> restrictEidPermission(permission, resolvedSources))
244+
.filter(Objects::nonNull)
244245
.toList();
245246

246-
return ExtRequestPrebidData.of(updatedPrebidDataBidders, updatedPermissions);
247+
return ExtRequestPrebidData.of(originalBidders, updatedPermissions);
247248
}
248249

249-
private ExtRequestPrebidDataEidPermissions updateEidPermission(ExtRequestPrebidDataEidPermissions permission,
250-
Set<String> resolvedSources) {
250+
private ExtRequestPrebidDataEidPermissions restrictEidPermission(ExtRequestPrebidDataEidPermissions permission,
251+
Set<String> resolvedSources) {
252+
253+
if (!resolvedSources.contains(permission.getSource())) {
254+
return permission;
255+
}
256+
257+
final List<String> current = ListUtils.emptyIfNull(permission.getBidders());
258+
final List<String> finalBidders = ListUtils.intersection(current, targetBidders);
251259

252-
return resolvedSources.contains(permission.getSource())
253-
? ExtRequestPrebidDataEidPermissions.of(
254-
permission.getSource(),
255-
(List<String>) CollectionUtils.union(permission.getBidders(), targetBidders))
256-
: permission;
260+
return finalBidders.isEmpty()
261+
? null
262+
: ExtRequestPrebidDataEidPermissions.of(permission.getSource(), finalBidders);
257263
}
258264

259265
@Override

extra/modules/live-intent-omni-channel-identity/src/test/java/org/prebid/server/hooks/modules/liveintent/omni/channel/identity/v1/LiveIntentOmniChannelIdentityProcessedAuctionRequestHookTest.java

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -375,14 +375,33 @@ public void callShouldReturnFailureWhenRequestingEidsIsFailed() {
375375
}
376376

377377
@Test
378-
public void biddersConfiguredRestrictionShouldBeRespected() {
378+
public void shouldRestrictExistingEidPermissionsByIntersectionAndKeepGlobalBiddersUnchanged() {
379+
// given
379380
final Uid givenUid = Uid.builder().id("id1").atype(2).build();
380381
final Eid givenEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build();
381382
final User givenUser = User.builder().eids(singletonList(givenEid)).build();
382-
final BidRequest givenBidRequest = BidRequest.builder().id("request").user(givenUser).build();
383383

384-
final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(configuredBidders, List.of(
385-
ExtRequestPrebidDataEidPermissions.of("liveintent.com", configuredBidders)));
384+
// existing global bidders and eid permissions including liveintent.com
385+
final ExtRequestPrebidData givenData = ExtRequestPrebidData.of(
386+
List.of("bidderX"),
387+
List.of(
388+
ExtRequestPrebidDataEidPermissions.of("some.other-source.com", List.of("bidderY")),
389+
ExtRequestPrebidDataEidPermissions.of("liveintent.com", List.of("bidder2", "bidder3"))
390+
));
391+
392+
final BidRequest givenBidRequest = BidRequest.builder()
393+
.id("request")
394+
.user(givenUser)
395+
.ext(ExtRequest.of(ExtRequestPrebid.builder().data(givenData).build()))
396+
.build();
397+
398+
// expected: global bidders unchanged, liveintent.com bidders intersected with configuredBidders => [bidder2]
399+
final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(
400+
List.of("bidderX"),
401+
List.of(
402+
ExtRequestPrebidDataEidPermissions.of("some.other-source.com", List.of("bidderY")),
403+
ExtRequestPrebidDataEidPermissions.of("liveintent.com", List.of("bidder2"))
404+
));
386405

387406
final Eid expectedEid = Eid.builder().source("liveintent.com").build();
388407

@@ -418,7 +437,7 @@ public void biddersConfiguredRestrictionShouldBeRespected() {
418437
}
419438

420439
@Test
421-
public void biddersConfiguredRestrictionShouldBeMergedWithProvided() {
440+
public void shouldNotAddNewEidPermissionsOrModifyGlobalBiddersWhenSourceNotPresent() {
422441
// given
423442
final Uid givenUid = Uid.builder().id("id1").atype(2).build();
424443
final Eid givenEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build();
@@ -429,12 +448,10 @@ public void biddersConfiguredRestrictionShouldBeMergedWithProvided() {
429448
ExtRequestPrebidDataEidPermissions.of("some.source.com", List.of("bidder3"))))
430449
).build())).build();
431450

432-
final List<String> expectedBidders = List.of("bidder3", "bidder2", "bidder1");
433-
434-
final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(expectedBidders, List.of(
451+
// expected: unchanged, because there is no existing permission for liveintent.com
452+
final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(List.of("bidder3"), List.of(
435453
ExtRequestPrebidDataEidPermissions.of("some.other-source.com", List.of("bidder3")),
436-
ExtRequestPrebidDataEidPermissions.of("some.source.com", List.of("bidder3")),
437-
ExtRequestPrebidDataEidPermissions.of("liveintent.com", configuredBidders)));
454+
ExtRequestPrebidDataEidPermissions.of("some.source.com", List.of("bidder3"))));
438455

439456
final Eid expectedEid = Eid.builder().source("liveintent.com").build();
440457

@@ -468,4 +485,64 @@ public void biddersConfiguredRestrictionShouldBeMergedWithProvided() {
468485
eq(MAPPER.encodeToString(givenBidRequest)),
469486
eq(5L));
470487
}
488+
489+
@Test
490+
public void shouldRemovePermissionWhenIntersectionIsEmpty() {
491+
// given
492+
final Uid givenUid = Uid.builder().id("id1").atype(2).build();
493+
final Eid givenEid = Eid.builder().source("some.source.com").uids(singletonList(givenUid)).build();
494+
final User givenUser = User.builder().eids(singletonList(givenEid)).build();
495+
496+
final ExtRequestPrebidData givenData = ExtRequestPrebidData.of(
497+
List.of("bidderGlobal"),
498+
List.of(
499+
ExtRequestPrebidDataEidPermissions.of("liveintent.com", List.of("not-allowed")),
500+
ExtRequestPrebidDataEidPermissions.of("keep.com", List.of("bidderGlobal"))
501+
));
502+
503+
final BidRequest givenBidRequest = BidRequest.builder()
504+
.id("request")
505+
.user(givenUser)
506+
.ext(ExtRequest.of(ExtRequestPrebid.builder().data(givenData).build()))
507+
.build();
508+
509+
// Respond with liveintent.com so that restriction is applied and becomes empty -> remove entry
510+
final Eid expectedEid = Eid.builder().source("liveintent.com").build();
511+
final String responseBody = MAPPER.encodeToString(IdResResponse.of(List.of(expectedEid)));
512+
given(httpClient.post(any(), any(), any(), anyLong()))
513+
.willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, responseBody)));
514+
515+
given(auctionInvocationContext.auctionContext()).willReturn(auctionContext);
516+
given(auctionContext.getActivityInfrastructure()).willReturn(activityInfrastructure);
517+
given(activityInfrastructure.isAllowed(any(), any())).willReturn(true);
518+
given(userFpdActivityMask.maskUser(any(), eq(false), eq(false)))
519+
.willAnswer(invocation -> invocation.getArgument(0));
520+
given(userFpdActivityMask.maskDevice(any(), eq(false), eq(false)))
521+
.willAnswer(invocation -> invocation.getArgument(0));
522+
523+
// when
524+
final InvocationResult<AuctionRequestPayload> result =
525+
target.call(AuctionRequestPayloadImpl.of(givenBidRequest), auctionInvocationContext).result();
526+
527+
// then
528+
final ExtRequestPrebidData expectedData = ExtRequestPrebidData.of(
529+
List.of("bidderGlobal"),
530+
List.of(
531+
ExtRequestPrebidDataEidPermissions.of("keep.com", List.of("bidderGlobal"))
532+
));
533+
534+
assertThat(result.status()).isEqualTo(InvocationStatus.success);
535+
assertThat(result.payloadUpdate().apply(AuctionRequestPayloadImpl.of(givenBidRequest)))
536+
.extracting(AuctionRequestPayload::bidRequest)
537+
.extracting(BidRequest::getExt)
538+
.extracting(ExtRequest::getPrebid)
539+
.extracting(ExtRequestPrebid::getData)
540+
.isEqualTo(expectedData);
541+
542+
verify(httpClient).post(
543+
eq("https://test.com/idres"),
544+
argThat(headers -> headers.contains("Authorization", "Bearer auth_token", true)),
545+
eq(MAPPER.encodeToString(givenBidRequest)),
546+
eq(5L));
547+
}
471548
}

0 commit comments

Comments
 (0)