ruby-jss 1.2.10 → 1.3.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.

Potentially problematic release.


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

Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +92 -1
  3. data/lib/jamf/api/abstract_classes/json_object.rb +1 -1
  4. data/lib/jamf/api/abstract_classes/prestage.rb +1 -1
  5. data/lib/jamf/api/connection.rb +7 -3
  6. data/lib/jamf/configuration.rb +7 -9
  7. data/lib/jamf/ruby_extensions.rb +1 -0
  8. data/lib/jamf/ruby_extensions/array.rb +1 -1
  9. data/lib/jamf/ruby_extensions/array/utils.rb +3 -3
  10. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  11. data/lib/jss.rb +2 -0
  12. data/lib/jss/api_connection.rb +2 -29
  13. data/lib/jss/api_object.rb +15 -2
  14. data/lib/jss/api_object/directory_binding.rb +273 -0
  15. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  16. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  17. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  18. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  19. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  20. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  21. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  22. data/lib/jss/api_object/distribution_point.rb +95 -35
  23. data/lib/jss/api_object/dock_item.rb +137 -0
  24. data/lib/jss/api_object/mobile_device_application.rb +12 -0
  25. data/lib/jss/api_object/network_segment.rb +152 -58
  26. data/lib/jss/api_object/package.rb +106 -41
  27. data/lib/jss/api_object/policy.rb +379 -4
  28. data/lib/jss/api_object/printer.rb +440 -0
  29. data/lib/jss/api_object/scopable/scope.rb +24 -24
  30. data/lib/jss/composer.rb +1 -1
  31. data/lib/jss/utility.rb +8 -22
  32. data/lib/jss/version.rb +1 -1
  33. metadata +13 -2
