ruby-jss 1.4.1 → 1.6.0

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +95 -0
  3. data/THANKS.md +3 -2
  4. data/lib/jamf.rb +18 -17
  5. data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
  6. data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +109 -101
  7. data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +55 -30
  8. data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
  9. data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
  10. data/lib/jamf/api/connection.rb +13 -9
  11. data/lib/jamf/api/connection/api_error.rb +8 -8
  12. data/lib/jamf/api/connection/token.rb +16 -15
  13. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  14. data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
  15. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  16. data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
  17. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  18. data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
  19. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  20. data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
  21. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  22. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  23. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  24. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  25. data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
  26. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  27. data/lib/jamf/api/mixins/change_log.rb +201 -51
  28. data/lib/jamf/api/{resources/collection_resources/computer.rb → mixins/filterable.rb} +19 -17
  29. data/lib/jamf/api/mixins/pageable.rb +208 -0
  30. data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
  31. data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
  32. data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
  33. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
  34. data/lib/jamf/api/resources/collection_resources/department.rb +0 -2
  35. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +10 -10
  36. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  37. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
  38. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  39. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  40. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  41. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  42. data/lib/jamf/client.rb +3 -3
  43. data/lib/jamf/client/management_action.rb +2 -3
  44. data/lib/jamf/composer.rb +2 -2
  45. data/lib/jamf/utility.rb +35 -7
  46. data/lib/jamf/validate.rb +63 -24
  47. data/lib/jamf/version.rb +1 -1
  48. data/lib/jss.rb +2 -2
  49. data/lib/jss/api_connection.rb +114 -406
  50. data/lib/jss/api_object.rb +3 -19
  51. data/lib/jss/api_object/categorizable.rb +1 -1
  52. data/lib/jss/api_object/computer.rb +13 -0
  53. data/lib/jss/api_object/configuration_profile.rb +61 -5
  54. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  55. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  56. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  57. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  58. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  59. data/lib/jss/api_object/distribution_point.rb +2 -2
  60. data/lib/jss/api_object/dock_item.rb +102 -96
  61. data/lib/jss/api_object/extendable.rb +1 -1
  62. data/lib/jss/api_object/group.rb +33 -2
  63. data/lib/jss/api_object/network_segment.rb +45 -13
  64. data/lib/jss/api_object/patch_source.rb +10 -9
  65. data/lib/jss/api_object/policy.rb +155 -25
  66. data/lib/jss/api_object/printer.rb +10 -4
  67. data/lib/jss/api_object/scopable.rb +10 -15
  68. data/lib/jss/api_object/scopable/scope.rb +31 -30
  69. data/lib/jss/api_object/script.rb +242 -352
  70. data/lib/jss/api_object/user.rb +1 -1
  71. data/lib/jss/client/management_action.rb +1 -2
  72. data/lib/jss/composer.rb +2 -2
  73. data/lib/jss/exceptions.rb +3 -0
  74. data/lib/jss/server.rb +15 -0
  75. data/lib/jss/utility.rb +213 -45
  76. data/lib/jss/version.rb +1 -1
  77. metadata +46 -64
  78. data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
  79. data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
  80. data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
  81. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
  82. data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
  83. data/lib/jamf/api/json_objects/android_details.rb +0 -139
  84. data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
  85. data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
  86. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
  87. data/lib/jamf/api/json_objects/criterion.rb +0 -152
  88. data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
  89. data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
  90. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
  91. data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
  92. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
  93. data/lib/jamf/api/json_objects/ios_details.rb +0 -244
  94. data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
  95. data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
  96. data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
  97. data/lib/jamf/api/mixins/locatable.rb +0 -124
  98. data/lib/jamf/api/mixins/referable.rb +0 -92
  99. data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
  100. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
  101. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
  102. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +0 -45
  103. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
  104. data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
  105. data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
  106. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
  107. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
@@ -120,30 +120,31 @@ module JSS
120
120
 
121
121
  # Fetch either an internal or external patch source
122
122
  #
