Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into setuid-tcf-support
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoxaAntoxic committed Dec 27, 2024
2 parents 8172dd6 + 11f0eaa commit 6b54360
Show file tree
Hide file tree
Showing 21 changed files with 183 additions and 88 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/slack-stale-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Post Stale PRs To Slack

on:
# run Monday 9am and on-demand
workflow_dispatch:
schedule:
- cron: '0 9 * * 1'

jobs:
fetch-PRs:
runs-on: ubuntu-latest
steps:
- name: Fetch pull requests
id: local
uses: paritytech/stale-pr-finder@v0.3.0
with:
GITHUB_TOKEN: ${{ github.token }}
days-stale: 14
ignoredLabels: "blocked"
- name: Post to a Slack channel
id: slack
uses: slackapi/slack-github-action@v1.27.1
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "${{ steps.local.outputs.message }}"
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
14 changes: 10 additions & 4 deletions docs/build.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# Build project

To build the project, you will need at least
[Java 11](https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz)
[Java 21](https://whichjdk.com/)
and [Maven](https://maven.apache.org/) installed.

If for whatever reason this Java reference will be stale,
you can always get the current project Java version from `pom.xml` property
```xml
<java.version>...</java.version>
```

To verify the installed Java run in console:

```bash
Expand All @@ -13,9 +19,9 @@ java -version
which should show something like (yours may be different):

```
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
openjdk version "21.0.5" 2024-10-15 LTS
OpenJDK Runtime Environment Corretto-21.0.5.11.1 (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.5.11.1 (build 21.0.5+11-LTS, mixed mode, sharing)
```

Follow next steps to create JAR which can be deployed locally.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public class RubiconBidder implements Bidder<BidRequest> {
private static final String FPD_KEYWORDS_FIELD = "keywords";
private static final String DFP_ADUNIT_CODE_FIELD = "dfp_ad_unit_code";
private static final String STYPE_FIELD = "stype";
private static final String TID_FIELD = "tid";
private static final String PREBID_EXT = "prebid";
private static final String PBS_LOGIN = "pbs_login";
private static final String PBS_VERSION = "pbs_version";
Expand Down Expand Up @@ -700,6 +701,7 @@ private RubiconImpExt makeImpExt(Imp imp,
.maxbids(getMaxBids(extRequest))
.gpid(getGpid(imp.getExt()))
.skadn(getSkadn(imp.getExt()))
.tid(getTid(imp.getExt()))
.prebid(rubiconImpExtPrebid)
.build();
}
Expand Down Expand Up @@ -947,6 +949,11 @@ private ObjectNode getSkadn(ObjectNode impExt) {
return skadnNode != null && skadnNode.isObject() ? (ObjectNode) skadnNode : null;
}

private String getTid(ObjectNode impExt) {
final JsonNode tidNode = impExt.get(TID_FIELD);
return tidNode != null && tidNode.isTextual() ? tidNode.asText() : null;
}

private String getAdSlot(Imp imp) {
final ObjectNode dataNode = toObjectNode(imp.getExt().get(FPD_DATA_FIELD));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ public class RubiconImpExt {

ObjectNode skadn;

String tid;

RubiconImpExtPrebid prebid;
}
6 changes: 6 additions & 0 deletions src/main/resources/bidder-config/driftpixel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ adapters:
- native
supported-vendors:
vendor-id: 0
usersync:
cookie-family-name: driftpixel
redirect:
url: "https://sync.driftpixel.live/psync?t=s&e=0&gdpr={{gdpr}}&consent={{gdpr_consent}}&us_privacy={{us_privacy}}&cb={{redirect_url}}"
support-cors: false
uid-macro: "%USER_ID%"
2 changes: 1 addition & 1 deletion src/main/resources/bidder-config/pgamssp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ adapters:
- video
- native
supported-vendors:
vendor-id: 0
vendor-id: 1353
usersync:
cookie-family-name: pgamssp
redirect:
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/bidder-config/pubmatic.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
adapters:
pubmatic:
endpoint: https://hbopenbid.pubmatic.com/translator?source=prebid-server
ortb-version: "2.6"
meta-info:
maintainer-email: header-bidding@pubmatic.com
app-media-types:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,6 @@ class GeneralModuleSpec extends ModuleBaseSpec {
assert metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)] == 1
assert metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)] == 1

and: "RB-Richmedia-Filter module call metrics shouldn't be updated"
assert !metrics[CALL_METRIC.formatted(PB_RICHMEDIA_FILTER.code, ALL_PROCESSED_BID_RESPONSES.metricValue, PB_RICHMEDIA_FILTER_ALL_PROCESSED_RESPONSES.code)]
assert !metrics[NOOP_METRIC.formatted(PB_RICHMEDIA_FILTER.code, ALL_PROCESSED_BID_RESPONSES.metricValue, PB_RICHMEDIA_FILTER_ALL_PROCESSED_RESPONSES.code)]

cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(pbsConfig)
}
Expand All @@ -352,7 +348,7 @@ class GeneralModuleSpec extends ModuleBaseSpec {
assert !response?.ext?.prebid?.modules?.trace?.stages?.outcomes?.groups?.invocationResults?.flatten()

and: "Ortb2blocking module call metrics shouldn't be updated"
def metrics = pbsServiceWithMultipleModuleWithRequireInvoke.sendCollectedMetricsRequest()
def metrics = pbsServiceWithMultipleModules.sendCollectedMetricsRequest()
assert !metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)]
assert !metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)]
assert !metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)]
Expand All @@ -362,7 +358,7 @@ class GeneralModuleSpec extends ModuleBaseSpec {
pbsServiceFactory.removeContainer(pbsConfig)
}

def "PBS should call module without account config when default-account module-execution config enabled module"() {
def "PBS shouldn't call module and not override host config when default-account module-execution config enabled module"() {
given: "PBS service with module-execution and default account configs"
def defaultAccountConfigSettings = AccountConfig.defaultAccountConfig.tap {
hooks = new AccountHooksConfiguration(admin: new AdminConfig(moduleExecution: [(ORTB2_BLOCKING): true]))
Expand Down Expand Up @@ -391,15 +387,53 @@ class GeneralModuleSpec extends ModuleBaseSpec {
assert !response?.ext?.prebid?.modules?.trace?.stages?.outcomes?.groups?.invocationResults?.flatten()

and: "Ortb2blocking module call metrics shouldn't be updated"
def metrics = pbsServiceWithMultipleModuleWithRequireInvoke.sendCollectedMetricsRequest()
def metrics = pbsServiceWithMultipleModules.sendCollectedMetricsRequest()
assert !metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)]
assert !metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)]
assert !metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)]
assert !metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)]

and: "RB-Richmedia-Filter module call metrics shouldn't be updated"
assert !metrics[CALL_METRIC.formatted(PB_RICHMEDIA_FILTER.code, ALL_PROCESSED_BID_RESPONSES.metricValue, PB_RICHMEDIA_FILTER_ALL_PROCESSED_RESPONSES.code)]
assert !metrics[NOOP_METRIC.formatted(PB_RICHMEDIA_FILTER.code, ALL_PROCESSED_BID_RESPONSES.metricValue, PB_RICHMEDIA_FILTER_ALL_PROCESSED_RESPONSES.code)]
cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(pbsConfig)
}

def "PBS should call module without account module config when default-account module-execution config enabling module"() {
given: "PBS service with module-execution and default account configs"
def defaultAccountConfigSettings = AccountConfig.defaultAccountConfig.tap {
hooks = new AccountHooksConfiguration(admin: new AdminConfig(moduleExecution: [(ORTB2_BLOCKING): true]))
}
def pbsConfig = MULTI_MODULE_CONFIG + ENABLED_INVOKE_CONFIG + ["settings.default-account-config": encode(defaultAccountConfigSettings)]
def pbsServiceWithMultipleModules = pbsServiceFactory.getService(pbsConfig)

and: "Default bid request with verbose trace"
def bidRequest = defaultBidRequest.tap {
ext.prebid.trace = TraceLevel.VERBOSE
}

and: "Save account without modules config"
def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(modules: null))
def account = new Account(uuid: bidRequest.getAccountId(), config: accountConfig)
accountDao.save(account)

and: "Flush metrics"
flushMetrics(pbsServiceWithMultipleModules)

when: "PBS processes auction request"
def response = pbsServiceWithMultipleModules.sendAuctionRequest(bidRequest)

then: "PBS response should include trace information about called modules"
verifyAll(response?.ext?.prebid?.modules?.trace?.stages?.outcomes?.groups?.invocationResults?.flatten() as List<InvocationResult>) {
it.status == [SUCCESS, SUCCESS]
it.action == [NO_ACTION, NO_ACTION]
it.hookId.moduleCode.sort() == [ORTB2_BLOCKING, ORTB2_BLOCKING].code.sort()
}

and: "Ortb2blocking module call metrics should be updated"
def metrics = pbsServiceWithMultipleModules.sendCollectedMetricsRequest()
assert metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)] == 1
assert metrics[CALL_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)] == 1
assert metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, BIDDER_REQUEST.metricValue, ORTB2_BLOCKING_BIDDER_REQUEST.code)] == 1
assert metrics[NOOP_METRIC.formatted(ORTB2_BLOCKING.code, RAW_BIDDER_RESPONSE.metricValue, ORTB2_BLOCKING_RAW_BIDDER_RESPONSE.code)] == 1

cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(pbsConfig)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class ActivityTraceLogSpec extends PrivacyBaseSpec {
accountDao.save(account)

when: "PBS processes auction requests"
def bidResponse = pbsServiceFactory.getService(PBS_CONFIG).sendAuctionRequest(bidRequest)
def bidResponse = activityPbsService.sendAuctionRequest(bidRequest)

then: "Bid response should contain basic info in debug"
def infrastructure = bidResponse.ext.debug.trace.activityInfrastructure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ 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
import org.prebid.server.functional.util.privacy.BogusConsent
import org.prebid.server.functional.util.privacy.CcpaConsent
Expand Down Expand Up @@ -320,10 +318,8 @@ class GdprAmpSpec extends PrivacyBaseSpec {
def startTime = Instant.now()

and: "Create new container"
def serverContainer = new PrebidServerContainer(GDPR_VENDOR_LIST_CONFIG +
["adapters.generic.meta-info.vendor-id": GENERIC_VENDOR_ID as String])
serverContainer.start()
def privacyPbsService = new PrebidServerService(serverContainer)
def config = GDPR_VENDOR_LIST_CONFIG + ["adapters.generic.meta-info.vendor-id": GENERIC_VENDOR_ID as String]
def defaultPrivacyPbsService = pbsServiceFactory.getService(config)

and: "Prepare tcf consent string"
def tcfConsent = new TcfConsent.Builder()
Expand All @@ -347,21 +343,21 @@ class GdprAmpSpec extends PrivacyBaseSpec {
vendorListResponse.setResponse(tcfPolicyVersion)

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

then: "Used vendor list have proper specification version of GVL"
def properVendorListPath = VENDOR_LIST_PATH.replace("{VendorVersion}", tcfPolicyVersion.vendorListVersion.toString())
PBSUtils.waitUntil { privacyPbsService.isFileExist(properVendorListPath) }
def vendorList = privacyPbsService.getValueFromContainer(properVendorListPath, VendorListConsent.class)
PBSUtils.waitUntil { defaultPrivacyPbsService.isFileExist(properVendorListPath) }
def vendorList = defaultPrivacyPbsService.getValueFromContainer(properVendorListPath, VendorListConsent.class)
assert vendorList.tcfPolicyVersion == tcfPolicyVersion.vendorListVersion

and: "Logs should contain proper vendor list version"
def logs = privacyPbsService.getLogsByTime(startTime)
def logs = defaultPrivacyPbsService.getLogsByTime(startTime)
assert getLogsByText(logs, "Created new TCF 2 vendor list for version " +
"v${tcfPolicyVersion.vendorListVersion}.${tcfPolicyVersion.vendorListVersion}")

cleanup: "Stop container with default request"
serverContainer.stop()
cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(config)

where:
tcfPolicyVersion << [TCF_POLICY_V2, TCF_POLICY_V4, TCF_POLICY_V5]
Expand Down Expand Up @@ -410,7 +406,10 @@ class GdprAmpSpec extends PrivacyBaseSpec {
}

def "PBS amp should emit the same error without a second GVL list request if a retry is too soon for the exponential-backoff"() {
given: "Test start time"
given: "Prebid server with privacy settings"
def defaultPrivacyPbsService = pbsServiceFactory.getService(GENERAL_PRIVACY_CONFIG)

and: "Test start time"
def startTime = Instant.now()

and: "Prepare tcf consent string"
Expand Down Expand Up @@ -438,33 +437,36 @@ class GdprAmpSpec extends PrivacyBaseSpec {
vendorListResponse.setResponse(tcfPolicyVersion, Delay.seconds(EXPONENTIAL_BACKOFF_MAX_DELAY + 3))

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

then: "PBS shouldn't fetch vendor list"
def vendorListPath = VENDOR_LIST_PATH.replace("{VendorVersion}", tcfPolicyVersion.vendorListVersion.toString())
assert !privacyPbsService.isFileExist(vendorListPath)
assert !defaultPrivacyPbsService.isFileExist(vendorListPath)

and: "Logs should contain proper vendor list version"
def logs = privacyPbsService.getLogsByTime(startTime)
def logs = defaultPrivacyPbsService.getLogsByTime(startTime)
def tcfError = "TCF 2 vendor list for version v${tcfPolicyVersion.vendorListVersion}.${tcfPolicyVersion.vendorListVersion} not found, started downloading."
assert getLogsByText(logs, tcfError)

and: "Second start for fetch second round of logs"
def secondStartTime = Instant.now()

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

then: "PBS shouldn't fetch vendor list"
assert !privacyPbsService.isFileExist(vendorListPath)
assert !defaultPrivacyPbsService.isFileExist(vendorListPath)

and: "Logs should contain proper vendor list version"
def logsSecond = privacyPbsService.getLogsByTime(secondStartTime)
def logsSecond = defaultPrivacyPbsService.getLogsByTime(secondStartTime)
assert getLogsByText(logsSecond, tcfError)

and: "Reset vendor list response"
vendorListResponse.reset()

cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(GENERAL_PRIVACY_CONFIG)

where:
tcfPolicyVersion << [TCF_POLICY_V2, TCF_POLICY_V4, TCF_POLICY_V5]
}
Expand Down Expand Up @@ -659,7 +661,10 @@ class GdprAmpSpec extends PrivacyBaseSpec {
}

def "PBS amp should set 3 for tcfPolicyVersion when tcfPolicyVersion is #tcfPolicyVersion"() {
given: "Tcf consent setup"
given: "Prebid server with privacy settings"
def defaultPrivacyPbsService = pbsServiceFactory.getService(GENERAL_PRIVACY_CONFIG)

and: "Tcf consent setup"
def tcfConsent = new TcfConsent.Builder()
.setPurposesLITransparency(BASIC_ADS)
.setTcfPolicyVersion(tcfPolicyVersion.value)
Expand All @@ -681,14 +686,17 @@ class GdprAmpSpec extends PrivacyBaseSpec {
vendorListResponse.setResponse(tcfPolicyVersion)

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

then: "Used vendor list have proper specification version of GVL"
def properVendorListPath = VENDOR_LIST_PATH.replace("{VendorVersion}", tcfPolicyVersion.vendorListVersion.toString())
PBSUtils.waitUntil { privacyPbsService.isFileExist(properVendorListPath) }
def vendorList = privacyPbsService.getValueFromContainer(properVendorListPath, VendorListConsent.class)
PBSUtils.waitUntil { defaultPrivacyPbsService.isFileExist(properVendorListPath) }
def vendorList = defaultPrivacyPbsService.getValueFromContainer(properVendorListPath, VendorListConsent.class)
assert vendorList.gvlSpecificationVersion == V3

cleanup: "Stop and remove pbs container"
pbsServiceFactory.removeContainer(GENERAL_PRIVACY_CONFIG)

where:
tcfPolicyVersion << [TCF_POLICY_V4, TCF_POLICY_V5]
}
Expand Down
Loading

0 comments on commit 6b54360

Please sign in to comment.