Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -4,7 +4,8 @@ enum PublicCountryIp {

USA_IP("209.232.44.21", "d646:2414:17b2:f371:9b62:f176:b4c0:51cd"),
UKR_IP("193.238.111.14", "3080:f30f:e4bc:0f56:41be:6aab:9d0a:58e2"),
CAN_IP("70.71.245.39", "f9b2:c742:1922:7d4b:7122:c7fc:8b75:98c8")
CAN_IP("70.71.245.39", "f9b2:c742:1922:7d4b:7122:c7fc:8b75:98c8"),
BGR_IP("31.211.128.0", "2002:1fd3:8000:0000:0000:0000:0000:0000")

final String v4
final String v6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class RegsExt {

@Deprecated(since = "enabling support of ortb 2.6")
Integer gdpr
Integer coppa
@Deprecated(since = "enabling support of ortb 2.6")
String usPrivacy
String gpc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import org.prebid.server.functional.model.config.AccountPrivacyConfig
import org.prebid.server.functional.model.config.PurposeConfig
import org.prebid.server.functional.model.db.Account
import org.prebid.server.functional.model.db.StoredRequest
import org.prebid.server.functional.model.pricefloors.Country
import org.prebid.server.functional.model.request.auction.BidRequest
import org.prebid.server.functional.model.request.auction.DistributionChannel
import org.prebid.server.functional.model.request.auction.Regs
import org.prebid.server.functional.model.request.auction.RegsExt
import org.prebid.server.functional.service.PrebidServerService
import org.prebid.server.functional.testcontainers.container.PrebidServerContainer
import org.prebid.server.functional.util.PBSUtils
Expand All @@ -27,6 +31,7 @@ import static org.prebid.server.functional.model.config.Purpose.P4
import static org.prebid.server.functional.model.config.PurposeEnforcement.BASIC
import static org.prebid.server.functional.model.config.PurposeEnforcement.NO
import static org.prebid.server.functional.model.mock.services.vendorlist.GvlSpecificationVersion.V3
import static org.prebid.server.functional.model.pricefloors.Country.BULGARIA
import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_ADAPTER_DISALLOWED_COUNT
import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_REQUEST_DISALLOWED_COUNT
import static org.prebid.server.functional.model.request.amp.ConsentType.BOGUS
Expand All @@ -36,6 +41,7 @@ import static org.prebid.server.functional.model.request.auction.ActivityType.FE
import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_EIDS
import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_PRECISE_GEO
import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_UFPD
import static org.prebid.server.functional.model.request.auction.PublicCountryIp.BGR_IP
import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID
import static org.prebid.server.functional.util.privacy.CcpaConsent.Signal.ENFORCED
import static org.prebid.server.functional.util.privacy.TcfConsent.GENERIC_VENDOR_ID
Expand Down Expand Up @@ -686,4 +692,162 @@ class GdprAmpSpec extends PrivacyBaseSpec {
where:
tcfPolicyVersion << [TCF_POLICY_V4, TCF_POLICY_V5]
}

def "PBS should process with GDPR enforcement when GDPR and COPPA configurations are present in request"() {
given: "Valid consent string without basic ads"
def validConsentString = new TcfConsent.Builder()
.setPurposesLITransparency(DEVICE_ACCESS)
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
.build()

and: "Amp default request"
def ampRequest = getGdprAmpRequest(validConsentString)

and: "Bid request with gdpr and coppa config"
def ampStoredRequest = getGdprBidRequest(DistributionChannel.SITE, validConsentString).tap {
regs = new Regs(gdpr: gdpr, coppa: coppa, ext: new RegsExt(gdpr: extGdpr, coppa: extCoppa))
setAccountId(ampRequest.account)
}

and: "Save account config without eea countries into DB"
def accountGdprConfig = new AccountGdprConfig(enabled: true, eeaCountries: PBSUtils.getRandomEnum(Country.class, [BULGARIA]))
def account = getAccountWithGdpr(ampRequest.account, accountGdprConfig)
accountDao.save(account)

and: "Stored request in DB"
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest)
storedRequestDao.save(storedRequest)

and: "Flush metrics"
flushMetrics(privacyPbsService)

when: "PBS processes amp request"
privacyPbsService.sendAmpRequest(ampRequest)

then: "Bidder shouldn't be called"
assert !bidder.getBidderRequests(ampStoredRequest.id)

then: "Metrics processed across activities should be updated"
def metrics = privacyPbsService.sendCollectedMetricsRequest()
assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(ampStoredRequest, FETCH_BIDS)] == 1
assert metrics[TEMPLATE_REQUEST_DISALLOWED_COUNT.getValue(ampStoredRequest, FETCH_BIDS)] == 1

where:
gdpr | coppa | extGdpr | extCoppa
1 | 1 | 1 | 1
1 | 1 | 1 | 0
1 | 1 | 1 | null
1 | 1 | 0 | 1
1 | 1 | 0 | 0
1 | 1 | 0 | null
1 | 1 | null | 1
1 | 1 | null | 0
1 | 1 | null | null
1 | 0 | 1 | 1
1 | 0 | 1 | 0
1 | 0 | 1 | null
1 | 0 | 0 | 1
1 | 0 | 0 | 0
1 | 0 | 0 | null
1 | 0 | null | 1
1 | 0 | null | 0
1 | 0 | null | null
1 | null | 1 | 1
1 | null | 1 | 0
1 | null | 1 | null
1 | null | 0 | 1
1 | null | 0 | 0
1 | null | 0 | null
1 | null | null | 1
1 | null | null | 0
1 | null | null | null

null | 1 | 1 | 1
null | 1 | 1 | 0
null | 1 | 1 | null
null | 0 | 1 | 1
null | 0 | 1 | 0
null | 0 | 1 | null
null | null | 1 | 1
null | null | 1 | 0
null | null | 1 | null
}

