ruby-jss 1.0.3b2 → 1.0.3b3

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +5 -1
  3. data/README.md +31 -18
  4. data/bin/cgrouper +1 -1
  5. data/bin/jamfHelperBackgrounder +1 -1
  6. data/bin/netseg-update +1 -1
  7. data/data/ruby-jss.conf.example +24 -0
  8. data/lib/jss-api.rb +24 -0
  9. data/lib/jss.rb +1 -2
  10. data/lib/jss/api_connection.rb +7 -9
  11. data/lib/jss/api_object.rb +1 -1
  12. data/lib/jss/api_object/account.rb +1 -1
  13. data/lib/jss/api_object/advanced_search.rb +1 -1
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +1 -1
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +1 -1
  17. data/lib/jss/api_object/building.rb +1 -1
  18. data/lib/jss/api_object/categorizable.rb +1 -1
  19. data/lib/jss/api_object/category.rb +1 -1
  20. data/lib/jss/api_object/computer.rb +1 -1
  21. data/lib/jss/api_object/computer/application_installs.rb +1 -1
  22. data/lib/jss/api_object/computer_invitation.rb +1 -1
  23. data/lib/jss/api_object/configuration_profile.rb +1 -1
  24. data/lib/jss/api_object/configuration_profile/mobile_device_configuration_profile.rb +24 -0
  25. data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +1 -1
  26. data/lib/jss/api_object/creatable.rb +1 -1
  27. data/lib/jss/api_object/criteriable.rb +1 -1
  28. data/lib/jss/api_object/criteriable/criteria.rb +1 -1
  29. data/lib/jss/api_object/criteriable/criterion.rb +1 -1
  30. data/lib/jss/api_object/department.rb +1 -1
  31. data/lib/jss/api_object/distribution_point.rb +1 -1
  32. data/lib/jss/api_object/ebook.rb +1 -1
  33. data/lib/jss/api_object/extendable.rb +1 -1
  34. data/lib/jss/api_object/extension_attribute.rb +1 -1
  35. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
  36. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
  37. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +1 -1
  38. data/lib/jss/api_object/group.rb +1 -1
  39. data/lib/jss/api_object/group/computer_group.rb +1 -1
  40. data/lib/jss/api_object/group/mobile_device_group.rb +1 -1
  41. data/lib/jss/api_object/group/user_group.rb +1 -1
  42. data/lib/jss/api_object/ldap_server.rb +1 -1
  43. data/lib/jss/api_object/locatable.rb +1 -1
  44. data/lib/jss/api_object/mac_application.rb +24 -0
  45. data/lib/jss/api_object/management_history.rb +1 -1
  46. data/lib/jss/api_object/management_history/audit_event.rb +24 -0
  47. data/lib/jss/api_object/management_history/casper_imaging_log.rb +24 -0
  48. data/lib/jss/api_object/management_history/casper_remote_log.rb +24 -0
  49. data/lib/jss/api_object/management_history/computer_usage_log.rb +24 -0
  50. data/lib/jss/api_object/management_history/ebook.rb +25 -0
  51. data/lib/jss/api_object/management_history/hashlike.rb +24 -0
  52. data/lib/jss/api_object/management_history/mac_app_store_app.rb +24 -0
  53. data/lib/jss/api_object/management_history/mdm_command.rb +24 -0
  54. data/lib/jss/api_object/management_history/mobile_device_app.rb +24 -0
  55. data/lib/jss/api_object/management_history/policy_log.rb +24 -0
  56. data/lib/jss/api_object/management_history/screen_sharing_log.rb +24 -0
  57. data/lib/jss/api_object/management_history/user_location_change.rb +24 -0
  58. data/lib/jss/api_object/matchable.rb +1 -1
  59. data/lib/jss/api_object/mdm.rb +1 -1
  60. data/lib/jss/api_object/mobile_device.rb +1 -1
  61. data/lib/jss/api_object/mobile_device_application.rb +1 -1
  62. data/lib/jss/api_object/netboot_server.rb +1 -1
  63. data/lib/jss/api_object/network_segment.rb +1 -1
  64. data/lib/jss/api_object/package.rb +1 -1
  65. data/lib/jss/api_object/patch_policy.rb +1 -1
  66. data/lib/jss/api_object/patch_source.rb +1 -1
  67. data/lib/jss/api_object/patch_source/patch_external_source.rb +1 -1
  68. data/lib/jss/api_object/patch_source/patch_internal_source.rb +1 -1
  69. data/lib/jss/api_object/patch_title.rb +1 -1
  70. data/lib/jss/api_object/patch_title/version.rb +1 -1
  71. data/lib/jss/api_object/peripheral.rb +1 -1
  72. data/lib/jss/api_object/peripheral_type.rb +1 -1
  73. data/lib/jss/api_object/policy.rb +1 -1
  74. data/lib/jss/api_object/purchasable.rb +1 -1
  75. data/lib/jss/api_object/removable_macaddr.rb +1 -1
  76. data/lib/jss/api_object/restricted_software.rb +24 -0
  77. data/lib/jss/api_object/scopable.rb +1 -1
  78. data/lib/jss/api_object/scopable/scope.rb +169 -155
  79. data/lib/jss/api_object/script.rb +1 -1
  80. data/lib/jss/api_object/self_servable.rb +1 -1
  81. data/lib/jss/api_object/self_servable/icon.rb +1 -1
  82. data/lib/jss/api_object/sitable.rb +1 -1
  83. data/lib/jss/api_object/site.rb +1 -1
  84. data/lib/jss/api_object/software_update_server.rb +1 -1
  85. data/lib/jss/api_object/updatable.rb +1 -1
  86. data/lib/jss/api_object/uploadable.rb +1 -1
  87. data/lib/jss/api_object/user.rb +1 -1
  88. data/lib/jss/api_object/vppable.rb +1 -1
  89. data/lib/jss/api_object/webhook.rb +1 -1
  90. data/lib/jss/client.rb +1 -1
  91. data/lib/jss/client/jamf_binary.rb +1 -1
  92. data/lib/jss/client/jamf_helper.rb +1 -1
  93. data/lib/jss/client/management_action.rb +1 -1
  94. data/lib/jss/compatibility.rb +1 -1
  95. data/lib/jss/composer.rb +1 -1
  96. data/lib/jss/configuration.rb +1 -1
  97. data/lib/jss/db_connection.rb +1 -1
  98. data/lib/jss/exceptions.rb +1 -1
  99. data/lib/jss/ruby_extensions.rb +1 -1
  100. data/lib/jss/ruby_extensions/array.rb +1 -1
  101. data/lib/jss/ruby_extensions/filetest.rb +1 -1
  102. data/lib/jss/ruby_extensions/hash.rb +1 -1
  103. data/lib/jss/ruby_extensions/ipaddr.rb +1 -1
  104. data/lib/jss/ruby_extensions/pathname.rb +1 -1
  105. data/lib/jss/ruby_extensions/string.rb +1 -1
  106. data/lib/jss/ruby_extensions/time.rb +1 -1
  107. data/lib/jss/server.rb +1 -1
  108. data/lib/jss/utility.rb +1 -1
  109. data/lib/jss/validate.rb +1 -1
  110. data/lib/jss/version.rb +2 -2
  111. data/lib/jss/xml_workaround.rb +1 -1
  112. data/lib/ruby-jss.rb +24 -0
  113. data/test/bin/runtests +1 -1
  114. data/test/lib/testhelper.rb +1 -1
  115. data/test/lib/testhelper/auth.rb +1 -1
  116. data/test/lib/testhelper/patch_mgmt.rb +1 -1
  117. data/test/specs/api_connection_spec.rb +1 -1
  118. data/test/specs/patch01_source_spec.rb +1 -1
  119. data/test/specs/patch02_internal_source_spec.rb +1 -1
  120. data/test/specs/patch03_external_source_spec.rb +1 -1
  121. data/test/specs/patch04_titles_spec.rb +1 -1
  122. data/test/specs/patch05_policies_spec.rb +1 -1
  123. data/test/specs/patch06_cleanup_spec.rb +1 -1
  124. data/test/specs/policy_spec.rb +1 -1
  125. metadata +2 -2
