ruby-jss 1.2.10 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +208 -1
  3. data/lib/jamf.rb +18 -16
  4. data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
  5. data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +110 -102
  6. data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +56 -31
  7. data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
  8. data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
  9. data/lib/jamf/api/connection.rb +20 -12
  10. data/lib/jamf/api/connection/api_error.rb +8 -8
  11. data/lib/jamf/api/connection/token.rb +36 -15
  12. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  13. data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
  14. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  15. data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
  16. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  17. data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
  20. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  21. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  22. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  23. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  24. data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
  25. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  26. data/lib/jamf/api/mixins/change_log.rb +201 -51
  27. data/lib/jamf/api/{resources/collection_resources/extension_attribute.rb → mixins/filterable.rb} +20 -14
  28. data/lib/jamf/api/mixins/pageable.rb +208 -0
  29. data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
  30. data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
  31. data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
  32. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
  33. data/lib/jamf/api/resources/collection_resources/department.rb +1 -3
  34. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
  35. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  36. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
  37. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  38. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  39. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  40. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  41. data/lib/jamf/configuration.rb +7 -9
  42. data/lib/jamf/ruby_extensions.rb +1 -0
  43. data/lib/jamf/ruby_extensions/array.rb +1 -1
  44. data/lib/jamf/ruby_extensions/array/utils.rb +3 -3
  45. data/lib/jamf/{api/resources/collection_resources/computer.rb → ruby_extensions/dig.rb} +22 -19
  46. data/lib/jamf/validate.rb +63 -24
  47. data/lib/jamf/version.rb +1 -1
  48. data/lib/jss.rb +4 -1
  49. data/lib/jss/api_connection.rb +111 -433
  50. data/lib/jss/api_object.rb +16 -13
  51. data/lib/jss/api_object/advanced_search.rb +27 -26
  52. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  53. data/lib/jss/api_object/categorizable.rb +1 -1
  54. data/lib/jss/api_object/computer.rb +13 -0
  55. data/lib/jss/api_object/configuration_profile.rb +60 -4
  56. data/lib/jss/api_object/directory_binding.rb +273 -0
  57. data/lib/jss/api_object/directory_binding_type.rb +96 -0
  58. data/lib/jss/api_object/directory_binding_type/active_directory.rb +539 -0
  59. data/lib/jss/api_object/directory_binding_type/admitmac.rb +594 -0
  60. data/lib/jss/api_object/directory_binding_type/centrify.rb +226 -0
  61. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  62. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  63. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  64. data/lib/jss/api_object/distribution_point.rb +97 -37
  65. data/lib/jss/api_object/dock_item.rb +143 -0
  66. data/lib/jss/api_object/ebook.rb +1 -2
  67. data/lib/jss/api_object/extendable.rb +1 -1
  68. data/lib/jss/api_object/extension_attribute.rb +4 -3
  69. data/lib/jss/api_object/group.rb +33 -2
  70. data/lib/jss/api_object/mac_application.rb +107 -8
  71. data/lib/jss/api_object/mobile_device_application.rb +12 -0
  72. data/lib/jss/api_object/network_segment.rb +195 -70
  73. data/lib/jss/api_object/package.rb +105 -40
  74. data/lib/jss/api_object/patch_source.rb +10 -9
  75. data/lib/jss/api_object/policy.rb +596 -32
  76. data/lib/jss/api_object/printer.rb +446 -0
  77. data/lib/jss/api_object/scopable.rb +10 -15
  78. data/lib/jss/api_object/scopable/scope.rb +371 -55
  79. data/lib/jss/api_object/self_servable.rb +17 -9
  80. data/lib/jss/api_object/uploadable.rb +1 -1
  81. data/lib/jss/api_object/user.rb +42 -1
  82. data/lib/jss/api_object/vpp_account.rb +209 -0
  83. data/lib/jss/api_object/vppable.rb +169 -13
  84. data/lib/jss/composer.rb +1 -1
  85. data/lib/jss/exceptions.rb +3 -0
  86. data/lib/jss/server.rb +15 -0
  87. data/lib/jss/utility.rb +143 -52
  88. data/lib/jss/validate.rb +53 -10
  89. data/lib/jss/version.rb +1 -1
  90. metadata +56 -61
  91. data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
  92. data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
  93. data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
  94. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
  95. data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
  96. data/lib/jamf/api/json_objects/android_details.rb +0 -139
  97. data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
  98. data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
  99. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
  100. data/lib/jamf/api/json_objects/criterion.rb +0 -152
  101. data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
  102. data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
  103. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
  104. data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
  105. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
  106. data/lib/jamf/api/json_objects/ios_details.rb +0 -244
  107. data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
  108. data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
  109. data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
  110. data/lib/jamf/api/mixins/locatable.rb +0 -124
  111. data/lib/jamf/api/mixins/referable.rb +0 -92
  112. data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
  113. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
  114. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
  115. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
  116. data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
  117. data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
  118. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
  119. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
