github.com/prebid/prebid-server/v2@v2.18.0/gdpr/purpose_enforcer.go (about) 1 package gdpr 2 3 import ( 4 "github.com/prebid/go-gdpr/api" 5 "github.com/prebid/go-gdpr/consentconstants" 6 tcf2 "github.com/prebid/go-gdpr/vendorconsent/tcf2" 7 "github.com/prebid/prebid-server/v2/config" 8 "github.com/prebid/prebid-server/v2/openrtb_ext" 9 ) 10 11 // PurposeEnforcer represents the enforcement strategy for determining if legal basis is achieved for a purpose 12 type PurposeEnforcer interface { 13 LegalBasis(vendorInfo VendorInfo, name string, consent tcf2.ConsentMetadata, overrides Overrides) bool 14 } 15 16 // PurposeEnforcerBuilder generates an instance of PurposeEnforcer for a given purpose and bidder 17 type PurposeEnforcerBuilder func(p consentconstants.Purpose, name string) PurposeEnforcer 18 19 // Overrides specifies enforcement algorithm rule adjustments 20 type Overrides struct { 21 allowLITransparency bool 22 blockVendorExceptions bool 23 enforcePurpose bool 24 enforceVendors bool 25 } 26 27 type BidderInfo struct { 28 bidderCoreName openrtb_ext.BidderName 29 bidder openrtb_ext.BidderName 30 } 31 type VendorInfo struct { 32 vendorID uint16 33 vendor api.Vendor 34 } 35 36 // PurposeEnforcers holds the full and basic enforcers for a purpose 37 type PurposeEnforcers struct { 38 Full PurposeEnforcer 39 Basic PurposeEnforcer 40 } 41 42 // NewPurposeEnforcerBuilder creates a new instance of PurposeEnforcerBuilder. This function uses 43 // closures so that any enforcer generated by the returned builder may use the config and also be 44 // cached and reused within a request context 45 func NewPurposeEnforcerBuilder(cfg TCF2ConfigReader) PurposeEnforcerBuilder { 46 cachedEnforcers := make([]PurposeEnforcers, 10) 47 48 return func(purpose consentconstants.Purpose, name string) PurposeEnforcer { 49 index := purpose - 1 50 51 var basicEnforcementVendor bool 52 if purpose == consentconstants.Purpose(1) { 53 basicEnforcementVendor = false 54 } else { 55 basicEnforcementVendors := cfg.BasicEnforcementVendors() 56 _, basicEnforcementVendor = basicEnforcementVendors[name] 57 } 58 59 enforceAlgo := cfg.PurposeEnforcementAlgo(purpose) 60 downgraded := isDowngraded(enforceAlgo, basicEnforcementVendor) 61 62 if enforceAlgo == config.TCF2BasicEnforcement || downgraded { 63 if cachedEnforcers[index].Basic != nil { 64 return cachedEnforcers[index].Basic 65 } 66 67 purposeCfg := purposeConfig{ 68 PurposeID: purpose, 69 EnforceAlgo: enforceAlgo, 70 EnforcePurpose: cfg.PurposeEnforced(purpose), 71 EnforceVendors: cfg.PurposeEnforcingVendors(purpose), 72 VendorExceptionMap: cfg.PurposeVendorExceptions(purpose), 73 BasicEnforcementVendorsMap: cfg.BasicEnforcementVendors(), 74 } 75 76 enforcer := &BasicEnforcement{ 77 cfg: purposeCfg, 78 } 79 cachedEnforcers[index].Basic = enforcer 80 return enforcer 81 } else { 82 if cachedEnforcers[index].Full != nil { 83 return cachedEnforcers[index].Full 84 } 85 86 purposeCfg := purposeConfig{ 87 PurposeID: purpose, 88 EnforceAlgo: enforceAlgo, 89 EnforcePurpose: cfg.PurposeEnforced(purpose), 90 EnforceVendors: cfg.PurposeEnforcingVendors(purpose), 91 VendorExceptionMap: cfg.PurposeVendorExceptions(purpose), 92 BasicEnforcementVendorsMap: cfg.BasicEnforcementVendors(), 93 } 94 95 enforcer := &FullEnforcement{ 96 cfg: purposeCfg, 97 } 98 cachedEnforcers[index].Full = enforcer 99 return enforcer 100 } 101 } 102 } 103 104 // isDowngraded determines if the enforcement algorithm used to determine legal basis for a 105 // purpose should be downgraded from full enforcement to basic 106 func isDowngraded(enforceAlgo config.TCF2EnforcementAlgo, basicEnforcementVendor bool) bool { 107 if enforceAlgo == config.TCF2FullEnforcement && basicEnforcementVendor { 108 return true 109 } 110 return false 111 }