@@ -1,3 +1,27 @@
1
+ ### Copyright 2019 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+
1
25
  #
2
26
  module JSS
3
27
 
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Pixar
1
+ # Copyright 2019 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Pixar
1
+ # Copyright 2019 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,3 +1,27 @@
1
+ ### Copyright 2019 Pixar
2
+
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+
1
25
  module JSS
2
26
 
3
27
  # Restricted Software items in the JSS.
@@ -1,4 +1,4 @@
1
- ### Copyright 2018 Pixar
1
+ ### Copyright 2019 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Pixar
1
+ # Copyright 2019 Pixar
2
2
 
3
3
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
4
4
  # with the following modification; you may not use this file except in
@@ -22,7 +22,6 @@
22
22
  #
23
23
  #
24
24
 
25
- #
26
25
  module JSS
27
26
 
28
27
  module Scopable
@@ -30,22 +29,17 @@ module JSS
30
29
  # Classes
31
30
  #####################################
32
31
 
32
+ # This class represents a Scope in the JSS, as can be applied to Scopable
33
+ # objects like Policies, Profiles, etc. Instances of this class are
34
+ # generally used as the value of the @scope attribute of those objects.
33
35
  #
34
- # This class represents a Scope in the JSS, as can be applied to Scopable objects like
35
- # Policies, Profiles, etc. Instances of this class are generally used as the value of the @scope attribute
36
- # of those objects.
37
- #
38
- # Scope data comes from the API as a hash within the overall object data. The main keys of the hash
39
- # define the included targets of the scope. A sub-hash defines limitations on those inclusions,
40
- # and another sub-hash defines explicit exclusions.
36
+ # Scope data comes from the API as a hash within the overall object data.
37
+ # The main keys of the hash define the included targets of the scope. A
38
+ # sub-hash defines limitations on those inclusions, and another sub-hash
39
+ # defines explicit exclusions.
41
40
  #
