Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class ActivityControllerCreationContext {

Map<PrivacyModuleQualifier, AccountPrivacyModuleConfig> privacyModulesConfigs;

Map<PrivacyModuleQualifier, Boolean> skipModuleConfigs;

@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
Set<PrivacyModuleQualifier> usedPrivacyModules = EnumSet.noneOf(PrivacyModuleQualifier.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
Expand All @@ -41,6 +42,8 @@ public class ActivityInfrastructureCreator {

private static final Logger logger = LoggerFactory.getLogger(ActivityInfrastructureCreator.class);

private static final int MODULE_MAX_SKIP_RATE = 100;

private final ActivityRuleFactory activityRuleFactory;
private final Purpose defaultPurpose4;
private final Metrics metrics;
Expand Down Expand Up @@ -144,9 +147,13 @@ private ActivityController from(Activity activity,
debug);
}

final Map<PrivacyModuleQualifier, Boolean> skipModulesConfigs = modulesConfigs.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> shouldSkipAllActivities(entry.getValue())));

final ActivityControllerCreationContext creationContext = ActivityControllerCreationContext.of(
activity,
modulesConfigs,
skipModulesConfigs,
gppContext);

final boolean allow = allowFromConfig(activityConfiguration.getAllow());
Expand All @@ -158,6 +165,13 @@ private ActivityController from(Activity activity,
return ActivityController.of(allow, rules, debug);
}

private static boolean shouldSkipAllActivities(AccountPrivacyModuleConfig config) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please rename this method to shouldSkipPrivacyModule

return Optional.ofNullable(config)
.map(AccountPrivacyModuleConfig::getSkipRate)
.map(skipRate -> ThreadLocalRandom.current().nextInt(MODULE_MAX_SKIP_RATE) < skipRate)
.orElse(false);
}

