-
Notifications
You must be signed in to change notification settings - Fork 710
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DSA: Bid response adrender, behalf & paid validations (#3523)
- Loading branch information
Showing
7 changed files
with
363 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,103 @@ | ||
package dsa | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/prebid/prebid-server/v2/exchange/entities" | ||
"github.com/prebid/prebid-server/v2/openrtb_ext" | ||
"github.com/prebid/prebid-server/v2/util/jsonutil" | ||
) | ||
|
||
"github.com/buger/jsonparser" | ||
// Required values representing whether a DSA object is required | ||
const ( | ||
Required int8 = 2 // bid responses without DSA object will not be accepted | ||
RequiredOnlinePlatform int8 = 3 // bid responses without DSA object will not be accepted, Publisher is Online Platform | ||
) | ||
|
||
// PubRender values representing publisher rendering intentions | ||
const ( | ||
// Required - bid responses without DSA object will not be accepted | ||
Required = 2 | ||
// RequiredOnlinePlatform - bid responses without DSA object will not be accepted, Publisher is an Online Platform | ||
RequiredOnlinePlatform = 3 | ||
PubRenderCannotRender int8 = 0 // publisher can't render | ||
PubRenderWillRender int8 = 2 // publisher will render | ||
) | ||
|
||
// AdRender values representing buyer/advertiser rendering intentions | ||
const ( | ||
AdRenderWillRender int8 = 1 // buyer/advertiser will render | ||
) | ||
|
||
var ( | ||
ErrDsaMissing = errors.New("DSA object missing when required") | ||
ErrBehalfTooLong = errors.New("DSA behalf exceeds limit of 100 chars") | ||
ErrPaidTooLong = errors.New("DSA paid exceeds limit of 100 chars") | ||
ErrNeitherWillRender = errors.New("DSA publisher and buyer both signal will not render") | ||
ErrBothWillRender = errors.New("DSA publisher and buyer both signal will render") | ||
) | ||
|
||
const ( | ||
behalfMaxLength = 100 | ||
paidMaxLength = 100 | ||
) | ||
|
||
// Validate determines whether a given bid is valid from a DSA perspective. | ||
// A bid is considered valid unless the bid request indicates that a DSA object is required | ||
// in bid responses and the object happens to be missing from the specified bid. | ||
func Validate(req *openrtb_ext.RequestWrapper, bid *entities.PbsOrtbBid) (valid bool) { | ||
if !dsaRequired(req) { | ||
return true | ||
// in bid responses and the object happens to be missing from the specified bid, or if the bid | ||
// DSA object contents are invalid | ||
func Validate(req *openrtb_ext.RequestWrapper, bid *entities.PbsOrtbBid) error { | ||
reqDSA := getReqDSA(req) | ||
bidDSA := getBidDSA(bid) | ||
|
||
if dsaRequired(reqDSA) && bidDSA == nil { | ||
return ErrDsaMissing | ||
} | ||
if bid == nil || bid.Bid == nil { | ||
return false | ||
if bidDSA == nil { | ||
return nil | ||
} | ||
if len(bidDSA.Behalf) > behalfMaxLength { | ||
return ErrBehalfTooLong | ||
} | ||
_, dataType, _, err := jsonparser.Get(bid.Bid.Ext, "dsa") | ||
if dataType == jsonparser.Object && err == nil { | ||
return true | ||
} else if err != nil && err != jsonparser.KeyPathNotFoundError { | ||
return true | ||
if len(bidDSA.Paid) > paidMaxLength { | ||
return ErrPaidTooLong | ||
} | ||
return false | ||
if reqDSA != nil && reqDSA.PubRender != nil && bidDSA.AdRender != nil { | ||
if *reqDSA.PubRender == PubRenderCannotRender && *bidDSA.AdRender != AdRenderWillRender { | ||
return ErrNeitherWillRender | ||
} | ||
if *reqDSA.PubRender == PubRenderWillRender && *bidDSA.AdRender == AdRenderWillRender { | ||
return ErrBothWillRender | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// dsaRequired examines the bid request to determine if the dsarequired field indicates | ||
// that bid responses include a dsa object | ||
func dsaRequired(req *openrtb_ext.RequestWrapper) bool { | ||
func dsaRequired(dsa *openrtb_ext.ExtRegsDSA) bool { | ||
if dsa == nil || dsa.Required == nil { | ||
return false | ||
} | ||
return *dsa.Required == Required || *dsa.Required == RequiredOnlinePlatform | ||
} | ||
|
||
// getReqDSA retrieves the DSA object from the request | ||
func getReqDSA(req *openrtb_ext.RequestWrapper) *openrtb_ext.ExtRegsDSA { | ||
if req == nil { | ||
return nil | ||
} | ||
regExt, err := req.GetRegExt() | ||
if regExt == nil || err != nil { | ||
return false | ||
return nil | ||
} | ||
regsDSA := regExt.GetDSA() | ||
if regsDSA == nil { | ||
return false | ||
return regExt.GetDSA() | ||
} | ||
|
||
// getBidDSA retrieves the DSA object from the bid | ||
func getBidDSA(bid *entities.PbsOrtbBid) *openrtb_ext.ExtBidDSA { | ||
if bid == nil || bid.Bid == nil { | ||
return nil | ||
} | ||
if regsDSA.Required == Required || regsDSA.Required == RequiredOnlinePlatform { | ||
return true | ||
var bidExt openrtb_ext.ExtBid | ||
if err := jsonutil.Unmarshal(bid.Bid.Ext, &bidExt); err != nil { | ||
return nil | ||
} | ||
return false | ||
return bidExt.DSA | ||
} |
Oops, something went wrong.