42
41
  # This class provides methods for adding, removing, or fully replacing the
43
- # various parts of the scope's inclusions, limitations, and exclusions.
44
- #
45
- # @todo Implement simple LDAP queries using the defined {LDAPServer}s to confirm the
46
- # existance of users or groups used in limitations and exclusions. As things are now
47
- # if you add invalid user or group names, you'll get a 409 conflict error when you try
48
- # to save your changes to the JSS.
42
+ # various items in scope's realms: targets, limitations, and exclusions.
49
43
  #
50
44
  # @see JSS::Scopable
51
45
  #
@@ -86,6 +80,9 @@ module JSS
86
80
  # their corresponding target group keys from SCOPING_CLASSES.
87
81
  TARGETS_AND_GROUPS = { computers: :computer_groups, mobile_devices: :mobile_device_groups }.freeze
88
82
 
83
+ # added to the ends of singular key names if needed, e.g. computer_group => computer_groups
84
+ ESS = 's'.freeze
85
+
89
86
  # These can be part of the base inclusion list of the scope,
90
87
  # along with the appropriate target and target group keys
91
88
  INCLUSIONS = %i[buildings departments].freeze
@@ -176,13 +173,13 @@ module JSS
176
173
  # If raw_scope is empty, a default scope, scoped to all targets, is created, and can be modified
177
174
  # as needed.
178
175
  #
179
- # @param target_key[Symbol] the kind of thing we're scopeing, one of {TARGETS_AND_GROUPS}
176
+ # @param target_key[Symbol] the kind of thing we're scoping, one of {TARGETS_AND_GROUPS}
180
177
  #
