diff --git a/src/main/java/org/prebid/server/auction/gpp/model/GppModelWrapper.java b/src/main/java/org/prebid/server/auction/gpp/model/GppModelWrapper.java index 1bde141d72f..e8f7d4e008b 100644 --- a/src/main/java/org/prebid/server/auction/gpp/model/GppModelWrapper.java +++ b/src/main/java/org/prebid/server/auction/gpp/model/GppModelWrapper.java @@ -17,33 +17,7 @@ public class GppModelWrapper extends GppModel { private IntObjectMap sectionIdToEncodedString; public GppModelWrapper(String encodedString) throws DecodingException { - super(padSections(encodedString)); - } - - private static String padSections(String gpp) { - final StringBuilder gppBuilder = new StringBuilder(gpp); - - int subsectionStart = 0; - int offset = 0; - for (int i = 1; i < gpp.length(); i++) { - final char currentChar = gpp.charAt(i); - - if (currentChar == '~' || currentChar == '.') { - if ((i - subsectionStart) % 4 != 0 && gpp.charAt(i - 1) != '=') { - gppBuilder.insert(i + offset, "A"); - offset++; - } - - subsectionStart = i + 1; - } - } - - final int lastSubsectionLength = gpp.length() - subsectionStart; - if (lastSubsectionLength > 0 && lastSubsectionLength % 4 != 0 && !gpp.endsWith("=")) { - gppBuilder.append("A"); - } - - return gppBuilder.toString(); + super(encodedString); } private void init() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSyncUserActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSyncUserActivitiesSpec.groovy index 657e0fef1e5..a6d9d6e7aad 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSyncUserActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSyncUserActivitiesSpec.groovy @@ -483,39 +483,6 @@ class GppSyncUserActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS cookie sync call when privacy module contain invalid GPP string should exclude bidders URLs"() { - given: "Cookie sync request with link to account" - def accountId = PBSUtils.randomString - def cookieSyncRequest = CookieSyncRequest.defaultCookieSyncRequest.tap { - it.gppSid = US_NAT_V1.value - it.account = accountId - it.gpp = INVALID_GPP_STRING - } - - and: "Activities set for cookie sync with allowing privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(SYNC_USER, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with cookie sync and privacy regulation setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - when: "PBS processes cookie sync request" - def response = activityPbsService.sendCookieSyncRequest(cookieSyncRequest) - - then: "Response should not contain any URLs for bidders" - assert !response.bidderStatus.userSync.url - - and: "Response should not contain any warning" - assert !response.warnings - } - def "PBS cookie sync call when request have different gpp consent but match and rejecting should exclude bidders URLs"() { given: "Cookie sync request with link to account" def accountId = PBSUtils.randomString @@ -1359,41 +1326,6 @@ class GppSyncUserActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS setuid request when privacy module contain invalid GPP string should reject bidders with status code invalidStatusCode"() { - given: "Cookie sync SetuidRequest with accountId" - def accountId = PBSUtils.randomString - def setuidRequest = SetuidRequest.defaultSetuidRequest.tap { - it.account = accountId - it.gppSid = US_NAT_V1.value - it.gpp = INVALID_GPP_STRING - } - - and: "UIDS Cookie" - def uidsCookie = UidsCookie.defaultUidsCookie - - and: "Activities set for cookie sync with allowing privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(SYNC_USER, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with cookie sync and allow activities setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - when: "PBS processes cookie sync request" - activityPbsService.sendSetUidRequest(setuidRequest, uidsCookie) - - then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == INVALID_STATUS_CODE - assert exception.responseBody == INVALID_STATUS_MESSAGE - } - def "PBS setuid request when request have different gpp consent but match and rejecting should reject bidders with status code invalidStatusCode"() { given: "Cookie sync SetuidRequest with accountId" def accountId = PBSUtils.randomString diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy index edd720700ca..73dfda85a23 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy @@ -77,7 +77,6 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE -import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -843,45 +842,6 @@ class GppTransmitEidsActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS auction call when privacy module contain invalid GPP string should remove EIDS fields in request"() { - given: "Default Generic BidRequests with EIDS fields and account id" - def accountId = PBSUtils.randomNumber as String - def bidRequest = getBidRequestWithPersonalData(accountId).tap { - regs.gppSid = [US_NAT_V1.intValue] - regs.gpp = INVALID_GPP_STRING - } - - and: "Activities set for transmitEIDS with rejecting privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_EIDS, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with privacy regulation setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - when: "PBS processes auction requests" - def response = activityPbsService.sendAuctionRequest(bidRequest) - - then: "Generic bidder request should have empty EIDS fields" - def genericBidderRequest = bidder.getBidderRequest(bidRequest.id) - verifyAll { - !genericBidderRequest.user.eids - !genericBidderRequest.user?.ext?.eids - } - - and: "Response should not contain any warnings" - assert !response.ext.warnings - - and: "Response should not contain any errors" - assert !response.ext.errors - } - def "PBS auction call when request have different gpp consent but match and rejecting should remove EIDS fields in request"() { given: "Default Generic BidRequests with EIDS fields and account id" def accountId = PBSUtils.randomNumber as String @@ -1870,55 +1830,6 @@ class GppTransmitEidsActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS amp call when privacy module contain invalid GPP string should remove EIDS fields in request"() { - given: "Default Generic BidRequest with EIDS fields field and account id" - def accountId = PBSUtils.randomNumber as String - def ampStoredRequest = getBidRequestWithPersonalData(accountId) - - and: "amp request with link to account" - def ampRequest = AmpRequest.defaultAmpRequest.tap { - it.account = accountId - it.gppSid = US_NAT_V1.value - it.consentString = INVALID_GPP_STRING - it.consentType = GPP - } - - and: "Activities set for transmitEIDS with allowing privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_EIDS, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with privacy regulation setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - and: "Stored request in DB" - def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) - storedRequestDao.save(storedRequest) - - when: "PBS processes amp request" - def response = activityPbsService.sendAmpRequest(ampRequest) - - then: "Generic bidder request should have empty EIDS fields" - def genericBidderRequest = bidder.getBidderRequest(ampStoredRequest.id) - verifyAll { - !genericBidderRequest.user.eids - !genericBidderRequest.user?.ext?.eids - } - - and: "Response should not contain any warnings" - assert !response.ext.warnings - - and: "Response should contain amp error" - assert response.ext?.errors[PREBID]*.code == [999] - assert response.ext?.errors[PREBID]*.message == ["Amp request parameter consent_string has invalid format: $INVALID_GPP_STRING"] - } - def "PBS amp call when request have different gpp consent but match and rejecting should remove EIDS fields in request"() { given: "Default Generic BidRequest with EIDS fields field and account id" def accountId = PBSUtils.randomNumber as String diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy index 0eaafecc6f0..920196ea576 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy @@ -15,10 +15,16 @@ import org.prebid.server.functional.model.request.amp.AmpRequest import org.prebid.server.functional.model.request.auction.Activity import org.prebid.server.functional.model.request.auction.ActivityRule import org.prebid.server.functional.model.request.auction.AllowActivities +import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Condition +import org.prebid.server.functional.model.request.auction.Data import org.prebid.server.functional.model.request.auction.Device +import org.prebid.server.functional.model.request.auction.Eid import org.prebid.server.functional.model.request.auction.Geo import org.prebid.server.functional.model.request.auction.RegsExt +import org.prebid.server.functional.model.request.auction.User +import org.prebid.server.functional.model.request.auction.UserExt +import org.prebid.server.functional.model.request.auction.UserExtData import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.gpp.UsCaV1Consent @@ -81,7 +87,6 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE -import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -1109,59 +1114,6 @@ class GppTransmitUfpdActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS auction call when privacy module contain invalid GPP string should remove UFPD fields in request"() { - given: "Default Generic BidRequests with UFPD fields and account id" - def accountId = PBSUtils.randomNumber as String - def bidRequest = getBidRequestWithPersonalData(accountId).tap { - regs.gppSid = [US_NAT_V1.intValue] - regs.gpp = INVALID_GPP_STRING - } - - and: "Activities set for transmitUfpd with rejecting privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_UFPD, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with privacy regulation setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - when: "PBS processes auction requests" - def response= activityPbsService.sendAuctionRequest(bidRequest) - - then: "Generic bidder request should have empty UFPD fields" - def bidderRequest = bidder.getBidderRequest(bidRequest.id) - verifyAll { - !bidderRequest.device.didsha1 - !bidderRequest.device.didmd5 - !bidderRequest.device.dpidsha1 - !bidderRequest.device.ifa - !bidderRequest.device.macsha1 - !bidderRequest.device.macmd5 - !bidderRequest.device.dpidmd5 - !bidderRequest.user.id - !bidderRequest.user.buyeruid - !bidderRequest.user.yob - !bidderRequest.user.gender - !bidderRequest.user.data - !bidderRequest.user.ext - } - - and: "Generic bidder request should have data in EIDS fields" - assert bidderRequest.user.eids == bidRequest.user.eids - - and: "Response should not contain any warnings" - assert !response.ext.warnings - - and: "Response should not contain any errors" - assert !response.ext.errors - } - def "PBS auction call when request have different gpp consent but match and rejecting should remove UFPD fields in request"() { given: "Default Generic BidRequests with UFPD fields and account id" def accountId = PBSUtils.randomNumber as String @@ -2435,69 +2387,6 @@ class GppTransmitUfpdActivitiesSpec extends PrivacyBaseSpec { ] } - def "PBS amp call when privacy module contain invalid GPP string should remove UFPD fields in request"() { - given: "Default Generic BidRequest with UFPD fields field and account id" - def accountId = PBSUtils.randomNumber as String - def ampStoredRequest = getBidRequestWithPersonalData(accountId) - - and: "amp request with link to account" - def ampRequest = AmpRequest.defaultAmpRequest.tap { - it.account = accountId - it.gppSid = US_NAT_V1.value - it.consentString = INVALID_GPP_STRING - it.consentType = GPP - } - - and: "Activities set for transmitUfpd with allowing privacy regulation" - def rule = new ActivityRule().tap { - it.privacyRegulation = [IAB_US_GENERAL] - } - - def activities = AllowActivities.getDefaultAllowActivities(TRANSMIT_UFPD, Activity.getDefaultActivity([rule])) - - and: "Account gpp configuration" - def accountGppConfig = new AccountGppConfig(code: IAB_US_GENERAL, enabled: true) - - and: "Existed account with privacy regulation setup" - def account = getAccountWithAllowActivitiesAndPrivacyModule(accountId, activities, [accountGppConfig]) - accountDao.save(account) - - and: "Stored request in DB" - def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) - storedRequestDao.save(storedRequest) - - when: "PBS processes amp request" - def response = activityPbsService.sendAmpRequest(ampRequest) - - then: "Generic bidder request should have empty UFPD fields" - def bidderRequest = bidder.getBidderRequest(ampStoredRequest.id) - verifyAll { - !bidderRequest.device.didsha1 - !bidderRequest.device.didmd5 - !bidderRequest.device.dpidsha1 - !bidderRequest.device.ifa - !bidderRequest.device.macsha1 - !bidderRequest.device.macmd5 - !bidderRequest.device.dpidmd5 - !bidderRequest.user.id - !bidderRequest.user.buyeruid - !bidderRequest.user.yob - !bidderRequest.user.gender - !bidderRequest.user.data - !bidderRequest.user.ext - } - - and: "Generic bidder request should have data in EIDS fields" - assert bidderRequest.user.eids == ampStoredRequest.user.eids - - and: "Response should not contain any warnings" - assert !response.ext.warnings - - and: "Response should contain amp error" - assert response.ext?.errors[PREBID]*.code == [999] - assert response.ext?.errors[PREBID]*.message == ["Amp request parameter consent_string has invalid format: $INVALID_GPP_STRING"] - } - def "PBS amp call when request have different gpp consent but match and rejecting should remove UFPD fields in request"() { given: "Default Generic BidRequest with UFPD fields field and account id" def accountId = PBSUtils.randomNumber as String diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy index aff17c4d49b..ed633ec5316 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy @@ -95,7 +95,6 @@ abstract class PrivacyBaseSpec extends BaseSpec { private static final Map GDPR_EEA_COUNTRY = ["gdpr.eea-countries": "$BULGARIA.ISOAlpha2, SK, VK" as String] protected static final String VENDOR_LIST_PATH = "/app/prebid-server/data/vendorlist-v{VendorVersion}/{VendorVersion}.json" - protected static final String INVALID_GPP_STRING = "DBABLA~BVQqAAAAAg.YA" // TODO replace BVQqAAAAAg with ${PBSUtils.getRandomString(7)} when proper fix is ready protected static final String VALID_VALUE_FOR_GPC_HEADER = "1" protected static final GppConsent SIMPLE_GPC_DISALLOW_LOGIC = new UsNatV1Consent.Builder().setGpc(true).build() protected static final VendorList vendorListResponse = new VendorList(networkServiceContainer) diff --git a/src/test/java/org/prebid/server/auction/gpp/model/GppContextCreatorTest.java b/src/test/java/org/prebid/server/auction/gpp/model/GppContextCreatorTest.java index 2d977ac65e7..dd5efdbe4c2 100644 --- a/src/test/java/org/prebid/server/auction/gpp/model/GppContextCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/gpp/model/GppContextCreatorTest.java @@ -37,7 +37,7 @@ public void fromShouldReturnGppContextWrapperWithErrorOnInvalidGpp() { assertThat(gppContext.regions()).isEqualTo(GppContext.Regions.builder().build()); }); assertThat(gppContextWrapper.getErrors()) - .containsExactly("GPP string invalid: Unable to decode 'invalidA'"); + .containsExactly("GPP string invalid: Unable to decode 'invalid'"); } @Test diff --git a/src/test/java/org/prebid/server/auction/gpp/model/GppModelWrapperTest.java b/src/test/java/org/prebid/server/auction/gpp/model/GppModelWrapperTest.java index 4f921fae0c3..587721151d5 100644 --- a/src/test/java/org/prebid/server/auction/gpp/model/GppModelWrapperTest.java +++ b/src/test/java/org/prebid/server/auction/gpp/model/GppModelWrapperTest.java @@ -5,16 +5,12 @@ import com.iab.gpp.encoder.error.EncodingException; import com.iab.gpp.encoder.section.HeaderV1; import com.iab.gpp.encoder.section.TcfEuV2; -import com.iab.gpp.encoder.section.UsNat; import com.iab.gpp.encoder.section.UspV1; import org.junit.jupiter.api.Test; import java.util.Comparator; -import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.assertThatNoException; public class GppModelWrapperTest { @@ -39,7 +35,7 @@ public class GppModelWrapperTest { + "1YN-"; @Test - public void wrapperShouldStoreSomeOfOriginalSections() throws DecodingException, EncodingException { + public void test() throws DecodingException, EncodingException { // given and when final GppModel originalGpp = new GppModel(GPP_STRING); final GppModel wrappedGpp = new GppModelWrapper(GPP_STRING); @@ -52,73 +48,6 @@ public void wrapperShouldStoreSomeOfOriginalSections() throws DecodingException, assertThat(wrappedGpp.encodeSection(UspV1.ID)).isEqualTo(originalGpp.encodeSection(UspV1.ID)); } - @Test - public void wrapperShouldPadSectionsIfNeeded() { - // given - final List samples = List.of( - "DBABLA~BVQqAAAAAg", - "DBABLA~BVVqCAAACg", - "DBABLA~BVVVBAAABg", - "DBABLA~BVVqCACACg", - "DBABLA~BVQVAAAAAg", - "DBABLA~BVVVBABABg"); - - for (String sample : samples) { - // when - final GppModel originalGpp = new GppModel(sample); - final GppModel wrappedGpp = new GppModelWrapper(sample); - - // then - assertThatExceptionOfType(DecodingException.class) - .isThrownBy(() -> originalGpp.getUsNatSection().getMspaCoveredTransaction()); - assertThatNoException() - .isThrownBy(() -> wrappedGpp.getUsNatSection().getMspaCoveredTransaction()); - } - } - - @Test - public void wrapperShouldNotModifyValidBase64SubsectionsWithPadChars() { - // given - final String gpp = "DBABLA~BVVVQAAARlA=.QA=="; - - // when - final GppModel wrappedGpp = new GppModelWrapper(gpp); - - // then - assertThat(wrappedGpp.encodeSection(UsNat.ID)).isEqualTo("BVVVQAAARlA=.QA=="); - } - - @Test - public void wrapperShouldNotModifyValidBase64SubsectionsWithoutPadChars() { - // given - final String gpp = "DBABLA~CqqqgAAAAIJo.YA=="; - - // when - final GppModel wrappedGpp = new GppModelWrapper(gpp); - - // then - assertThat(wrappedGpp.encodeSection(UsNat.ID)).isEqualTo("CqqqgAAAAIJo.YA=="); - assertThatNoException() - .isThrownBy(() -> wrappedGpp.getUsNatSection().getMspaCoveredTransaction()); - } - - @Test - public void wrapperShouldPadSubsections() { - // given - final String gpp = "DBABLA~BVVVQAAARl.Q"; - - // when - final GppModel originalGpp = new GppModel(gpp); - final GppModel wrappedGpp = new GppModelWrapper(gpp); - - // then - assertThat(wrappedGpp.encodeSection(UsNat.ID)).isEqualTo("BVVVQAAARlA.QA"); - assertThatExceptionOfType(DecodingException.class) - .isThrownBy(() -> originalGpp.getUsNatSection().getMspaCoveredTransaction()); - assertThatNoException() - .isThrownBy(() -> wrappedGpp.getUsNatSection().getMspaCoveredTransaction()); - } - public static String normalizeEncodedTcfEuV2Section(String encodedSection) { try { final GppModel normalizer = new GppModel();