@@ -147,7 +147,7 @@ module JSS
147
147
 
148
148
  ### now build the pkg
149
149
  begin
150
- it_built = system "#{PKGBUILD} --identifier '#{pkg_id}' --version '#{version}' --ownership #{pkg_ownership} --install-location / --root '#{root}' #{signing} #{comp_plist_arg} '#{pkg_out}' "
150
+ it_built = system "#{PKGBUILD} --identifier '#{pkg_id}' --version '#{version}' --ownership #{pkg_ownership} --install-location / --root '#{root}' #{signing} #{comp_plist_arg} '#{pkg_out}'"
151
151
 
152
152
  raise 'There was an error building the .pkg' unless it_built
153
153
  ensure
@@ -87,6 +87,9 @@ module JSS
87
87
  ###
88
88
  class AuthenticationError < RuntimeError; end
89
89
 
90
+ ###
91
+ class AuthorizationError < RuntimeError ; end
92
+
90
93
  ### ConflictError - raise this when
91
94
  ### attempts to PUT or PUSH to the API
92
95
  ### result in a 409 Conflict http error.
@@ -110,6 +110,21 @@ module JSS
110
110
  @act_code_data[:code]
111
111
  end
112
112
 
113
+ # Update the activation code and organization name for this server
114
+ #
115
+ # @param org: [String] the organization to which the server is licensed
116
+ # @param code: [String ] the activation code for the server licence
117
+ #
118
+ # @return [void]
119
+ def update_activation_code(org:, code:)
120
+ xml = REXML::Document.new JSS::APIConnection::XML_HEADER
121
+ acode = xml.add_element ACTIVATION_CODE_KEY.to_s
122
+ acode.add_element('organization_name').text = org
123
+ acode.add_element('code').text = code
124
+
125
+ @api.put_rsrc ACTIVATION_CODE_RSRC, xml.to_s
126
+ end
127
+
113
128
  # Remove the api object from
114
129
  # the instance_variables used to create
115
130
  # pretty-print (pp) output.
@@ -23,73 +23,157 @@
23
23
  #
24
24
  #
25
25
 
26
- #
27
26
  module JSS
28
27
 
29
28
  # A collection of useful utility methods. Mostly for
30
29
  # converting values between formats, parsing data, and
31
30
  # user interaction.
32
31
 
33
- # Converts an OS Version into an Array of higher OS versions.
32
+ # Hash of 'minor' => 'maint'
33
+ # The maximum maint release for macOS 10.minor.maint
34
+ # e.g the highest release of 10.6 was 10.6.8, the highest release of
35
+ # 10.15 was 10.15.7
36
+ #
37
+ # 12 is the default for the current OS and higher
38
+ # (and hoping apple doesn't release 10.16.13)
39
+ OS_TEN_MAXS = {
40
+ 2 => 8,
41
+ 3 => 9,
42
+ 4 => 11,
43
+ 5 => 8,
44
+ 6 => 8,
45
+ 7 => 5,
46
+ 8 => 5,
47
+ 9 => 5,
48
+ 10 => 5,
49
+ 11 => 6,
50
+ 12 => 6,
51
+ 13 => 6,
52
+ 14 => 6,
53
+ 15 => 7,
54
+ 16 => 12
55
+ }
56
+
57
+ # Hash of 'major' => 'minor'
58
+ # The maximum minor release for macOS major.minor
59
+ # e.g. the highest release of 11 is 11.12
60
+ #
61
+ # 12 is the default for the current OS and higher
62
+ # (and hoping apple doesn't release 11.13)
63
+ MAC_OS_MAXS = {
64
+ 11 => 12,
65
+ 12 => 12,
66
+ 13 => 12,
67
+ 14 => 12,
68
+ 15 => 12,
69
+ 16 => 12,
70
+ 17 => 12,
71
+ 18 => 12,
72
+ 19 => 12,
73
+ 20 => 12
74
+ }
75
+
76
+ # Converts an OS Version into an Array of equal or higher OS versions, up to
77
+ # some non-existant max, hopefully far in the future, currently 20.12
78
+ #
79
+ # This array can then be joined with commas and used as the value of the
80
+ # os_requirements for Packages and Scripts.
81
+ #
82
+ # It's unlikely that this method, as written, will still be in use by
83
+ # the release of macOS 20.12, but currently thats the upper limit.
84
+ #
85
+ # Hopefully well before then JAMF will implement a "minimum OS" in Jamf Pro
86
+ # itself, then we could avoid the inherant limitations in using a method like
87
+ # this.
34
88
  #