181
178
  # @param raw_scope[Hash] the JSON :scope data from an API query that is scopable, e.g. a Policy.
182
179
  #
183
180
  def initialize(target_key, raw_scope = nil)
184
181
  raw_scope ||= DEFAULT_SCOPE
185
- raise JSS::InvalidDataError, "The target class of a Scope must be one of the symbols :#{TARGETS_AND_GROUPS.keys.join(', :')}" unless TARGETS_AND_GROUPS.keys.include? target_key
182
+ raise JSS::InvalidDataError, "The target class of a Scope must be one of the symbols :#{TARGETS_AND_GROUPS.keys.join(', :')}" unless TARGETS_AND_GROUPS.key?(target_key)
186
183
 
187
184
  @target_key = target_key
188
185
  @target_class = SCOPING_CLASSES[@target_key]
@@ -195,19 +192,28 @@ module JSS
195
192
  @all_key = "all_#{target_key}".to_sym
196
193
  @all_targets = raw_scope[@all_key]
197
194
 
198
- # Everything gets mapped from an Array of Hashes to an Array of names (or an empty array)
199
- # since names are all that really matter when submitting the scope.
195
+ # Everything gets mapped from an Array of Hashes to
196
+ # an Array of ids
200
197
  @inclusions = {}
201
- @inclusion_keys.each { |k| @inclusions[k] = raw_scope[k] ? raw_scope[k].map { |n| n[:name] } : [] }
198
+ @inclusion_keys.each do |k|
199
+ raw_scope[k] ||= []
200
+ @inclusions[k] = raw_scope[k].compact.map { |n| n[:id].to_i }
201
+ end # @inclusion_keys.each do |k|
202
202
 
203
203
  @limitations = {}
204
204
  if raw_scope[:limitations]
205
- LIMITATIONS.each { |k| @limitations[k] = raw_scope[:limitations][k] ? raw_scope[:limitations][k].map { |n| n[:name] } : [] }
206
- end
205
+ LIMITATIONS.each do |k|
206
+ raw_scope[:limitations][k] ||= []
207
+ @limitations[k] = raw_scope[:limitations][k].compact.map { |n| n[:id].to_i }
208
+ end # LIMITATIONS.each do |k|
209
+ end # if raw_scope[:limitations]
207
210
 
208
211
  @exclusions = {}
209
212
  if raw_scope[:exclusions]
210
- @exclusion_keys.each { |k| @exclusions[k] = raw_scope[:exclusions][k] ? raw_scope[:exclusions][k].map { |n| n[:name] } : [] }
213
+ @exclusion_keys.each do |k|
214
+ raw_scope[:exclusions][k] ||= []
215
+ @exclusions[k] = raw_scope[:exclusions][k].compact.map { |n| n[:id].to_i }
216
+ end
211
217
  end
212
218
 
213
219
  @container = nil
@@ -246,7 +252,7 @@ module JSS
246
252
  # @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of items
247
253
  # being included, :computer, :building, etc...
248
254
  #
249
- # @param list[Array] the names of the items being added
255
+ # @param list[Array] identifiers of the items being added
250
256
  #
251
257
  # @example
252
258
  # set_targets(:computers, ['kimchi','mantis'])
@@ -254,56 +260,54 @@ module JSS
254
260
  # @return [void]
255
261
  #
256
262
  def set_targets(key, list)
257
- raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
258
- raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array
263
+ key = pluralize_key(key)
264
+ raise JSS::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array
265
+
266
+ # check the idents
267
+ list.map! do |ident|
268
+ item_id = validate_item(:target, key, ident)
269
+ if @exclusions[key] && @exclusions[key].include?(item_id)
270
+ raise JSS::AlreadyExistsError, \
271
+ "Can't set #{key} target to '#{ident}' because it's already an explicit exclusion."
272
+ end
273
+ item_id
274
+ end # each
259
275
 
260
276
  return nil if list.sort == @inclusions[key].sort
261
277
 
