module Jamf::OAPIValidate

A collection of methods implementing data constraints as defined in the OAPI3 standard. See

swagger.io/docs/specification/data-models/data-types/

This module is extended into Jamf::Validate, where these become module methods

As with that module: Some of these methods can take multiple input types, such as a String or an number. All of them will either raise an exception if the value isn’t valid, or will return a standardized form of the input (e.g. a number, even if given a String)

IMPORTANT - This module MUST be extended into Jamf::Validate.

Public Instance Methods

boolean(val, attr_name: nil, msg: nil) click to toggle source

Confirm that the given value is a boolean value, accepting strings and symbols and returning real booleans as needed Accepts: true, false, ‘true’, ‘false’, ‘yes’, ‘no’, ‘t’,‘f’, ‘y’, or ‘n’ as strings or symbols, case insensitive

TODO: use this throughout ruby-jss

@param val [Boolean,String,Symbol] The value to validate

@param msg A custom error message when the value is invalid

@return [Boolean] the valid boolean

    # File lib/jamf/oapi_validate.rb
184 def boolean(val, attr_name: nil, msg: nil)
185   return val if Jamf::TRUE_FALSE.include? val
186   return true if val.to_s =~ /^(t(rue)?|y(es)?)$/i
187   return false if val.to_s =~ /^(f(alse)?|no?)$/i
188 
189   raise_invalid_data_error(msg || "#{attr_name} value must be boolean true or false, or an equivalent string or symbol")
190 end
class_instance(val, klass:, attr_name: nil, msg: nil) click to toggle source

validate that a value is of a specific class

@param val [Object] The value to validate

@param klass [Class, Symbol] The class which the val must be an instance of

@param msg A custom error message when the value is invalid

@return [Object] the valid value

    # File lib/jamf/oapi_validate.rb
161 def class_instance(val, klass:, attr_name: nil, msg: nil)
162   return val if val.instance_of? klass
163 
164   # try to instantiate the class with the value. It should raise an error
165   # if not good
166   klass.new val
167 rescue => e
168   raise_invalid_data_error(msg || "#{attr_name} value must be a #{klass}, or #{klass}.new must accept it as the only parameter, but #{klass}.new raised: #{e.class}: #{e}")
169 end
float(val, attr_name: nil, msg: nil) click to toggle source

Confirm that a value is a Float or a string representation of a Float Return the Float, or raise an error

@param val the value to validate

@param msg A custom error message when the value is invalid

@return [Float]

    # File lib/jamf/oapi_validate.rb
243 def float(val, attr_name: nil, msg: nil)
244   val = val.to_f if val.is_a?(Integer)
245   val = val.to_f if val.is_a?(String) && (val.j_float? || val.j_integer?)
246   return val if val.is_a? Float
247 
248   raise_invalid_data_error(msg || "#{attr_name} value must be an floating point number")
249 end
fully_validate_integer(val, attr_def:, attr_name: nil) click to toggle source

run all the possible validations on an integer

    # File lib/jamf/oapi_validate.rb
111 def fully_validate_integer(val, attr_def:, attr_name: nil)
112   val = integer val, attr_name: attr_name
113   validate_numeric_constraints(val, attr_def: attr_def, attr_name: attr_name)
114 end
fully_validate_number(val, attr_def:, attr_name: nil) click to toggle source

run all the possible validations on a ‘number’

    # File lib/jamf/oapi_validate.rb
117 def fully_validate_number(val, attr_def:, attr_name: nil)
118   val =
119     if %w[float double].include? attr_def[:format]
120       float val, attr_name: attr_name
121     else
122       number val, attr_name: attr_name
123     end
124   validate_numeric_constraints(val, attr_def: attr_def, attr_name: attr_name)
125 end
fully_validate_string(val, attr_def:, attr_name: nil) click to toggle source

run all the possible validations on a string

    # File lib/jamf/oapi_validate.rb