35
- # It's unlikely that this library will still be in use as-is by the release of OS X 10.19.15.
36
- # Hopefully well before then JAMF will implement a "minimum OS" in the JSS itself.
89
+ # When the highest maint. release of an OS version is not known, because its
90
+ # the currently released OS version or higher, then this method assumes '12'
91
+ # e.g. '10.16.12', '11.12', '12.12', etc.
37
92
  #
38
- # @param min_os [String] the mimimum OS version to expand, e.g. ">=10.6.7" or "10.6.7"
93
+ # Apple has never released more than 11 updates to a version of macOS
94
+ # (that being 10.4), so hopefully 12 is enough
39
95
  #
40
- # @return [Array] Nearly all potential OS versions from the minimum to 10.19.x.
96
+ # Since Big Sur might report itself as either '10.16.x' or '11.x', this method
97
+ # will allow for both possibilities, and the array will contain whatever
98
+ # iterations needed for both version numbers
99
+ #
100
+ # @param min_os [String] the mimimum OS version to expand, e.g. ">=10.9.4" or "11.1"
101
+ #
102
+ # @return [Array] Nearly all potential OS versions from the minimum to 20.12
41
103
  #
42
104
  # @example
43
- # JSS.expand_min_os ">=10.6.7" # => returns this array
44
- # # ["10.6.7",
45
- # # "10.6.8",
46
- # # "10.6.9",
47
- # # "10.6.10",
48
- # # "10.6.11",
49
- # # "10.6.12",
50
- # # "10.6.13",
51
- # # "10.6.14",
52
- # # "10.6.15",
53
- # # "10.7.x",
54
- # # "10.8.x",
55
- # # "10.9.x",
56
- # # "10.10.x",
57
- # # "10.11.x",
58
- # # "10.12.x",
59
- # # "10.13.x",
60
- # # "10.14.x",
61
- # # "10.15.x",
105
+ # JSS.expand_min_os ">=10.9.4" # => returns this array
106
+ # # ["10.9.4",
107
+ # # "10.9.5",
108
+ # # "10.10.x"
109
+ # # ...
62
110
  # # "10.16.x",
63
- # # "10.17.x",
64
- # # "10.18.x",
65
- # # "10.19.x"]
111
+ # # "11.x",
112
+ # # "12.x",
113
+ # # ...
114
+ # # "20.x"]
66
115
  #
67
116
  #
68
117
  def self.expand_min_os(min_os)
69
118
  min_os = min_os.delete '>='
70
119
 
71
120
  # split the version into major, minor and maintenance release numbers
72
- (maj, min, maint) = min_os.split('.')
121
+ major, minor, maint = min_os.split('.')
73
122
  maint = 'x' if maint.nil? || maint == '0'
74
123
 