def "PBS should process with GDPR enforcement when request comes from EEA IP with COPPA enabled"() {
given: "Valid consent string without basic ads"
def validConsentString = new TcfConsent.Builder()
.setPurposesLITransparency(DEVICE_ACCESS)
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
.build()

and: "Amp default request"
def ampRequest = getGdprAmpRequest(validConsentString)

and: "Bid request with gdpr and coppa config"
def ampStoredRequest = getGdprBidRequest(DistributionChannel.SITE, validConsentString).tap {
regs = new Regs(gdpr: 1, coppa: 1, ext: new RegsExt(gdpr: 1, coppa: 1))
device.geo.country = requestCountry
device.geo.region = null
device.ip = requestIpV4
device.ipv6 = requestIpV6
}

and: "Save account config without eea countries into DB"
def accountGdprConfig = new AccountGdprConfig(enabled: true, eeaCountries: accountCountry)
def account = getAccountWithGdpr(ampRequest.account, accountGdprConfig)
accountDao.save(account)

and: "Stored request in DB"
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest)
storedRequestDao.save(storedRequest)

and: "Flush metrics"
flushMetrics(privacyPbsService)

when: "PBS processes amp request"
privacyPbsService.sendAmpRequest(ampRequest, header)

then: "Bidder shouldn't be called"
assert !bidder.getBidderRequests(ampStoredRequest.id)

then: "Metrics processed across activities should be updated"
def metrics = privacyPbsService.sendCollectedMetricsRequest()
assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(ampStoredRequest, FETCH_BIDS)] == 1
assert metrics[TEMPLATE_REQUEST_DISALLOWED_COUNT.getValue(ampStoredRequest, FETCH_BIDS)] == 1

where:
requestCountry | accountCountry | requestIpV4 | requestIpV6 | header
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use accountCountry and header in your test

BULGARIA | BULGARIA | BGR_IP.v4 | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | null | BGR_IP.v4 | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | BULGARIA | BGR_IP.v4 | null | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | null | BGR_IP.v4 | null | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | BULGARIA | null | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | null | null | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | BULGARIA | null | null | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | null | null | null | ["X-Forwarded-For": BGR_IP.v4]
null | BULGARIA | BGR_IP.v4 | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
null | null | BGR_IP.v4 | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
null | BULGARIA | BGR_IP.v4 | null | ["X-Forwarded-For": BGR_IP.v4]
null | null | BGR_IP.v4 | null | ["X-Forwarded-For": BGR_IP.v4]
null | BULGARIA | null | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
null | null | null | BGR_IP.v6 | ["X-Forwarded-For": BGR_IP.v4]
null | BULGARIA | null | null | ["X-Forwarded-For": BGR_IP.v4]
null | null | null | null | ["X-Forwarded-For": BGR_IP.v4]
BULGARIA | BULGARIA | BGR_IP.v4 | BGR_IP.v6 | [:]
BULGARIA | null | BGR_IP.v4 | BGR_IP.v6 | [:]
BULGARIA | BULGARIA | BGR_IP.v4 | null | [:]
BULGARIA | null | BGR_IP.v4 | null | [:]
BULGARIA | BULGARIA | null | BGR_IP.v6 | [:]
BULGARIA | null | null | BGR_IP.v6 | [:]
BULGARIA | BULGARIA | null | null | [:]
BULGARIA | null | null | null | [:]
null | BULGARIA | BGR_IP.v4 | BGR_IP.v6 | [:]
null | null | BGR_IP.v4 | BGR_IP.v6 | [:]
null | BULGARIA | BGR_IP.v4 | null | [:]
null | null | BGR_IP.v4 | null | [:]
null | BULGARIA | null | BGR_IP.v6 | [:]
null | null | null | BGR_IP.v6 | [:]
null | BULGARIA | null | null | [:]
null | null | null | null | [:]
}
}
Loading