@@ -0,0 +1,440 @@
1
+ module JSS
2
+ ### Module Constants
3
+ #####################################
4
+
5
+ ### Module Variables
6
+ #####################################
7
+
8
+ ### Module Methods
9
+ #####################################
10
+
11
+ ### Classes
12
+ #####################################
13
+
14
+ ### Printer object inside JSS
15
+ ###
16
+ ### @see JSS::APIObject
17
+ class Printer < JSS::APIObject
18
+ ## Mix-Ins
19
+ #####################################
20
+ include JSS::Creatable
21
+ include JSS::Updatable
22
+ include JSS::Categorizable
23
+
24
+ ## Class Constants
25
+ #####################################
26
+
27
+ ### The base for REST resources of this class
28
+ RSRC_BASE = 'printers'.freeze
29
+
30
+ ### the hash key used for the JSON list output of all objects in the JSS
31
+ RSRC_LIST_KEY = :printers
32
+
33
+ ### The hash key used for the JSON object output
34
+ ### It's also used in various error messages
35
+ RSRC_OBJECT_KEY = :printer
36
+
37
+ # Where is the Category in the API JSON?
38
+ CATEGORY_SUBSET = :top
39
+
40
+ # How is the category stored in the API data?
41
+ CATEGORY_DATA_TYPE = String
42
+
43
+ ## Attributes
44
+ #####################################
45
+
46
+ ### @return [String] The URI path for the specific printer.
47
+ attr_reader :uri
48
+
49
+ ### @return [String] The CUPs name to be used
50
+ attr_reader :CUPS_name
51
+
52
+ ### @return [String] The physical location of the printer.
53
+ attr_reader :location
54
+
55
+ ### @return [String] The specific model of printer.
56
+ attr_reader :model
57
+
58
+ ### @return [Boolean] Is this printer to be shared?
59
+ attr_reader :shared
60
+
61
+ ### @return [String] Information for this specific printer.
62
+ attr_reader :info
63
+
64
+ ### @return [String] Notes for this specific printer.
65
+ attr_reader :notes
66
+
67
+ ### @return [Boolean] Make this printer as the default printer upon installation.
68
+ attr_reader :make_default
69
+
70
+ ### @return [Boolean] Use a generic PPD.
71
+ attr_reader :use_generic
72
+
73
+ ### @return [String] The PPD file name.
74
+ attr_reader :ppd
75
+
76
+ ### @return [String] The contents of the PPD file.
77
+ attr_reader :ppd_contents
78
+
79
+ ### @return [String] The path the PPD file will be installed.
80
+ attr_reader :ppd_path
81
+
82
+ ### @return [String] The OS version requirements seperated by commas
83
+ attr_reader :os_requirements
84
+
85
+ ## Constructor
86
+ #####################################
87
+
88
+ ###
89
+ def initialize(args = {})
90
+ super args
91
+
92
+ if self.in_jss?
93
+
94
+ @uri = @init_data[:uri]
95
+ @CUPS_name = @init_data[:CUPS_name]
96
+ @location = @init_data[:location]
97
+ @model = @init_data[:model]
98
+ @shared = @init_data[:shared]
99
+ @info = @init_data[:info]
100
+ @notes = @init_data[:notes]
101
+ @make_default = @init_data[:make_default]
102
+ @use_generic = @init_data[:use_generic]
103
+ @ppd = @init_data[:ppd]
104
+ @ppd_contents = @init_data[:ppd_contents]
105
+ @ppd_path = @init_data[:ppd_path]
106
+ @os_requirements = @init_data[:os_requirements]
107
+ else
108
+
109
+ raise JSS::MissingDataError, "CUPS_name must be provided." unless !@init_data[:CUPS_name].nil?
110
+ raise JSS::MissingDataError, "uri must be provided." unless !@init_data[:uri].nil?
111
+
112
+ raise JSS::InvalidDataError, "uri must be a String." unless @init_data[:uri].is_a?(String) || @init_data[:uri].nil?
113
+ raise JSS::InvalidDataError, "CUPS_name must be a String." unless @init_data[:CUPS_name].is_a?(String)
114
+ raise JSS::InvalidDataError, "location must be a String." unless @init_data[:location].is_a?(String) || @init_data[:location].nil?
115
+ raise JSS::InvalidDataError, "model must be a String." unless @init_data[:model].is_a?(String) || @init_data[:model].nil?
116
+ raise JSS::InvalidDataError, "info must be a String." unless @init_data[:info].is_a?(String) || @init_data[:info].nil?
117
+ raise JSS::InvalidDataError, "notes must be a String." unless @init_data[:notes].is_a?(String) || @init_data[:notes].nil?
118
+ raise JSS::InvalidDataError, "ppd must be a String." unless @init_data[:ppd].is_a?(String) || @init_data[:ppd].nil?
119
+ raise JSS::InvalidDataError, "ppd_contents must be a String." unless @init_data[:ppd_contents].is_a?(String) || @init_data[:ppd_contents].nil?
120
+ raise JSS::InvalidDataError, "ppd_path must be a String." unless @init_data[:ppd_path].is_a?(String) || @init_data[:ppd_path].nil?
121
+ raise JSS::InvalidDataError, "os_requirements must be a String." unless @init_data[:os_requirements].is_a?(String) || @init_data[:os_requirements].nil?
122
+ raise JSS::InvalidDataError, "shared must be a String." unless (@init_data[:shared].is_a?(TrueClass) || @init_data[:shared].is_a?(FalseClass)) || @init_data[:shared].nil?
123
+ raise JSS::InvalidDataError, "make_default must be a String." unless (@init_data[:make_default].is_a?(TrueClass) || @init_data[:make_default].is_a?(FalseClass)) || @init_data[:make_default].nil?
124
+ raise JSS::InvalidDataError, "use_generic must be a String." unless (@init_data[:use_generic].is_a?(TrueClass) || @init_data[:use_generic].is_a?(FalseClass)) || @init_data[:use_generic].nil?
125
+
126
+ @uri = @init_data[:uri]
127
+ @CUPS_name = @init_data[:CUPS_name]
128
+ @location = @init_data[:location]
129
+ @model = @init_data[:model]
130
+ @shared = @init_data[:shared]
131
+ @info = @init_data[:info]
132
+ @notes = @init_data[:notes]
133
+ @make_default = @init_data[:make_default]
134
+ @use_generic = @init_data[:use_generic]
135
+ @ppd = @init_data[:ppd]
136
+ @ppd_contents = @init_data[:ppd_contents]
137
+ @ppd_path = @init_data[:ppd_path]
138
+ @os_requirements = @init_data[:os_requirements]
139
+ end
140
+ end
141
+
142
+
143
+ ## Class Methods
144
+ #####################################
145
+
146
+
147
+ # The URI path for the specific printer.
148
+ #
149
+ # @author Tyler Morgan
150
+ #
151
+ # @param newvalue [String]
152
+ #
153
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
154
+ #
155
+ # @return [void]
156
+ def uri=(newvalue)
157
+
158
+ raise JSS::InvalidDataError, "URI must be a string." unless newvalue.is_a? String
159
+
160
+ @uri = newvalue
161
+
162
+ @need_to_update = true
163
+ end
164
+
165
+
166
+ # The CUPs name to be used
167
+ #
168
+ # @author Tyler Morgan
169
+ #
170
+ # @param newvalue [String]
171
+ #
172
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
173
+ #
174
+ # @return [void]
175
+ def CUPS_name=(newvalue)
176
+
177
+ raise JSS::InvalidDataError, "CUPS_name must be a string." unless newvalue.is_a? String
178
+
179
+ @CUPS_name = newvalue
180
+
181
+ @need_to_update = true
182
+ end
183
+
184
+
185
+ # The physical location of the printer.
186
+ #
187
+ # @author Tyler Morgan
188
+ #
189
+ # @param newvalue [String]
190
+ #
191
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
192
+ #
193
+ # @return [void]
194
+ def location=(newvalue)
195
+
196
+ raise JSS::InvalidDataError, "location must be a string." unless newvalue.is_a? String
197
+
198
+ @location = newvalue
199
+
200
+ @need_to_update = true
201
+ end
202
+
203
+
204
+ # The specific model of printer.
205
+ #
206
+ # @author Tyler Morgan
207
+ #
208
+ # @param newvalue [String]
209
+ #
210
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
211
+ #
212
+ # @return [void]
213
+ def model=(newvalue)
214
+
215
+ raise JSS::InvalidDataError, "model must be a string." unless newvalue.is_a? String
216
+
217
+ @model = newvalue
218
+
219
+ @need_to_update = true
220
+ end
221
+
222
+
223
+ # Is this printer to be shared?
224
+ #
225
+ # @author Tyler Morgan
226
+ #
227
+ # @param newvalue [Boolean]
228
+ #
229
+ # @raise [JSS::InvalidDataError] If newvalue is not a Boolean
230
+ #
231
+ # @return [void]
232
+ def shared=(newvalue)
233
+
234
+ raise JSS::InvalidDataError, "shared must be a string." unless newvalue.is_a?(TrueClass) || newvalue.is_a?(FalseClass)
235
+
236
+ @shared = newvalue
237
+
238
+ @need_to_update = true
239
+ end
240
+
241
+
242
+ # Information for this specific printer.
243
+ #
244
+ # @author Tyler Morgan
245
+ #
246
+ # @param newvalue [String]
247
+ #
248
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
249
+ #
250
+ # @return [void]
251
+ def info=(newvalue)
252
+
253
+ raise JSS::InvalidDataError, "info must be a string." unless newvalue.is_a? String
254
+
255
+ @info = newvalue
256
+
257
+ @need_to_update = true
258
+ end
259
+
260
+
261
+ # Notes for this specific printer.
262
+ #
263
+ # @author Tyler Morgan
264
+ #
265
+ # @param newvalue [String]
266
+ #
267
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
268
+ #
269
+ # @return [void]
270
+ def notes=(newvalue)
271
+
272
+ raise JSS::InvalidDataError, "notes must be a string." unless newvalue.is_a? String
273
+
274
+ @notes = newvalue
275
+
276
+ @need_to_update = true
277
+ end
278
+
279
+
280
+ # Make this printer as the default printer upon installation.
281
+ #
282
+ # @author Tyler Morgan
283
+ #
284
+ # @param newvalue [Boolean]
285
+ #
286
+ # @raise [JSS::InvalidDataError] If newvalue is not a Boolean
287
+ #
288
+ # @return [void]
289
+ def make_default=(newvalue)
290
+
291
+ raise JSS::InvalidDataError, "make_default must be a string." unless newvalue.is_a?(TrueClass) || newvalue.is_a?(FalseClass)
292
+
293
+ @make_default = newvalue
294
+
295
+ @need_to_update = true
296
+ end
297
+
298
+
299
+ # Use a generic PPD.
300
+ #
301
+ # @author Tyler Morgan
302
+ #
303
+ # @param newvalue [Boolean]
304
+ #
305
+ # @raise [JSS::InvalidDataError] If newvalue is not a Boolean
306
+ #
307
+ # @return [void]
308
+ def use_generic=(newvalue)
309
+
310
+ raise JSS::InvalidDataError, "use_generic must be a string." unless newvalue.is_a?(TrueClass) || newvalue.is_a?(FalseClass)
311
+
312
+ @use_generic = newvalue
313
+
314
+ @need_to_update = true
315
+ end
316
+
317
+
318
+ # The PPD file name.
319
+ #
320
+ # @author Tyler Morgan
321
+ #
322
+ # @param newvalue [String]
323
+ #
324
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
325
+ #
326
+ # @return [void]
327
+ def ppd=(newvalue)
328
+
329
+ raise JSS::InvalidDataError, "ppd must be a string." unless newvalue.is_a? String
330
+
331
+ @ppd = newvalue
332
+
333
+ @need_to_update = true
334
+ end
335
+
336
+
337
+ # The contents of the PPD file.
338
+ #
339
+ # @author Tyler Morgan
340
+ #
341
+ # @param newvalue [String]
342
+ #
343
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
344
+ #
345
+ # @return [void]
346
+ def ppd_contents=(newvalue)
347
+
348
+ raise JSS::InvalidDataError, "ppd_contents must be a string." unless newvalue.is_a? String
349
+
350
+ @ppd_contents = newvalue
351
+
352
+ @need_to_update = true
353
+ end
354
+
355
+
356
+ # The path the PPD file will be installed.
357
+ #
358
+ # @author Tyler Morgan
359
+ #
360
+ # @param newvalue [String]
361
+ #
362
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
363
+ #
364
+ # @return [void]
365
+ def ppd_path=(newvalue)
366
+
367
+ raise JSS::InvalidDataError, "ppd_path must be a string." unless newvalue.is_a? String
368
+
369
+ @ppd_path = newvalue
370
+
371
+ @need_to_update = true
372
+ end
373
+
374
+
375
+ # The OS version requirements seperated by commas
376
+ #
377
+ # @author Tyler Morgan
378
+ #
379
+ # @param newvalue [String]
380
+ #
381
+ # @raise [JSS::InvalidDataError] If newvalue is not a String
382
+ #
383
+ # @example Limit Printer object to only High Sierra devices and Mojave 10.14.5 OS versions
384
+ # printer.os_requirements = "10.13.x, 10.14.5"
385
+ #
386
+ # @return [void]
387
+ def os_requirements=(newvalue)
388
+
389
+ raise JSS::InvalidDataError, "os_requirements must be a string." unless newvalue.is_a? String
390
+
391
+ @os_requirements = newvalue
392
+
393
+ @need_to_update = true
394
+ end
395
+
396
+ # Remove the various large data
397
+ # from the instance_variables used to create
398
+ # pretty-print (pp) output.
399
+ #
400
+ # @return [Array] the desired instance_variables
401
+ #
402
+ def pretty_print_instance_variables
403
+ vars = super
404
+ vars.delete :@ppd_contents
405
+ vars
406
+ end
407
+
408
+
409
+ ## Private Instance Methods
410
+ #####################################
411
+ private
412
+
413
+ ### Return the xml for creating or updating this script in the JSS
414
+ ###
415
+ def rest_xml
416
+ doc = REXML::Document.new
417
+ printer = doc.add_element 'printer'
418
+
419
+ printer.add_element('id').text = @id
420
+ printer.add_element('name').text = @name
421
+ printer.add_element('uri').text = @uri
422
+ printer.add_element('CUPS_name').text = @CUPS_name
423
+ printer.add_element('location').text = @location
424
+ printer.add_element('model').text = @model
425
+ printer.add_element('shared').text = @shared
426
+ printer.add_element('info').text = @info
427
+ printer.add_element('notes').text = @notes
428
+ printer.add_element('make_default').text = @make_default
429
+ printer.add_element('use_generic').text = @use_generic
430
+ printer.add_element('ppd').text = @ppd
431
+ printer.add_element('ppd_contents').text = @ppd_contents
432
+ printer.add_element('ppd_path').text = @ppd_path
433
+ printer.add_element('os_requirements').text = @os_requirements
434
+ add_category_to_xml(doc)
435
+
436
+ doc.to_s
437
+
438
+ end
439
+ end
440
+ end
@@ -392,7 +392,7 @@ module JSS
392
392
  @exclusions = {}
