Skip to content

Commit b43c76f

Browse files
authored
Test: setuid tcf support (#3658)
* Add functional tests for setuid tcf support
1 parent 6b54360 commit b43c76f

File tree

2 files changed

+243
-2
lines changed

2 files changed

+243
-2
lines changed

src/test/groovy/org/prebid/server/functional/tests/SetUidSpec.groovy

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class SetUidSpec extends BaseSpec {
3737
"adapters.${APPNEXUS.value}.usersync.cookie-family-name" : APPNEXUS.value,
3838
"adapters.${GENERIC.value}.usersync.${USER_SYNC_TYPE.value}.url" : USER_SYNC_URL,
3939
"adapters.${GENERIC.value}.usersync.${USER_SYNC_TYPE.value}.support-cors": CORS_SUPPORT.toString()]
40+
private static final String TCF_ERROR_MESSAGE = "The gdpr_consent param prevents cookies from being saved"
41+
private static final int UNAVAILABLE_FOR_LEGAL_REASONS_CODE = 451
4042

4143
@Shared
4244
PrebidServerService prebidServerService = pbsServiceFactory.getService(PBS_CONFIG)
@@ -199,8 +201,8 @@ class SetUidSpec extends BaseSpec {
199201

200202
then: "Request should fail with error"
201203
def exception = thrown(PrebidServerException)
202-
assert exception.statusCode == 451
203-
assert exception.responseBody == "The gdpr_consent param prevents cookies from being saved"
204+
assert exception.statusCode == UNAVAILABLE_FOR_LEGAL_REASONS_CODE
205+
assert exception.responseBody == TCF_ERROR_MESSAGE
204206

205207
and: "usersync.FAMILY.tcf.blocked metric should be updated"
206208
def metric = prebidServerService.sendCollectedMetricsRequest()
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
package org.prebid.server.functional.tests.privacy
2+
3+
import org.prebid.server.functional.model.UidsCookie
4+
import org.prebid.server.functional.model.config.AccountAuctionConfig
5+
import org.prebid.server.functional.model.config.AccountConfig
6+
import org.prebid.server.functional.model.config.AccountGdprConfig
7+
import org.prebid.server.functional.model.config.AccountPrivacyConfig
8+
import org.prebid.server.functional.model.config.PurposeConfig
9+
import org.prebid.server.functional.model.db.Account
10+
import org.prebid.server.functional.model.request.setuid.SetuidRequest
11+
import org.prebid.server.functional.model.response.cookiesync.UserSyncInfo
12+
import org.prebid.server.functional.service.PrebidServerException
13+
import org.prebid.server.functional.service.PrebidServerService
14+
import org.prebid.server.functional.util.PBSUtils
15+
import org.prebid.server.functional.util.privacy.TcfConsent
16+
import org.prebid.server.util.ResourceUtil
17+
18+
import static org.prebid.server.functional.model.AccountStatus.ACTIVE
19+
import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
20+
import static org.prebid.server.functional.model.config.Purpose.P1
21+
import static org.prebid.server.functional.model.config.PurposeEnforcement.FULL
22+
import static org.prebid.server.functional.model.config.PurposeEnforcement.NO
23+
import static org.prebid.server.functional.model.request.setuid.UidWithExpiry.getDefaultUidWithExpiry
24+
import static org.prebid.server.functional.model.response.cookiesync.UserSyncInfo.Type.REDIRECT
25+
import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer
26+
import static org.prebid.server.functional.util.privacy.TcfConsent.GENERIC_VENDOR_ID
27+
import static org.prebid.server.functional.util.privacy.TcfConsent.PurposeId.DEVICE_ACCESS
28+
29+
class GdprSetUidSpec extends PrivacyBaseSpec {
30+
31+
private static final boolean CORS_SUPPORT = false
32+
private static final String USER_SYNC_URL = "$networkServiceContainer.rootUri/generic-usersync"
33+
private static final UserSyncInfo.Type USER_SYNC_TYPE = REDIRECT
34+
private static final Map<String, String> VENDOR_GENERIC_PBS_CONFIG = GENERIC_VENDOR_CONFIG +
35+
["gdpr.purposes.p1.enforce-purpose" : NO.value,
36+
"adapters.${GENERIC.value}.usersync.${USER_SYNC_TYPE.value}.url" : USER_SYNC_URL,
37+
"adapters.${GENERIC.value}.usersync.${USER_SYNC_TYPE.value}.support-cors": CORS_SUPPORT.toString()]
38+
private static final String TCF_ERROR_MESSAGE = "The gdpr_consent param prevents cookies from being saved"
39+
private static final int UNAVAILABLE_FOR_LEGAL_REASONS_CODE = 451
40+
41+
private static final PrebidServerService prebidServerService = pbsServiceFactory.getService(VENDOR_GENERIC_PBS_CONFIG)
42+
43+
def "PBS setuid shouldn't failed with tcf when purpose access device not enforced"() {
44+
given: "Default setuid request with account"
45+
def setuidRequest = SetuidRequest.defaultSetuidRequest.tap {
46+
it.account = PBSUtils.randomNumber.toString()
47+
it.uid = UUID.randomUUID().toString()
48+
it.bidder = GENERIC
49+
it.gdpr = "1"
50+
it.gdprConsent = new TcfConsent.Builder()
51+
.setPurposesLITransparency(DEVICE_ACCESS)
52+
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
53+
.build()
54+
}
55+
56+
and: "Default uids cookie with rubicon bidder"
57+
def uidsCookie = UidsCookie.defaultUidsCookie.tap {
58+
it.tempUIDs = [(GENERIC): defaultUidWithExpiry]
59+
}
60+
61+
and: "Save account config with purpose into DB"
62+
def accountConfig = new AccountConfig(
63+
auction: new AccountAuctionConfig(debugAllow: true),
64+
privacy: new AccountPrivacyConfig(gdpr: new AccountGdprConfig(purposes: [(P1): new PurposeConfig(enforcePurpose: NO)], enabled: true)))
65+
def account = new Account(status: ACTIVE, uuid: setuidRequest.account, config: accountConfig)
66+
accountDao.save(account)
67+
68+
when: "PBS processes setuid request"
69+
def response = prebidServerService.sendSetUidRequest(setuidRequest, uidsCookie)
70+
71+
then: "Response should contain tempUids cookie and headers"
72+
assert response.headers.size() == 7
73+
assert response.uidsCookie.tempUIDs[GENERIC].uid == setuidRequest.uid
74+
assert response.responseBody ==
75+
ResourceUtil.readByteArrayFromClassPath("org/prebid/server/functional/tracking-pixel.png")
76+
}
77+
78+
def "PBS setuid should failed with tcf when purpose access device enforced for account"() {
79+
given: "Default setuid request with account"
80+
def setuidRequest = SetuidRequest.defaultSetuidRequest.tap {
81+
it.account = PBSUtils.randomNumber.toString()
82+
it.uid = UUID.randomUUID().toString()
83+
it.bidder = GENERIC
84+
it.gdpr = "1"
85+
it.gdprConsent = new TcfConsent.Builder()
86+
.setPurposesLITransparency(DEVICE_ACCESS)
87+
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
88+
.build()
89+
}
90+
91+
and: "Default uids cookie with rubicon bidder"
92+
def uidsCookie = UidsCookie.defaultUidsCookie.tap {
93+
it.tempUIDs = [(GENERIC): defaultUidWithExpiry]
94+
}
95+
96+
and: "Save account config with purpose into DB"
97+
def accountConfig = new AccountConfig(
98+
auction: new AccountAuctionConfig(debugAllow: true),
99+
privacy: new AccountPrivacyConfig(gdpr: new AccountGdprConfig(purposes: [(P1): new PurposeConfig(enforcePurpose: FULL)], enabled: true)))
100+
def account = new Account(status: ACTIVE, uuid: setuidRequest.account, config: accountConfig)
101+
accountDao.save(account)
102+
103+
when: "PBS processes setuid request"
104+
prebidServerService.sendSetUidRequest(setuidRequest, uidsCookie)
105+
106+
then: "Request should fail with error"
107+
def exception = thrown(PrebidServerException)
108+
assert exception.statusCode == UNAVAILABLE_FOR_LEGAL_REASONS_CODE
109+
assert exception.responseBody == TCF_ERROR_MESSAGE
110+
111+
and: "Metric should be increased usersync.FAMILY.tcf.blocked"
112+
def metric = prebidServerService.sendCollectedMetricsRequest()
113+
assert metric["usersync.${GENERIC.value}.tcf.blocked"] == 1
114+
}
115+
116+
def "PBS setuid should failed with tcf when purpose access device enforced for host"() {
117+
given: "PBS config"
118+
def pbsConfig = VENDOR_GENERIC_PBS_CONFIG + ["gdpr.purposes.p1.enforce-purpose": FULL.value]
119+
def prebidServerService = pbsServiceFactory.getService(pbsConfig)
120+
121+
and: "Default setuid request with account"
122+
def setuidRequest = SetuidRequest.defaultSetuidRequest.tap {
123+
it.account = PBSUtils.randomNumber.toString()
124+
it.uid = UUID.randomUUID().toString()
125+
it.bidder = GENERIC
126+
it.gdpr = "1"
127+
it.gdprConsent = new TcfConsent.Builder()
128+
.setPurposesLITransparency(DEVICE_ACCESS)
129+
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
130+
.build()
131+
}
132+
133+
and: "Default uids cookie with rubicon bidder"
134+
def uidsCookie = UidsCookie.defaultUidsCookie.tap {
135+
it.tempUIDs = [(GENERIC): defaultUidWithExpiry]
136+
}
137+
138+
and: "Save account config with purpose into DB"
139+
def accountConfig = new AccountConfig(
140+
auction: new AccountAuctionConfig(debugAllow: true),
141+
privacy: new AccountPrivacyConfig(gdpr: new AccountGdprConfig(purposes: [(P1): new PurposeConfig(enforcePurpose: NO)], enabled: true)))
142+
def account = new Account(status: ACTIVE, uuid: setuidRequest.account, config: accountConfig)
143+
accountDao.save(account)
144+
145+
when: "PBS processes setuid request"
146+
prebidServerService.sendSetUidRequest(setuidRequest, uidsCookie)
147+
148+
then: "Request should fail with error"
149+
def exception = thrown(PrebidServerException)
150+
assert exception.statusCode == UNAVAILABLE_FOR_LEGAL_REASONS_CODE
151+
assert exception.responseBody == TCF_ERROR_MESSAGE
152+
153+
and: "Metric should be increased usersync.FAMILY.tcf.blocked"
154+
def metric = prebidServerService.sendCollectedMetricsRequest()
155+
assert metric["usersync.${GENERIC.value}.tcf.blocked"] == 1
156+
157+
cleanup: "Stop and remove pbs container"
158+
pbsServiceFactory.removeContainer(pbsConfig)
159+
}
160+
161+
def "PBS setuid shouldn't failed with tcf when purpose access device not enforced for host and host-vendor-id empty"() {
162+
given: "PBS config"
163+
def pbsConfig = VENDOR_GENERIC_PBS_CONFIG + ["gdpr.purposes.p1.enforce-purpose": NO.value,
164+
"gdpr.host-vendor-id" : ""]
165+
def prebidServerService = pbsServiceFactory.getService(pbsConfig)
166+
167+
and: "Default setuid request with account"
168+
def setuidRequest = SetuidRequest.defaultSetuidRequest.tap {
169+
it.account = PBSUtils.randomNumber.toString()
170+
it.uid = UUID.randomUUID().toString()
171+
it.bidder = GENERIC
172+
it.gdpr = "1"
173+
it.gdprConsent = new TcfConsent.Builder()
174+
.setPurposesLITransparency(DEVICE_ACCESS)
175+
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
176+
.build()
177+
}
178+
179+
and: "Default uids cookie with rubicon bidder"
180+
def uidsCookie = UidsCookie.defaultUidsCookie.tap {
181+
it.tempUIDs = [(GENERIC): defaultUidWithExpiry]
182+
}
183+
184+
and: "Save account config with purpose into DB"
185+
def accountConfig = new AccountConfig(
186+
auction: new AccountAuctionConfig(debugAllow: true),
187+
privacy: new AccountPrivacyConfig(gdpr: new AccountGdprConfig(purposes: [(P1): new PurposeConfig(enforcePurpose: NO)], enabled: true)))
188+
def account = new Account(status: ACTIVE, uuid: setuidRequest.account, config: accountConfig)
189+
accountDao.save(account)
190+
191+
when: "PBS processes setuid request"
192+
def response = prebidServerService.sendSetUidRequest(setuidRequest, uidsCookie)
193+
194+
then: "Response should contain tempUids cookie and headers"
195+
assert response.headers.size() == 7
196+
assert response.uidsCookie.tempUIDs[GENERIC].uid == setuidRequest.uid
197+
assert response.responseBody ==
198+
ResourceUtil.readByteArrayFromClassPath("org/prebid/server/functional/tracking-pixel.png")
199+
200+
cleanup: "Stop and remove pbs container"
201+
pbsServiceFactory.removeContainer(pbsConfig)
202+
}
203+
204+
def "PBS setuid shouldn't failed with purpose access device enforced for account when bidder included in vendorExceptions"() {
205+
given: "Default setuid request with account"
206+
def setuidRequest = SetuidRequest.defaultSetuidRequest.tap {
207+
it.account = PBSUtils.randomNumber.toString()
208+
it.uid = UUID.randomUUID().toString()
209+
it.bidder = GENERIC
210+
it.gdpr = "1"
211+
it.gdprConsent = new TcfConsent.Builder()
212+
.setPurposesLITransparency(DEVICE_ACCESS)
213+
.setVendorLegitimateInterest([GENERIC_VENDOR_ID])
214+
.build()
215+
}
216+
217+
and: "Default uids cookie with rubicon bidder"
218+
def uidsCookie = UidsCookie.defaultUidsCookie.tap {
219+
it.tempUIDs = [(GENERIC): defaultUidWithExpiry]
220+
}
221+
222+
and: "Save account config with purpose into DB"
223+
def purposeConfig = new PurposeConfig(enforcePurpose: FULL, vendorExceptions: [GENERIC.value])
224+
def accountConfig = new AccountConfig(
225+
auction: new AccountAuctionConfig(debugAllow: true),
226+
privacy: new AccountPrivacyConfig(gdpr: new AccountGdprConfig(purposes: [(P1): purposeConfig], enabled: true)))
227+
def account = new Account(status: ACTIVE, uuid: setuidRequest.account, config: accountConfig)
228+
accountDao.save(account)
229+
230+
when: "PBS processes setuid request"
231+
def response = prebidServerService.sendSetUidRequest(setuidRequest, uidsCookie)
232+
233+
then: "Response should contain tempUids cookie and headers"
234+
assert response.headers.size() == 7
235+
assert response.uidsCookie.tempUIDs[GENERIC].uid == setuidRequest.uid
236+
assert response.responseBody ==
237+
ResourceUtil.readByteArrayFromClassPath("org/prebid/server/functional/tracking-pixel.png")
238+
}
239+
}

0 commit comments

Comments
 (0)