75
- # if the maint release number is an "x" just start the list of OK OS's with it
76
- if maint == 'x'
77
- ok_oses = [maj + '.' + min.to_s + '.x']
124
+ ok_oses = []
125
+
126
+ # if major == 11 e.g. big sur, e.g. 10.16,
127
+ # reset major & min so that we get coverage for both
128
+ # 10.16 and 11, since clients may report it as either
129
+ if major == '11'
130
+ major = '10'
131
+ maint = minor
132
+ minor = '16'
133
+ end
134
+
135
+ # Deal with 10.x.x up to 10.16
136
+ if major == '10'
137
+ # if the maint release number is an "x" just start the list of OK OS's with it
138
+ if maint == 'x'
139
+ ok_oses << min_os
140
+
141
+ # otherwise, start with it and explicitly add all maint releases for
142
+ # that maint version. if unknown because its a current or future OS,
143
+ # go as h
144
+ else
145
+ max_maint_for_minor = OS_TEN_MAXS[minor.to_i]
146
+ (maint.to_i..max_maint_for_minor).each do |m|
147
+ ok_oses << "#{major}.#{minor}.#{m}"
148
+ end # each m
149
+ end
150
+
151
+ # now account for all macOS versions starting with 10.
152
+ # up to 10.16.x
153
+ ((minor.to_i + 1)..16).each do |v|
154
+ ok_oses << "#{major}.#{v}.x"
155
+ end # each v
156
+
157
+ # now reset major to 11, so we can continue with BigSur and up
158
+ major = '11'
159
+ minor = minor == '16' ? maint : 'x'
160
+ end # if major == 10
78
161
 
79
- # otherwise, start with it and explicitly add all maint releases up to 15
80
- # (and hope apple doesn't do more than 15 maint releases for an OS)
162
+ # Now deal with Big Sur and higher, macOS 10.16/11
163
+ if minor == 'x'
164
+ ok_oses << "#{major}.#{minor}"
81
165
  else
82
- ok_oses = []
83
- (maint.to_i..15).each do |m|
84
- ok_oses << maj + '.' + min + '.' + m.to_s
166
+ max_minor_for_major = MAC_OS_MAXS[major.to_i]
167
+ (minor.to_i..max_minor_for_major).each do |m|
168
+ ok_oses << "#{major}.#{m}"
85
169
  end # each m
86
- end
170
+ end # if minor == x
87
171
 
88
- # now account for all OS X versions starting with 10.
89
- # up to at least 10.19.x
90
- ((min.to_i + 1)..19).each do |v|
91
- ok_oses << maj + '.' + v.to_s + '.x'
172
+ # now account for all macOS versions 11 and up
173
+ ((major.to_i + 1)..MAC_OS_MAXS.keys.max).each do |v|
174
+ ok_oses << "#{v}.x"
92
175
  end # each v
176
+
93
177
  ok_oses
94
178
  end
95
179
 
@@ -109,6 +193,7 @@ module JSS
109
193
  #
110
194
  def self.processor_ok?(requirement, processor = nil)
111
195
  return true if requirement.to_s.empty? || requirement =~ /none/i
196
+
112
197
  processor ||= `/usr/bin/uname -p`
113
198
  requirement == (processor.to_s.include?('86') ? 'x86' : 'ppc')
114
199
  end
@@ -129,6 +214,7 @@ module JSS
129
214
  def self.os_ok?(requirement, os_to_check = nil)
130
215
  return true if requirement.to_s =~ /none/i
131
216
  return true if requirement.to_s == 'n'
217
+
132
218
  requirement = JSS.to_s_and_a(requirement)[:arrayform]
133
219
  return true if requirement.empty?
134
220
 
@@ -201,6 +287,7 @@ module JSS
201
287
  case plist
202
288
  when String
203
289
  return Plist.parse_xml plist if plist.include? '</plist>'
290
+
204
291
  plist = Pathname.new plist
205
292
  when Pathname
206
293
  true
@@ -237,9 +324,7 @@ module JSS
237
324
 
238
325
  # if the UTC offset of the datetime is zero, make a new one with the correct local offset
239
326
  # (which might also be zero if we happen to be in GMT)
240
- if the_dt.offset.zero?
241
- the_dt = DateTime.new(the_dt.year, the_dt.month, the_dt.day, the_dt.hour, the_dt.min, the_dt.sec, JSS::TIME_ZONE_OFFSET)
242
- end
327
+ the_dt = DateTime.new(the_dt.year, the_dt.month, the_dt.day, the_dt.hour, the_dt.min, the_dt.sec, JSS::TIME_ZONE_OFFSET) if the_dt.offset.zero?
243
328
  # now convert it to a Time and return it