123
- # BUG: there's an API bug: fetching a non-existent ids
123
+ # BUG: there's an API bug: fetching a non-existent
124
124
  # which is why we rescue internal server errors.
125
125
  #
126
126
  # @see APIObject.fetch
127
127
  #
128
- def self.fetch(arg, api: JSS.api)
128
+ def self.fetch(searchterm = nil, **args)
129
129
  if self == JSS::PatchSource
130
130
  begin
131
- fetched = JSS::PatchInternalSource.fetch arg, api: api
132
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
131
+ fetched = JSS::PatchInternalSource.fetch searchterm, **args
132
+ rescue
133
133
  fetched = nil
134
134
  end
135
135
  unless fetched
136
136
  begin
137
- fetched = JSS::PatchExternalSource.fetch arg, api: api
138
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
137
+ fetched = JSS::PatchExternalSource.fetch searchterm, **args
138
+ rescue
139
139
  raise JSS::NoSuchItemError, 'No matching PatchSource found'
140
140
  end
141
141
  end
142
142
  return fetched
143
143
  end # if self == JSS::PatchSource
144
+
144
145
  begin
145
- super
146
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
146
+ super searchterm, **args
147
+ rescue JSS::NoSuchItemError
147
148
  raise JSS::NoSuchItemError, "No matching #{self::RSRC_OBJECT_KEY} found"
148
149
  end
149
150
  end
@@ -211,7 +212,7 @@ module JSS
211
212
  begin
212
213
  # TODO: remove this and adjust parsing when jamf fixes the JSON
213
214
  raw = JSS::XMLWorkaround.data_via_xml(rsrc, AVAILABLE_TITLES_DATA_MAP, api)
214
- rescue RestClient::ResourceNotFound
215
+ rescue JSS::NoSuchItemError
215
216
  return []
216
217
  end
217
218
 
@@ -263,14 +263,14 @@ module JSS
263
263
  }.freeze
264
264
 
265
265
  LOG_FLUSH_INTERVAL_PERIODS = {
266
- day: 'Day',
267
- days: 'Day',
268
- week: 'Week',
269
- weeks: 'Week',
270
- month: 'Month',
271
- months: 'Month',
272
- year: 'Year',
273
- years: 'Year'
266
+ day: 'Days',
267
+ days: 'Days',
268
+ week: 'Weeks',
269
+ weeks: 'Weeks',
270
+ month: 'Months',
271
+ months: 'Months',
272
+ year: 'Years',
273
+ years: 'Years'
274
274
  }.freeze
275
275
 
276
276
  # the object type for this object in
@@ -287,6 +287,86 @@ module JSS
287
287
  # How is the category stored in the API data?
288
288
  CATEGORY_DATA_TYPE = Hash
289
289
 
