Skip to content

Commit 3c63d78

Browse files
authored
Core: Add TransmitEids activity (prebid#2901)
1 parent 28ae7cf commit 3c63d78

169 files changed

Lines changed: 12545 additions & 7676 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

extra/modules/confiant-ad-quality/src/main/java/org/prebid/server/hooks/modules/com/confiant/adquality/config/ConfiantAdQualityModuleConfiguration.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import io.vertx.core.Promise;
55
import io.vertx.core.Vertx;
6-
import org.prebid.server.auction.PrivacyEnforcementService;
6+
import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask;
77
import org.prebid.server.hooks.modules.com.confiant.adquality.core.BidsScanner;
88
import org.prebid.server.hooks.modules.com.confiant.adquality.core.RedisClient;
99
import org.prebid.server.hooks.modules.com.confiant.adquality.core.RedisScanStateChecker;
@@ -20,6 +20,7 @@
2020
import org.springframework.context.annotation.Configuration;
2121
import org.springframework.context.annotation.PropertySource;
2222

23+
import java.util.Collections;
2324
import java.util.List;
2425

2526
@ConditionalOnProperty(prefix = "hooks." + ConfiantAdQualityModule.CODE, name = "enabled", havingValue = "true")
@@ -37,7 +38,7 @@ ConfiantAdQualityModule confiantAdQualityModule(
3738
RedisConfig redisConfig,
3839
RedisRetryConfig retryConfig,
3940
Vertx vertx,
40-
PrivacyEnforcementService privacyEnforcementService,
41+
UserFpdActivityMask userFpdActivityMask,
4142
ObjectMapper objectMapper) {
4243

4344
final RedisConnectionConfig writeNodeConfig = redisConfig.getWriteNode();
@@ -55,14 +56,14 @@ ConfiantAdQualityModule confiantAdQualityModule(
5556

5657
bidsScanner.start(scannerPromise);
5758

58-
return new ConfiantAdQualityModule(List.of(
59-
new ConfiantAdQualityBidResponsesScanHook(bidsScanner, biddersToExcludeFromScan, privacyEnforcementService)));
59+
return new ConfiantAdQualityModule(Collections.singletonList(
60+
new ConfiantAdQualityBidResponsesScanHook(bidsScanner, biddersToExcludeFromScan, userFpdActivityMask)));
6061
}
6162

6263
@Bean
6364
ObjectMapper objectMapper() {
6465
return new ObjectMapper();
65-
};
66+
}
6667

6768
@Bean
6869
@ConfigurationProperties(prefix = "hooks.modules.confiant-ad-quality.redis-config")

extra/modules/confiant-ad-quality/src/main/java/org/prebid/server/hooks/modules/com/confiant/adquality/v1/ConfiantAdQualityBidResponsesScanHook.java

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;
1010
import org.prebid.server.activity.infrastructure.payload.impl.ActivityInvocationPayloadImpl;
1111
import org.prebid.server.activity.infrastructure.payload.impl.BidRequestActivityInvocationPayload;
12-
import org.prebid.server.auction.PrivacyEnforcementService;
1312
import org.prebid.server.auction.model.AuctionContext;
1413
import org.prebid.server.auction.model.BidderResponse;
14+
import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask;
1515
import org.prebid.server.hooks.execution.v1.bidder.AllProcessedBidResponsesPayloadImpl;
1616
import org.prebid.server.hooks.modules.com.confiant.adquality.core.AnalyticsMapper;
1717
import org.prebid.server.hooks.modules.com.confiant.adquality.core.BidsMapper;
@@ -29,6 +29,7 @@
2929
import java.util.Collections;
3030
import java.util.List;
3131
import java.util.Map;
32+
import java.util.Objects;
3233
import java.util.stream.Collectors;
3334
import java.util.stream.Stream;
3435

@@ -37,19 +38,16 @@ public class ConfiantAdQualityBidResponsesScanHook implements AllProcessedBidRes
3738
private static final String CODE = "confiant-ad-quality-bid-responses-scan-hook";
3839

3940
private final BidsScanner bidsScanner;
40-
4141
private final List<String> biddersToExcludeFromScan;
42+
private final UserFpdActivityMask userFpdActivityMask;
4243

43-
private final PrivacyEnforcementService privacyEnforcementService;
44-
45-
public ConfiantAdQualityBidResponsesScanHook(
46-
BidsScanner bidsScanner,
47-
List<String> biddersToExcludeFromScan,
48-
PrivacyEnforcementService privacyEnforcementService) {
44+
public ConfiantAdQualityBidResponsesScanHook(BidsScanner bidsScanner,
45+
List<String> biddersToExcludeFromScan,
46+
UserFpdActivityMask userFpdActivityMask) {
4947

50-
this.bidsScanner = bidsScanner;
51-
this.biddersToExcludeFromScan = biddersToExcludeFromScan;
52-
this.privacyEnforcementService = privacyEnforcementService;
48+
this.bidsScanner = Objects.requireNonNull(bidsScanner);
49+
this.biddersToExcludeFromScan = Objects.requireNonNull(biddersToExcludeFromScan);
50+
this.userFpdActivityMask = Objects.requireNonNull(userFpdActivityMask);
5351
}
5452

5553
@Override
@@ -83,10 +81,8 @@ private BidRequest getBidRequest(AuctionInvocationContext auctionInvocationConte
8381
final boolean disallowTransmitGeo = !auctionContext.getActivityInfrastructure()
8482
.isAllowed(Activity.TRANSMIT_GEO, activityInvocationPayload);
8583

86-
final User maskedUser = privacyEnforcementService
87-
.maskUserConsideringActivityRestrictions(bidRequest.getUser(), true, disallowTransmitGeo);
88-
final Device maskedDevice = privacyEnforcementService
89-
.maskDeviceConsideringActivityRestrictions(bidRequest.getDevice(), true, disallowTransmitGeo);
84+
final User maskedUser = userFpdActivityMask.maskUser(bidRequest.getUser(), true, true, disallowTransmitGeo);
85+
final Device maskedDevice = userFpdActivityMask.maskDevice(bidRequest.getDevice(), true, disallowTransmitGeo);
9086

9187
return bidRequest.toBuilder()
9288
.user(maskedUser)

extra/modules/confiant-ad-quality/src/test/java/org/prebid/server/hooks/modules/com/confiant/adquality/v1/ConfiantAdQualityBidResponsesScanHookTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.mockito.junit.MockitoJUnit;
1414
import org.mockito.junit.MockitoRule;
1515
import org.prebid.server.activity.infrastructure.ActivityInfrastructure;
16-
import org.prebid.server.auction.PrivacyEnforcementService;
1716
import org.prebid.server.auction.model.AuctionContext;
1817
import org.prebid.server.auction.model.BidderResponse;
18+
import org.prebid.server.auction.privacy.enforcement.mask.UserFpdActivityMask;
1919
import org.prebid.server.bidder.model.BidderSeatBid;
2020
import org.prebid.server.hooks.execution.v1.bidder.AllProcessedBidResponsesPayloadImpl;
2121
import org.prebid.server.hooks.modules.com.confiant.adquality.core.BidsMapper;
@@ -61,15 +61,15 @@ public class ConfiantAdQualityBidResponsesScanHookTest {
6161
private ActivityInfrastructure activityInfrastructure;
6262

6363
@Mock
64-
private PrivacyEnforcementService privacyEnforcementService;
64+
private UserFpdActivityMask userFpdActivityMask;
6565

6666
private ConfiantAdQualityBidResponsesScanHook target;
6767

6868
private final RedisParser redisParser = new RedisParser(new ObjectMapper());
6969

7070
@Before
7171
public void setUp() {
72-
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(), privacyEnforcementService);
72+
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(), userFpdActivityMask);
7373
}
7474

7575
@Test
@@ -176,7 +176,7 @@ public void callShouldSubmitToScanBidsWhichAreNotPartOfTheExcludeToScanListWhenH
176176
.bidRequest(BidRequest.builder().cur(List.of("USD")).build())
177177
.build();
178178

179-
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(secureBidderName), privacyEnforcementService);
179+
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(secureBidderName), userFpdActivityMask);
180180