393
393
  @exclusion_keys.each { |k| @exclusions[k] = [] }
394
394
  end
395
- @container&.should_update
395
+ @container.should_update if @container
396
396
  end
397
397
 
398
398
  # Replace a list of item names for as targets in this scope.
@@ -420,7 +420,7 @@ module JSS
420
420
  list.map! do |ident|
421
421
  item_id = validate_item(:target, key, ident)
422
422
 
423
- if @exclusions[key]&.include?(item_id)
423
+ if @exclusions[key] && @exclusions[key].include?(item_id)
424
424
  raise JSS::AlreadyExistsError, \
425
425
  "Can't set #{key} target to '#{ident}' because it's already an explicit exclusion."
426
426
  end
@@ -432,7 +432,7 @@ module JSS
432
432
 
433
433
  @inclusions[key] = list
434
434
  @all_targets = false
435
- @container&.should_update
435
+ @container.should_update if @container
436
436
  end # sinclude_in_scope
437
437
  alias set_target set_targets
438
438
  alias set_inclusion set_targets
@@ -458,13 +458,13 @@ module JSS
458
458
  def add_target(key, item)
459
459
  key = pluralize_key(key)
460
460
  item_id = validate_item(:target, key, item)
461
- return if @inclusions[key]&.include?(item_id)
461
+ return if @inclusions[key] && @exclusions[key].include?(item_id)
462
462
 
