-
Notifications
You must be signed in to change notification settings - Fork 765
/
Copy pathpolicy.go
151 lines (127 loc) · 3.75 KB
/
policy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package ccpa
import (
"errors"
"fmt"
gpplib "github.com/prebid/go-gpp"
gppConstants "github.com/prebid/go-gpp/constants"
"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/prebid-server/v2/errortypes"
"github.com/prebid/prebid-server/v2/openrtb_ext"
gppPolicy "github.com/prebid/prebid-server/v2/privacy/gpp"
)
// Policy represents the CCPA regulatory information from an OpenRTB bid request.
type Policy struct {
Consent string
NoSaleBidders []string
}
// ReadFromRequestWrapper extracts the CCPA regulatory information from an OpenRTB bid request.
func ReadFromRequestWrapper(req *openrtb_ext.RequestWrapper, gpp gpplib.GppContainer) (Policy, error) {
var noSaleBidders []string
var gppSIDs []int8
var requestUSPrivacy string
var warn error
if req == nil || req.BidRequest == nil {
return Policy{}, nil
}
if req.BidRequest.Regs != nil {
requestUSPrivacy = req.BidRequest.Regs.USPrivacy
gppSIDs = req.BidRequest.Regs.GPPSID
}
consent, err := SelectCCPAConsent(requestUSPrivacy, gpp, gppSIDs)
if err != nil {
warn = &errortypes.Warning{
Message: "regs.us_privacy consent does not match uspv1 in GPP, using regs.gpp",
WarningCode: errortypes.InvalidPrivacyConsentWarningCode}
}
if consent == "" {
// Read consent from request.regs.ext
regsExt, err := req.GetRegExt()
if err != nil {
return Policy{}, fmt.Errorf("error reading request.regs.ext: %s", err)
}
if regsExt != nil {
consent = regsExt.GetUSPrivacy()
}
}
// Read no sale bidders from request.ext.prebid
reqExt, err := req.GetRequestExt()
if err != nil {
return Policy{}, fmt.Errorf("error reading request.ext: %s", err)
}
reqPrebid := reqExt.GetPrebid()
if reqPrebid != nil {
noSaleBidders = reqPrebid.NoSale
}
return Policy{consent, noSaleBidders}, warn
}
func ReadFromRequest(req *openrtb2.BidRequest) (Policy, error) {
var gpp gpplib.GppContainer
if req != nil && req.Regs != nil && len(req.Regs.GPP) > 0 {
gpp, _ = gpplib.Parse(req.Regs.GPP)
}
return ReadFromRequestWrapper(&openrtb_ext.RequestWrapper{BidRequest: req}, gpp)
}
// Write mutates an OpenRTB bid request with the CCPA regulatory information.
func (p Policy) Write(req *openrtb_ext.RequestWrapper) error {
if req == nil {
return nil
}
regsExt, err := req.GetRegExt()
if err != nil {
return err
}
reqExt, err := req.GetRequestExt()
if err != nil {
return err
}
regsExt.SetUSPrivacy(p.Consent)
setPrebidNoSale(p.NoSaleBidders, reqExt)
return nil
}
func SelectCCPAConsent(requestUSPrivacy string, gpp gpplib.GppContainer, gppSIDs []int8) (string, error) {
var consent string
var err error
if len(gpp.SectionTypes) > 0 {
if gppPolicy.IsSIDInList(gppSIDs, gppConstants.SectionUSPV1) {
if i := gppPolicy.IndexOfSID(gpp, gppConstants.SectionUSPV1); i >= 0 {
consent = gpp.Sections[i].GetValue()
}
}
}
if requestUSPrivacy != "" {
if consent == "" {
consent = requestUSPrivacy
} else if consent != requestUSPrivacy {
err = errors.New("request.us_privacy consent does not match uspv1")
}
}
return consent, err
}
func setPrebidNoSale(noSaleBidders []string, ext *openrtb_ext.RequestExt) {
if len(noSaleBidders) == 0 {
setPrebidNoSaleClear(ext)
} else {
setPrebidNoSaleWrite(noSaleBidders, ext)
}
}
func setPrebidNoSaleClear(ext *openrtb_ext.RequestExt) {
prebid := ext.GetPrebid()
if prebid == nil {
return
}
// Remove no sale member
prebid.NoSale = []string{}
ext.SetPrebid(prebid)
}
func setPrebidNoSaleWrite(noSaleBidders []string, ext *openrtb_ext.RequestExt) {
if ext == nil {
// This should hopefully not be possible. The only caller insures that this has been initialized
return
}
prebid := ext.GetPrebid()
if prebid == nil {
prebid = &openrtb_ext.ExtRequestPrebid{}
}
prebid.NoSale = noSaleBidders
ext.SetPrebid(prebid)
}