290
+ # All valid script parameters
291
+ SCRIPT_PARAMETERS_AVAILABLE = %i[parameter4 parameter5 parameter6 parameter7 parameter8 parameter9 parameter10 parameter11].freeze
292
+
293
+ # Class Methods
294
+ ######################
295
+
296
+ # Flush logs for a given policy older than some number of days, weeks,
297
+ # months or years, possibly limited to one or more computers.
298
+ #
299
+ # With no parameters, flushes all logs for the policy for all computers.
300
+ #
301
+ # NOTE: Currently the API doesn't have a way to flush only failed policies.
302
+ #
303
+ # WARNING: Log flushing can take a long time, and the API call doesnt return
304
+ # until its finished. The connection timeout will be temporarily raised to
305
+ # 30 minutes, unless it's already higher.
306
+ #
307
+ # @param policy[Integer,String] The id or name of the policy to flush
308
+ #
309
+ # @param older_than[Integer] 0, 1, 2, 3, or 6
310
+ #
311
+ # @param period[Symbol] :days, :weeks, :months, or :years
312
+ #
313
+ # @param computers[Array<Integer,String>] Identifiers of the target computers
314
+ # either ids, names, SNs, macaddrs, or UDIDs. If omitted, flushes logs for
315
+ # all computers
316
+ #
317
+ # @param api [JSS::APIConnection] the API connection to use.
318
+ #
319
+ # @return [void]
320
+ #
321
+ def self.flush_logs(policy, older_than: 0, period: :days, computers: [], api: JSS.api)
322
+ orig_timeout = api.cnx.options.timeout
323
+ pol_id = valid_id policy
324
+ raise JSS::NoSuchItemError, "No Policy identified by '#{policy}'." unless pol_id
325
+
326
+ older_than = LOG_FLUSH_INTERVAL_INTEGERS[older_than]
327
+ raise JSS::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}" unless older_than
328
+
329
+ period = LOG_FLUSH_INTERVAL_PERIODS[period]
330
+ raise JSS::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}" unless period
331
+
332
+ computers = [computers] unless computers.is_a? Array
333
+
334
+ # log flushes can be really slow
335
+ api.timeout = 1800 unless orig_timeout && orig_timeout > 1800
336
+
337
+ return api.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{pol_id}/interval/#{older_than}+#{period}" if computers.empty?
338
+
339
+ flush_logs_for_specific_computers pol_id, older_than, period, computers, api
340
+ ensure
341
+ api.timeout = orig_timeout
342
+ end
343
+
344
+ # use an XML body in a DELETE request to flush logs for
345
+ # a list of computers - used by the flush_logs class method
346
+ def self.flush_logs_for_specific_computers(pol_id, older_than, period, computers, api)
347
+ # build the xml body for a DELETE request
348
+ xml_doc = REXML::Document.new JSS::APIConnection::XML_HEADER
349
+ lf = xml_doc.add_element 'logflush'
350
+ lf.add_element('log').text = 'policy'
351
+ lf.add_element('log_id').text = pol_id.to_s
352
+ lf.add_element('interval').text = "#{older_than} #{period}"
353
+ comps_elem = lf.add_element 'computers'
354
+ computers.each do |c|
355
+ id = JSS::Computer.valid_id c
356
+ next unless id
357
+
358
+ ce = comps_elem.add_element 'computer'
359
+ ce.add_element('id').text = id.to_s
360
+ end
361
+
362
+ # Do a DELETE request with a body.
363
+ api.cnx.delete(LOG_FLUSH_RSRC) do |req|
364
+ req.headers[JSS::APIConnection::HTTP_CONTENT_TYPE_HEADER] = JSS::APIConnection::MIME_XML
365
+ req.body = xml_doc.to_s
366
+ end
367
+ end
368
+ private_class_method :flush_logs_for_specific_computers
369
+
290
370
  # Attributes
291
371
  ######################
292
372
 
@@ -1408,6 +1488,53 @@ module JSS
1408
1488
  removed
1409
1489
  end
1410
1490
 
1491
+ # Set a script parameter
1492
+ #
1493
+ # @param identifier [Integer,String] identifier the id or name of a script in this policy
1494
+ #
1495
+ # @param opts [Hash] opts the options to alter for this script
1496
+ #
1497
+ # @option [String] parameter4: the value of the 4th parameter passed to the script. this
1498
+ # overrides the same parameter in the script object itself.
1499
+ #
1500
+ # @option [String] parameter5: the value of the 5th parameter passed to the script. this
1501
+ # overrides the same parameter in the script object itself.
1502
+ #
1503
+ # @option [String] parameter6: the value of the 6th parameter passed to the script. this
1504
+ # overrides the same parameter in the script object itself.
1505
+ #
1506
+ # @option [String] parameter7: the value of the 7th parameter passed to the script. this
1507
+ # overrides the same parameter in the script object itself.
1508
+ #
1509
+ # @option [String] parameter8: the value of the 8th parameter passed to the script. this
1510
+ # overrides the same parameter in the script object itself.
1511
+ #
1512
+ # @option [String] parameter9: the value of the 9th parameter passed to the script. this
1513
+ # overrides the same parameter in the script object itself.
1514
+ #
1515
+ # @option [String] parameter10: the value of the 10th parameter passed to the script. this
1516
+ # overrides the same parameter in the script object itself.
1517
+ #
1518
+ # @option [String] parameter11: the value of the 11th parameter passed to the script. this
1519
+ # overrides the same parameter in the script object itself.
1520
+ #
1521
+ # @return [Array] the scripts array
1522
+ #
1523
+ def set_script_parameters(identifier, **opts)
1524
+ id = JSS::Script.valid_id identifier, api: @api
1525
+ raise JSS::NoSuchItemError, "No script matches '#{identifier}'" unless id
1526
+
1527
+ script_data = @scripts.select { |s| s[:id] == id }[0]
1528
+ raise JSS::InvalidDataError, "Script #{id} is not configured. Use add_script method." unless script_data
1529
+
1530
+ opts.each do |parameter, value|
1531
+ script_data[parameter] = value if SCRIPT_PARAMETERS_AVAILABLE.include? parameter
1532
+ end
1533
+
1534
+ @need_to_update = true
1535
+ @scripts
1536
+ end # end set_script_parameter
1537
+
1411
1538
  ###### Directory Bindings