463
- raise JSS::AlreadyExistsError, "Can't set #{key} target to '#{item}' because it's already an explicit exclusion." if @exclusions[key]&.include?(item_id)
463
+ 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)
464
464
 
465
465
  @inclusions[key] << item_id
466
466
  @all_targets = false
467
- @container&.should_update
467
+ @container.should_update if @container
468
468
  end
469
469
  alias add_inclusion add_target
470
470
 
@@ -483,10 +483,10 @@ module JSS
483
483
  key = pluralize_key(key)
484
484
  item_id = validate_item :target, key, item, error_if_not_found: false
485
485
  return unless item_id
486
- return unless @inclusions[key]&.include?(item_id)
486
+ return unless @inclusions[key] && @exclusions[key].include?(item_id)
487
487
 
488
488
  @inclusions[key].delete item_id
489
- @container&.should_update
489
+ @container.should_update if @container
490
490
  end
491
491
  alias remove_inclusion remove_target
492
492
 
@@ -513,7 +513,7 @@ module JSS
513
513
  # check the idents
514
514
  list.map! do |ident|
515
515
  item_id = validate_item(:limitation, key, ident)
516
- if @exclusions[key]&.include?(item_id)
516
+ if @exclusions[key] && @exclusions[key].include?(item_id)
517
517
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
518
518
  end