private static boolean allowFromConfig(Boolean configValue) {
return configValue != null ? configValue : ActivityInfrastructure.ALLOW_ACTIVITY_BY_DEFAULT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.prebid.server.activity.infrastructure.creator.ActivityControllerCreationContext;
import org.prebid.server.activity.infrastructure.creator.PrivacyModuleCreationContext;
import org.prebid.server.activity.infrastructure.creator.privacy.PrivacyModuleCreator;
import org.prebid.server.activity.infrastructure.privacy.AbstainPrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModule;
import org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier;
import org.prebid.server.activity.infrastructure.rule.AndRule;
Expand All @@ -17,6 +18,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -82,6 +84,14 @@ private static boolean isModuleEnabled(AccountPrivacyModuleConfig accountPrivacy
private PrivacyModule createPrivacyModule(PrivacyModuleQualifier privacyModuleQualifier,
ActivityControllerCreationContext creationContext) {

final boolean isSkipped = Optional.ofNullable(creationContext.getSkipModuleConfigs())
.map(configs -> configs.get(privacyModuleQualifier))
.orElse(false);

if (isSkipped) {
return new AbstainPrivacyModule(privacyModuleQualifier);
}

return privacyModulesCreators.get(privacyModuleQualifier)
.from(creationContext(privacyModuleQualifier, creationContext));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.prebid.server.activity.infrastructure.privacy;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.prebid.server.activity.infrastructure.debug.Loggable;
import org.prebid.server.activity.infrastructure.payload.ActivityInvocationPayload;

import java.util.Objects;

public class AbstainPrivacyModule implements PrivacyModule, Loggable {

private final PrivacyModuleQualifier privacyModuleQualifier;

public AbstainPrivacyModule(PrivacyModuleQualifier privacyModuleQualifier) {
this.privacyModuleQualifier = Objects.requireNonNull(privacyModuleQualifier);
}

@Override
public Result proceed(ActivityInvocationPayload activityInvocationPayload) {
return Result.ABSTAIN;
}

@Override
public JsonNode asLogEntry(ObjectMapper mapper) {
return mapper.createObjectNode()
.put("privacy_module", privacyModuleQualifier.moduleName())
.put("skipped", true)
.put("result", Result.ABSTAIN.name());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public sealed interface AccountPrivacyModuleConfig permits

PrivacyModuleQualifier getCode();

@JsonProperty("skipRate")
Integer getSkipRate();

@JsonProperty
Boolean enabled();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class AccountUSCustomLogicModuleConfig implements AccountPrivacyModuleCon
@Accessors(fluent = true)
Boolean enabled;

Integer skipRate;

Config config;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class AccountUSNatModuleConfig implements AccountPrivacyModuleConfig {
@Accessors(fluent = true)
Boolean enabled;

Integer skipRate;

Config config;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.prebid.server.activity.Activity;
Expand All @@ -22,6 +23,7 @@
import org.prebid.server.settings.model.PurposeEid;
import org.prebid.server.settings.model.Purposes;
import org.prebid.server.settings.model.activity.AccountActivityConfiguration;
import org.prebid.server.settings.model.activity.privacy.AccountUSCustomLogicModuleConfig;
import org.prebid.server.settings.model.activity.privacy.AccountUSNatModuleConfig;
import org.prebid.server.settings.model.activity.rule.AccountActivityConditionsRuleConfig;

Expand All @@ -30,12 +32,15 @@
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
import static org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier.US_CUSTOM_LOGIC;
import static org.prebid.server.activity.infrastructure.privacy.PrivacyModuleQualifier.US_NAT;

@ExtendWith(MockitoExtension.class)
public class ActivityInfrastructureCreatorTest {
Expand Down Expand Up @@ -91,8 +96,8 @@ public void parseShouldSkipPrivacyModulesDuplicatesAndEmitWarnings() {
.activities(Map.of(Activity.SYNC_USER, AccountActivityConfiguration.of(
null, singletonList(AccountActivityConditionsRuleConfig.of(null, null)))))
.modules(asList(
AccountUSNatModuleConfig.of(null, null),
AccountUSNatModuleConfig.of(null, null)))
AccountUSNatModuleConfig.of(null, null, null),
AccountUSNatModuleConfig.of(null, null, null)))
.build())
.build();

Expand All @@ -104,6 +109,30 @@ null, singletonList(AccountActivityConditionsRuleConfig.of(null, null)))))
verify(metrics).updateAlertsMetrics(eq(MetricName.general));
}

@Test
public void parseShouldPopulateSkipConfigForModules() {
// given
final Account account = Account.builder()
.privacy(AccountPrivacyConfig.builder()
.activities(Map.of(Activity.SYNC_USER, AccountActivityConfiguration.of(
null, singletonList(AccountActivityConditionsRuleConfig.of(null, null)))))
.modules(asList(
AccountUSNatModuleConfig.of(null, 100, null),
AccountUSCustomLogicModuleConfig.of(null, 0, null)))
.build())
.build();

// when
creator.parse(account, null, debug);

// then
final ArgumentCaptor<ActivityControllerCreationContext> captor =
ArgumentCaptor.forClass(ActivityControllerCreationContext.class);
verify(activityRuleFactory).from(any(), captor.capture());
assertThat(captor.getValue().getSkipModuleConfigs())
.containsOnly(entry(US_NAT, true), entry(US_CUSTOM_LOGIC, false));
}

@Test
public void parseShouldReturnExpectedResult() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ private static PrivacyModuleCreationContext givenCreationContext(List<Integer> s

return PrivacyModuleCreationContext.of(
Activity.CALL_BIDDER,
AccountUSCustomLogicModuleConfig.of(true, config),
AccountUSCustomLogicModuleConfig.of(true, null, config),
GppContextCreator.from(null, sectionsIds).build().getGppContext());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private static PrivacyModuleCreationContext givenCreationContext(List<Integer> s

return PrivacyModuleCreationContext.of(
Activity.CALL_BIDDER,
AccountUSNatModuleConfig.of(true, AccountUSNatModuleConfig.Config.of(skipSectionsIds)),
AccountUSNatModuleConfig.of(true, null, AccountUSNatModuleConfig.Config.of(skipSectionsIds)),
GppContextCreator.from(null, sectionsIds).build().getGppContext());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,6 @@ private static BidRequest givenBidRequest(String country, String region, String
}

private static ActivityControllerCreationContext creationContext(GppContext gppContext) {
return ActivityControllerCreationContext.of(null, null, gppContext);
return ActivityControllerCreationContext.of(null, null, null, gppContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void fromShouldCreateDefaultRuleIfNoneOfConfiguredPrivacyModulesMatches()
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList("not_configured"));
final ActivityControllerCreationContext creationContext = creationContext(Map.of(
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(null, null)));
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(null, null, null)));

// when
final Rule rule = target.from(config, creationContext);
Expand All @@ -70,7 +70,7 @@ public void fromShouldCreateRuleWithAllConfiguredPrivacyModules() {
// given
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList("*"));
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null);
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null, null);
final ActivityControllerCreationContext creationContext = creationContext(
Map.of(PrivacyModuleQualifier.US_NAT, moduleConfig));