244
329
  Time.at the_dt.strftime('%s').to_i, usec
245
330
  end # parse_time
@@ -261,6 +346,7 @@ module JSS
261
346
  #
262
347
  def self.epoch_to_time(epoch)
263
348
  return nil if NIL_DATES.include? epoch
349
+
264
350
  Time.at(epoch.to_i / 1000.0)
265
351
  end # parse_date
266
352
 
@@ -280,6 +366,7 @@ module JSS
280
366
  def self.api_object_class(name)
281
367
  klass = api_object_names[name.downcase.to_sym]
282
368
  raise JSS::InvalidDataError, "Unknown API Object Class: #{name}" unless klass
369
+
283
370
  klass
284
371
  end
285
372
 
@@ -297,11 +384,13 @@ module JSS
297
384
  #
298
385
  def self.api_object_names
299
386
  return @api_object_names if @api_object_names
387
+
300
388
  @api_object_names ||= {}
301
389
  JSS.constants.each do |const|
302
390
  klass = JSS.const_get const
303
391
  next unless klass.is_a? Class
304
392
  next unless klass.ancestors.include? JSS::APIObject
393
+
305
394
  @api_object_names[klass.const_get(:RSRC_LIST_KEY).to_sym] = klass if klass.constants.include? :RSRC_LIST_KEY
306
395
  @api_object_names[klass.const_get(:RSRC_OBJECT_KEY).to_sym] = klass if klass.constants.include? :RSRC_OBJECT_KEY
307
396
  end
@@ -338,6 +427,7 @@ module JSS
338
427
  #
339
428
  def self.array_to_rexml_array(element, list)
340
429
  raise JSS::InvalidDataError, 'Arg. must be an Array.' unless list.is_a? Array
430
+
341
431
  element = element.to_s
342
432
  list.map do |v|
343
433
  e = REXML::Element.new(element)
@@ -364,6 +454,7 @@ module JSS
364
454
  #
365
455
  def self.hash_to_rexml_array(hash)
366
456
  raise InvalidDataError, 'Arg. must be a Hash.' unless hash.is_a? Hash
457
+
367
458
  ary = []
368
459
  hash.each_pair do |k, v|
369
460
  el = REXML::Element.new k.to_s
@@ -442,11 +533,11 @@ module JSS
442
533
 
443
534
  {
444
535
  major: major.to_i,
445
- minor: minor.to_i,
446
- revision: revision.to_i,
447
- maint: revision.to_i,
448
- patch: revision.to_i,
449
- build: build,
536
+ minor: minor.to_i,
537
+ revision: revision.to_i,
538
+ maint: revision.to_i,
539
+ patch: revision.to_i,
540
+ build: build,
450
541
  version: Gem::Version.new("#{major}.#{minor}.#{revision}")
451
542
  }
452
543
  end
@@ -471,6 +562,7 @@ module JSS
471
562
  @stdin_lines ||= ($stdin.tty? ? [] : $stdin.read.lines.map { |l| l.chomp("\n") })
472
563
 
473
564
  return @stdin_lines.join("\n") if line <= 0
565
+
474
566
  idx = line - 1
475
567
  @stdin_lines[idx]
476
568
  end
@@ -503,10 +595,9 @@ module JSS
503
595
  # @return [Boolean] The new state of devmode
504
596
  #
505
597
  def self.devmode(setting)
506
- @devmode = setting == :on ? true : false
598
+ @devmode = setting == :on
507
599
  end
508
600
 
509
-
510
601
  # is devmode currently on?
511
602
  #
512
603
  # @return [Boolean]
@@ -111,8 +111,8 @@ module JSS
111
111
 
112
112
  # Confirm that the given value is a boolean value, accepting
113
113
  # strings and symbols and returning real booleans as needed
114
- # Accepts: true, false, 'true', 'false', :true, :false, 'yes', 'no', :yes,
115
- # or :no (all Strings and Symbols are case insensitive)
114
+ # Accepts: true, false, 'true', 'false', 'yes', 'no', 't','f', 'y', or 'n'
115
+ # as strings or symbols, case insensitive
116
116
  #
