ruby-jss 1.2.10 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

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