100 def fully_validate_string(val, attr_def:, attr_name: nil)
101   val = string val, attr_name: attr_name
102 
103   min_length val, min: attr_def[:min_length], attr_name: attr_name if attr_def[:min_length]
104   max_length val, max: attr_def[:max_length], attr_name: attr_name if attr_def[:max_length]
105   matches_pattern val, attr_def[:pattern], attr_name: attr_name if attr_def[:pattern]
106 
107   val
108 end
in_enum(val, enum:, attr_name: nil, msg: nil) click to toggle source

Does a value exist in a given enum array?

@param val [Object] The thing that must be in the enum

@param enum [Array] the enum of allowed values

@param msg A custom error message when the value is invalid

@return [Object] The valid object

    # File lib/jamf/oapi_validate.rb
478 def in_enum(val, enum:, attr_name: nil, msg: nil)
479   return val if  enum.include? val
480 
481   raise_invalid_data_error(msg || "#{attr_name} value must be one of: #{enum.join ', '}")
482 end
integer(val, attr_name: nil, msg: nil) click to toggle source

Confirm that a value is an integer or a string representation of an integer. Return the integer, or raise an error

@param val the value to validate

@param msg A custom error message when the value is invalid

@return [Integer]

    # File lib/jamf/oapi_validate.rb
227 def integer(val, attr_name: nil, msg: nil)
228   val = val.to_i if val.is_a?(String) && val.j_integer?
229   return val if val.is_a? Integer
230 
231   raise_invalid_data_error(msg || "#{attr_name} value must be an integer")
232 end
matches_pattern(val, pattern:, attr_name: nil, msg: nil) click to toggle source

Does a string match a given regular expression?

@param val [String] The value to match

@param pattern [pattern] the regular expression

@param msg A custom error message when the value is invalid

@return [Object] The valid object

    # File lib/jamf/oapi_validate.rb
494 def matches_pattern(val, pattern:, attr_name: nil, msg: nil)
495   return val if val =~ pattern
496 
497   raise_invalid_data_error(msg || "#{attr_name} value does not match RegExp: #{pattern}")
498 end
max_items(val, max:, attr_name: nil, msg: nil) click to toggle source

validate that the given value contains no more than some maximum number of items

While this is intended for Arrays, it will work for any object that responds to size

@param val [Object] the value to validate

@param max [Object] the maximum number of items allowed

@param msg [String] A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
432 def max_items(val, max:, attr_name: nil, msg: nil)
433   raise ArgumentError, 'max must be a number' unless max.is_a?(Numeric)
434   return val if val.size <= max
435 
436   raise_invalid_data_error(msg || "#{attr_name} value must contain no more than #{max} items")
437 end
max_length(val, max:, attr_name: nil, msg: nil) click to toggle source

validate that the given value’s length is less than or equal to some maximum

While this is intended for Strings, it will work for any object that responds to length

@param val [Object] the value to validate

@param max [Object] the maximum length allowed

@param msg [String] A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
392 def max_length(val, max:, attr_name: nil, msg: nil)
393   raise ArgumentError, 'max must be a number' unless max.is_a?(Numeric)
394   return val if val.length <= max
395 
396   raise_invalid_data_error(msg || "length of #{attr_name} value must be <= #{max}")
397 end
maximum(val, max:, attr_name: nil, exclusive: false, msg: nil) click to toggle source

validate that the given value is less than or equal to some maximum

While intended for Numbers, this will work for any Comparable objects

If exclusive, the max value is excluded from the range and the value must be less than the max.

@param val [Object] the thing to validate

@param max A value that the val must be less than or equal to

@param exclusuve [Boolean] Should the max be excluded from the valid range?

true: val must be < max, false: val must be <= max

@param msg A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
330 def maximum(val, max:, attr_name: nil, exclusive: false, msg: nil)
331   if exclusive
332     return val if val < max
333   elsif val <= max
334     return val
335   end
336   raise_invalid_data_error(msg || "#{attr_name} value must be <= #{max}")
337 end
min_items(val, min:, attr_name: nil, msg: nil) click to toggle source

validate that the given value contains at least some minimum number of items

While this is intended for Arrays, it will work for any object that responds to size

@param val [Object] the value to validate

@param min [Object] the minimum number of items allowed

