diff --git a/docs/application-settings.md b/docs/application-settings.md index 0f2ed0076c3..5ef0b2d1958 100644 --- a/docs/application-settings.md +++ b/docs/application-settings.md @@ -25,6 +25,9 @@ There are two ways to configure application settings: database and file. This do - `analytics-config.auction-events.` - defines which channels are supported by analytics for this account - `bid-validations.banner-creative-max-size` - Overrides creative max size validation for banners. - `status` - allows to mark account as `active` or `inactive`. +- `cookie-sync.default-limit` - if the "limit" isn't specified in the `/cookie_sync` request, this is what to use +- `cookie-sync.max-limit` - if the "limit" is specified in the `/cookie_sync` request, it can't be greater than this value +- `cookie-sync.default-coop-sync` - if the "coopSync" value isn't specified in the `/cookie_sync` request, use this Here are the definitions of the "purposes" that can be defined in the GDPR setting configurations: ``` @@ -77,6 +80,10 @@ accounts: auction-events: amp: true status: active + cookie-sync: + default-limit: 5 + max-limit: 8 + default-coop-sync: true gdpr: enabled: true integration-enabled: @@ -187,7 +194,7 @@ Prebid Server returns expected data in the expected order. Here's an example con settings: database: type: mysql - account-query: SELECT uuid, price_granularity, banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, tcf_config, analytics_sampling_factor, truncate_target_attr, default_integration, analytics_config, bid_validations, status FROM accounts_account where uuid = ? LIMIT 1 + account-query: SELECT uuid, price_granularity, banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, tcf_config, analytics_sampling_factor, truncate_target_attr, default_integration, analytics_config, bid_validations, status, config FROM accounts_account where uuid = ? LIMIT 1 ``` The SQL query for account must: @@ -203,7 +210,9 @@ The SQL query for account must: * maximum targeting attribute size, integer * default integration value, string * analytics configuration, JSON string, see below + * bid validations configuration, JSON string, see below * status, string. Expected values: "active", "inactive", NULL. Only "inactive" has any effect and only when settings.enforce-valid-account is on. + * consolidated configuration, JSON string, see below * specify a special single `%ACCOUNT_ID%` placeholder in the `WHERE` clause that will be replaced with account ID in runtime @@ -215,7 +224,7 @@ If a host company doesn't support a given field, or they have a different table settings: database: type: mysql - account-query: SELECT uuid, 'med', banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, tcf_config, 0, null, default_integration, '{}', '{}' FROM myaccountstable where uuid = ? LIMIT 1 + account-query: SELECT uuid, 'med', banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, tcf_config, 0, null, default_integration, '{}', '{}', status, '{}' FROM myaccountstable where uuid = ? LIMIT 1 ``` ### Configuration Details @@ -351,7 +360,7 @@ Valid values are: #### Analytics Validations configuration JSON -The `analytics_config` configuration column format: +The `analytics_config` configuration column format: ```json { @@ -363,6 +372,21 @@ The `analytics_config` configuration column format: } ``` +#### Consolidated configuration JSON + +The `config` column is envisioned as a new home for all configuration values. All new configuration values are added here. +The schema of this JSON document has following format so far: + +```json +{ + "cookie-sync": { + "default-limit": 5, + "max-limit": 8, + "default-coop-sync": true + } +} +``` + #### Creating the accounts table Traditionally the table name used by Prebid Server is `accounts_account`. No one remembers why. But here's SQL @@ -386,6 +410,7 @@ you could use to create your table: `analytics_config` varchar(512) DEFAULT NULL, `bid_validations` json DEFAULT NULL, `status` enum('active','inactive') DEFAULT 'active', + `config` json DEFAULT NULL, `updated_by` int(11) DEFAULT NULL, `updated_by_user` varchar(64) DEFAULT NULL, `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, diff --git a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java index 6fe030ec019..81c9a25d467 100644 --- a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java +++ b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java @@ -45,6 +45,7 @@ import org.prebid.server.proto.response.UsersyncInfo; import org.prebid.server.settings.ApplicationSettings; import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountCookieSyncConfig; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.util.HttpUtil; @@ -76,7 +77,7 @@ public class CookieSyncHandler implements Handler { private final TcfDefinerService tcfDefinerService; private final PrivacyEnforcementService privacyEnforcementService; private final Integer gdprHostVendorId; - private final boolean defaultCoopSync; + private final Boolean defaultCoopSync; private final List> listOfCoopSyncBidders; private final Set setOfCoopSyncBidders; private final AnalyticsReporterDelegator analyticsDelegator; @@ -189,11 +190,12 @@ private Future accountById(String accountId, Timeout timeout) { return StringUtils.isBlank(accountId) ? Future.succeededFuture(Account.empty(accountId)) : applicationSettings.getAccountById(accountId, timeout) - .otherwise(Account.empty(accountId)); + .otherwise(Account.empty(accountId)); } private void handleCookieSyncContextResult(AsyncResult cookieSyncContextResult, RoutingContext routingContext) { + if (cookieSyncContextResult.succeeded()) { final CookieSyncContext cookieSyncContext = cookieSyncContextResult.result(); @@ -204,12 +206,11 @@ private void handleCookieSyncContextResult(AsyncResult cookie return; } - final CookieSyncRequest cookieSyncRequest = cookieSyncContext.getCookieSyncRequest(); - final Set biddersToSync = biddersToSync(cookieSyncRequest); - isAllowedForHostVendorId(tcfContext) - .setHandler(hostTcfResponseResult -> - respondByTcfResponse(hostTcfResponseResult, biddersToSync, cookieSyncContext)); + .setHandler(hostTcfResponseResult -> respondByTcfResponse( + hostTcfResponseResult, + biddersToSync(cookieSyncContext), + cookieSyncContext)); } else { final Throwable error = cookieSyncContextResult.cause(); handleErrors(error, routingContext, null); @@ -239,25 +240,42 @@ private static boolean isGdprParamsNotConsistent(CookieSyncRequest request) { *