117
117
  # TODO: use this throughout ruby-jss
118
118
  #
@@ -123,11 +123,11 @@ module JSS
123
123
  # @return [Boolean] the valid boolean
124
124
  #
125
125
  def self.boolean(bool, msg = nil)
126
- msg ||= 'Value must be boolean true or false'
127
126
  return bool if JSS::TRUE_FALSE.include? bool
128
- return true if bool.to_s =~ /^(true|yes)$/i
129
- return false if bool.to_s =~ /^(false|no)$/i
127
+ return true if bool.to_s =~ /^(t(rue)?|y(es)?)$/i
128
+ return false if bool.to_s =~ /^(f(alse)?|no?)$/i
130
129
 
130
+ msg ||= 'Value must be boolean true or false, or an equivalent string or symbol'
131
131
  raise JSS::InvalidDataError, msg
132
132
  end
133
133
 
@@ -176,10 +176,10 @@ module JSS
176
176
  # @return [String] the valid uuid string
177
177
  #
178
178
  def self.uuid(val, msg = nil)
179
- msg ||= 'value must be valid uuid'
180
- raise JSS::InvalidDataError, msg unless val.is_a?(String) && val =~ UUID_RE
179
+ return val if val.is_a?(String) && val =~ UUID_RE
181
180
 
182
- val
181
+ msg ||= 'value must be valid uuid'
182
+ raise JSS::InvalidDataError, msg
183
183
  end
184
184
 
185
185
  # validate that the given value is an integer in the JSS::IBeacon::MAJOR_MINOR_RANGE
@@ -191,13 +191,56 @@ module JSS
191
191
  # @return [String] the valid integer
192
192
  #
193
193
  def self.ibeacon_major_minor(val, msg = nil)
194
- msg ||= "value must be an integer in the range #{JSS::IBeacon::MAJOR_MINOR_RANGE}"
195
194
  val = val.to_i if val.is_a?(String) && val.jss_integer?
196
195
  ok = val.is_a? Integer
197
196
  ok = JSS::IBeacon::MAJOR_MINOR_RANGE.include? val if ok
197
+ return val if ok
198
+
199
+ msg ||= "value must be an integer in the range #{JSS::IBeacon::MAJOR_MINOR_RANGE}"
198
200
  raise JSS::InvalidDataError, msg unless ok
201
+ end
199
202
 
200
- val
203
+ # validate a country name or code from JSS::APP_STORE_COUNTRY_CODES
204
+ # returning the validated code, or raising an error
205
+ #
206
+ # @param country[String] The country name or code
207
+ #
208
+ # @param msg[String] A custom error message when the value is invalid
209
+ #
210
+ # @return [String] the valid two-letter country code
211
+ #
212
+ def self.app_store_country_code(country, msg = nil)
213
+ country = country.to_s.upcase
214
+ return country if JSS::APP_STORE_COUNTRY_CODES.value? country
215
+
216
+ JSS::APP_STORE_COUNTRY_CODES.each do |name, code|
217
+ return code if name.upcase == country
218
+ end
219
+
220
+ msg ||= 'Unknown country name or code. See JSS::APP_STORE_COUNTRY_CODES or JSS.country_code_match(str)'
221
+ raise JSS::InvalidDataError, msg
222
+ end
223
+
224
+ # validate an email address - must match the RegEx /^\S+@\S+\.\S+$/
225
+ # i.e.:
226
+ # 1 or more non-whitespace chars, followed by
227
+ # an @ character, followed by
228
+ # 1 or more non-whitespace chars, followed by
229
+ # a dot, followed by
230
+ # 1 or more non-whitespace chars
231
+ #
232
+ # @param email[String] The email address
233
+ #
234
+ # @param msg[String] A custom error message when the value is invalid
235
+ #
236
+ # @return [String] the validly formatted email address
237
+ #
238
+ def self.email_address(email, msg = nil)
239
+ msg ||= "'#{email}' is not formatted as a valid email address"
240
+ email = email.to_s
241
+ return email if email =~ /^\S+@\S+\.\S+$/
242
+
243
+ raise JSS::InvalidDataError, msg
201
244
  end
202
245
 
203
246
  end # module validate