diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go index 76762d8b9ea..2fde59c25e4 100644 --- a/endpoints/openrtb2/amp_auction.go +++ b/endpoints/openrtb2/amp_auction.go @@ -103,6 +103,7 @@ func NewAmpEndpoint( storedRespFetcher, hookExecutionPlanBuilder, tmaxAdjustments, + openrtb_ext.NormalizeBidderName, }).AmpAuction), nil } diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index 4fce4c15786..3a929c43abe 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -126,9 +126,12 @@ func NewEndpoint( ipValidator, storedRespFetcher, hookExecutionPlanBuilder, - tmaxAdjustments}).Auction), nil + tmaxAdjustments, + openrtb_ext.NormalizeBidderName}).Auction), nil } +type normalizeBidderName func(name string) (openrtb_ext.BidderName, bool) + type endpointDeps struct { uuidGenerator uuidutil.UUIDGenerator ex exchange.Exchange @@ -149,6 +152,7 @@ type endpointDeps struct { storedRespFetcher stored_requests.Fetcher hookExecutionPlanBuilder hooks.ExecutionPlanBuilder tmaxAdjustments *exchange.TmaxAdjustmentsPreprocessed + normalizeBidderName normalizeBidderName } func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { @@ -765,7 +769,7 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp } } - var aliases map[string]string + var requestAliases map[string]string reqExt, err := req.GetRequestExt() if err != nil { return []error{fmt.Errorf("request.ext is invalid: %v", err)} @@ -777,17 +781,17 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp } if reqPrebid != nil { - aliases = reqPrebid.Aliases + requestAliases = reqPrebid.Aliases - if err := deps.validateAliases(aliases); err != nil { + if err := deps.validateAliases(requestAliases); err != nil { return []error{err} } - if err := deps.validateAliasesGVLIDs(reqPrebid.AliasGVLIDs, aliases); err != nil { + if err := deps.validateAliasesGVLIDs(reqPrebid.AliasGVLIDs, requestAliases); err != nil { return []error{err} } - if err := deps.validateBidAdjustmentFactors(reqPrebid.BidAdjustmentFactors, aliases); err != nil { + if err := deps.validateBidAdjustmentFactors(reqPrebid.BidAdjustmentFactors, requestAliases); err != nil { return []error{err} } @@ -795,7 +799,7 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp return []error{err} } - if err := deps.validateEidPermissions(reqPrebid.Data, aliases); err != nil { + if err := deps.validateEidPermissions(reqPrebid.Data, requestAliases); err != nil { return []error{err} } @@ -844,7 +848,7 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp } } - if errs := deps.validateUser(req, aliases, gpp); errs != nil { + if errs := deps.validateUser(req, requestAliases, gpp); errs != nil { if len(errs) > 0 { errL = append(errL, errs...) } @@ -871,7 +875,7 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp if errortypes.ContainsFatalError([]error{err}) { return errL } - } else if _, err := ccpaPolicy.Parse(exchange.GetValidBidders(aliases)); err != nil { + } else if _, err := ccpaPolicy.Parse(exchange.GetValidBidders(requestAliases)); err != nil { if _, invalidConsent := err.(*errortypes.Warning); invalidConsent { errL = append(errL, &errortypes.Warning{ Message: fmt.Sprintf("CCPA consent is invalid and will be ignored. (%v)", err), @@ -894,7 +898,7 @@ func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp } impIDs[imp.ID] = i - errs := deps.validateImp(imp, aliases, i, hasStoredResponses, storedBidResp) + errs := deps.validateImp(imp, requestAliases, i, hasStoredResponses, storedBidResp) if len(errs) > 0 { errL = append(errL, errs...) } @@ -986,7 +990,7 @@ func validateSChains(sChains []*openrtb_ext.ExtRequestPrebidSChain) error { return err } -func (deps *endpointDeps) validateEidPermissions(prebid *openrtb_ext.ExtRequestPrebidData, aliases map[string]string) error { +func (deps *endpointDeps) validateEidPermissions(prebid *openrtb_ext.ExtRequestPrebidData, requestAliases map[string]string) error { if prebid == nil { return nil } @@ -1006,7 +1010,7 @@ func (deps *endpointDeps) validateEidPermissions(prebid *openrtb_ext.ExtRequestP return fmt.Errorf(`request.ext.prebid.data.eidpermissions[%d] missing or empty required field: "bidders"`, i) } - if err := validateBidders(eid.Bidders, deps.bidderMap, aliases); err != nil { + if err := deps.validateBidders(eid.Bidders, deps.bidderMap, requestAliases); err != nil { return fmt.Errorf(`request.ext.prebid.data.eidpermissions[%d] contains %v`, i, err) } } @@ -1014,20 +1018,16 @@ func (deps *endpointDeps) validateEidPermissions(prebid *openrtb_ext.ExtRequestP return nil } -func validateBidders(bidders []string, knownBidders map[string]openrtb_ext.BidderName, knownAliases map[string]string) error { +func (deps *endpointDeps) validateBidders(bidders []string, knownBidders map[string]openrtb_ext.BidderName, knownRequestAliases map[string]string) error { for _, bidder := range bidders { if bidder == "*" { if len(bidders) > 1 { return errors.New(`bidder wildcard "*" mixed with specific bidders`) } } else { - bidderName := bidder - normalizedCoreBidder, ok := openrtb_ext.NormalizeBidderName(bidderName) - if ok { - bidderName = normalizedCoreBidder.String() - } - _, isCoreBidder := knownBidders[bidderName] - _, isAlias := knownAliases[bidder] + bidderNormalized, _ := deps.normalizeBidderName(bidder) + _, isCoreBidder := knownBidders[bidderNormalized.String()] + _, isAlias := knownRequestAliases[bidder] if !isCoreBidder && !isAlias { return fmt.Errorf(`unrecognized bidder "%v"`, bidder) } diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index 55bf68ff730..8204a80e3db 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -1186,6 +1186,7 @@ func TestStoredRequests(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } testStoreVideoAttr := []bool{true, true, false, false, false} @@ -1635,6 +1636,7 @@ func TestValidateRequest(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } testCases := []struct { @@ -2414,6 +2416,7 @@ func TestSetIntegrationType(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } testCases := []struct { @@ -2480,6 +2483,7 @@ func TestStoredRequestGenerateUuid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } req := &openrtb2.BidRequest{} @@ -2584,6 +2588,7 @@ func TestOversizedRequest(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody)) @@ -2623,6 +2628,7 @@ func TestRequestSizeEdgeCase(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(reqBody)) @@ -2962,6 +2968,7 @@ func TestValidateImpExt(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } for _, group := range testGroups { @@ -3017,6 +3024,7 @@ func TestCurrencyTrunc(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3065,6 +3073,7 @@ func TestCCPAInvalid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3117,6 +3126,7 @@ func TestNoSaleInvalid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3172,6 +3182,7 @@ func TestValidateSourceTID(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3217,6 +3228,7 @@ func TestSChainInvalid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3785,6 +3797,7 @@ func TestEidPermissionsInvalid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } ui := int64(1) @@ -3853,6 +3866,13 @@ func TestValidateEidPermissions(t *testing.T) { }}}}, expectedError: nil, }, + { + description: "Valid - One - Case Insensitive", + request: &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Data: &openrtb_ext.ExtRequestPrebidData{EidPermissions: []openrtb_ext.ExtRequestPrebidDataEidPermission{ + {Source: "sourceA", Bidders: []string{"A"}}, + }}}}, + expectedError: nil, + }, { description: "Valid - Many", request: &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Data: &openrtb_ext.ExtRequestPrebidData{EidPermissions: []openrtb_ext.ExtRequestPrebidDataEidPermission{ @@ -3901,9 +3921,16 @@ func TestValidateEidPermissions(t *testing.T) { }}}}, expectedError: errors.New(`request.ext.prebid.data.eidpermissions[1] contains unrecognized bidder "z"`), }, + { + description: "Valid - Alias Case Sensitive", + request: &openrtb_ext.ExtRequest{Prebid: openrtb_ext.ExtRequestPrebid{Data: &openrtb_ext.ExtRequestPrebidData{EidPermissions: []openrtb_ext.ExtRequestPrebidDataEidPermission{ + {Source: "sourceA", Bidders: []string{"B"}}, + }}}}, + expectedError: errors.New(`request.ext.prebid.data.eidpermissions[0] contains unrecognized bidder "B"`), + }, } - endpoint := &endpointDeps{bidderMap: knownBidders} + endpoint := &endpointDeps{bidderMap: knownBidders, normalizeBidderName: fakeNormalizeBidderName} for _, test := range testCases { result := endpoint.validateEidPermissions(test.request.Prebid.Data, knownAliases) assert.Equal(t, test.expectedError, result, test.description) @@ -3939,6 +3966,13 @@ func TestValidateBidders(t *testing.T) { knownAliases: map[string]string{"c": "c"}, expectedError: nil, }, + { + description: "Valid - One Core Bidder - Case Insensitive", + bidders: []string{"A"}, + knownBidders: map[string]openrtb_ext.BidderName{"a": openrtb_ext.BidderName("a")}, + knownAliases: map[string]string{"c": "c"}, + expectedError: nil, + }, { description: "Valid - Many Core Bidders", bidders: []string{"a", "b"}, @@ -3953,6 +3987,13 @@ func TestValidateBidders(t *testing.T) { knownAliases: map[string]string{"c": "c"}, expectedError: nil, }, + { + description: "Valid - One Alias Bidder - Case Sensitive", + bidders: []string{"C"}, + knownBidders: map[string]openrtb_ext.BidderName{"a": openrtb_ext.BidderName("a")}, + knownAliases: map[string]string{"c": "c"}, + expectedError: errors.New(`unrecognized bidder "C"`), + }, { description: "Valid - Many Alias Bidders", bidders: []string{"c", "d"}, @@ -3974,13 +4015,6 @@ func TestValidateBidders(t *testing.T) { knownAliases: map[string]string{"c": "c"}, expectedError: errors.New(`unrecognized bidder "z"`), }, - { - description: "Invalid - Unknown Bidder Case Sensitive", - bidders: []string{"A"}, - knownBidders: map[string]openrtb_ext.BidderName{"a": openrtb_ext.BidderName("a")}, - knownAliases: map[string]string{"c": "c"}, - expectedError: errors.New(`unrecognized bidder "A"`), - }, { description: "Invalid - Unknown Bidder With Known Bidders", bidders: []string{"a", "c", "z"}, @@ -4011,8 +4045,9 @@ func TestValidateBidders(t *testing.T) { }, } + endpoint := &endpointDeps{normalizeBidderName: fakeNormalizeBidderName} for _, test := range testCases { - result := validateBidders(test.bidders, test.knownBidders, test.knownAliases) + result := endpoint.validateBidders(test.bidders, test.knownBidders, test.knownAliases) assert.Equal(t, test.expectedError, result, test.description) } } @@ -4102,6 +4137,7 @@ func TestAuctionWarnings(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } for _, test := range testCases { t.Run(test.name, func(t *testing.T) { @@ -4148,6 +4184,7 @@ func TestParseRequestParseImpInfoError(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -4228,6 +4265,7 @@ func TestParseGzipedRequest(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -4828,6 +4866,7 @@ func TestParseRequestMergeBidderParams(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -4931,6 +4970,7 @@ func TestParseRequestStoredResponses(t *testing.T) { &mockStoredResponseFetcher{mockStoredResponses}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -5029,6 +5069,7 @@ func TestParseRequestStoredBidResponses(t *testing.T) { &mockStoredResponseFetcher{mockStoredBidResponses}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -5065,6 +5106,7 @@ func TestValidateStoredResp(t *testing.T) { &mockStoredResponseFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } testCases := []struct { @@ -5878,6 +5920,7 @@ func TestParseRequestMultiBid(t *testing.T) { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } hookExecutor := hookexecution.NewHookExecutor(deps.hookExecutionPlanBuilder, hookexecution.EndpointAuction, deps.metricsEngine) @@ -6043,3 +6086,7 @@ func TestValidateAliases(t *testing.T) { }) } } + +func fakeNormalizeBidderName(name string) (openrtb_ext.BidderName, bool) { + return openrtb_ext.BidderName(strings.ToLower(name)), true +} diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/eidpermissions-insensitive-bidder-name.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/eidpermissions-insensitive-bidder-name.json deleted file mode 100644 index b06b2593e26..00000000000 --- a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/eidpermissions-insensitive-bidder-name.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "description": "This demonstrates ext.prebid.data.eidpermissions.bidders with case insensitive bidder names", - "config": { - "mockBidders": [ - { - "bidderName": "appnexus", - "currency": "USD", - "price": 1.00 - }, - { - "bidderName": "rubicon", - "currency": "USD", - "price": 1.00 - } - ] - }, - "mockBidRequest": { - "id": "some-request-id", - "site": { - "page": "prebid.org" - }, - "user": { - "ext": { - "consent": "gdpr-consent-string" - } - }, - "regs": { - "ext": { - "gdpr": 1, - "us_privacy": "1NYN" - } - }, - "imp": [ - { - "id": "some-impression-id", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - }, - { - "w": 300, - "h": 600 - } - ] - }, - "ext": { - "APPNEXUS": { - "placementId": 12883451 - } - } - } - ], - "tmax": 500, - "ext": { - "prebid": { - "data": { - "eidpermissions": [ - { - "source": "source1", - "bidders": [ - "APPNEXUS" - ] - } - ] - }, - "cache": { - "bids": {} - }, - "channel": { - "name": "video", - "version": "1.0" - }, - "targeting": { - "includewinners": false, - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.10 - } - ] - } - } - } - } - }, - "expectedBidResponse": { - "id": "some-request-id", - "seatbid": [ - { - "bid": [ - { - "id": "appnexus-bid", - "impid": "some-impression-id", - "price": 1 - } - ], - "seat": "APPNEXUS" - } - ], - "bidid": "test bid id", - "cur": "USD", - "nbr": 0 - }, - "expectedReturnCode": 200 -} \ No newline at end of file diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go index fc6d2a91a62..8faf15543d3 100644 --- a/endpoints/openrtb2/video_auction.go +++ b/endpoints/openrtb2/video_auction.go @@ -92,7 +92,8 @@ func NewVideoEndpoint( ipValidator, empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, - tmaxAdjustments}).VideoAuctionEndpoint), nil + tmaxAdjustments, + openrtb_ext.NormalizeBidderName}).VideoAuctionEndpoint), nil } /* diff --git a/endpoints/openrtb2/video_auction_test.go b/endpoints/openrtb2/video_auction_test.go index 181a68929ed..19af821f205 100644 --- a/endpoints/openrtb2/video_auction_test.go +++ b/endpoints/openrtb2/video_auction_test.go @@ -1227,6 +1227,7 @@ func mockDepsWithMetrics(t *testing.T, ex *mockExchangeVideo) (*endpointDeps, *m empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } return deps, metrics, mockModule } @@ -1274,6 +1275,7 @@ func mockDeps(t *testing.T, ex *mockExchangeVideo) *endpointDeps { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } } @@ -1298,6 +1300,7 @@ func mockDepsAppendBidderNames(t *testing.T, ex *mockExchangeAppendBidderNames) empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } return deps @@ -1324,6 +1327,7 @@ func mockDepsNoBids(t *testing.T, ex *mockExchangeVideoNoBids) *endpointDeps { empty_fetcher.EmptyFetcher{}, hooks.EmptyPlanBuilder{}, nil, + openrtb_ext.NormalizeBidderName, } return edep diff --git a/exchange/exchangetest/eidpermissions-allowed-alias.json b/exchange/exchangetest/eidpermissions-allowed-alias.json index f10bdcf86c0..de3c0e1dca6 100644 --- a/exchange/exchangetest/eidpermissions-allowed-alias.json +++ b/exchange/exchangetest/eidpermissions-allowed-alias.json @@ -10,7 +10,11 @@ "eids": [ { "source": "source1", - "id": "anyId" + "uids": [ + { + "id": "id1" + } + ] } ] } @@ -66,7 +70,11 @@ "eids": [ { "source": "source1", - "id": "anyId" + "uids": [ + { + "id": "id1" + } + ] } ] } diff --git a/exchange/exchangetest/eidpermissions-allowed-case-insensitive.json b/exchange/exchangetest/eidpermissions-allowed-case-insensitive.json new file mode 100644 index 00000000000..86797501495 --- /dev/null +++ b/exchange/exchangetest/eidpermissions-allowed-case-insensitive.json @@ -0,0 +1,144 @@ +{ + "incomingRequest": { + "ortbRequest": { + "id": "some-request-id", + "site": { + "page": "test.somepage.com" + }, + "user": { + "ext": { + "eids": [ + { + "source": "source1", + "uids": [ + { + "id": "id1" + } + ] + } + ] + } + }, + "ext": { + "prebid": { + "data": { + "eidpermissions": [ + { + "source": "source1", + "bidders": [ + "APPNEXUS" + ] + } + ] + } + } + }, + "imp": [ + { + "id": "my-imp-id", + "video": { + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "prebid": { + "bidder": { + "appnexus": { + "placementId": 1 + } + } + } + } + } + ] + } + }, + "outgoingRequests": { + "appnexus": { + "expectRequest": { + "ortbRequest": { + "id": "some-request-id", + "site": { + "page": "test.somepage.com" + }, + "user": { + "ext": { + "eids": [ + { + "source": "source1", + "uids": [ + { + "id": "id1" + } + ] + } + ] + } + }, + "imp": [ + { + "id": "my-imp-id", + "video": { + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "placementId": 1 + } + } + } + ] + } + }, + "mockResponse": { + "pbsSeatBids": [ + { + "pbsBids": [ + { + "ortbBid": { + "id": "apn-bid", + "impid": "my-imp-id", + "price": 0.3, + "w": 200, + "h": 250, + "crid": "creative-1" + }, + "bidType": "video" + } + ], + "seat": "appnexus" + } + ] + } + } + }, + "response": { + "bids": { + "id": "some-request-id", + "seatbid": [ + { + "seat": "appnexus", + "bid": [ + { + "id": "apn-bid", + "impid": "my-imp-id", + "price": 0.3, + "w": 200, + "h": 250, + "crid": "creative-1", + "ext": { + "origbidcpm": 0.3, + "prebid": { + "type": "video" + } + } + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/exchange/exchangetest/eidpermissions-allowed.json b/exchange/exchangetest/eidpermissions-allowed.json index 6b27212cbcf..9daee27a9b6 100644 --- a/exchange/exchangetest/eidpermissions-allowed.json +++ b/exchange/exchangetest/eidpermissions-allowed.json @@ -10,7 +10,11 @@ "eids": [ { "source": "source1", - "id": "anyId" + "uids": [ + { + "id": "id1" + } + ] } ] } @@ -63,7 +67,11 @@ "eids": [ { "source": "source1", - "id": "anyId" + "uids": [ + { + "id": "id1" + } + ] } ] } diff --git a/exchange/exchangetest/eidpermissions-denied.json b/exchange/exchangetest/eidpermissions-denied.json index df112905235..04eb51bb600 100644 --- a/exchange/exchangetest/eidpermissions-denied.json +++ b/exchange/exchangetest/eidpermissions-denied.json @@ -10,7 +10,11 @@ "eids": [ { "source": "source1", - "id": "anyId" + "uids": [ + { + "id": "id1" + } + ] } ] } diff --git a/exchange/utils.go b/exchange/utils.go index 0a38e487632..0d9c90cda99 100644 --- a/exchange/utils.go +++ b/exchange/utils.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math/rand" + "strings" "github.com/buger/jsonparser" "github.com/prebid/go-gdpr/vendorconsent" @@ -710,7 +711,7 @@ func removeUnpermissionedEids(request *openrtb2.BidRequest, bidder string, reque allowed := false if rule, hasRule := eidRules[eid.Source]; hasRule { for _, ruleBidder := range rule { - if ruleBidder == "*" || ruleBidder == bidder { + if ruleBidder == "*" || strings.EqualFold(ruleBidder, bidder) { allowed = true break } diff --git a/exchange/utils_test.go b/exchange/utils_test.go index ee6dad1ad96..0dbf5b38e5c 100644 --- a/exchange/utils_test.go +++ b/exchange/utils_test.go @@ -2768,6 +2768,14 @@ func TestRemoveUnpermissionedEids(t *testing.T) { }, expectedUserExt: json.RawMessage(`{"eids":[{"source":"source1","uids":[{"id":"anyID"}]}]}`), }, + { + description: "Allowed By Specific Bidder - Case Insensitive", + userExt: json.RawMessage(`{"eids":[{"source":"source1","uids":[{"id":"anyID"}]}]}`), + eidPermissions: []openrtb_ext.ExtRequestPrebidDataEidPermission{ + {Source: "source1", Bidders: []string{"BIDDERA"}}, + }, + expectedUserExt: json.RawMessage(`{"eids":[{"source":"source1","uids":[{"id":"anyID"}]}]}`), + }, { description: "Allowed By All Bidders", userExt: json.RawMessage(`{"eids":[{"source":"source1","uids":[{"id":"anyID"}]}]}`),