262
- # emptying the list?
263
- if list.empty?
264
- @inclusion[key] = list
265
- # if ALL the @inclusion keys are empty, then set all targets to true.
266
- @all_targets = @inclusions.values.reject { |a| a.nil? || a.empty? }.empty?
267
- @container.should_update if @container
268
- return list
269
- end
270
-
271
- # check the names
272
- list.each do |name|
273
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name
274
- raise JSS::AlreadyExistsError, "Can't set #{key} scope to '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(name)
275
- end # each
276
-
277
278
  @inclusions[key] = list
278
279
  @all_targets = false
279
280
  @container.should_update if @container
280
281
  end # sinclude_in_scope
282
+ alias set_target set_targets
281
283
  alias set_inclusion set_targets
284
+ alias set_inclusions set_targets
282
285
 
283
- # Add a single item a a target in this scope.
286
+ # Add a single item as a target in this scope.
284
287
  #
285
- # The item name will be checked for existence in the JSS, and an exception raised if the item doesn't exist.
288
+ # The item name will be checked for existence in the JSS, and an exception
289
+ # raised if the item doesn't exist.
286
290
  #
287
291
  # @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of item being added, :computer, :building, etc...
288
292
  #
289
- # @param item[String] the name of the item being added
293
+ # @param item[String,integer] a valid identifier of the item being added
290
294
  #
291
295
  # @example
292
- # add_target(:computer, "mantis")
296
+ # add_target(:computers, "mantis")
297
+ #
298
+ # @example
299
+ # add_target(:computer_groups, 2342)
293
300
  #
294
301
  # @return [void]
295
302
  #
296
303
  def add_target(key, item)
297
- raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
298
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
304
+ key = pluralize_key(key)
305
+ item_id = validate_item(:target, key, item)
306
+ return if @inclusions[key] && @inclusions[key].include?(item_id)
299
307
 
300
- return nil if @inclusions[key] && @inclusions[key].include?(item)
308
+ 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)
301
309
 
302
- # check the name
303
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item
304
- raise JSS::AlreadyExistsError, "Can't set #{key} scope to '#{item}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item)
305
-
306
- @inclusions[key] << item
310
+ @inclusions[key] << item_id
307
311
  @all_targets = false
308
312
  @container.should_update if @container
309
313
  end
@@ -313,7 +317,7 @@ module JSS
313
317
  #
314
318
  # @param key[Symbol] the key from #{SCOPING_CLASSES} for the kind of item being removed, :computer, :building, etc...
315
319
  #
316
- # @param item[String] the name of the item being removed
320
+ # @param item[String,integer] a valid identifier of the item being removed
317
321
  #
318
322
  # @example
319
323
  # remove_target(:computer, "mantis")
@@ -321,16 +325,11 @@ module JSS
321
325
  # @return [void]
322
326
  #
323
327
  def remove_target(key, item)
324
- raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key
325
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
326
-
327
- return nil unless @inclusions[key] && @inclusions[key].include?(item)
328
-
329
- @inclusions[key] -= [item]
330
-
331
- # if ALL the @inclusion keys are empty, then set all targets to true.
332
- @all_targets = @inclusions.values.reject { |a| a.nil? || a.empty? }.empty?
333
-
328
+ key = pluralize_key(key)
329
+ item_id = validate_item :target, key, item, error_if_not_found: false
330
+ return unless item_id
331
+ return unless @inclusions[key] && @inclusions[key].include?(item_id)
332
+ @inclusions[key].delete item_id
334
333
  @container.should_update if @container
335
334
  end
336
335
  alias remove_inclusion remove_target
@@ -342,35 +341,32 @@ module JSS
342
341
  #
343
342
  # @param key[Symbol] the type of items being set as limitations, :network_segments, :users, etc...
344
343
  #
345
- # @param list[Array] the names of the items being set as limitations
344
+ # @param list[Array] the identifiers of the items being set as limitations
346
345
  #
347
346
  # @example