1412
1539
 
1413
1540
  # @return [Array] the id's of the directory_bindings handled by the policy
@@ -1715,34 +1842,37 @@ module JSS
1715
1842
  end
1716
1843
  alias execute run
1717
1844
 
1718
- # Flush all policy logs for this policy older than
1719
- # some number of days, weeks, months or years.
1845
+ # Flush logs for this policy older than
1846
+ # some number of days, weeks, months or years, possibly limited to
1847
+ # one or more computers
1848
+ #
1849
+ # With no parameters, flushes all logs for all computers
1720
1850
  #
1721
- # With no parameters, flushes all logs
1851
+ # NOTE: Currently the API doesn't have a way to flush only failed policies.
1722
1852
  #
1723
- # NOTE: Currently the API doesn't have a way to
1724
- # flush only failed policies.
1853
+ # WARNING: Log flushing can take a long time, and the API call doesnt return
1854
+ # until its finished. The connection timeout will be temporarily raised to
1855
+ # 30 minutes, unless it's already higher.
1725
1856
  #
1726
1857
  # @param older_than[Integer] 0, 1, 2, 3, or 6
1727
1858
  #
1728
1859
  # @param period[Symbol] :days, :weeks, :months, or :years
1729
1860
  #
1861
+ # @param computers[Array<Integer,String>] Identifiers of the target computers
1862
+ # either ids, names, SNs, macaddrs, or UDIDs
1863
+ #
1730
1864
  # @return [void]
1731
1865
  #
1732
- def flush_logs(older_than: 0, period: :days)
1866
+ def flush_logs(older_than: 0, period: :days, computers: [])
1733
1867
  raise JSS::NoSuchItemError, "Policy doesn't exist in the JSS. Use #create first." unless @in_jss
1734
1868
 
1735
- unless LOG_FLUSH_INTERVAL_INTEGERS.key?(older_than)
1736
- raise JSS::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}"
1737
- end
1738
-
1739
- unless LOG_FLUSH_INTERVAL_PERIODS.key?(period)
1740
- raise JSS::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}"
1741
- end
1742
-
1743
- interval = "#{LOG_FLUSH_INTERVAL_INTEGERS[older_than]}+#{LOG_FLUSH_INTERVAL_PERIODS[period]}"
1744
-
1745
- @api.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{@id}/interval/#{interval}"
1869
+ JSS::Policy.flush_logs(
1870
+ @id,
1871
+ older_than: older_than,
1872
+ period: period,
1873
+ computers: computers,
1874
+ api: @api
1875
+ )
1746
1876
  end
1747
1877
 
1748
1878
  # Private Instance Methods
@@ -376,9 +376,9 @@ module JSS
376
376
  #
377
377
  # @author Tyler Morgan
378
378
  #
379
- # @param newvalue [String]
379
+ # @param newvalue [String, Float, Array[String], Array[Float]]
380
380
  #