* If bidder list was omitted in request, that means sync should be done for all bidders. */ - private Set biddersToSync(CookieSyncRequest cookieSyncRequest) { + private Set biddersToSync(CookieSyncContext cookieSyncContext) { + final CookieSyncRequest cookieSyncRequest = cookieSyncContext.getCookieSyncRequest(); + final List requestBidders = cookieSyncRequest.getBidders(); + if (CollectionUtils.isEmpty(requestBidders)) { return activeBidders; } - final Boolean requestCoopSync = cookieSyncRequest.getCoopSync(); - final boolean coop = requestCoopSync != null ? requestCoopSync : defaultCoopSync; + final Account account = cookieSyncContext.getAccount(); + + if (coopSyncAllowed(cookieSyncRequest, account)) { + final Integer requestLimit = resolveLimit(cookieSyncContext); - if (coop) { - final Integer limit = cookieSyncRequest.getLimit(); - return limit == null + return requestLimit == null ? addAllCoopSyncBidders(requestBidders) - : addCoopSyncBidders(requestBidders, limit); + : addCoopSyncBidders(requestBidders, requestLimit); } return new HashSet<>(requestBidders); } + private Boolean coopSyncAllowed(CookieSyncRequest cookieSyncRequest, Account account) { + final Boolean requestCoopSync = cookieSyncRequest.getCoopSync(); + if (requestCoopSync != null) { + return requestCoopSync; + } + + final AccountCookieSyncConfig accountCookieSyncConfig = account.getCookieSync(); + final Boolean accountCoopSync = accountCookieSyncConfig != null + ? accountCookieSyncConfig.getDefaultCoopSync() + : null; + + return ObjectUtils.firstNonNull(accountCoopSync, defaultCoopSync); + } + /** * If host vendor id is null, host allowed to sync cookies. */ @@ -265,7 +283,7 @@ private Future isAllowedForHostVendorId(TcfContext tcfCon return gdprHostVendorId == null ? Future.succeededFuture(HostVendorTcfResponse.allowedVendor()) : tcfDefinerService.resultForVendorIds(Collections.singleton(gdprHostVendorId), tcfContext) - .map(this::toHostVendorTcfResponse); + .map(this::toHostVendorTcfResponse); } private HostVendorTcfResponse toHostVendorTcfResponse(TcfResponse tcfResponse) { @@ -327,6 +345,7 @@ private String bidderNameFor(String bidder) { private void respondByTcfResponse(AsyncResult hostTcfResponseResult, Set biddersToSync, CookieSyncContext cookieSyncContext) { + final TcfContext tcfContext = cookieSyncContext.getPrivacyContext().getTcfContext(); if (hostTcfResponseResult.succeeded()) { @@ -406,6 +425,7 @@ private Set extractCcpaEnforcedBidders(Account account, Collection bidders, RejectedBidders rejectedBidders) { + updateCookieSyncTcfMetrics(bidders, rejectedBidders.getRejectedByTcf()); final RoutingContext routingContext = cookieSyncContext.getRoutingContext(); @@ -418,10 +438,10 @@ private void respondWithRejectedBidders(CookieSyncContext cookieSyncContext, updateCookieSyncMatchMetrics(bidders, bidderStatuses); - final CookieSyncRequest cookieSyncRequest = cookieSyncContext.getCookieSyncRequest(); - final Integer limit = cookieSyncRequest.getLimit(); - final List updatedBidderStatuses = trimBiddersToLimit(limit, bidderStatuses); + final List updatedBidderStatuses = + trimBiddersToLimit(bidderStatuses, resolveLimit(cookieSyncContext)); final String status = uidsCookie.hasLiveUids() ? "ok" : "no_cookie"; + final CookieSyncResponse response = CookieSyncResponse.of(status, updatedBidderStatuses); final String body = mapper.encode(response); @@ -548,14 +568,33 @@ private void updateCookieSyncMatchMetrics(Collection syncBidders, .forEach(metrics::updateCookieSyncMatchesMetric); } - private static List trimBiddersToLimit(Integer limit, - List bidderStatuses) { + private static Integer resolveLimit(CookieSyncContext cookieSyncContext) { + final Integer limit = cookieSyncContext.getCookieSyncRequest().getLimit(); + + final AccountCookieSyncConfig cookieSyncConfig = cookieSyncContext.getAccount().getCookieSync(); + if (cookieSyncConfig == null) { + return limit; + } + + final Integer resolvedLimit = ObjectUtils.defaultIfNull(limit, cookieSyncConfig.getDefaultLimit()); + if (resolvedLimit == null) { + return null; + } + + final Integer maxLimit = cookieSyncConfig.getMaxLimit(); + + return maxLimit == null ? resolvedLimit : Math.min(resolvedLimit, maxLimit); + } + + private static List trimBiddersToLimit(List bidderStatuses, + Integer limit) { + if (limit != null && limit > 0 && limit < bidderStatuses.size()) { Collections.shuffle(bidderStatuses); return bidderStatuses.subList(0, limit); - } else { - return bidderStatuses; } + + return bidderStatuses; } private void handleErrors(Throwable error, RoutingContext routingContext, TcfContext tcfContext) { diff --git a/src/main/java/org/prebid/server/settings/JdbcApplicationSettings.java b/src/main/java/org/prebid/server/settings/JdbcApplicationSettings.java index 9c1aae70b5c..f8bfe553105 100644 --- a/src/main/java/org/prebid/server/settings/JdbcApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/JdbcApplicationSettings.java @@ -112,7 +112,7 @@ public Future getAccountById(String accountId, Timeout timeout) { return jdbcClient.executeQuery( selectAccountQuery, Collections.singletonList(accountId), - result -> mapToModelOrError(result, row -> Account.builder() + result -> mapToModelOrError(result, row -> partialAccountBuilderFrom(row.getString(13)) .id(row.getString(0)) .priceGranularity(row.getString(1)) .bannerCacheTtl(row.getInteger(2)) @@ -153,6 +153,12 @@ private static Future failedIfNull(T value, String id, String errorPrefix : Future.failedFuture(new PreBidException(String.format("%s not found: %s", errorPrefix, id))); } + private Account.AccountBuilder partialAccountBuilderFrom(String config) { + final Account partialAccount = toModel(config, Account.class); + + return partialAccount != null ? partialAccount.toBuilder() : Account.builder(); + } + private T toModel(String source, Class targetClass) { try { return source != null ? mapper.decodeValue(source, targetClass) : null; diff --git a/src/main/java/org/prebid/server/settings/model/Account.java b/src/main/java/org/prebid/server/settings/model/Account.java index 479c2bc680a..3495b38b486 100644 --- a/src/main/java/org/prebid/server/settings/model/Account.java +++ b/src/main/java/org/prebid/server/settings/model/Account.java @@ -1,10 +1,11 @@ package org.prebid.server.settings.model; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Value; import org.apache.commons.lang3.ObjectUtils; -@Builder +@Builder(toBuilder = true) @Value public class Account { @@ -34,6 +35,9 @@ public class Account { AccountStatus status; + @JsonProperty("cookie-sync") + AccountCookieSyncConfig cookieSync; + public Account merge(Account another) { return Account.builder() .id(ObjectUtils.defaultIfNull(id, another.id)) @@ -50,6 +54,7 @@ public Account merge(Account another) { .analyticsConfig(ObjectUtils.defaultIfNull(analyticsConfig, another.analyticsConfig)) .bidValidations(ObjectUtils.defaultIfNull(bidValidations, another.bidValidations)) .status(ObjectUtils.defaultIfNull(status, another.status)) + .cookieSync(ObjectUtils.defaultIfNull(cookieSync, another.cookieSync)) .build(); } diff --git a/src/main/java/org/prebid/server/settings/model/AccountCookieSyncConfig.java b/src/main/java/org/prebid/server/settings/model/AccountCookieSyncConfig.java new file mode 100644 index 00000000000..574f7798772 --- /dev/null +++ b/src/main/java/org/prebid/server/settings/model/AccountCookieSyncConfig.java @@ -0,0 +1,17 @@ +package org.prebid.server.settings.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Value; + +@Value(staticConstructor = "of") +public class AccountCookieSyncConfig { + + @JsonProperty("default-limit") + Integer defaultLimit; + + @JsonProperty("max-limit") + Integer maxLimit; + + @JsonProperty("default-coop-sync") + Boolean defaultCoopSync; +} diff --git a/src/main/java/org/prebid/server/spring/config/model/AccountConfigurationProperties.java b/src/main/java/org/prebid/server/spring/config/model/AccountConfigurationProperties.java index 3eac6b136cb..220324d45b6 100644 --- a/src/main/java/org/prebid/server/spring/config/model/AccountConfigurationProperties.java +++ b/src/main/java/org/prebid/server/spring/config/model/AccountConfigurationProperties.java @@ -5,6 +5,8 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAnalyticsConfig; +import org.prebid.server.settings.model.AccountBidValidationConfig; +import org.prebid.server.settings.model.AccountCookieSyncConfig; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.settings.model.AccountStatus; @@ -32,8 +34,12 @@ public class AccountConfigurationProperties { private String analyticsConfig; + private String bidValidations; + private AccountStatus status; + private String cookieSync; + public Account toAccount(JacksonMapper mapper) { return Account.builder() .priceGranularity(getPriceGranularity()) @@ -46,7 +52,9 @@ public Account toAccount(JacksonMapper mapper) { .truncateTargetAttr(getTruncateTargetAttr()) .defaultIntegration(getDefaultIntegration()) .analyticsConfig(toModel(mapper, getAnalyticsConfig(), AccountAnalyticsConfig.class)) + .bidValidations(toModel(mapper, getBidValidations(), AccountBidValidationConfig.class)) .status(getStatus()) + .cookieSync(toModel(mapper, getCookieSync(), AccountCookieSyncConfig.class)) .build(); } diff --git a/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java b/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java index 5be749e12de..6ebc7a31c0c 100644 --- a/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/CookieSyncHandlerTest.java @@ -39,6 +39,7 @@ import org.prebid.server.proto.response.UsersyncInfo; import org.prebid.server.settings.ApplicationSettings; import org.prebid.server.settings.model.Account; +import org.prebid.server.settings.model.AccountCookieSyncConfig; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.settings.model.EnabledForRequestType; @@ -420,6 +421,47 @@ public void shouldRespondWithCoopBiddersWhenRequestCoopSyncTrue() throws IOExcep UsersyncInfo.of("http://rubiconexample.com", "redirect", false)).build()))); } + @Test + public void shouldRespondWithCoopBiddersWhenAccountCoopSyncTrue() throws IOException { + // given + given(bidderCatalog.isActive(anyString())).willReturn(true); + + final List> coopBidders = singletonList(singletonList(RUBICON)); + + cookieSyncHandler = new CookieSyncHandler("http://external-url", 2000, uidsCookieService, applicationSettings, + bidderCatalog, tcfDefinerService, privacyEnforcementService, 1, false, coopBidders, + analyticsReporterDelegator, metrics, timeoutFactory, jacksonMapper); + + given(routingContext.getBody()).willReturn(givenRequestBody( + CookieSyncRequest.builder() + .bidders(singletonList(APPNEXUS)) + .account("account") + .build())); + + given(applicationSettings.getAccountById(anyString(), any())).willReturn(Future.succeededFuture( + Account.builder() + .cookieSync(AccountCookieSyncConfig.of(null, null, true)) + .build())); + + appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://adnxsexample.com", null, null, "redirect", false); + rubiconUsersyncer = new Usersyncer(RUBICON, "http://rubiconexample.com", null, null, "redirect", false); + givenUsersyncersReturningFamilyName(); + + givenTcfServiceReturningVendorIdResult(singleton(1)); + givenTcfServiceReturningBidderNamesResult(set(RUBICON, APPNEXUS)); + + // when + cookieSyncHandler.handle(routingContext); + + // then + final CookieSyncResponse cookieSyncResponse = captureCookieSyncResponse(); + assertThat(cookieSyncResponse).isEqualTo(CookieSyncResponse.of("no_cookie", asList( + BidderUsersyncStatus.builder().bidder(APPNEXUS).noCookie(true).usersync( + UsersyncInfo.of("http://adnxsexample.com", "redirect", false)).build(), + BidderUsersyncStatus.builder().bidder(RUBICON).noCookie(true).usersync( + UsersyncInfo.of("http://rubiconexample.com", "redirect", false)).build()))); + } + @Test public void shouldRespondWithPrioritisedCoopBidderWhenRequestCoopDefaultTrueAndLimitIsLessThanCoopSize() throws IOException { @@ -1044,6 +1086,79 @@ public void shouldLimitBidderStatuses() throws IOException { given(bidderCatalog.isActive(anyString())).willReturn(true); + given(applicationSettings.getAccountById(anyString(), any())).willReturn(Future.succeededFuture( + Account.builder() + .cookieSync(AccountCookieSyncConfig.of(5, 5, null)) + .build())); + + rubiconUsersyncer = new Usersyncer(RUBICON, + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", + null, null, "redirect", false); + appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", + false); + givenUsersyncersReturningFamilyName(); + + givenTcfServiceReturningVendorIdResult(singleton(1)); + givenTcfServiceReturningBidderNamesResult(singleton(APPNEXUS)); + + // when + cookieSyncHandler.handle(routingContext); + + // then + final CookieSyncResponse cookieSyncResponse = captureCookieSyncResponse(); + assertThat(cookieSyncResponse.getBidderStatus()).hasSize(1); + } + + @Test + public void shouldLimitBidderStatusesWithAccountDefaultLimit() throws IOException { + // given + given(routingContext.getBody()).willReturn(givenRequestBody(CookieSyncRequest.builder() + .bidders(asList(RUBICON, APPNEXUS)) + .gdpr(0) + .account("account") + .build())); + + given(bidderCatalog.isActive(anyString())).willReturn(true); + + given(applicationSettings.getAccountById(anyString(), any())).willReturn(Future.succeededFuture( + Account.builder() + .cookieSync(AccountCookieSyncConfig.of(1, null, null)) + .build())); + + rubiconUsersyncer = new Usersyncer(RUBICON, + "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", + null, null, "redirect", false); + appnexusUsersyncer = new Usersyncer(APPNEXUS_COOKIE, "http://rubiconexample.com", null, null, "redirect", + false); + givenUsersyncersReturningFamilyName(); + + givenTcfServiceReturningVendorIdResult(singleton(1)); + givenTcfServiceReturningBidderNamesResult(singleton(APPNEXUS)); + + // when + cookieSyncHandler.handle(routingContext); + + // then + final CookieSyncResponse cookieSyncResponse = captureCookieSyncResponse(); + assertThat(cookieSyncResponse.getBidderStatus()).hasSize(1); + } + + @Test + public void shouldLimitBidderStatusesWithAccountMaxLimit() throws IOException { + // given + given(routingContext.getBody()).willReturn(givenRequestBody(CookieSyncRequest.builder() + .bidders(asList(RUBICON, APPNEXUS)) + .gdpr(0) + .account("account") + .build())); + + given(bidderCatalog.isActive(anyString())).willReturn(true); + + given(applicationSettings.getAccountById(anyString(), any())).willReturn(Future.succeededFuture( + Account.builder() + .cookieSync(AccountCookieSyncConfig.of(5, 1, null)) + .build())); + rubiconUsersyncer = new Usersyncer(RUBICON, "http://adnxsexample.com/sync?gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}", null, null, "redirect", false); diff --git a/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java index 785452ce407..8469d64f3f5 100644 --- a/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/FileApplicationSettingsTest.java @@ -11,6 +11,7 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; +import org.prebid.server.settings.model.AccountCookieSyncConfig; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.settings.model.AccountStatus; import org.prebid.server.settings.model.BidValidationEnforcement; @@ -111,7 +112,8 @@ public void getAccountByIdShouldReturnPresentAccount() { + "bidValidations: {" + "banner-creative-max-size: 'enforce'" + "}," - + "status: 'active'" + + "status: 'active'," + + "cookie-sync: {default-limit: 5,max-limit: 8,default-coop-sync: true}" + "}" + "]")); @@ -149,6 +151,7 @@ public void getAccountByIdShouldReturnPresentAccount() { .analyticsConfig(AccountAnalyticsConfig.of(singletonMap("amp", true))) .bidValidations(AccountBidValidationConfig.of(BidValidationEnforcement.enforce)) .status(AccountStatus.active) + .cookieSync(AccountCookieSyncConfig.of(5, 8, true)) .build()); } diff --git a/src/test/java/org/prebid/server/settings/JdbcApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/JdbcApplicationSettingsTest.java index 440bdea0545..3011dd57dfd 100644 --- a/src/test/java/org/prebid/server/settings/JdbcApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/JdbcApplicationSettingsTest.java @@ -25,6 +25,7 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAnalyticsConfig; import org.prebid.server.settings.model.AccountBidValidationConfig; +import org.prebid.server.settings.model.AccountCookieSyncConfig; import org.prebid.server.settings.model.AccountGdprConfig; import org.prebid.server.settings.model.AccountStatus; import org.prebid.server.settings.model.BidValidationEnforcement; @@ -64,7 +65,7 @@ public class JdbcApplicationSettingsTest extends VertxTest { private static final String SELECT_ACCOUNT_QUERY = "SELECT uuid, price_granularity, banner_cache_ttl, video_cache_ttl, " + "events_enabled, enforce_ccpa, tcf_config, analytics_sampling_factor, truncate_target_attr, " - + "default_integration, analytics_config, bid_validations, status " + + "default_integration, analytics_config, bid_validations, status, config " + "FROM accounts_account where uuid = %ACCOUNT_ID% LIMIT 1"; private static final String SELECT_QUERY = @@ -116,7 +117,7 @@ public static void beforeClass() throws SQLException { + "banner_cache_ttl INT, video_cache_ttl INT, events_enabled BIT, enforce_ccpa BIT, " + "tcf_config varchar(512), analytics_sampling_factor INT, truncate_target_attr INT, " + "default_integration varchar(64), analytics_config varchar(512), bid_validations varchar(512), " - + "status varchar(25));"); + + "status varchar(25), config varchar(4096));"); connection.createStatement().execute("CREATE TABLE stored_requests (id SERIAL PRIMARY KEY, " + "accountId varchar(40) NOT NULL, reqid varchar(40) NOT NULL, requestData varchar(512));"); connection.createStatement().execute("CREATE TABLE stored_requests2 (id SERIAL PRIMARY KEY, " @@ -133,11 +134,12 @@ public static void beforeClass() throws SQLException { connection.createStatement().execute("insert into accounts_account " + "(uuid, price_granularity, banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, " + "tcf_config, analytics_sampling_factor, truncate_target_attr, default_integration, analytics_config, " - + "bid_validations, status) " + + "bid_validations, status, config) " + "values ('1001','med', 100, 100, TRUE, TRUE, '{\"enabled\": true, " + "\"integration-enabled\": {\"amp\": true, \"app\": true, \"video\": true, \"web\": true}}', 1, 0, " + "'web', '{\"auction-events\": {\"amp\": true}}', '{\"banner-creative-max-size\": \"enforce\"}', " - + "'active');"); + + "'active', " + + "'{\"cookie-sync\": {\"default-limit\": 5, \"max-limit\": 8, \"default-coop-sync\": true}}');"); connection.createStatement().execute( "insert into stored_requests (accountId, reqid, requestData) values ('1001', '1','value1');"); connection.createStatement().execute( @@ -209,6 +211,7 @@ public void getAccountByIdShouldReturnAccountWithAllFieldsPopulated(TestContext .analyticsConfig(AccountAnalyticsConfig.of(singletonMap("amp", true))) .bidValidations(AccountBidValidationConfig.of(BidValidationEnforcement.enforce)) .status(AccountStatus.active) + .cookieSync(AccountCookieSyncConfig.of(5, 8, true)) .build()); async.complete(); }));