348
- # set_limitation(:network_segments, ['foo','bar'])
347
+ # set_limitation(:network_segments, ['foo',231])
349
348
  #
350
349
  # @return [void]
351
350
  #
352
351
  # @todo handle ldap user group lookups
353
352
  #
354
353
  def set_limitation(key, list)
355
- raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key
356
- raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array
357
- return nil if list.sort == @limitations[key].sort
358
-
359
- if list.empty?
360
- @limitations[key] = []
361
- @container.should_update if @container
362
- return list
363
- end
364
-
365
- # check the names
366
- list.each do |name|
367
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name
368
- raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(name)
354
+ key = pluralize_key(key)
355
+ raise JSS::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array
356
+
357
+ # check the idents
358
+ list.map! do |ident|
359
+ item_id = validate_item(:limitation, key, ident)
360
+ raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item_id)
361
+ item_id
369
362
  end # each
370
363
 
364
+ return nil if list.sort == @limitations[key].sort
365
+
371
366
  @limitations[key] = list
372
367
  @container.should_update if @container
373
- end # limit scope
368
+ end # set_limitation
369
+ alias set_limitations set_limitation
374
370
 
375
371
  # Add a single item for limiting this scope.
376
372
  #
@@ -378,7 +374,7 @@ module JSS
378
374
  #
379
375
  # @param key[Symbol] the type of item being added, :computer, :building, etc...
380
376
  #
381
- # @param item[String] the name of the item being added
377
+ # @param item[String,integer] a valid identifier of the item being added
382
378
  #
383
379
  # @example
384
380
  # add_limitation(:network_segments, "foo")
@@ -388,16 +384,13 @@ module JSS
388
384
  # @todo handle ldap user/group lookups
389
385
  #
390
386
  def add_limitation(key, item)
391
- raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key
392
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
393
-
394
- return nil if @limitations[key] && @limitations[key].include?(item)
387
+ key = pluralize_key(key)
388
+ item_id = validate_item(:limitation, key, item)
389
+ return nil if @limitations[key] && @limitations[key].include?(item_id)
395
390
 
396
- # check the name
397
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item
398
- raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item)
391
+ raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item_id)
399
392
 
400
- @limitations[key] << item
393
+ @limitations[key] << item_id
401
394
  @container.should_update if @container
402
395
  end
403
396
 
@@ -405,7 +398,7 @@ module JSS
405
398
  #
406
399
  # @param key[Symbol] the type of item being removed, :computer, :building, etc...
407
400
  #
408
- # @param item[String] the name of the item being removed
401
+ # @param item[String,integer] a valid identifier of the item being removed
409
402
  #
410
403
  # @example
411
404
  # remove_limitation(:network_segments, "foo")
@@ -415,12 +408,11 @@ module JSS
415
408
  # @todo handle ldap user/group lookups
416
409
  #
417
410
  def remove_limitation(key, item)
418
- raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key
419
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
420
-
421
- return nil unless @limitations[key] && @limitations[key].include?(item)
422
-
423
- @limitations[key] -= [item]
411
+ key = pluralize_key(key)
412
+ item_id = validate_item :limitation, key, item, error_if_not_found: false
413
+ return unless item_id
414
+ return unless @limitations[key] && @limitations[key].include?(item_id)
415
+ @limitations[key].delete item_id
424
416
  @container.should_update if @container
425
417
  end ###
426
418
 
@@ -431,7 +423,7 @@ module JSS
431
423
  #
432
424
  # @param key[Symbol] the type of item being excluded, :computer, :building, etc...
433
425
  #
434
- # @param list[Array] the names of the items being added
426
+ # @param list[Array] the identifiers of the items being set
435
427
  #
436
428
  # @example
437
429
  # set_exclusion(:network_segments, ['foo','bar'])
@@ -439,27 +431,23 @@ module JSS
439
431
  # @return [void]
440
432
  #
441
433
  def set_exclusion(key, list)