381
- # @raise [JSS::InvalidDataError] If newvalue is not a String
381
+ # @raise [JSS::InvalidDataError] If newvalue is not a String, Float, Array containing Strings, or Array containing Floats.
382
382
  #
383
383
  # @example Limit Printer object to only High Sierra devices and Mojave 10.14.5 OS versions
384
384
  # printer.os_requirements = "10.13.x, 10.14.5"
@@ -386,8 +386,14 @@ module JSS
386
386
  # @return [void]
387
387
  def os_requirements=(newvalue)
388
388
 
389
- raise JSS::InvalidDataError, "os_requirements must be a string." unless newvalue.is_a? String
390
-
389
+ if newvalue.is_a? Array
390
+ # Parse Array
391
+ raise JSS::InvalidDataError, "If setting os_requirements with an array, it must contain strings or floats." unless newvalue[0].is_a?(String) || newvalue[0].is_a?(Float)
392
+ newvalue = newvalue.map { |x| x.to_s }.join(',')
393
+ else
394
+ raise JSS::InvalidDataError, "os_requirements must either be a string, float, or an array containing strings or floats." unless (newvalue.is_a?(String) || newvalue.is_a?(Float)) && !newvalue.nil?
395
+ end
396
+
391
397
  @os_requirements = newvalue
392
398
 
393
399
  @need_to_update = true
@@ -100,22 +100,17 @@ module JSS
100
100
  @need_to_update = true if @in_jss
101
101
  end
102
102
 
103
-
104
- ### A wrapper around the update method, to try catching RestClient::Conflict
105
- ### 409 errors when we couldn't verify all ldap users/groups due to lack of ldap connections
106
- ###
103
+ # A wrapper around the update method, to try catching 409 conflict errors
104
+ # when we couldn't verify all ldap users/groups due to lack of ldap connections
105
+ #
107
106
  def update
108
- begin
109
- super
110
-
111
- rescue RestClient::Conflict => conflict
112
- if self.scope.unable_to_verify_ldap_entries == true
113
- raise JSS::InvalidDataError, "Potentially non-existant LDAP user or group in new scope values."
114
- else
115
- raise conflict
116
- end
117
-
118
- end # begin
107
+ super
108
+ rescue JSS::ConflictError => conflict
109
+ if scope.unable_to_verify_ldap_entries == true
110
+ raise JSS::InvalidDataError, "Potentially non-existant LDAP user or group in new scope values."
111
+ else
112
+ raise conflict
113
+ end
119
114
  end # update
120
115
 
121
116
  end # module Scopable
@@ -224,6 +224,7 @@ module JSS
224
224
  # A reference to the object that contains this Scope
225
225
  #
226
226
  # For telling it when a change is made and an update needed
227
+ # and for accessing its api connection
227
228
  attr_accessor :container
228
229
 
229
230
  # @return [Boolean] should we expect a potential 409 Conflict
@@ -246,7 +247,6 @@ module JSS
246
247
  attr_reader :all_targets
247
248
  alias all_targets? all_targets
248
249
 
249
-
250
250
  # The items which form the base scope of included targets
251
251
  #
252
252
  # This is the group of targets to which the limitations and exclusions apply.
@@ -408,7 +408,7 @@ module JSS
408
408
  @exclusions = {}
409
409
  @exclusion_keys.each { |k| @exclusions[k] = [] }
410
410
  end
411
- @container.should_update if @container
411
+ @container&.should_update
412
412
  end
413
413
 
414
414
  # Replace a list of item names for as targets in this scope.
@@ -436,7 +436,7 @@ module JSS
436
436
  list.map! do |ident|
437
437
  item_id = validate_item(:target, key, ident)
438
438
 
439
- if @exclusions[key] && @exclusions[key].include?(item_id)
439
+ if @exclusions[key]&.include?(item_id)
440
440
  raise JSS::AlreadyExistsError, \
441
441
  "Can't set #{key} target to '#{ident}' because it's already an explicit exclusion."
442
442
  end