181181
doReturn(List.of(secureBidderResponse, notSecureBadBidderResponse, notSecureGoodBidderResponse)).when(allProcessedBidResponsesPayload).bidResponses();
182182
doReturn(Future.succeededFuture(bidsScanResult)).when(bidsScanner).submitBids(any());
@@ -234,7 +234,7 @@ public void callShouldSubmitToScanOnlyBidsWithDataWhenSomeBiddersRespondWithEmpt
234234
.bidRequest(BidRequest.builder().cur(List.of("USD")).build())
235235
.build();
236236

237-
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(secureBidderName), privacyEnforcementService);
237+
target = new ConfiantAdQualityBidResponsesScanHook(bidsScanner, List.of(secureBidderName), userFpdActivityMask);
238238

239239
doReturn(List.of(secureBidderResponse, notSecureBadBidderResponse, emptyBidderResponse)).when(allProcessedBidResponsesPayload).bidResponses();
240240
doReturn(Future.succeededFuture(bidsScanResult)).when(bidsScanner).submitBids(any());
@@ -277,9 +277,9 @@ public void callShouldSubmitBidsWithoutMaskedGeoInfoWhenTransmitGeoIsAllowed() {
277277
final Boolean transmitGeoIsAllowed = true;
278278
final BidsScanResult bidsScanResult = redisParser.parseBidsScanResult(
279279
"[[[{\"tag_key\": \"tag\", \"issues\":[{\"spec_name\":\"malicious_domain\",\"value\":\"ads.deceivenetworks.net\",\"first_adinstance\":\"e91e8da982bb8b7f80100426\"}]}]]]");
280-
final User user = privacyEnforcementService.maskUserConsideringActivityRestrictions(
281-
getUser(), true, !transmitGeoIsAllowed);
282-
final Device device = privacyEnforcementService.maskDeviceConsideringActivityRestrictions(
280+
final User user = userFpdActivityMask.maskUser(
281+
getUser(), true, true, !transmitGeoIsAllowed);
282+
final Device device = userFpdActivityMask.maskDevice(
283283
getDevice(), true, !transmitGeoIsAllowed);
284284

285285
bidsScanner.enableScan();
@@ -306,9 +306,9 @@ public void callShouldSubmitBidsWithMaskedGeoInfoWhenTransmitGeoIsNotAllowed() {
306306
final Boolean transmitGeoIsAllowed = false;
307307
final BidsScanResult bidsScanResult = redisParser.parseBidsScanResult(
308308
"[[[{\"tag_key\": \"tag\", \"issues\":[{\"spec_name\":\"malicious_domain\",\"value\":\"ads.deceivenetworks.net\",\"first_adinstance\":\"e91e8da982bb8b7f80100426\"}]}]]]");
309-
final User user = privacyEnforcementService.maskUserConsideringActivityRestrictions(
310-
getUser(), true, !transmitGeoIsAllowed);
311-
final Device device = privacyEnforcementService.maskDeviceConsideringActivityRestrictions(
309+
final User user = userFpdActivityMask.maskUser(
310+
getUser(), true, true, !transmitGeoIsAllowed);
311+
final Device device = userFpdActivityMask.maskDevice(
312312
getDevice(), true, !transmitGeoIsAllowed);
313313

314314
bidsScanner.enableScan();

src/main/java/com/iab/openrtb/request/User.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
@Value
1818
public class User {
1919

20+
public static final User EMPTY = User.builder().build();
21+
2022
/**
2123
* Exchange-specific ID for the user.
2224
*/

src/main/java/org/prebid/server/activity/Activity.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public enum Activity {
1616
@JsonProperty("transmitUfpd")
1717
TRANSMIT_UFPD,
1818

19+
@JsonProperty("transmitEids")
20+
TRANSMIT_EIDS,
21+
1922
@JsonProperty("transmitPreciseGeo")
2023
TRANSMIT_GEO,
2124

src/main/java/org/prebid/server/activity/infrastructure/creator/ActivityInfrastructureCreator.java

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
import org.prebid.server.metric.Metrics;
1616
import org.prebid.server.proto.openrtb.ext.request.TraceLevel;
1717
import org.prebid.server.settings.model.Account;
18+
import org.prebid.server.settings.model.AccountGdprConfig;
1819
import org.prebid.server.settings.model.AccountPrivacyConfig;
20+
import org.prebid.server.settings.model.GdprConfig;
21+
import org.prebid.server.settings.model.Purpose;
22+
import org.prebid.server.settings.model.PurposeEid;
23+
import org.prebid.server.settings.model.Purposes;
1924
import org.prebid.server.settings.model.activity.AccountActivityConfiguration;
2025
import org.prebid.server.settings.model.activity.privacy.AccountPrivacyModuleConfig;
2126

@@ -27,6 +32,7 @@
2732
import java.util.Objects;
2833
import java.util.Optional;
2934
import java.util.function.BinaryOperator;
35+
import java.util.function.Function;
3036
import java.util.function.Supplier;
3137
import java.util.function.UnaryOperator;
3238
import java.util.stream.Collectors;
@@ -36,14 +42,20 @@ public class ActivityInfrastructureCreator {
3642
private static final Logger logger = LoggerFactory.getLogger(ActivityInfrastructureCreator.class);
3743

3844
private final ActivityRuleFactory activityRuleFactory;
45+
private final Purpose defaultPurpose4;
3946
private final Metrics metrics;
4047
private final JacksonMapper jacksonMapper;
4148

4249
public ActivityInfrastructureCreator(ActivityRuleFactory activityRuleFactory,
50+
GdprConfig gdprConfig,
4351
Metrics metrics,
4452
JacksonMapper jacksonMapper) {
4553

4654
this.activityRuleFactory = Objects.requireNonNull(activityRuleFactory);
55+
this.defaultPurpose4 = Optional.ofNullable(gdprConfig)
56+
.map(GdprConfig::getPurposes)
57+
.map(Purposes::getP4)
58+
.orElse(null);
4759
this.metrics = Objects.requireNonNull(metrics);
4860
this.jacksonMapper = Objects.requireNonNull(jacksonMapper);
4961
}
@@ -74,12 +86,15 @@ Map<Activity, ActivityController> parse(Account account, GppContext gppContext,
7486

7587
return Arrays.stream(Activity.values()).collect(Collectors.toMap(
7688
UnaryOperator.identity(),
77-
activity -> from(
78-
activity,
79-
activitiesConfiguration.get(activity),
80-
modulesConfigs,
81-
gppContext,
82-
debug),
89+
fallbackActivity(
90+
activitiesConfiguration,
91+
accountPrivacyConfig,
92+
activity -> from(
93+
activity,
94+
activitiesConfiguration.get(activity),
95+
modulesConfigs,
96+
gppContext,
97+
debug)),
8398
(oldValue, newValue) -> oldValue,
8499
enumMapFactory()));
85100
}
@@ -94,6 +109,28 @@ private BinaryOperator<AccountPrivacyModuleConfig> takeFirstAndLogDuplicates(Str
94109
};
95110
}
96111

112+
// TODO: remove this wrapper after transition period
113+
private Function<Activity, ActivityController> fallbackActivity(
114+
Map<Activity, AccountActivityConfiguration> activitiesConfiguration,
115+
Optional<AccountPrivacyConfig> accountPrivacyConfig,
116+
Function<Activity, ActivityController> activityControllerCreator) {
117+
118+
final boolean imitateTransmitEids = !activitiesConfiguration.containsKey(Activity.TRANSMIT_EIDS)
119+
&& activitiesConfiguration.containsKey(Activity.TRANSMIT_UFPD)
120+
&& accountPrivacyConfig
121+
.map(AccountPrivacyConfig::getGdpr)
122+
.map(AccountGdprConfig::getPurposes)
123+
.map(Purposes::getP4)
124+
.or(() -> Optional.ofNullable(defaultPurpose4))
125+
.map(Purpose::getEid)
126+
.map(PurposeEid::getActivityTransition)
127+
.orElse(true);
128+
129+
return originalActivity -> originalActivity == Activity.TRANSMIT_EIDS && imitateTransmitEids
130+
? activityControllerCreator.apply(Activity.TRANSMIT_UFPD)
131+
: activityControllerCreator.apply(originalActivity);
132+
}
133+
97134
private ActivityController from(Activity activity,
98135
AccountActivityConfiguration activityConfiguration,
99136
Map<PrivacyModuleQualifier, AccountPrivacyModuleConfig> modulesConfigs,

src/main/java/org/prebid/server/activity/infrastructure/privacy/usnat/USNatModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public USNatModule(Activity activity, USNatGppReader gppReader) {
2828
private static PrivacyModule innerModule(Activity activity, USNatGppReader gppReader) {
2929
return switch (activity) {
3030
case SYNC_USER, MODIFY_UFDP -> new USNatSyncUser(gppReader);
31-
case TRANSMIT_UFPD -> new USNatTransmitUfpd(gppReader);
31+
case TRANSMIT_UFPD, TRANSMIT_EIDS -> new USNatTransmitUfpd(gppReader);
3232
case TRANSMIT_GEO -> new USNatTransmitGeo(gppReader);
3333
case CALL_BIDDER, TRANSMIT_TID, REPORT_ANALYTICS -> USNatDefault.instance();
3434
};

0 commit comments

Comments
 (0)