442
- raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key
443
- raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array
444
- return nil if list.sort == @exclusions[key].sort
445
-
446
- if list.empty?
447
- @exclusions[key] = []
448
- @container.should_update if @container
449
- return list
450
- end
434
+ key = pluralize_key(key)
435
+ raise JSS::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array
451
436
 
452
- # check the names
453
- list.each do |name|
454
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name
437
+ # check the idents
438
+ list.map! do |ident|
439
+ item_id = validate_item(:exclusion, key, ident)
455
440
  case key
456
441
  when *@inclusion_keys
457
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{name}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(name)
442
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(item_id)
458
443
  when *LIMITATIONS
459
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{name}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(name)
444
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item_id)
460
445
  end
446
+ item_id
461
447
  end # each
462
448
 
449
+ return nil if list.sort == @exclusions[key].sort
450
+
463
451
  @exclusions[key] = list
464
452
  @container.should_update if @container
465
453
  end # limit scope
@@ -470,7 +458,7 @@ module JSS
470
458
  #
471
459
  # @param key[Symbol] the type of item being added to the exclusions, :computer, :building, etc...
472
460
  #
473
- # @param item[String] the name of the item being added
461
+ # @param item[String,integer] a valid identifier of the item being added
474
462
  #
475
463
  # @example
476
464
  # add_exclusion(:network_segments, "foo")
@@ -478,17 +466,13 @@ module JSS
478
466
  # @return [void]
479
467
  #
480
468
  def add_exclusion(key, item)
481
- raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key
482
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
483
-
484
- return nil if @exclusions[key] && @exclusions[key].include?(item)
485
-
486
- # check the name
487
- raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item
469
+ key = pluralize_key(key)
470
+ item_id = validate_item(:exclusion, key, item)
471
+ return if @exclusions[key] && @exclusions[key].include?(item_id)
488
472
  raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(item)
489
473
  raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item)
490
474
 
491
- @exclusions[key] << item
475
+ @exclusions[key] << item_id
492
476
  @container.should_update if @container
493
477
  end
494
478
 
@@ -496,7 +480,7 @@ module JSS
496
480
  #
497
481
  # @param key[Symbol] the type of item being removed from the excludions, :computer, :building, etc...
498
482
  #
499
- # @param item[String] the name of the item being removed
483
+ # @param item[String,integer] a valid identifier of the item being removed
500
484
  #
501
485
  # @example
502
486
  # remove_exclusion(:network_segments, "foo")
@@ -504,12 +488,10 @@ module JSS
504
488
  # @return [void]
505
489
  #
506
490
  def remove_exclusion(key, item)
507
- raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key
508
- raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String
509
-
510
- return nil unless @exclusions[key] && @exclusions[key].include?(item)
511
-
512
- @exclusions[key] -= [item]
491
+ key = pluralize_key(key)
492
+ item_id = validate_item :exclusion, key, item, error_if_not_found: false
493
+ return unless @exclusions[key] && @exclusions[key].include?(item_id)
494
+ @exclusions[key].delete item_id
513
495
  @container.should_update if @container
514
496
  end
515
497
 
@@ -524,24 +506,42 @@ module JSS
524
506
  scope.add_element(@all_key.to_s).text = @all_targets
525
507
 
526
508
  @inclusions.each do |klass, list|
527
- list_as_hash = list.map { |i| { name: i } }
528
- scope << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name)
509
+ list.compact!
510
+ list.delete 0
511
+ list_as_hash = list.map { |i| { id: i } }
512
+ scope << SCOPING_CLASSES[klass].xml_list(list_as_hash, :id)
529
513
  end
530
514
 
531
515
  limitations = scope.add_element('limitations')
532
516
  @limitations.each do |klass, list|
533
- list_as_hash = list.map { |i| { name: i } }
534
- limitations << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name)
517
+ list.compact!
518
+ list.delete 0
519
+ list_as_hash = list.map { |i| { id: i } }
520
+ limitations << SCOPING_CLASSES[klass].xml_list(list_as_hash, :id)
535
521
  end