@param msg [String] A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
412 def min_items(val, min:, attr_name: nil, msg: nil)
413   raise ArgumentError, 'min must be a number' unless min.is_a?(Numeric)
414   return val if val.size >= min
415 
416   raise_invalid_data_error(msg || "#{attr_name} value must contain at least #{min} items")
417 end
min_length(val, min:, attr_name: nil, msg: nil) click to toggle source

validate that the given value’s length is greater than or equal to some minimum

While this is intended for Strings, it will work for any object that responds to length

@param val [Object] the value to validate

@param min [Object] The minimum length allowed

@param msg [String] A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
372 def min_length(val, min:, attr_name: nil, msg: nil)
373   raise ArgumentError, 'min must be a number' unless min.is_a?(Numeric)
374   return val if val.length >= min
375 
376   raise_invalid_data_error(msg || "length of #{attr_name} value must be >= #{min}")
377 end
minimum(val, min:, attr_name: nil, exclusive: false, msg: nil) click to toggle source

validate that the given value is greater than or equal to some minimum

If exclusive, the min value is excluded from the range and the value must be greater than the min.

While intended for Numbers, this will work for any Comparable objects

@param val [Object] the thing to validate

@param min [Object] A value that the val must be greater than or equal to

@param exclusuve [Boolean] Should the min be excluded from the valid range?

true: val must be > min, false: val must be >= min

@param msg [String] A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
303 def minimum(val, min:, attr_name: nil, exclusive: false, msg: nil)
304   if exclusive
305     return val if val > min
306   elsif val >= min
307     return val
308   end
309   raise_invalid_data_error(msg || "#{attr_name} value must be >= #{min}")
310 end
multiple_of(val, multiplier:, attr_name: nil, msg: nil) click to toggle source

Validate that a given number is multiple of some other given number

@param val [Number] the number to validate

@param multiplier [Number] the number what the val must be a multiple of.

this must be positive.

@param msg A custom error message when the value is invalid

@return [String] the valid value

    # File lib/jamf/oapi_validate.rb
350 def multiple_of(val, multiplier:, attr_name: nil, msg: nil)
351   raise ArgumentError, 'multiplier must be a positive number' unless multiplier.is_a?(Numeric) && multiplier.positive?
352   raise Jamf::InvalidDataError, 'Value must be a number' unless val.is_a?(Numeric)
353 
354   return val if (val % multiplier).zero?
355 
356   raise_invalid_data_error(msg || "#{attr_name} value must be a multiple of #{multiplier}")
357 end
not_nil(val, attr_name: nil, msg: nil) click to toggle source

validate that a value is not nil

@param val the value to validate

@param msg A custom error message when the value is invalid

@return [Object] the valid value

    # File lib/jamf/oapi_validate.rb
462 def not_nil(val, attr_name: nil, msg: nil)
463   return val unless val.nil?
464 
465   raise_invalid_data_error(msg || "#{attr_name} value may not be nil")
466 end
number(val, attr_name: nil, msg: nil) click to toggle source

Confirm that a value is an number or a string representation of an number. Return the number, or raise an error

@param val the value to validate

@param msg A custom error message when the value is invalid

@return [Integer]

    # File lib/jamf/oapi_validate.rb
201 def number(val, attr_name: nil, msg: nil)
202   if val.ia_a?(Integer) || val.is_a?(Float)
203     return val
204 
205   elsif val.is_a?(String)
206 
207     if val.j_integer?
208       return val.to_i
209     elsif val.j_float?
210       return val.to_f
211     end
212 
213   end
214 
215   raise_invalid_data_error(msg || "#{attr_name} value must be a number")
216 end
oapi_attr(val, attr_def:, attr_name: nil) click to toggle source

Validate that a value is valid based on its definition in an objects OAPI_PROPERTIES constant.

@param val [Object] The value to validate

@param klass [Class, Symbol] The class which the val must be

@param msg A custom error message when the value is invalid

@return [Boolean] the valid boolean

   # File lib/jamf/oapi_validate.rb
