github.com/prebid/prebid-server/v2@v2.18.0/floors/validate.go (about)

     1  package floors
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/prebid/prebid-server/v2/config"
     8  	"github.com/prebid/prebid-server/v2/openrtb_ext"
     9  )
    10  
    11  var validSchemaDimensions = map[string]struct{}{
    12  	SiteDomain: {},
    13  	PubDomain:  {},
    14  	Domain:     {},
    15  	Bundle:     {},
    16  	Channel:    {},
    17  	MediaType:  {},
    18  	Size:       {},
    19  	GptSlot:    {},
    20  	AdUnitCode: {},
    21  	Country:    {},
    22  	DeviceType: {},
    23  }
    24  
    25  // validateSchemaDimensions validates schema dimesions given in floors JSON
    26  func validateSchemaDimensions(fields []string) error {
    27  	for i := range fields {
    28  		if _, isPresent := validSchemaDimensions[fields[i]]; !isPresent {
    29  			return fmt.Errorf("Invalid schema dimension provided = '%s' in Schema Fields = '%v'", fields[i], fields)
    30  		}
    31  	}
    32  	return nil
    33  }
    34  
    35  // validateFloorRulesAndLowerValidRuleKey validates rule keys for number of schema dimension fields and drops invalid rules.
    36  // It also lower case of rule if any charactor in a rule is upper
    37  func validateFloorRulesAndLowerValidRuleKey(schema openrtb_ext.PriceFloorSchema, delimiter string, ruleValues map[string]float64) []error {
    38  	var errs []error
    39  	for key, val := range ruleValues {
    40  		parsedKey := strings.Split(key, delimiter)
    41  		if len(parsedKey) != len(schema.Fields) {
    42  			// Number of fields in rule and number of schema fields are not matching
    43  			errs = append(errs, fmt.Errorf("Invalid Floor Rule = '%s' for Schema Fields = '%v'", key, schema.Fields))
    44  			delete(ruleValues, key)
    45  			continue
    46  		}
    47  		lowerKey := strings.ToLower(key)
    48  		if strings.Compare(key, lowerKey) != 0 {
    49  			delete(ruleValues, key)
    50  			ruleValues[lowerKey] = val
    51  		}
    52  	}
    53  	return errs
    54  }
    55  
    56  // validateFloorParams validates SchemaVersion, SkipRate and FloorMin
    57  func validateFloorParams(extFloorRules *openrtb_ext.PriceFloorRules) error {
    58  	if extFloorRules.Data != nil && extFloorRules.Data.FloorsSchemaVersion != 0 && extFloorRules.Data.FloorsSchemaVersion != 2 {
    59  		return fmt.Errorf("Invalid FloorsSchemaVersion = '%v', supported version 2", extFloorRules.Data.FloorsSchemaVersion)
    60  	}
    61  
    62  	if extFloorRules.Data != nil && (extFloorRules.Data.SkipRate < skipRateMin || extFloorRules.Data.SkipRate > skipRateMax) {
    63  		return fmt.Errorf("Invalid SkipRate = '%v' at ext.prebid.floors.data.skiprate", extFloorRules.Data.SkipRate)
    64  	}
    65  
    66  	if extFloorRules.SkipRate < skipRateMin || extFloorRules.SkipRate > skipRateMax {
    67  		return fmt.Errorf("Invalid SkipRate = '%v' at ext.prebid.floors.skiprate", extFloorRules.SkipRate)
    68  	}
    69  
    70  	if extFloorRules.FloorMin < 0.0 {
    71  		return fmt.Errorf("Invalid FloorMin = '%v', value should be >= 0", extFloorRules.FloorMin)
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  // selectValidFloorModelGroups validates each modelgroup for SkipRate and ModelGroup and drops invalid modelGroups
    78  func selectValidFloorModelGroups(modelGroups []openrtb_ext.PriceFloorModelGroup, account config.Account) ([]openrtb_ext.PriceFloorModelGroup, []error) {
    79  	var errs []error
    80  	var validModelGroups []openrtb_ext.PriceFloorModelGroup
    81  	if len(modelGroups) == 0 {
    82  		return validModelGroups, []error{fmt.Errorf("No model group present in floors.data")}
    83  	}
    84  
    85  	for _, modelGroup := range modelGroups {
    86  		if err := validateSchemaDimensions(modelGroup.Schema.Fields); err != nil {
    87  			errs = append(errs, err)
    88  			continue
    89  		}
    90  
    91  		if account.PriceFloors.MaxSchemaDims > 0 && len(modelGroup.Schema.Fields) > account.PriceFloors.MaxSchemaDims {
    92  			errs = append(errs, fmt.Errorf("Invalid Floor Model = '%v' due to number of schema fields = '%v' are greater than limit %v", modelGroup.ModelVersion, len(modelGroup.Schema.Fields), account.PriceFloors.MaxSchemaDims))
    93  			continue
    94  		}
    95  
    96  		if account.PriceFloors.MaxRule > 0 && len(modelGroup.Values) > account.PriceFloors.MaxRule {
    97  			errs = append(errs, fmt.Errorf("Invalid Floor Model = '%v' due to number of rules = '%v' are greater than limit %v", modelGroup.ModelVersion, len(modelGroup.Values), account.PriceFloors.MaxRule))
    98  			continue
    99  		}
   100  
   101  		if modelGroup.SkipRate < skipRateMin || modelGroup.SkipRate > skipRateMax {
   102  			errs = append(errs, fmt.Errorf("Invalid Floor Model = '%v' due to SkipRate = '%v' is out of range (1-100)", modelGroup.ModelVersion, modelGroup.SkipRate))
   103  			continue
   104  		}
   105  
   106  		if modelGroup.ModelWeight != nil && (*modelGroup.ModelWeight < modelWeightMin || *modelGroup.ModelWeight > modelWeightMax) {
   107  			errs = append(errs, fmt.Errorf("Invalid Floor Model = '%v' due to ModelWeight = '%v' is out of range (1-100)", modelGroup.ModelVersion, *modelGroup.ModelWeight))
   108  			continue
   109  		}
   110  
   111  		if modelGroup.Default < 0.0 {
   112  			errs = append(errs, fmt.Errorf("Invalid Floor Model = '%v' due to Default = '%v' is less than 0", modelGroup.ModelVersion, modelGroup.Default))
   113  			continue
   114  		}
   115  
   116  		validModelGroups = append(validModelGroups, modelGroup)
   117  	}
   118  	return validModelGroups, errs
   119  }