536
522
 
537
523
  exclusions = scope.add_element('exclusions')
538
524
  @exclusions.each do |klass, list|
539
- list_as_hash = list.map { |i| { name: i } }
540
- exclusions << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name)
525
+ list.compact!
526
+ list.delete 0
527
+ list_as_hash = list.map { |i| { id: i } }
528
+ exclusions << SCOPING_CLASSES[klass].xml_list(list_as_hash, :id)
541
529
  end
542
530
  scope
543
531
  end # scope_xml
544
532
 
533
+ # Remove the init_data and api object from
534
+ # the instance_variables used to create
535
+ # pretty-print (pp) output.
536
+ #
537
+ # @return [Array] the desired instance_variables
538
+ #
539
+ def pretty_print_instance_variables
540
+ vars = instance_variables.sort
541
+ vars.delete :@container
542
+ vars
543
+ end
544
+
545
545
  # Aliases
546
546
 
547
547
  alias all_targets? all_targets
@@ -550,29 +550,43 @@ module JSS
550
550
  #####################################
551
551
  private
552
552
 
553
- # Given a name of some class of item to be used in the scope, check that it
554
- # exists in the JSS.
553
+ # look up a valid id or nil, for use in a scope type
555
554
  #
556
- # @return [Boolean] does the name exist for the key in JSS or LDAP?
555
+ # @param realm [Symbol] How is this key being used in the scope?
556
+ # :target, :limitation, or :exclusion
557
557
  #
558
- def check_name(key, name)
559
- found_in_jss = SCOPING_CLASSES[key].all_names(api: container.api).include?(name)
560
-
561
- return true if found_in_jss
562
-
563
- return false unless CHECK_LDAP_KEYS.include?(key)
564
-
565
- begin
566
- return JSS::LDAPServer.user_in_ldap?(name, api: container.api) if LDAP_USER_KEYS.include?(key)
567
- return JSS::LDAPServer.group_in_ldap?(name, api: container.api) if LDAP_GROUP_KEYS.include?(key)
568
-
569
- # if an ldap server isn't connected, make a note of it and return true
570
- rescue JSS::InvalidConnectionError
571
- @unable_to_verify_ldap_entries = true
572
- return true
573
- end # begin
574
-
575
- false
558
+ # @param key [Symbol] What kind of thing are we adding to the scope?
559
+ # e.g computer, network_segment, etc.
560
+ #
561
+ # @param ident [String, Integer] A unique identifier for the item being
562
+ # validated, jss id, name, serial number, etc.
563
+ #
564
+ # @return [Integer, nil] the valid id for the item, or nil if not found
565
+ #
566
+ def validate_item(realm, key, ident, error_if_not_found: true)
567
+ # which keys allowed depends on how the item is used...
568
+ possible_keys =
569
+ case realm
570
+ when :target then @inclusion_keys
571
+ when :limitation then LIMITATIONS
572
+ when :exclusion then @exclusion_keys
573
+ else
574
+ raise ArgumentError, 'Unknown realm, must be :target, :limitation, or :exclusion'
575
+ end
576
+ key = pluralize_key(key)
577
+ raise JSS::InvalidDataError, "#{realm} key must be one of :#{possible_keys.join(', :')}" \
578
+ unless possible_keys.include? key
579
+
580
+ # return nil or a valid id
581
+ id = SCOPING_CLASSES[key].valid_id ident
582
+ raise JSS::NoSuchItemError, "No existing #{key} matching '#{ident}'" if error_if_not_found && id.nil?
583
+ id
584
+ end # validate_item(type, key, ident)
585
+
586
+ # the symbols used in the API data are plural, e.g. 'network_segments'
587
+ # this will pluralize them, allowing us to use singulars as well.
588
+ def pluralize_key(key)
589
+ key.to_s.end_with?(ESS) ? key : "#{key}s".to_sym
576
590
  end
577
591
 
578
592
  end # class Scope