56 def oapi_attr(val, attr_def:, attr_name: nil)
57   # check that the new val is not nil unless nil is OK
58   val = not_nil(val, attr_name: attr_name) unless attr_def[:nil_ok]
59 
60   # if the new val is nil here, then nil is OK andd we shouldn't
61   # check anything else
62   return val if val.nil?
63 
64   val =
65     case attr_def[:class]
66     when :j_id
67       Jamf::Validate.j_id value, attr_name: attr_name
68 
69     when Class
70       class_instance val, klass: attr_def[:class], attr_name: attr_name
71 
72     when :boolean
73       boolean val, attr_name: attr_name
74 
75     when :string
76       fully_validate_string(val, attr_def: attr_def, attr_name: attr_name)
77 
78     when :integer
79       fully_validate_integer(val, attr_def: attr_def, attr_name: attr_name)
80 
81     when :number
82       fully_validate_number(val, attr_def: attr_def, attr_name: attr_name)
83 
84     when :hash
85       hash val, attr_name: attr_name
86 
87     end # case
88 
89   # Now that the val is in whatever correct format after the above tests,
90   # we test for enum membership if needed
91   # otherwise, just return the val
92   if attr_def[:enum]
93     in_enum val, enum: attr_def[:enum], attr_name: attr_name
94   else
95     val
96   end
97 end
object(val, attr_name: nil, msg: nil) click to toggle source

Confirm that a value is a Hash Return the Hash, or raise an error

@param val the value to validate

@param msg A custom error message when the value is invalid

@return [Hash]

    # File lib/jamf/oapi_validate.rb
260 def object(val, attr_name: nil, msg: nil)
261   return val if val.is_a? Hash
262 
263   raise_invalid_data_error(msg || "#{attr_name} value must be a Hash")
264 end
string(val, attr_name: nil, msg: nil, to_s: false) click to toggle source

Confirm that a value is a String Return the String, or raise an error

@param val the value to validate

@param msg A custom error message when the value is invalid

@param to_s: [Boolean] If true, this method always succeds and returns

the result of calling #to_s on the value

@return [Hash]

    # File lib/jamf/oapi_validate.rb
278 def string(val, attr_name: nil, msg: nil, to_s: false)
279   val = val.to_s if to_s
280   return val if val.is_a? String
281 
282   raise_invalid_data_error(msg || "#{attr_name} value must be a String")
283 end
unique_array(val, attr_name: nil, msg: nil) click to toggle source

validate that an array has only unique items, no duplicate values

@param val [Array] The array to validate

@param msg [String] A custom error message when the value is invalid

@param return [Array] the valid array

    # File lib/jamf/oapi_validate.rb
447 def unique_array(val, attr_name: nil, msg: nil)
448   raise ArgumentError, 'Value must be an Array' unless val.is_a?(Array)
449   return val if val.uniq.size == val.size
450 
451   raise_invalid_data_error(msg || "#{attr_name} value must contain only unique items")
452 end
validate_array_constraints(val, attr_def:, attr_name: nil) click to toggle source

run the array constraint validations for an array value. The individual array items must already be validated

    # File lib/jamf/oapi_validate.rb
143 def validate_array_constraints(val, attr_def:, attr_name: nil)
144   min_items val, min: attr_def[:minItems], attr_name: attr_name if attr_def[:minItems]
145   max_items val, max: attr_def[:maxItems], attr_name: attr_name if attr_def[:maxItems]
146   unique_array val, attr_name: attr_name if attr_def[:uniqueItems]
147 
148   val
149 end
validate_numeric_constraints(val, attr_def:, attr_name: nil) click to toggle source

run the numeric constraint validations for any numeric value The number itself must already be validated

    # File lib/jamf/oapi_validate.rb
129 def validate_numeric_constraints(val, attr_def:, attr_name: nil)
130   ex_min = attr_def[:exclusive_minimum]
131   ex_max = attr_def[:exclusive_maximum]
132   mult_of = attr_def[:multiple_of]
133 
134   minimum val, min: attr_def[:minimum], exclusive: ex_min, attr_name: attr_name if attr_def[:minimum]
135   maximum val, max: attr_def[:maximum], exclusive: ex_max, attr_name: attr_name if attr_def[:maximum]
136   multiple_of val, multiplier: mult_of, attr_name: attr_name if mult_of
137 
138   val
139 end