@@ -448,7 +448,7 @@ module JSS
448
448
 
449
449
  @targets[key] = list
450
450
  @all_targets = false
451
- @container.should_update if @container
451
+ @container&.should_update
452
452
  end # sinclude_in_scope
453
453
  alias set_target set_targets
454
454
  alias set_inclusion set_targets
@@ -474,13 +474,13 @@ module JSS
474
474
  def add_target(key, item)
475
475
  key = pluralize_key(key)
476
476
  item_id = validate_item(:target, key, item)
477
- return if @targets[key] && @exclusions[key].include?(item_id)
477
+ return if @targets[key]&.include?(item_id)
478
478
 
479
- raise JSS::AlreadyExistsError, "Can't set #{key} target to '#{item}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item_id)
479
+ raise JSS::AlreadyExistsError, "Can't set #{key} target to '#{item}' because it's already an explicit exclusion." if @exclusions[key]&.include?(item_id)
480
480
 
481
481
  @targets[key] << item_id
482
482
  @all_targets = false
483
- @container.should_update if @container
483
+ @container&.should_update
484
484
  end
485
485
  alias add_inclusion add_target
486
486
 
@@ -499,10 +499,10 @@ module JSS
499
499
  key = pluralize_key(key)
500
500
  item_id = validate_item :target, key, item, error_if_not_found: false
501
501
  return unless item_id
502
- return unless @targets[key] && @exclusions[key].include?(item_id)
502
+ return unless @targets[key]&.include?(item_id)
503
503
 
504
504
  @targets[key].delete item_id
505
- @container.should_update if @container
505
+ @container&.should_update
506
506
  end
507
507
  alias remove_inclusion remove_target
508
508
 
@@ -529,7 +529,7 @@ module JSS
529
529
  # check the idents
530
530
  list.map! do |ident|
531
531
  item_id = validate_item(:limitation, key, ident)
532
- if @exclusions[key] && @exclusions[key].include?(item_id)
532
+ if @exclusions[key]&.include?(item_id)
533
533
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
534
534
  end
535
535
 
@@ -539,7 +539,7 @@ module JSS
539
539
  return nil if list.sort == @limitations[key].sort
540
540
 
541
541
  @limitations[key] = list
542
- @container.should_update if @container
542
+ @container&.should_update
543
543
  end # set_limitation
544
544
  alias set_limitations set_limitation
545
545
 
@@ -561,14 +561,14 @@ module JSS
561
561
  def add_limitation(key, item)
562
562
  key = pluralize_key(key)
563
563
  item_id = validate_item(:limitation, key, item)
564
- return nil if @limitations[key] && @exclusions[key].include?(item_id)
564
+ return nil if @limitations[key]&.include?(item_id)
565
565
 
566
- if @exclusions[key] && @exclusions[key].include?(item_id)
566
+ if @exclusions[key]&.include?(item_id)
567
567
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
568
568
  end
569
569
 
570
570
  @limitations[key] << item_id
571
- @container.should_update if @container
571
+ @container&.should_update
572
572
  end
573
573
 
574
574
  # Remove a single item for limiting this scope.
@@ -588,10 +588,10 @@ module JSS
588
588
  key = pluralize_key(key)
589
589
  item_id = validate_item :limitation, key, item, error_if_not_found: false
590
590
  return unless item_id
591
- return unless @limitations[key] && @exclusions[key].include?(item_id)
591
+ return unless @limitations[key]&.include?(item_id)
592
592
 
593
593
  @limitations[key].delete item_id
594
- @container.should_update if @container
594
+ @container&.should_update
595
595
  end ###
596
596
 
597
597
  # Replace an exclusion list for this scope
@@ -617,7 +617,9 @@ module JSS
617
617
  item_id = validate_item(:exclusion, key, ident)
618
618
  case key
619
619
  when *@target_keys
620
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included." if @targets[key] && @exclusions[key].include?(item_id)
620
+ if @targets[key] && @exclusions[key].include?(item_id)
621
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included."
622
+ end
621
623
  when *LIMITATIONS
