@@ -13,9 +13,12 @@ import org.prebid.server.functional.model.request.auction.UserExt
1313import org.prebid.server.functional.service.PrebidServerException
1414import org.prebid.server.functional.util.PBSUtils
1515
16+ import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST
1617import static org.prebid.server.functional.model.bidder.BidderName.ALIAS
1718import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
19+ import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE
1820import static org.prebid.server.functional.model.bidder.BidderName.OPENX
21+ import static org.prebid.server.functional.model.bidder.BidderName.RUBICON
1922import static org.prebid.server.functional.model.bidder.BidderName.UNKNOWN
2023import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD
2124import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED
@@ -338,4 +341,256 @@ class EidsSpec extends BaseSpec {
338341 and : " Bid response shouldn't contain warning"
339342 assert ! bidResponse. ext. warnings
340343 }
344+
345+ def " PBS should pass user.eids to all bidders when any of required eid permissions doesn't match" () {
346+ given : " Default BidRequest with eids"
347+ def eidPermission = EidPermission . getDefaultEidPermission([RUBICON ])
348+ def userEid = updateEidClosure(Eid . from(eidPermission))
349+
350+ def bidRequest = BidRequest . defaultBidRequest. tap {
351+ user = new User (eids : [userEid])
352+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [eidPermission])
353+ }
354+
355+ when : " PBS processes auction request"
356+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
357+
358+ then : " Bidder request should contain requested eids"
359+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
360+ assert bidderRequest. user. eids == [userEid]
361+
362+ and : " Bid response shouldn't contain any errors and warnings"
363+ assert ! bidResponse. ext. errors
364+ assert ! bidResponse. ext. warnings
365+
366+ where :
367+ updateEidClosure << [
368+ { Eid eid -> eid. tap { it. inserter = null } },
369+ { Eid eid -> eid. tap { it. matcher = null } },
370+ { Eid eid -> eid. tap { it. matchMethod = null } },
371+
372+ { Eid eid -> eid. tap { it. inserter = " " } },
373+ { Eid eid -> eid. tap { it. matcher = " " } },
374+
375+ { Eid eid -> eid. tap { it. source = PBSUtils . randomString } },
376+ { Eid eid -> eid. tap { it. inserter = PBSUtils . randomString } },
377+ { Eid eid -> eid. tap { it. matcher = PBSUtils . randomString } },
378+ { Eid eid -> eid. tap { it. matchMethod = PBSUtils . randomNumber } }
379+ ]
380+ }
381+
382+ def " PBS shouldn't pass user.eids to unmatched bidders when eidPermissions fields match user.eids" () {
383+ given : " Default BidRequest with eids"
384+ def eidPermissionWithUnmatchedBidder = eidPermission. tap {
385+ bidders = [RUBICON ]
386+ }
387+ def userEid = updateEidClosure(eidPermissionWithUnmatchedBidder)
388+
389+ def bidRequest = BidRequest . defaultBidRequest. tap {
390+ user = new User (eids : [userEid])
391+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [eidPermissionWithUnmatchedBidder])
392+ }
393+
394+ when : " PBS processes auction request"
395+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
396+
397+ then : " Bidder request shouldn't contain eids"
398+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
399+ assert ! bidderRequest. user. eids
400+
401+ and : " Bid response shouldn't contain any errors and warnings"
402+ assert ! bidResponse. ext. errors
403+ assert ! bidResponse. ext. warnings
404+
405+ where :
406+ eidPermission | updateEidClosure
407+ new EidPermission (source : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid) }
408+ new EidPermission (source : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. source = eid. source } }
409+ new EidPermission (inserter : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
410+ new EidPermission (inserter : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. inserter = eid. inserter } }
411+ new EidPermission (matcher : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
412+ new EidPermission (matcher : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. matcher = eid. matcher } }
413+ new EidPermission (matchMethod : PBSUtils . randomNumber) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
414+ new EidPermission (matchMethod : PBSUtils . randomNumber) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. matchMethod = eid. matchMethod } }
415+ }
416+
417+ def " PBS should filter only unauthorized eids when multiple eids with different permissions are present" () {
418+ given : " Default BidRequest with eids"
419+ def eidPermissionWithUnmatchedBidder = EidPermission . getDefaultEidPermission([RUBICON ])
420+ def userEid = Eid . from(eidPermissionWithUnmatchedBidder)
421+ def properEids = [Eid . defaultEid, Eid . defaultEid]
422+ def bidRequest = BidRequest . defaultBidRequest. tap {
423+ user = new User (eids : properEids + userEid)
424+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [eidPermissionWithUnmatchedBidder])
425+ }
426+
427+ when : " PBS processes auction request"
428+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
429+
430+ then : " Bidder request should contain requested eids"
431+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
432+ assert bidderRequest. user. eids == properEids
433+
434+ and : " Bid response shouldn't contain any errors and warnings"
435+ assert ! bidResponse. ext. errors
436+ assert ! bidResponse. ext. warnings
437+ }
438+
439+ def " PBS should pass user.eids to matched bidders when eidPermissions fields match user.eids" () {
440+ given : " Default BidRequest with eids"
441+ def eidPermissionAllowingCurrentBidder = eidPermission. tap {
442+ bidders = [[GENERIC , GENERIC_CAMEL_CASE ]. shuffled(). first()]
443+ }
444+ def userEid = updateEidClosure(eidPermissionAllowingCurrentBidder)
445+
446+ def bidRequest = BidRequest . defaultBidRequest. tap {
447+ user = new User (eids : [userEid])
448+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [eidPermissionAllowingCurrentBidder])
449+ }
450+
451+ when : " PBS processes auction request"
452+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
453+
454+ then : " Bidder request should contain requested eids"
455+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
456+ assert bidderRequest. user. eids == [userEid]
457+
458+ and : " Bid response shouldn't contain any errors and warnings"
459+ assert ! bidResponse. ext. errors
460+ assert ! bidResponse. ext. warnings
461+
462+ where :
463+ eidPermission | updateEidClosure
464+ new EidPermission (source : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid) }
465+ new EidPermission (source : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. source = eid. source } }
466+ new EidPermission (inserter : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
467+ new EidPermission (inserter : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. inserter = eid. inserter } }
468+ new EidPermission (matcher : PBSUtils . randomString) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
469+ new EidPermission (matcher : PBSUtils . randomString) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. matcher = eid. matcher } }
470+ new EidPermission (matchMethod : PBSUtils . randomNumber) | { EidPermission eid -> Eid . from(eid). tap { it. source = PBSUtils . randomString } }
471+ new EidPermission (matchMethod : PBSUtils . randomNumber) | { EidPermission eid -> Eid . getDefaultEid(). tap { it. matchMethod = eid. matchMethod } }
472+ }
473+
474+ def " PBS should apply most specific eidPermissions rule when multiple rules match" () {
475+ given : " Default BidRequest with eids"
476+ def userEid = Eid . getDefaultEid()
477+ def moreSpecificEidPermission = moreSpecificPermissionClosure(userEid). tap {
478+ it. bidders = [RUBICON ]
479+ }
480+ def lessSpecificEidPermission = lessSpecificPermissionClosure(userEid). tap {
481+ it. bidders = [GENERIC ]
482+ }
483+ def bidRequest = BidRequest . defaultBidRequest. tap {
484+ user = new User (eids : [userEid])
485+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [moreSpecificEidPermission, lessSpecificEidPermission]. shuffled())
486+ }
487+
488+ when : " PBS processes auction request"
489+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
490+
491+ then : " Bidder request shouldn't contain eids"
492+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
493+ assert ! bidderRequest. user. eids
494+
495+ and : " Bid response shouldn't contain any errors and warnings"
496+ assert ! bidResponse. ext. errors
497+ assert ! bidResponse. ext. warnings
498+
499+ where :
500+ moreSpecificPermissionClosure | lessSpecificPermissionClosure
501+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. source = null } })
502+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. inserter = null } })
503+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. matcher = null } })
504+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. matchMethod = null } })
505+ ({ Eid eid -> EidPermission . from(eid). tap { it. source = null } }) | ({ Eid eid -> new EidPermission (inserter : eid. inserter, matcher : eid. matcher) })
506+ ({ Eid eid -> new EidPermission (inserter : eid. inserter, matcher : eid. matcher) }) | ({ Eid eid -> new EidPermission (matchMethod : eid. matchMethod) })
507+ }
508+
509+ def " PBS should allow access to bidder defined in most specific rule when multiple rules match" () {
510+ given : " Default BidRequest with eids"
511+ def userEid = Eid . getDefaultEid()
512+ def moreSpecificEidPermission = moreSpecificPermissionClosure(userEid). tap {
513+ it. bidders = [GENERIC ]
514+ }
515+ def lessSpecificEidPermission = lessSpecificPermissionClosure(userEid). tap {
516+ it. bidders = [RUBICON ]
517+ }
518+ def bidRequest = BidRequest . defaultBidRequest. tap {
519+ user = new User (eids : [userEid])
520+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [moreSpecificEidPermission, lessSpecificEidPermission]. shuffled())
521+ }
522+
523+ when : " PBS processes auction request"
524+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
525+
526+ then : " Bidder request should contain requested eids"
527+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
528+ assert bidderRequest. user. eids == [userEid]
529+
530+ and : " Bid response shouldn't contain any errors and warnings"
531+ assert ! bidResponse. ext. errors
532+ assert ! bidResponse. ext. warnings
533+
534+ where :
535+ moreSpecificPermissionClosure | lessSpecificPermissionClosure
536+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. source = null } })
537+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. inserter = null } })
538+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. matcher = null } })
539+ ({ Eid eid -> EidPermission . from(eid) }) | ({ Eid eid -> EidPermission . from(eid). tap { it. matchMethod = null } })
540+ ({ Eid eid -> EidPermission . from(eid). tap { it. source = null } }) | ({ Eid eid -> new EidPermission (inserter : eid. inserter, matcher : eid. matcher) })
541+ ({ Eid eid -> new EidPermission (inserter : eid. inserter, matcher : eid. matcher) }) | ({ Eid eid -> new EidPermission (matchMethod : eid. matchMethod) })
542+ }
543+
544+ def " PBS should apply permissions from any matching rule when specificity is equal" () {
545+ given : " Default BidRequest with eids"
546+ def userEid = Eid . getDefaultEid()
547+ def allowingRule = allowingPermissionClosure(userEid). tap {
548+ it. bidders = [GENERIC ]
549+ }
550+ def restrictingRule = restrictingPermissionClosure(userEid). tap {
551+ it. bidders = [RUBICON ]
552+ }
553+ def bidRequest = BidRequest . defaultBidRequest. tap {
554+ user = new User (eids : [userEid])
555+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [allowingRule, restrictingRule]. shuffled())
556+ }
557+
558+ when : " PBS processes auction request"
559+ def bidResponse = defaultPbsService. sendAuctionRequest(bidRequest)
560+
561+ then : " Bidder request should contain requested eids"
562+ def bidderRequest = bidder. getBidderRequest(bidRequest. id)
563+ assert bidderRequest. user. eids == [userEid]
564+
565+ and : " Bid response shouldn't contain any errors and warnings"
566+ assert ! bidResponse. ext. errors
567+ assert ! bidResponse. ext. warnings
568+
569+ where :
570+ allowingPermissionClosure | restrictingPermissionClosure
571+ ({ Eid eid -> new EidPermission (source : eid. source) }) | ({ Eid eid -> new EidPermission (inserter : eid. inserter) })
572+ ({ Eid eid -> new EidPermission (matcher : eid. matcher) }) | ({ Eid eid -> new EidPermission (source : eid. source) })
573+ ({ Eid eid -> new EidPermission (matchMethod : eid. matchMethod) }) | ({ Eid eid -> new EidPermission (matcher : eid. matcher) })
574+ ({ Eid eid -> new EidPermission (source : eid. source, matcher : eid. matcher) }) | ({ Eid eid -> new EidPermission (inserter : eid. inserter, matchMethod : eid. matchMethod) })
575+ ({ Eid eid -> new EidPermission (source : eid. source, inserter : eid. inserter) }) | ({ Eid eid -> new EidPermission (matcher : eid. matcher, matchMethod : eid. matchMethod) })
576+ ({ Eid eid -> new EidPermission (source : eid. source, matchMethod : eid. matchMethod) }) | ({ Eid eid -> new EidPermission (inserter : eid. inserter, matcher : eid. matcher) })
577+ ({ Eid eid -> EidPermission . from(eid). tap { matchMethod = null } }) | ({ Eid eid -> EidPermission . from(eid). tap { matcher = null } })
578+ }
579+
580+ def " PBS should throw an error when all eidPermissions fields are empty" () {
581+ given : " Default bid request with invalid eidPermission"
582+ def bidRequest = BidRequest . defaultBidRequest. tap {
583+ ext. prebid. data = new ExtRequestPrebidData (eidpermissions : [new EidPermission ()])
584+ }
585+
586+ when : " PBS processes auction request"
587+ defaultPbsService. sendAuctionRequest(bidRequest)
588+
589+ then : " PBS should throw error"
590+ def exception = thrown(PrebidServerException )
591+ assert exception. statusCode == BAD_REQUEST . code()
592+ assert exception. responseBody == " Invalid request format: " +
593+ " Missing required parameter(s) in request.ext.prebid.data.eidPermissions[]. " +
594+ " Either one or a combination of inserter, source, matcher, or mm should be defined."
595+ }
341596}
0 commit comments