519
519
 
@@ -523,7 +523,7 @@ module JSS
523
523
  return nil if list.sort == @limitations[key].sort
524
524
 
525
525
  @limitations[key] = list
526
- @container&.should_update
526
+ @container.should_update if @container
527
527
  end # set_limitation
528
528
  alias set_limitations set_limitation
529
529
 
@@ -545,14 +545,14 @@ module JSS
545
545
  def add_limitation(key, item)
546
546
  key = pluralize_key(key)
547
547
  item_id = validate_item(:limitation, key, item)
548
- return nil if @limitations[key]&.include?(item_id)
548
+ return nil if @limitations[key] && @exclusions[key].include?(item_id)
549
549
 
550
- if @exclusions[key]&.include?(item_id)
550
+ if @exclusions[key] && @exclusions[key].include?(item_id)
551
551
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
552
552
  end
553
553
 
554
554
  @limitations[key] << item_id
555
- @container&.should_update
555
+ @container.should_update if @container
556
556
  end
557
557
 
558
558
  # Remove a single item for limiting this scope.
@@ -572,10 +572,10 @@ module JSS
572
572
  key = pluralize_key(key)
573
573
  item_id = validate_item :limitation, key, item, error_if_not_found: false
574
574
  return unless item_id
575
- return unless @limitations[key]&.include?(item_id)
575
+ return unless @limitations[key] && @exclusions[key].include?(item_id)
576
576
 
