Skip to content

Commit

Permalink
Remove redundant enforce-ccpa property (#1458)
Browse files Browse the repository at this point in the history
  • Loading branch information
And1sS authored Oct 6, 2021
1 parent 250b990 commit ba5ca49
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 83 deletions.
22 changes: 18 additions & 4 deletions docs/application-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ Here's an example YAML file containing account-specific settings:
events:
enabled: true
privacy:
enforce-ccpa: true
ccpa:
enabled: true
integration-enabled:
video: true
web: true
app: true
amp: true
gdpr:
enabled: true
integration-enabled:
Expand Down Expand Up @@ -252,7 +258,15 @@ example:
}
},
"privacy": {
"enforce-ccpa": true,
"ccpa": {
"enabled": true,
"integration-enabled": {
"web": true,
"amp": false,
"app": true,
"video": false
}
},
"gdpr": {
"enabled": true,
"integration-enabled": {
Expand Down Expand Up @@ -393,7 +407,7 @@ several tables. MySQL and Postgres provides necessary functions allowing to proj
expected JSON format.

Let's assume following table schema for example:
```sql
```mysql-sql
'CREATE TABLE `accounts_account` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) NOT NULL,
Expand All @@ -419,7 +433,7 @@ ENGINE=InnoDB DEFAULT CHARSET=utf8'

The following Mysql SQL query could be used to construct a JSON document of required shape on the fly:

```sql
```mysql-sql
SELECT
JSON_MERGE_PATCH(config, JSON_OBJECT(
'id', uuid,
Expand Down
115 changes: 62 additions & 53 deletions src/main/java/org/prebid/server/auction/PrivacyEnforcementService.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
import java.util.stream.Collectors;

/**
* Service provides masking for OpenRTB user sensitive information.
* Service provides masking for OpenRTB client sensitive information.
*/
public class PrivacyEnforcementService {

Expand Down Expand Up @@ -135,8 +135,9 @@ private String resolveIpAddress(Device device, Privacy privacy) {
return null;
}

public Future<PrivacyContext> contextFromSetuidRequest(
HttpServerRequest httpRequest, Account account, Timeout timeout) {
public Future<PrivacyContext> contextFromSetuidRequest(HttpServerRequest httpRequest,
Account account,
Timeout timeout) {

final Privacy privacy = privacyExtractor.validPrivacyFromSetuidRequest(httpRequest);
final String ipAddress = resolveIpFromRequest(httpRequest);
Expand All @@ -149,8 +150,10 @@ public Future<PrivacyContext> contextFromSetuidRequest(
.map(tcfContext -> PrivacyContext.of(privacy, tcfContext));
}

public Future<PrivacyContext> contextFromCookieSyncRequest(
CookieSyncRequest cookieSyncRequest, HttpServerRequest httpRequest, Account account, Timeout timeout) {
public Future<PrivacyContext> contextFromCookieSyncRequest(CookieSyncRequest cookieSyncRequest,
HttpServerRequest httpRequest,
Account account,
Timeout timeout) {

final Privacy privacy = privacyExtractor.validPrivacyFrom(cookieSyncRequest);
final String ipAddress = resolveIpFromRequest(httpRequest);
Expand Down Expand Up @@ -220,6 +223,7 @@ Future<List<BidderPrivacyResult>> mask(AuctionContext auctionContext,

public Future<Map<Integer, PrivacyEnforcementAction>> resultForVendorIds(Set<Integer> vendorIds,
TcfContext tcfContext) {

return tcfDefinerService.resultForVendorIds(vendorIds, tcfContext)
.map(TcfResponse::getActions);
}
Expand All @@ -233,16 +237,13 @@ private Map<String, BidderPrivacyResult> ccpaResult(BidRequest bidRequest,
Privacy privacy,
MetricName requestType) {

if (isCcpaEnforced(privacy.getCcpa(), account, requestType)) {
return maskCcpa(extractCcpaEnforcedBidders(bidders, bidRequest, aliases), device, bidderToUser);
}

return Collections.emptyMap();
return isCcpaEnforced(privacy.getCcpa(), account, requestType)
? maskCcpa(extractCcpaEnforcedBidders(bidders, bidRequest, aliases), device, bidderToUser)
: Collections.emptyMap();
}

public boolean isCcpaEnforced(Ccpa ccpa, Account account) {
final boolean shouldEnforceCcpa = isCcpaEnabled(account);

return shouldEnforceCcpa && ccpa.isEnforced();
}

Expand All @@ -255,20 +256,19 @@ private Boolean isCcpaEnabled(Account account) {
final AccountPrivacyConfig accountPrivacyConfig = account.getPrivacy();
final AccountCcpaConfig accountCcpaConfig =
accountPrivacyConfig != null ? accountPrivacyConfig.getCcpa() : null;
final Boolean accountEnforceCcpa = accountPrivacyConfig != null ? accountPrivacyConfig.getEnforceCcpa() : null;
final Boolean accountCcpaEnabled = accountCcpaConfig != null ? accountCcpaConfig.getEnabled() : null;

return ObjectUtils.firstNonNull(accountCcpaEnabled, accountEnforceCcpa, ccpaEnforce);
return ObjectUtils.defaultIfNull(accountCcpaEnabled, ccpaEnforce);
}

private boolean isCcpaEnabled(Account account, MetricName requestType) {
final AccountPrivacyConfig accountPrivacyConfig = account.getPrivacy();
final AccountCcpaConfig accountCcpaConfig =
accountPrivacyConfig != null ? accountPrivacyConfig.getCcpa() : null;
final Boolean accountEnforceCcpa = accountPrivacyConfig != null ? accountPrivacyConfig.getEnforceCcpa() : null;

final Boolean accountCcpaEnabled = accountCcpaConfig != null ? accountCcpaConfig.getEnabled() : null;
if (requestType == null) {
return ObjectUtils.firstNonNull(accountCcpaEnabled, accountEnforceCcpa, ccpaEnforce);
return ObjectUtils.defaultIfNull(accountCcpaEnabled, ccpaEnforce);
}

final EnabledForRequestType enabledForRequestType = accountCcpaConfig != null
Expand All @@ -278,11 +278,12 @@ private boolean isCcpaEnabled(Account account, MetricName requestType) {
final Boolean enabledForType = enabledForRequestType != null
? enabledForRequestType.isEnabledFor(requestType)
: null;
return ObjectUtils.firstNonNull(enabledForType, accountCcpaEnabled, accountEnforceCcpa, ccpaEnforce);
return ObjectUtils.firstNonNull(enabledForType, accountCcpaEnabled, ccpaEnforce);
}

private Map<String, BidderPrivacyResult> maskCcpa(
Set<String> biddersToMask, Device device, Map<String, User> bidderToUser) {
private Map<String, BidderPrivacyResult> maskCcpa(Set<String> biddersToMask,
Device device,
Map<String, User> bidderToUser) {

return biddersToMask.stream()
.collect(Collectors.toMap(Function.identity(),
Expand All @@ -306,17 +307,18 @@ private User maskCcpaUser(User user) {
}

private Device maskCcpaDevice(Device device) {
return device != null
? device.toBuilder()
.ip(ipAddressHelper.maskIpv4(device.getIp()))
.ipv6(ipAddressHelper.anonymizeIpv6(device.getIpv6()))
.geo(maskGeoDefault(device.getGeo()))
.ifa(null)
.macsha1(null).macmd5(null)
.dpidsha1(null).dpidmd5(null)
.didsha1(null).didmd5(null)
.build()
: null;
if (device != null) {
return device.toBuilder()
.ip(ipAddressHelper.maskIpv4(device.getIp()))
.ipv6(ipAddressHelper.anonymizeIpv6(device.getIpv6()))
.geo(maskGeoDefault(device.getGeo()))
.ifa(null)
.macsha1(null).macmd5(null)
.dpidsha1(null).dpidmd5(null)
.didsha1(null).didmd5(null)
.build();
}
return null;
}

private static boolean isCoppaMaskingRequired(Privacy privacy) {
Expand Down Expand Up @@ -350,17 +352,18 @@ private User maskCoppaUser(User user) {
}

private Device maskCoppaDevice(Device device) {
return device != null
? device.toBuilder()
.ip(ipAddressHelper.maskIpv4(device.getIp()))
.ipv6(ipAddressHelper.anonymizeIpv6(device.getIpv6()))
.geo(maskGeoForCoppa(device.getGeo()))
.ifa(null)
.macsha1(null).macmd5(null)
.dpidsha1(null).dpidmd5(null)
.didsha1(null).didmd5(null)
.build()
: null;
if (device != null) {
return device.toBuilder()
.ip(ipAddressHelper.maskIpv4(device.getIp()))
.ipv6(ipAddressHelper.anonymizeIpv6(device.getIpv6()))
.geo(maskGeoForCoppa(device.getGeo()))
.ifa(null)
.macsha1(null).macmd5(null)
.dpidsha1(null).dpidmd5(null)
.didsha1(null).didmd5(null)
.build();
}
return null;
}

/**
Expand All @@ -377,8 +380,10 @@ private static Geo maskGeoForCoppa(Geo geo) {
* Returns {@link Future &lt;{@link Map}&lt;{@link String}, {@link PrivacyEnforcementAction}&gt;&gt;},
* where bidder names mapped to actions for GDPR masking for pbs server.
*/
private Future<Map<String, PrivacyEnforcementAction>> getBidderToEnforcementAction(
TcfContext tcfContext, Set<String> bidders, BidderAliases aliases, Account account) {
private Future<Map<String, PrivacyEnforcementAction>> getBidderToEnforcementAction(TcfContext tcfContext,
Set<String> bidders,
BidderAliases aliases,
Account account) {

return tcfDefinerService.resultForBidderNames(
Collections.unmodifiableSet(bidders),
Expand All @@ -388,8 +393,10 @@ private Future<Map<String, PrivacyEnforcementAction>> getBidderToEnforcementActi
.map(tcfResponse -> mapTcfResponseToEachBidder(tcfResponse, bidders));
}

private Set<String> extractCcpaEnforcedBidders(List<String> bidders, BidRequest bidRequest, BidderAliases
aliases) {
private Set<String> extractCcpaEnforcedBidders(List<String> bidders,
BidRequest bidRequest,
BidderAliases aliases) {

final Set<String> ccpaEnforcedBidders = new HashSet<>(bidders);

final ExtRequest extBidRequest = bidRequest.getExt();
Expand All @@ -414,7 +421,8 @@ private static Map<String, PrivacyEnforcementAction> mapTcfResponseToEachBidder(
Set<String> bidders) {

final Map<String, PrivacyEnforcementAction> bidderNameToAction = tcfResponse.getActions();
return bidders.stream().collect(Collectors.toMap(Function.identity(), bidderNameToAction::get));
return bidders.stream()
.collect(Collectors.toMap(Function.identity(), bidderNameToAction::get));
}

private void updateCcpaMetrics(Ccpa ccpa) {
Expand Down Expand Up @@ -476,7 +484,7 @@ private static boolean shouldMaskUser(User user) {
return true;
}
final ExtUser extUser = user.getExt();
return extUser != null && (CollectionUtils.isNotEmpty(extUser.getEids()));
return extUser != null && CollectionUtils.isNotEmpty(extUser.getEids());
}

/**
Expand All @@ -497,6 +505,7 @@ private List<BidderPrivacyResult> getBidderToPrivacyResult(
Device device) {

final boolean isLmtEnabled = lmtEnforce && isLmtEnabled(device);

return bidderToUser.entrySet().stream()
.filter(entry -> bidders.contains(entry.getKey()))
.map(bidderUserEntry -> createBidderPrivacyResult(
Expand Down Expand Up @@ -599,12 +608,13 @@ private Device maskTcfDevice(Device device, boolean maskIp, boolean maskGeo, boo
* Returns masked for GDPR {@link Geo} by rounding lon and lat properties.
*/
private static Geo maskGeoDefault(Geo geo) {
return geo != null
? geo.toBuilder()
.lat(maskGeoCoordinate(geo.getLat()))
.lon(maskGeoCoordinate(geo.getLon()))
.build()
: null;
if (geo != null) {
return geo.toBuilder()
.lat(maskGeoCoordinate(geo.getLat()))
.lon(maskGeoCoordinate(geo.getLon()))
.build();
}
return null;
}

/**
Expand Down Expand Up @@ -651,7 +661,6 @@ private static List<BidderPrivacyResult> merge(

private static AccountGdprConfig accountGdprConfig(Account account) {
final AccountPrivacyConfig privacyConfig = account.getPrivacy();

return privacyConfig != null ? privacyConfig.getGdpr() : null;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package org.prebid.server.settings.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

@Value(staticConstructor = "of")
public class AccountPrivacyConfig {

@JsonProperty("enforce-ccpa")
Boolean enforceCcpa;

AccountGdprConfig gdpr;

AccountCcpaConfig ccpa;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.prebid.server.auction.model.BidderPrivacyResult;
import org.prebid.server.auction.model.IpAddress;
import org.prebid.server.bidder.BidderCatalog;
import org.prebid.server.bidder.BidderInfo;
import org.prebid.server.exception.InvalidRequestException;
import org.prebid.server.execution.Timeout;
import org.prebid.server.execution.TimeoutFactory;
Expand All @@ -47,7 +48,6 @@
import org.prebid.server.proto.openrtb.ext.request.ExtUserEid;
import org.prebid.server.proto.openrtb.ext.request.ExtUserPrebid;
import org.prebid.server.proto.request.CookieSyncRequest;
import org.prebid.server.bidder.BidderInfo;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountCcpaConfig;
import org.prebid.server.settings.model.AccountPrivacyConfig;
Expand Down Expand Up @@ -156,8 +156,8 @@ public void contextFromBidRequestShouldReturnTcfContextForCoppa() {
final Future<PrivacyContext> privacyContext = privacyEnforcementService.contextFromBidRequest(auctionContext);

// then
FutureAssertion.assertThat(privacyContext).succeededWith(
PrivacyContext.of(Privacy.of(EMPTY, EMPTY, Ccpa.EMPTY, 1), tcfContext));
FutureAssertion.assertThat(privacyContext)
.succeededWith(PrivacyContext.of(Privacy.of(EMPTY, EMPTY, Ccpa.EMPTY, 1), tcfContext));
}

@Test
Expand Down Expand Up @@ -477,7 +477,6 @@ public void shouldMaskForCcpaWhenAccountHasCppaConfigEnabledForRequestType() {
final AuctionContext context = AuctionContext.builder()
.account(Account.builder()
.privacy(AccountPrivacyConfig.of(
null,
null,
AccountCcpaConfig.builder()
.enabledForRequestType(EnabledForRequestType.of(false, false, true, false))
Expand Down Expand Up @@ -529,7 +528,7 @@ public void shouldMaskForCcpaWhenAccountHasCppaEnforcedTrue() {

final AuctionContext context = AuctionContext.builder()
.account(Account.builder()
.privacy(AccountPrivacyConfig.of(true, null, null))
.privacy(AccountPrivacyConfig.of(null, AccountCcpaConfig.builder().enabled(true).build()))
.build())
.requestTypeMetric(MetricName.openrtb2app)
.bidRequest(bidRequest)
Expand Down Expand Up @@ -578,7 +577,6 @@ public void shouldMaskForCcpaWhenAccountHasCcpaConfigEnabled() {
final AuctionContext context = AuctionContext.builder()
.account(Account.builder()
.privacy(AccountPrivacyConfig.of(
null,
null,
AccountCcpaConfig.builder().enabled(true).build()))
.build())
Expand Down Expand Up @@ -777,8 +775,7 @@ public void shouldNotMaskForTcfWhenTcfServiceAllowAllAndDeviceLmtIsOneAndLmtIsNo
.build();
assertThat(result).containsOnly(expectedBidderPrivacy);

verify(tcfDefinerService)
.resultForBidderNames(eq(singleton(BIDDER_NAME)), any(), any(), any());
verify(tcfDefinerService).resultForBidderNames(eq(singleton(BIDDER_NAME)), any(), any(), any());
}

@Test
Expand Down Expand Up @@ -1466,7 +1463,7 @@ public void isCcpaEnforcedShouldReturnFalseWhenEnforcedPropertyIsTrueInConfigura

final Ccpa ccpa = Ccpa.of("1YYY");
final Account account = Account.builder()
.privacy(AccountPrivacyConfig.of(false, null, null))
.privacy(AccountPrivacyConfig.of(null, AccountCcpaConfig.builder().enabled(false).build()))
.build();

// when and then
Expand Down Expand Up @@ -1497,7 +1494,6 @@ public void isCcpaEnforcedShouldReturnFalseWhenAccountCcpaConfigHasEnabledTrue()
final Ccpa ccpa = Ccpa.of("1YYY");
final Account account = Account.builder()
.privacy(AccountPrivacyConfig.of(
null,
null,
AccountCcpaConfig.builder().enabled(true).build()))
.build();
Expand Down
Loading

0 comments on commit ba5ca49

Please sign in to comment.