Expand All @@ -89,7 +89,7 @@ public void fromShouldCreateRuleWithAllConfiguredPrivacyModulesThatMatches() {
// given
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList("iab.*"));
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null);
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null, null);
final ActivityControllerCreationContext creationContext = creationContext(
Map.of(PrivacyModuleQualifier.US_NAT, moduleConfig));

Expand All @@ -108,7 +108,7 @@ public void fromShouldCreateRuleAndModifyContextWithUsedPrivacyModules() {
// given
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList(PrivacyModuleQualifier.US_NAT.moduleName()));
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null);
final AccountPrivacyModuleConfig moduleConfig = AccountUSNatModuleConfig.of(null, null, null);
final ActivityControllerCreationContext creationContext = creationContext(
Map.of(PrivacyModuleQualifier.US_NAT, moduleConfig));

Expand All @@ -129,7 +129,7 @@ public void fromShouldSkipAlreadyUsedPrivacyModule() {
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList(PrivacyModuleQualifier.US_NAT.moduleName()));
final ActivityControllerCreationContext creationContext = creationContext(Map.of(
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(true, null)));
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(true, null, null)));
creationContext.use(PrivacyModuleQualifier.US_NAT);

// when
Expand All @@ -145,7 +145,25 @@ public void fromShouldSkipDisabledPrivacyModule() {
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList(PrivacyModuleQualifier.US_NAT.moduleName()));
final ActivityControllerCreationContext creationContext = creationContext(Map.of(
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(false, null)));
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(false, null, null)));

// when
final Rule rule = target.from(config, creationContext);

// then
assertThat(rule.proceed(null)).isEqualTo(Rule.Result.ABSTAIN);
}

@Test
public void fromShouldDisableSkippedPrivacyModule() {
// given
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList(PrivacyModuleQualifier.US_NAT.moduleName()));
final ActivityControllerCreationContext creationContext = ActivityControllerCreationContext.of(
null,
Map.of(PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(true, null, null)),
Map.of(PrivacyModuleQualifier.US_NAT, true),
null);

// when
final Rule rule = target.from(config, creationContext);
Expand All @@ -162,7 +180,7 @@ public void fromShouldSkipPrivacyModuleWithoutCreator() {
final AccountActivityPrivacyModulesRuleConfig config = AccountActivityPrivacyModulesRuleConfig.of(
singletonList(PrivacyModuleQualifier.US_NAT.moduleName()));
final ActivityControllerCreationContext creationContext = creationContext(Map.of(
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(null, null)));
PrivacyModuleQualifier.US_NAT, AccountUSNatModuleConfig.of(null, null, null)));

// when
final Rule rule = target.from(config, creationContext);
Expand All @@ -174,6 +192,6 @@ public void fromShouldSkipPrivacyModuleWithoutCreator() {
private static ActivityControllerCreationContext creationContext(
Map<PrivacyModuleQualifier, AccountPrivacyModuleConfig> modulesConfigs) {

return ActivityControllerCreationContext.of(null, modulesConfigs, null);
return ActivityControllerCreationContext.of(null, modulesConfigs, null, null);
}
}
Loading