577
577
  @limitations[key].delete item_id
578
- @container&.should_update
578
+ @container.should_update if @container
579
579
  end ###
580
580
 
581
581
  # Replace an exclusion list for this scope
@@ -601,9 +601,9 @@ module JSS
601
601
  item_id = validate_item(:exclusion, key, ident)
602
602
  case key
603
603
  when *@inclusion_keys
604
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included." if @inclusions[key]&.include?(item_id)
604
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included." if @inclusions[key] && @exclusions[key].include?(item_id)
605
605
  when *LIMITATIONS
606
- if @limitations[key]&.include?(item_id)
606
+ if @limitations[key] && @exclusions[key].include?(item_id)
607
607
  raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already an explicit limitation."
608
608
  end
609
609
  end
@@ -613,7 +613,7 @@ module JSS
613
613
  return nil if list.sort == @exclusions[key].sort
614
614
 
615
615
  @exclusions[key] = list
616
- @container&.should_update
616
+ @container.should_update if @container
617
617
  end # limit scope
618
618
 
619
619
  # Add a single item for exclusions of this scope.
@@ -632,14 +632,14 @@ module JSS
632
632
  def add_exclusion(key, item)
633
633
  key = pluralize_key(key)
634
634
  item_id = validate_item(:exclusion, key, item)
635
- return if @exclusions[key]&.include?(item_id)
635
+ return if @exclusions[key] && @exclusions[key].include?(item_id)
636
636
 
637
- raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @inclusions[key]&.include?(item)
637
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(item)
638
638
 
639
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key]&.include?(item)
639
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item)
640
640
 
641
641
  @exclusions[key] << item_id
642
- @container&.should_update
642
+ @container.should_update if @container
643
643
  end
644
644
 
645
645
  # Remove a single item for exclusions of this scope
@@ -656,10 +656,10 @@ module JSS
656
656
  def remove_exclusion(key, item)
657
657
  key = pluralize_key(key)
658
658
  item_id = validate_item :exclusion, key, item, error_if_not_found: false
659
- return unless @exclusions[key]&.include?(item_id)
659
+ return unless @exclusions[key] && @exclusions[key].include?(item_id)
660
660
 
661
661
  @exclusions[key].delete item_id
662
- @container&.should_update
662
+ @container.should_update if @container
663
663
  end
664
664
 
665
665
  # @api private