github.com/prebid/prebid-server/v2@v2.18.0/dsa/validate.go (about) 1 package dsa 2 3 import ( 4 "errors" 5 6 "github.com/prebid/prebid-server/v2/exchange/entities" 7 "github.com/prebid/prebid-server/v2/openrtb_ext" 8 "github.com/prebid/prebid-server/v2/util/jsonutil" 9 ) 10 11 // Required values representing whether a DSA object is required 12 const ( 13 Required int8 = 2 // bid responses without DSA object will not be accepted 14 RequiredOnlinePlatform int8 = 3 // bid responses without DSA object will not be accepted, Publisher is Online Platform 15 ) 16 17 // PubRender values representing publisher rendering intentions 18 const ( 19 PubRenderCannotRender int8 = 0 // publisher can't render 20 PubRenderWillRender int8 = 2 // publisher will render 21 ) 22 23 // AdRender values representing buyer/advertiser rendering intentions 24 const ( 25 AdRenderWillRender int8 = 1 // buyer/advertiser will render 26 ) 27 28 var ( 29 ErrDsaMissing = errors.New("DSA object missing when required") 30 ErrBehalfTooLong = errors.New("DSA behalf exceeds limit of 100 chars") 31 ErrPaidTooLong = errors.New("DSA paid exceeds limit of 100 chars") 32 ErrNeitherWillRender = errors.New("DSA publisher and buyer both signal will not render") 33 ErrBothWillRender = errors.New("DSA publisher and buyer both signal will render") 34 ) 35 36 const ( 37 behalfMaxLength = 100 38 paidMaxLength = 100 39 ) 40 41 // Validate determines whether a given bid is valid from a DSA perspective. 42 // A bid is considered valid unless the bid request indicates that a DSA object is required 43 // in bid responses and the object happens to be missing from the specified bid, or if the bid 44 // DSA object contents are invalid 45 func Validate(req *openrtb_ext.RequestWrapper, bid *entities.PbsOrtbBid) error { 46 reqDSA := getReqDSA(req) 47 bidDSA := getBidDSA(bid) 48 49 if dsaRequired(reqDSA) && bidDSA == nil { 50 return ErrDsaMissing 51 } 52 if bidDSA == nil { 53 return nil 54 } 55 if len(bidDSA.Behalf) > behalfMaxLength { 56 return ErrBehalfTooLong 57 } 58 if len(bidDSA.Paid) > paidMaxLength { 59 return ErrPaidTooLong 60 } 61 if reqDSA != nil && reqDSA.PubRender != nil && bidDSA.AdRender != nil { 62 if *reqDSA.PubRender == PubRenderCannotRender && *bidDSA.AdRender != AdRenderWillRender { 63 return ErrNeitherWillRender 64 } 65 if *reqDSA.PubRender == PubRenderWillRender && *bidDSA.AdRender == AdRenderWillRender { 66 return ErrBothWillRender 67 } 68 } 69 return nil 70 } 71 72 // dsaRequired examines the bid request to determine if the dsarequired field indicates 73 // that bid responses include a dsa object 74 func dsaRequired(dsa *openrtb_ext.ExtRegsDSA) bool { 75 if dsa == nil || dsa.Required == nil { 76 return false 77 } 78 return *dsa.Required == Required || *dsa.Required == RequiredOnlinePlatform 79 } 80 81 // getReqDSA retrieves the DSA object from the request 82 func getReqDSA(req *openrtb_ext.RequestWrapper) *openrtb_ext.ExtRegsDSA { 83 if req == nil { 84 return nil 85 } 86 regExt, err := req.GetRegExt() 87 if regExt == nil || err != nil { 88 return nil 89 } 90 return regExt.GetDSA() 91 } 92 93 // getBidDSA retrieves the DSA object from the bid 94 func getBidDSA(bid *entities.PbsOrtbBid) *openrtb_ext.ExtBidDSA { 95 if bid == nil || bid.Bid == nil { 96 return nil 97 } 98 var bidExt openrtb_ext.ExtBid 99 if err := jsonutil.Unmarshal(bid.Bid.Ext, &bidExt); err != nil { 100 return nil 101 } 102 return bidExt.DSA 103 }