622
624
  if @limitations[key] && @exclusions[key].include?(item_id)
623
625
  raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already an explicit limitation."
@@ -629,7 +631,7 @@ module JSS
629
631
  return nil if list.sort == @exclusions[key].sort
630
632
 
631
633
  @exclusions[key] = list
632
- @container.should_update if @container
634
+ @container&.should_update
633
635
  end # limit scope
634
636
 
635
637
  # Add a single item for exclusions of this scope.
@@ -648,14 +650,14 @@ module JSS
648
650
  def add_exclusion(key, item)
649
651
  key = pluralize_key(key)
650
652
  item_id = validate_item(:exclusion, key, item)
651
- return if @exclusions[key] && @exclusions[key].include?(item_id)
653
+ return if @exclusions[key]&.include?(item_id)
652
654
 
653
- raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @targets[key] && @targets[key].include?(item)
655
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @targets[key]&.include?(item)
654
656
 
655
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item)
657
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key]&.include?(item)
656
658
 
657
659
  @exclusions[key] << item_id
658
- @container.should_update if @container
660
+ @container&.should_update
659
661
  end
660
662
 
661
663
  # Remove a single item for exclusions of this scope
@@ -672,10 +674,10 @@ module JSS
672
674
  def remove_exclusion(key, item)
673
675
  key = pluralize_key(key)
674
676
  item_id = validate_item :exclusion, key, item, error_if_not_found: false
675
- return unless @exclusions[key] && @exclusions[key].include?(item_id)
677
+ return unless @exclusions[key]&.include?(item_id)
676
678
 
677
679
  @exclusions[key].delete item_id
678
- @container.should_update if @container
680
+ @container&.should_update
679
681
  end
680
682
 
681
683
  # @api private
@@ -773,7 +775,7 @@ module JSS
773
775
  ################
774
776
  def scoped_machines
775
777
  scoped_machines = {}
776
- @target_class.all_objects.each do |machine|
778
+ @target_class.all_objects(api: container.api).each do |machine|
777
779
  scoped_machines[machine.id] = machine.name if in_scope? machine
778
780
  end
779
781
  scoped_machines
@@ -809,7 +811,6 @@ module JSS
809
811
  a_target?(machine_data) && within_limitations?(machine_data) && !excluded?(machine_data)
810
812
  end
811
813
 
812
-
813
814
  # Private Instance Methods
814
815
  #####################################
815
816
  private
@@ -850,15 +851,15 @@ module JSS
850
851
 
851
852
  # id will be a string
852
853
  if key == :jamf_ldap_users
853
- id = ident if JSS::User.all_names(:refresh).include?(ident) || JSS::LDAPServer.user_in_ldap?(ident)
854
+ id = ident if JSS::User.all_names(:refresh, api: container.api).include?(ident) || JSS::LDAPServer.user_in_ldap?(ident)
854
855
 
855
856
  # id will be a string
856
857
  elsif key == :ldap_user_groups
857
- id = ident if JSS::LDAPServer.group_in_ldap? ident
858
+ id = ident if JSS::LDAPServer.group_in_ldap? ident, api: container.api
858
859
 
859
860
  # id will be an integer
860
861
  else
861
- id = SCOPING_CLASSES[key].valid_id ident
862
+ id = SCOPING_CLASSES[key].valid_id ident, api: container.api
862
863
  end
863
864
 
864
865
  raise JSS::NoSuchItemError, "No existing #{key} matching '#{ident}'" if error_if_not_found && id.nil?
@@ -930,7 +931,7 @@ module JSS
930
931
  # @return [Array] the general, locacation, and parsed group IDs
931
932
  #
932
933
  def fetch_subsets(ident)
933
- id = @target_class.valid_id ident
934
+ id = @target_class.valid_id ident, api: container.api
934
935
  raise JSS::NoSuchItemError, "No #{@target_class} matching #{machine}" unless id
935
936
 
936
937
  if @target_class == JSS::MobileDevice