ruby-jss 1.2.6 → 1.4.1

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 (250) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +189 -1
  3. data/README.md +1 -1
  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 +1 -1
  8. data/lib/jamf.rb +1 -1
  9. data/lib/jamf/api/abstract_classes/advanced_search.rb +1 -1
  10. data/lib/jamf/api/abstract_classes/collection_resource.rb +17 -9
  11. data/lib/jamf/api/abstract_classes/generic_reference.rb +1 -1
  12. data/lib/jamf/api/abstract_classes/json_object.rb +2 -2
  13. data/lib/jamf/api/abstract_classes/prestage.rb +2 -2
  14. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +1 -1
  15. data/lib/jamf/api/abstract_classes/resource.rb +1 -1
  16. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  17. data/lib/jamf/api/attribute_classes/ip_address.rb +1 -1
  18. data/lib/jamf/api/attribute_classes/timestamp.rb +1 -1
  19. data/lib/jamf/api/connection.rb +9 -5
  20. data/lib/jamf/api/connection/api_error.rb +1 -1
  21. data/lib/jamf/api/connection/api_error_styleguide.rb +1 -1
  22. data/lib/jamf/api/connection/token.rb +22 -2
  23. data/lib/jamf/api/json_objects/account_prefs.rb +1 -1
  24. data/lib/jamf/api/json_objects/android_details.rb +1 -1
  25. data/lib/jamf/api/json_objects/appletv_details.rb +1 -1
  26. data/lib/jamf/api/json_objects/attachment.rb +1 -1
  27. data/lib/jamf/api/json_objects/cellular_network.rb +1 -1
  28. data/lib/jamf/api/json_objects/change_log_entry.rb +1 -1
  29. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +1 -1
  30. data/lib/jamf/api/json_objects/country.rb +1 -1
  31. data/lib/jamf/api/json_objects/criterion.rb +1 -1
  32. data/lib/jamf/api/json_objects/device_enrollment_device.rb +1 -1
  33. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  34. data/lib/jamf/api/json_objects/extension_attribute_value.rb +1 -1
  35. data/lib/jamf/api/json_objects/installed_application.rb +1 -1
  36. data/lib/jamf/api/json_objects/installed_certificate.rb +1 -1
  37. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +1 -1
  38. data/lib/jamf/api/json_objects/installed_ebook.rb +1 -1
  39. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +1 -1
  40. data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +1 -1
  41. data/lib/jamf/api/json_objects/ios_details.rb +1 -1
  42. data/lib/jamf/api/json_objects/location.rb +1 -1
  43. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  44. data/lib/jamf/api/json_objects/md_prestage_names.rb +1 -1
  45. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +1 -1
  46. data/lib/jamf/api/json_objects/mobile_device_details.rb +1 -1
  47. data/lib/jamf/api/json_objects/mobile_device_security.rb +1 -1
  48. data/lib/jamf/api/json_objects/prestage_assignment.rb +1 -1
  49. data/lib/jamf/api/json_objects/prestage_location.rb +1 -1
  50. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +1 -1
  51. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  52. data/lib/jamf/api/json_objects/prestage_sync_status.rb +1 -1
  53. data/lib/jamf/api/json_objects/purchasing_data.rb +1 -1
  54. data/lib/jamf/api/mixins/abstract.rb +1 -1
  55. data/lib/jamf/api/mixins/bulk_deletable.rb +1 -1
  56. data/lib/jamf/api/mixins/change_log.rb +1 -1
  57. data/lib/jamf/api/mixins/extendable.rb +1 -1
  58. data/lib/jamf/api/mixins/immutable.rb +1 -1
  59. data/lib/jamf/api/mixins/locatable.rb +1 -1
  60. data/lib/jamf/api/mixins/lockable.rb +1 -1
  61. data/lib/jamf/api/mixins/referable.rb +1 -1
  62. data/lib/jamf/api/mixins/searchable.rb +1 -1
  63. data/lib/jamf/api/mixins/uncreatable.rb +1 -1
  64. data/lib/jamf/api/mixins/undeletable.rb +1 -1
  65. data/lib/jamf/api/resources/collection_resources/account.rb +1 -1
  66. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +1 -1
  67. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +1 -1
  68. data/lib/jamf/api/resources/collection_resources/building.rb +1 -1
  69. data/lib/jamf/api/resources/collection_resources/category.rb +1 -1
  70. data/lib/jamf/api/resources/collection_resources/computer.rb +1 -1
  71. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +1 -1
  72. data/lib/jamf/api/resources/collection_resources/department.rb +2 -2
  73. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +4 -4
  74. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +1 -1
  75. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +1 -1
  76. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +1 -1
  77. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +1 -1
  78. data/lib/jamf/api/resources/collection_resources/script.rb +1 -1
  79. data/lib/jamf/api/resources/collection_resources/site.rb +1 -1
  80. data/lib/jamf/api/resources/collection_resources/time_zone.rb +1 -1
  81. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +1 -1
  82. data/lib/jamf/api/resources/singleton_resources/authorization.rb +1 -1
  83. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +1 -1
  84. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +1 -1
  85. data/lib/jamf/client.rb +1 -1
  86. data/lib/jamf/client/jamf_binary.rb +1 -1
  87. data/lib/jamf/client/jamf_helper.rb +1 -1
  88. data/lib/jamf/client/management_action.rb +1 -1
  89. data/lib/jamf/compatibility.rb +1 -1
  90. data/lib/jamf/composer.rb +1 -1
  91. data/lib/jamf/configuration.rb +8 -10
  92. data/lib/jamf/exceptions.rb +1 -1
  93. data/lib/jamf/ruby_extensions.rb +2 -1
  94. data/lib/jamf/ruby_extensions/array.rb +2 -2
  95. data/lib/jamf/ruby_extensions/array/predicates.rb +1 -1
  96. data/lib/jamf/ruby_extensions/array/utils.rb +4 -4
  97. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  98. data/lib/jamf/ruby_extensions/filetest.rb +1 -1
  99. data/lib/jamf/ruby_extensions/filetest/predicates.rb +1 -1
  100. data/lib/jamf/ruby_extensions/hash.rb +1 -1
  101. data/lib/jamf/ruby_extensions/hash/backports.rb +2 -2
  102. data/lib/jamf/ruby_extensions/ipaddr.rb +1 -1
  103. data/lib/jamf/ruby_extensions/ipaddr/utils.rb +1 -1
  104. data/lib/jamf/ruby_extensions/object.rb +1 -1
  105. data/lib/jamf/ruby_extensions/object/predicates.rb +1 -1
  106. data/lib/jamf/ruby_extensions/pathname.rb +1 -1
  107. data/lib/jamf/ruby_extensions/pathname/predicates.rb +1 -1
  108. data/lib/jamf/ruby_extensions/pathname/utils.rb +1 -1
  109. data/lib/jamf/ruby_extensions/string.rb +1 -1
  110. data/lib/jamf/ruby_extensions/string/backports.rb +1 -1
  111. data/lib/jamf/ruby_extensions/string/conversions.rb +1 -1
  112. data/lib/jamf/ruby_extensions/string/predicates.rb +14 -4
  113. data/lib/jamf/utility.rb +1 -1
  114. data/lib/jamf/validate.rb +1 -1
  115. data/lib/jamf/version.rb +2 -2
  116. data/lib/jpapi.rb +1 -1
  117. data/lib/jss-api.rb +1 -1
  118. data/lib/jss.rb +3 -1
  119. data/lib/jss/api_connection.rb +3 -30
  120. data/lib/jss/api_object.rb +23 -4
  121. data/lib/jss/api_object/account.rb +1 -1
  122. data/lib/jss/api_object/advanced_search.rb +28 -27
  123. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +1 -1
  124. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
  125. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +1 -1
  126. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  127. data/lib/jss/api_object/building.rb +1 -1
  128. data/lib/jss/api_object/categorizable.rb +1 -1
  129. data/lib/jss/api_object/category.rb +1 -1
  130. data/lib/jss/api_object/computer.rb +12 -6
  131. data/lib/jss/api_object/computer/application_installs.rb +1 -1
  132. data/lib/jss/api_object/computer_invitation.rb +1 -1
  133. data/lib/jss/api_object/configuration_profile.rb +4 -2
  134. data/lib/jss/api_object/configuration_profile/mobile_device_configuration_profile.rb +1 -1
  135. data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +1 -1
  136. data/lib/jss/api_object/creatable.rb +1 -1
  137. data/lib/jss/api_object/criteriable.rb +1 -1
  138. data/lib/jss/api_object/criteriable/criteria.rb +1 -1
  139. data/lib/jss/api_object/criteriable/criterion.rb +1 -1
  140. data/lib/jss/api_object/department.rb +1 -1
  141. data/lib/jss/api_object/directory_binding.rb +273 -0
  142. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  143. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  144. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  145. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  146. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  147. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  148. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  149. data/lib/jss/api_object/distribution_point.rb +96 -36
  150. data/lib/jss/api_object/dock_item.rb +137 -0
  151. data/lib/jss/api_object/ebook.rb +2 -3
  152. data/lib/jss/api_object/extendable.rb +67 -28
  153. data/lib/jss/api_object/extension_attribute.rb +5 -4
  154. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
  155. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
  156. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +1 -1
  157. data/lib/jss/api_object/group.rb +1 -1
  158. data/lib/jss/api_object/group/computer_group.rb +1 -1
  159. data/lib/jss/api_object/group/mobile_device_group.rb +1 -1
  160. data/lib/jss/api_object/group/user_group.rb +1 -1
  161. data/lib/jss/api_object/ibeacon.rb +1 -1
  162. data/lib/jss/api_object/ldap_server.rb +1 -1
  163. data/lib/jss/api_object/locatable.rb +1 -1
  164. data/lib/jss/api_object/mac_application.rb +108 -9
  165. data/lib/jss/api_object/management_history.rb +1 -1
  166. data/lib/jss/api_object/management_history/audit_event.rb +1 -1
  167. data/lib/jss/api_object/management_history/casper_imaging_log.rb +1 -1
  168. data/lib/jss/api_object/management_history/casper_remote_log.rb +1 -1
  169. data/lib/jss/api_object/management_history/computer_usage_log.rb +1 -1
  170. data/lib/jss/api_object/management_history/ebook.rb +1 -1
  171. data/lib/jss/api_object/management_history/hashlike.rb +1 -1
  172. data/lib/jss/api_object/management_history/mac_app_store_app.rb +1 -1
  173. data/lib/jss/api_object/management_history/mdm_command.rb +1 -1
  174. data/lib/jss/api_object/management_history/mobile_device_app.rb +1 -1
  175. data/lib/jss/api_object/management_history/policy_log.rb +1 -1
  176. data/lib/jss/api_object/management_history/screen_sharing_log.rb +1 -1
  177. data/lib/jss/api_object/management_history/user_location_change.rb +1 -1
  178. data/lib/jss/api_object/matchable.rb +1 -1
  179. data/lib/jss/api_object/mdm.rb +1 -1
  180. data/lib/jss/api_object/mobile_device.rb +12 -6
  181. data/lib/jss/api_object/mobile_device_application.rb +13 -1
  182. data/lib/jss/api_object/netboot_server.rb +1 -1
  183. data/lib/jss/api_object/network_segment.rb +153 -59
  184. data/lib/jss/api_object/package.rb +106 -41
  185. data/lib/jss/api_object/patch_policy.rb +1 -1
  186. data/lib/jss/api_object/patch_source.rb +1 -1
  187. data/lib/jss/api_object/patch_source/patch_external_source.rb +1 -1
  188. data/lib/jss/api_object/patch_source/patch_internal_source.rb +1 -1
  189. data/lib/jss/api_object/patch_title.rb +1 -1
  190. data/lib/jss/api_object/patch_title/version.rb +1 -1
  191. data/lib/jss/api_object/peripheral.rb +1 -1
  192. data/lib/jss/api_object/peripheral_type.rb +1 -1
  193. data/lib/jss/api_object/policy.rb +492 -8
  194. data/lib/jss/api_object/printer.rb +440 -0
  195. data/lib/jss/api_object/purchasable.rb +1 -1
  196. data/lib/jss/api_object/removable_macaddr.rb +1 -1
  197. data/lib/jss/api_object/restricted_software.rb +1 -1
  198. data/lib/jss/api_object/scopable.rb +1 -1
  199. data/lib/jss/api_object/scopable/scope.rb +387 -72
  200. data/lib/jss/api_object/script.rb +1 -1
  201. data/lib/jss/api_object/self_servable.rb +24 -16
  202. data/lib/jss/api_object/self_servable/icon.rb +1 -1
  203. data/lib/jss/api_object/sitable.rb +1 -1
  204. data/lib/jss/api_object/site.rb +1 -1
  205. data/lib/jss/api_object/software_update_server.rb +1 -1
  206. data/lib/jss/api_object/updatable.rb +1 -1
  207. data/lib/jss/api_object/uploadable.rb +2 -2
  208. data/lib/jss/api_object/user.rb +43 -2
  209. data/lib/jss/api_object/vpp_account.rb +209 -0
  210. data/lib/jss/api_object/vppable.rb +170 -14
  211. data/lib/jss/api_object/webhook.rb +1 -1
  212. data/lib/jss/client.rb +1 -1
  213. data/lib/jss/client/jamf_binary.rb +1 -1
  214. data/lib/jss/client/jamf_helper.rb +1 -1
  215. data/lib/jss/client/management_action.rb +1 -1
  216. data/lib/jss/compatibility.rb +1 -1
  217. data/lib/jss/composer.rb +2 -2
  218. data/lib/jss/configuration.rb +1 -1
  219. data/lib/jss/db_connection.rb +1 -1
  220. data/lib/jss/exceptions.rb +1 -1
  221. data/lib/jss/ruby_extensions.rb +1 -1
  222. data/lib/jss/ruby_extensions/array.rb +1 -1
  223. data/lib/jss/ruby_extensions/filetest.rb +1 -1
  224. data/lib/jss/ruby_extensions/hash.rb +1 -1
  225. data/lib/jss/ruby_extensions/ipaddr.rb +1 -1
  226. data/lib/jss/ruby_extensions/pathname.rb +1 -1
  227. data/lib/jss/ruby_extensions/string.rb +1 -1
  228. data/lib/jss/ruby_extensions/string/backports.rb +1 -1
  229. data/lib/jss/ruby_extensions/string/conversions.rb +1 -1
  230. data/lib/jss/ruby_extensions/string/predicates.rb +14 -4
  231. data/lib/jss/ruby_extensions/time.rb +1 -1
  232. data/lib/jss/server.rb +1 -1
  233. data/lib/jss/utility.rb +9 -23
  234. data/lib/jss/validate.rb +54 -11
  235. data/lib/jss/version.rb +2 -2
  236. data/lib/jss/xml_workaround.rb +1 -1
  237. data/lib/ruby-jss.rb +1 -1
  238. data/test/bin/runtests +1 -1
  239. data/test/lib/testhelper.rb +1 -1
  240. data/test/lib/testhelper/auth.rb +1 -1
  241. data/test/lib/testhelper/patch_mgmt.rb +1 -1
  242. data/test/specs/api_connection_spec.rb +1 -1
  243. data/test/specs/patch01_source_spec.rb +1 -1
  244. data/test/specs/patch02_internal_source_spec.rb +1 -1
  245. data/test/specs/patch03_external_source_spec.rb +1 -1
  246. data/test/specs/patch04_titles_spec.rb +1 -1
  247. data/test/specs/patch05_policies_spec.rb +1 -1
  248. data/test/specs/patch06_cleanup_spec.rb +1 -1
  249. data/test/specs/policy_spec.rb +1 -1
  250. metadata +15 -2
@@ -1,4 +1,4 @@
1
- ### Copyright 2019 Pixar
1
+ ### Copyright 2020 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2019 Pixar
1
+ ### Copyright 2020 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 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
@@ -41,17 +41,21 @@ module JSS
41
41
  # This class provides methods for adding, removing, or fully replacing the
42
42
  # various items in scope's realms: targets, limitations, and exclusions.
43
43
  #
44
- # IMPORTANT:
44
+ # This class also provides a way to see if a machine will be included in
45
+ # this scope.
46
+ #
47
+ # IMPORTANT - Users & User Groups in Targets and Exclusions:
48
+ #
45
49
  # The classic API has bugs regarding the use of Users, UserGroups,
46
50
  # LDAP/Local Users, & LDAP User Groups in scopes. Here's a discussion
47
51
  # of those bugs and how ruby-jss handles them.
48
52
  #
49
53
  # Targets/Inclusions
50
- # - 'Users' can only be JSS::Users - No LDAP
54
+ # - 'Users' in the Scope UI can only be JSS::Users - No LDAP
51
55
  # - BUG: They do not appear in API data (XML or JSON) and are
52
56
  # NOT SUPPORTED in ruby-jss.
53
57
  # - You must use the Web UI to work with them in a Scope.
54
- # - 'User Groups' can only be JSS::UserGroups - No LDAP
58
+ # - 'User Groups' in the Scope UI can only be JSS::UserGroups - No LDAP
55
59
  # - BUG: They do not appear in API data (XML or JSON) and are
56
60
  # NOT SUPPORTED in ruby-jss.
57
61
  # - You must use the Web UI to work with them in a Scope.
@@ -70,11 +74,11 @@ module JSS
70
74
  # scope=>limitations=>user_groups
71
75
  #
72
76
  # Exclusions, combines the behavior of Inclusions & Limitations
73
- # - 'Users' can only be JSS::Users - No LDAP
77
+ # - 'Users' in the Scope UI can only be JSS::Users - No LDAP
74
78
  # - BUG: They do not appear in API data (XML or JSON) and are
75
79
  # NOT SUPPORTED in ruby-jss.
76
80
  # - You must use the Web UI to work with them in a Scope.
77
- # - 'User Groups' can only be JSS::UserGroups - No LDAP
81
+ # - 'User Groups' in the Scope UI can only be JSS::UserGroups - No LDAP
78
82
  # - BUG: They do not appear in API data (XML or JSON) and are
79
83
  # NOT SUPPORTED in ruby-jss.
80
84
  # - You must use the Web UI to work with them in a Scope.
@@ -226,56 +230,64 @@ module JSS
226
230
  # if we can't connect to LDAP servers for verification?
227
231
  attr_accessor :unable_to_verify_ldap_entries
228
232
 
229
- # what type of target is this scope for? Computers or Mobiledevices?
233
+ # what type of target is this scope for? Computers or MobileDevices?
230
234
  attr_reader :target_class
231
235
 
232
- # @return [Hash<Array>]
233
- #
234
- # The items which form the base scope of included targets
235
- #
236
- # This is the group of targets to which the limitations and exclusions apply.
237
- # they keys are:
238
- # - :targets
239
- # - :target_groups
240
- # - :departments
241
- # - :buildings
242
- # and the values are Arrays of names of those things.
243
- #
244
- attr_reader :inclusions
236
+ # what type of target group is this scope for? ComputerGroups or MobileDeviceGroups?
237
+ attr_reader :group_class
245
238
 
246
239
  # @return [Boolean]
247
240
  #
248
241
  # Does this scope cover all targets?
249
242
  #
250
- # If this is true, the @inclusions Hash is ignored, and all
243
+ # If this is true, the @targets Hash is ignored, and all
251
244
  # targets in the JSS form the base scope.
252
245
  #
253
246
  attr_reader :all_targets
247
+ alias all_targets? all_targets
248
+
254
249
 
255
- # @return [Hash<Array>]
250
+ # The items which form the base scope of included targets
256
251
  #
257
- # The items in these arrays are the limitations applied to targets in the @inclusions .
252
+ # This is the group of targets to which the limitations and exclusions apply.
253
+ # they keys are:
254
+ # - :computers or :mobile_devices (which are directly targeted)
255
+ # - :direct_targets - a synonym for :mobile_devices or :computers
256
+ # - :computer_groups or :mobile_device_groups (which target all of their memebers)
257
+ # - :group_targets - a synonym for :computer_groups or :mobile_device_groups
258
+ # - :departments
259
+ # - :buildings
260
+ # and the values are Arrays of names of those things.
261
+ #
262
+ # @return [Hash{Symbol: Array<Integer>}]
263
+ attr_reader :targets
264
+ # backward compatibility
265
+ alias inclusions targets
266
+
267
+ # The items in these arrays are the limitations applied to targets in the @targets .
258
268
  #
259
- # The arrays of names are:
269
+ # The arrays of ids are:
260
270
  # - :network_segments
261
- # - :users
271
+ # - :jamf_ldap_users
262
272
  # - :user_groups
263
273
  #
274
+ # @return [Hash{Symbol: Array<Integer, String>}]
264
275
  attr_reader :limitations
265
276
 
266
- # @return [Hash<Array>]
267
- #
268
- # The items in these arrays are the exclusions applied to targets in the @inclusions .
277
+ # The items in these arrays are the exclusions applied to targets in the @targets .
269
278
  #
270
- # The arrays of names are:
271
- # - :targets
272
- # - :target_groups
279
+ # The arrays of ids are:
280
+ # - :computers or :mobile_devices (which are directly excluded)
281
+ # - :direct_exclusions - a synonym for :mobile_devices or :computers
282
+ # - :computer_groups or :mobile_device_groups (which exclude all of their memebers)
283
+ # - :group_exclusions - a synonym for :computer_groups or :mobile_device_groups
273
284
  # - :departments
274
285
  # - :buildings
275
286
  # - :network_segments
276
287
  # - :users
277
288
  # - :user_groups
278
289
  #
290
+ # @return [Hash{Symbol: Array<Integer, String>}]
279
291
  attr_reader :exclusions
280
292
 
281
293
  # Public Instance Methods
@@ -299,7 +311,7 @@ module JSS
299
311
  @group_key = TARGETS_AND_GROUPS[@target_key]
300
312
  @group_class = SCOPING_CLASSES[@group_key]
301
313
 
302
- @inclusion_keys = [@target_key, @group_key] + INCLUSIONS
314
+ @target_keys = [@target_key, @group_key] + INCLUSIONS
303
315
  @exclusion_keys = [@target_key, @group_key] + EXCLUSIONS
304
316
 
305
317
  @all_key = "all_#{target_key}".to_sym
@@ -307,11 +319,13 @@ module JSS
307
319
 
308
320
  # Everything gets mapped from an Array of Hashes to
309
321
  # an Array of ids
310
- @inclusions = {}
311
- @inclusion_keys.each do |k|
322
+ @targets = {}
323
+ @target_keys.each do |k|
312
324
  raw_scope[k] ||= []
313
- @inclusions[k] = raw_scope[k].compact.map { |n| n[:id].to_i }
314
- end # @inclusion_keys.each do |k|
325
+ @targets[k] = raw_scope[k].compact.map { |n| n[:id].to_i }
326
+ @targets[:direct_targets] = @targets[k] if k == @target_key
327
+ @targets[:group_targets] = @targets[k] if k == @group_key
328
+ end # @target_keys.each do |k|
315
329
 
316
330
  # the :users key from the API is what we call :jamf_ldap_users
317
331
  # and the :user_groups key from the API we call :ldap_user_groups
@@ -365,6 +379,8 @@ module JSS
365
379
  api_data = raw_scope[:exclusions][k]
366
380
  api_data ||= []
367
381
  @exclusions[k] = api_data.compact.map { |n| n[:id].to_i }
382
+ @exclusions[:direct_exclusions] = @exclusions[k] if k == @target_key
383
+ @exclusions[:group_exclusions] = @exclusions[k] if k == @group_key
368
384
  end # if ...elsif... else
369
385
  end # @exclusion_keys.each
370
386
  end # if raw_scope[:exclusions]
@@ -382,8 +398,8 @@ module JSS
382
398
  # @return [void]
383
399
  #
384
400
  def include_all(clear = false)
385
- @inclusions = {}
386
- @inclusion_keys.each { |k| @inclusions[k] = [] }
401
+ @targets = {}
402
+ @target_keys.each { |k| @targets[k] = [] }
387
403
  @all_targets = true
388
404
  if clear
389
405
  @limitations = {}
@@ -392,7 +408,7 @@ module JSS
392
408
  @exclusions = {}
393
409
  @exclusion_keys.each { |k| @exclusions[k] = [] }
394
410
  end
395
- @container&.should_update
411
+ @container.should_update if @container
396
412
  end
397
413
 
398
414
  # Replace a list of item names for as targets in this scope.
@@ -420,7 +436,7 @@ module JSS
420
436
  list.map! do |ident|
421
437
  item_id = validate_item(:target, key, ident)
422
438
 
423
- if @exclusions[key]&.include?(item_id)
439
+ if @exclusions[key] && @exclusions[key].include?(item_id)
424
440
  raise JSS::AlreadyExistsError, \
425
441
  "Can't set #{key} target to '#{ident}' because it's already an explicit exclusion."
426
442
  end
@@ -428,11 +444,11 @@ module JSS
428
444
  item_id
429
445
  end # each
430
446
 
431
- return nil if list.sort == @inclusions[key].sort
447
+ return nil if list.sort == @targets[key].sort
432
448
 
433
- @inclusions[key] = list
449
+ @targets[key] = list
434
450
  @all_targets = false
435
- @container&.should_update
451
+ @container.should_update if @container
436
452
  end # sinclude_in_scope
437
453
  alias set_target set_targets
438
454
  alias set_inclusion set_targets
@@ -458,13 +474,13 @@ module JSS
458
474
  def add_target(key, item)
459
475
  key = pluralize_key(key)
460
476
  item_id = validate_item(:target, key, item)
461
- return if @inclusions[key]&.include?(item_id)
477
+ return if @targets[key] && @exclusions[key].include?(item_id)
462
478
 
463
- raise JSS::AlreadyExistsError, "Can't set #{key} target to '#{item}' because it's already an explicit exclusion." if @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] && @exclusions[key].include?(item_id)
464
480
 
465
- @inclusions[key] << item_id
481
+ @targets[key] << item_id
466
482
  @all_targets = false
467
- @container&.should_update
483
+ @container.should_update if @container
468
484
  end
469
485
  alias add_inclusion add_target
470
486
 
@@ -483,10 +499,10 @@ module JSS
483
499
  key = pluralize_key(key)
484
500
  item_id = validate_item :target, key, item, error_if_not_found: false
485
501
  return unless item_id
486
- return unless @inclusions[key]&.include?(item_id)
502
+ return unless @targets[key] && @exclusions[key].include?(item_id)
487
503
 
488
- @inclusions[key].delete item_id
489
- @container&.should_update
504
+ @targets[key].delete item_id
505
+ @container.should_update if @container
490
506
  end
491
507
  alias remove_inclusion remove_target
492
508
 
@@ -513,7 +529,7 @@ module JSS
513
529
  # check the idents
514
530
  list.map! do |ident|
515
531
  item_id = validate_item(:limitation, key, ident)
516
- if @exclusions[key]&.include?(item_id)
532
+ if @exclusions[key] && @exclusions[key].include?(item_id)
517
533
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
518
534
  end
519
535
 
@@ -523,7 +539,7 @@ module JSS
523
539
  return nil if list.sort == @limitations[key].sort
524
540
 
525
541
  @limitations[key] = list
526
- @container&.should_update
542
+ @container.should_update if @container
527
543
  end # set_limitation
528
544
  alias set_limitations set_limitation
529
545
 
@@ -545,14 +561,14 @@ module JSS
545
561
  def add_limitation(key, item)
546
562
  key = pluralize_key(key)
547
563
  item_id = validate_item(:limitation, key, item)
548
- return nil if @limitations[key]&.include?(item_id)
564
+ return nil if @limitations[key] && @exclusions[key].include?(item_id)
549
565
 
550
- if @exclusions[key]&.include?(item_id)
566
+ if @exclusions[key] && @exclusions[key].include?(item_id)
551
567
  raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
552
568
  end
553
569
 
554
570
  @limitations[key] << item_id
555
- @container&.should_update
571
+ @container.should_update if @container
556
572
  end
557
573
 
558
574
  # Remove a single item for limiting this scope.
@@ -572,10 +588,10 @@ module JSS
572
588
  key = pluralize_key(key)
573
589
  item_id = validate_item :limitation, key, item, error_if_not_found: false
574
590
  return unless item_id
575
- return unless @limitations[key]&.include?(item_id)
591
+ return unless @limitations[key] && @exclusions[key].include?(item_id)
576
592
 
577
593
  @limitations[key].delete item_id
578
- @container&.should_update
594
+ @container.should_update if @container
579
595
  end ###
580
596
 
581
597
  # Replace an exclusion list for this scope
@@ -600,10 +616,10 @@ module JSS
600
616
  list.map! do |ident|
601
617
  item_id = validate_item(:exclusion, key, ident)
602
618
  case key
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)
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)
605
621
  when *LIMITATIONS
606
- if @limitations[key]&.include?(item_id)
622
+ if @limitations[key] && @exclusions[key].include?(item_id)
607
623
  raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already an explicit limitation."
608
624
  end
609
625
  end
@@ -613,7 +629,7 @@ module JSS
613
629
  return nil if list.sort == @exclusions[key].sort
614
630
 
615
631
  @exclusions[key] = list
616
- @container&.should_update
632
+ @container.should_update if @container
617
633
  end # limit scope
618
634
 
619
635
  # Add a single item for exclusions of this scope.
@@ -632,14 +648,14 @@ module JSS
632
648
  def add_exclusion(key, item)
633
649
  key = pluralize_key(key)
634
650
  item_id = validate_item(:exclusion, key, item)
635
- return if @exclusions[key]&.include?(item_id)
651
+ return if @exclusions[key] && @exclusions[key].include?(item_id)
636
652
 
637
- raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @inclusions[key]&.include?(item)
653
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @targets[key] && @targets[key].include?(item)
638
654
 
639
- raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key]&.include?(item)
655
+ raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item)
640
656
 
641
657
  @exclusions[key] << item_id
642
- @container&.should_update
658
+ @container.should_update if @container
643
659
  end
644
660
 
645
661
  # Remove a single item for exclusions of this scope
@@ -656,10 +672,10 @@ module JSS
656
672
  def remove_exclusion(key, item)
657
673
  key = pluralize_key(key)
658
674
  item_id = validate_item :exclusion, key, item, error_if_not_found: false
659
- return unless @exclusions[key]&.include?(item_id)
675
+ return unless @exclusions[key] && @exclusions[key].include?(item_id)
660
676
 
661
677
  @exclusions[key].delete item_id
662
- @container&.should_update
678
+ @container.should_update if @container
663
679
  end
664
680
 
665
681
  # @api private
@@ -672,7 +688,8 @@ module JSS
672
688
  scope = REXML::Element.new 'scope'
673
689
  scope.add_element(@all_key.to_s).text = @all_targets
674
690
 
675
- @inclusions.each do |klass, list|
691
+ @target_keys.each do |klass|
692
+ list = @targets[klass]
676
693
  list.compact!
677
694
  list.delete 0
678
695
  list_as_hashes = list.map { |i| { id: i } }
@@ -702,7 +719,8 @@ module JSS
702
719
  end
703
720
 
704
721
  exclusions = scope.add_element('exclusions')
705
- @exclusions.each do |klass, list|
722
+ @exclusion_keys.each do |klass|
723
+ list = @exclusions[klass]
706
724
  list.compact!
707
725
  list.delete 0
708
726
  if klass == :jamf_ldap_users
@@ -737,9 +755,60 @@ module JSS
737
755
  vars
738
756
  end
739
757
 
740
- # Aliases
758
+ # Return a hash of id => name for all machines in the target class
759
+ # that are within this scope.
760
+ #
761
+ # WARNING: This must instantiate all machines in the target class.
762
+ # It will still be slow, at least the first time for each target class.
763
+ # On the upside, the instantiated machines will be cached, so generating
764
+ # this list for other scopes with the same target class will be much
765
+ # much faster.
766
+ # In tests, 1600 Computers took about 7 minutes the first time,
767
+ # but less than 1 second after caching.
768
+ #
769
+ # See also the warning for #in_scope?
770
+ #
771
+ # @return [Hash{Integer => String}]
772
+ #
773
+ ################
774
+ def scoped_machines
775
+ scoped_machines = {}
776
+ @target_class.all_objects.each do |machine|
777
+ scoped_machines[machine.id] = machine.name if in_scope? machine
778
+ end
779
+ scoped_machines
780
+ end
781
+
782
+ # is a given machine is in this scope?
783
+ #
784
+ # For a parameter you may pass either an instantiated
785
+ # JSS::MobileDevice or JSS::Computer, or an identifier for one.
786
+ # If an identifier is passed, it is not instantiated, but an API
787
+ # request is made for just the required subsets of data, thus
788
+ # speeding things up a bit when calling this method many times.
789
+ #
790
+ # WARNING: For scopes that include Jamf Users and Jamf User Groups
791
+ # as targets or exclusions, this method may return an incorrect value.
792
+ # See the discussion in the documentation for the Scopable::Scope class
793
+ # under 'IMPORTANT - Users & User Groups in Targets and Exclusions'
794
+ #
795
+ # NOTE: currently in-range iBeacons are transient, and are not reported
796
+ # to the JSS as inventory data. As such they are ignored in this result.
797
+ # If a scope contains iBeacon limitations or exclusions, it is up to
798
+ # the user to be aware of that when evaluating the meaning of this result.
799
+ #
800
+ # @param machine[Integer, String, JSS::MobileDevice, JSS::Computer]
801
+ # Either an identifier for the machine, or an instantiated object
802
+ #
803
+ # @return [Boolean]
804
+ #
805
+ ##############
806
+ def in_scope?(machine)
807
+ machine_data = fetch_machine_data machine
808
+
809
+ a_target?(machine_data) && within_limitations?(machine_data) && !excluded?(machine_data)
810
+ end
741
811
 
742
- alias all_targets? all_targets
743
812
 
744
813
  # Private Instance Methods
745
814
  #####################################
@@ -765,7 +834,7 @@ module JSS
765
834
  # which keys allowed depends on how the item is used...
766
835
  possible_keys =
767
836
  case realm
768
- when :target then @inclusion_keys
837
+ when :target then @target_keys
769
838
  when :limitation then LIMITATIONS
770
839
  when :exclusion then @exclusion_keys
771
840
  else
@@ -809,6 +878,252 @@ module JSS
809
878
  end
810
879
  end
811
880
 
881
+ # The data used by the methods that figure out if a machine is
882
+ # in this scope, a Hash of Hashes. the sub hashes are:
883
+ #
884
+ # general: the 'general' subset
885
+ # location: the 'location' subset
886
+ # group_ids: an Array of the group ids to which the machine belongs.
887
+ #
888
+ # @param machine[Integer, String, JSS::MobileDevice, JSS::Computer]
889
+ # Either an identifier for the machine, or an instantiated object
890
+ #
891
+ # @return
892
+ #
893
+ def fetch_machine_data(machine)
894
+ case machine
895
+ when JSS::Computer
896
+ raise JSS::InvalidDataError, "Targets of this scope must be #{@target_class}" unless @target_class == JSS::Computer
897
+
898
+ general = machine.init_data[:general]
899
+ location = machine.init_data[:location]
900
+ group_ids = group_ids machine.computer_groups
901
+
902
+ # put in standardize place for easier use
903
+ # MDevs already have this at general[:managed]
904
+ general[:managed] = general[:remote_management][:managed]
905
+
906
+ when JSS::MobileDevice
907
+ raise JSS::InvalidDataError, "Targets of this scope must be #{@target_class}" unless @target_class == JSS::MobileDevice
908
+
909
+ general = machine.init_data[:general]
910
+ location = machine.init_data[:location]
911
+ group_ids = group_ids machine.mobile_device_groups
912
+
913
+ else
914
+ general, location, group_ids = fetch_subsets(machine)
915
+ end # case
916
+
917
+ {
918
+ general: general,
919
+ location: location,
920
+ group_ids: group_ids
921
+ }
922
+ end
923
+
924
+ # When we are given an indentifier for a machine,
925
+ # fetch just the subsets of API data we need to
926
+ # determine if the machine is in this scope
927
+ #
928
+ # @param ident[String, Integer]
929
+ #
930
+ # @return [Array] the general, locacation, and parsed group IDs
931
+ #
932
+ def fetch_subsets(ident)
933
+ id = @target_class.valid_id ident
934
+ raise JSS::NoSuchItemError, "No #{@target_class} matching #{machine}" unless id
935
+
936
+ if @target_class == JSS::MobileDevice
937
+ grp_subset = 'MobileDeviceGroups'
938
+ top_key = :mobile_device
939
+ else
940
+ grp_subset = 'GroupsAccounts'
941
+ top_key = :computer
942
+ end
943
+ subset_rsrc = "#{@target_class::RSRC_BASE}/id/#{id}/subset/General&Location&#{grp_subset}"
944
+ data = container.api.get_rsrc(subset_rsrc)[top_key]
945
+ grp_data =
946
+ if @target_class == JSS::MobileDevice
947
+ data[:mobile_device_groups]
948
+ else
949
+ data[:groups_accounts][:computer_group_memberships]
950
+ end
951
+
952
+ [data[:general], data[:location], group_ids(grp_data)]
953
+ end
954
+
955
+ # Given the raw API data for a machines group membership,
956
+ # return an array of the IDs of the groups.
957
+ #
958
+ # @param raw[Array] The API array of the machine's group memberships
959
+ #
960
+ # @return [Array] The ID's of the groups to which the machine belongs.
961
+ #
962
+ def group_ids(raw)
963
+ if @target_class == JSS::MobileDevice
964
+ raw.map { |mdg| mdg[:id] }
965
+ else
966
+ names_to_ids = @group_class.map_all_ids_to(:name).invert
967
+ raw.map { |gn| names_to_ids[gn] }
968
+ end
969
+ end
970
+
971
+ # @param machine_data[Hash] See #fetch_machine_data
972
+ # @return [Boolean]
973
+ ################
974
+ def a_target?(machine_data)
975
+ return false unless machine_data[:general][:managed]
976
+ return true if \
977
+ all_targets? || \
978
+ machine_directly_scoped?(machine_data, :target) || \
979
+ machine_in_scope_group?(machine_data, :target) || \
980
+ machine_in_scope_buildings?(machine_data, :target) || \
981
+ machine_in_scope_depts?(machine_data, :target)
982
+
983
+ false
984
+ end
985
+
986
+ # @param machine_data[Hash] See #fetch_machine_data
987
+ # @return [Boolean]
988
+ ################
989
+ def within_limitations?(machine_data)
990
+ return false if \
991
+ machine_in_scope_netsegs?(machine_data, :limitation) == false || \
992
+ machine_in_scope_jamf_ldap_users_list?(machine_data, :limitation) == false || \
993
+ machine_in_scope_ldap_usergroup_list?(machine_data, :limitation) == false
994
+
995
+ true
996
+ end
997
+
998
+ # @param machine_data[Hash] See #fetch_machine_data
999
+ # @return [Boolean]
1000
+ ################
1001
+ def excluded?(machine_data)
1002
+ return true if
1003
+ machine_directly_scoped?(machine_data, :exclusion) || \
1004
+ machine_in_scope_group?(machine_data, :exclusion) || \
1005
+ machine_in_scope_buildings?(machine_data, :exclusion) || \
1006
+ machine_in_scope_depts?(machine_data, :exclusion) || \
1007
+ machine_in_scope_netsegs?(machine_data, :exclusion) || \
1008
+ machine_in_scope_jamf_ldap_users_list?(machine_data, :exclusion) || \
1009
+ machine_in_scope_ldap_usergroup_list?(machine_data, :exclusion)
1010
+
1011
+ false
1012
+ end
1013
+
1014
+ # @param machine_data[Hash] See #fetch_machine_data
1015
+ # @param part[Symbol] either :target or :exclusion
1016
+ # @return [Boolean] Is the machine directly spcified in this part of the scope?
1017
+ ################
1018
+ def machine_directly_scoped?(machine_data, part)
1019
+ scope_list = part == :target ? @targets[:direct_targets] : @exclusions[:direct_exclusions]
1020
+ scope_list.include? machine_data[:general][:id]
1021
+ end
1022
+
1023
+ # @param machine_data[Hash] See #fetch_machine_data
1024
+ # @param part[Symbol] either :target or :exclusion
1025
+ # @return [Boolean] Is the machine a member of any group listed in this part of the scope?
1026
+ ################
1027
+ def machine_in_scope_group?(machine_data, part)
1028
+ scope_list = part == :target ? @targets[:group_targets] : @exclusions[:group_exclusions]
1029
+ # if the list is empty, return nil
1030
+ return if scope_list.empty?
1031
+
1032
+ # if the intersection of the machine's group ids, and those of the scope part
1033
+ # is not empty, then the machine is in at least one of the groups
1034
+ !(machine_data[:group_ids] & scope_list).empty?
1035
+ end
1036
+
1037
+ # @param machine_data[Hash] See #fetch_machine_data
1038
+ # @param part[Symbol] either :target or :exclusion
1039
+ # @return [Boolean] Is the machine in any building listed in this part of the scope?
1040
+ #################
1041
+ def machine_in_scope_buildings?(machine_data, part)
1042
+ scope_list = part == :target ? @targets[:buildings] : @exclusions[:buildings]
1043
+
1044
+ # nil if empty
1045
+ return if scope_list.empty?
1046
+ # false if no building for the machine - it isn't in any dept
1047
+ return false if machine_data[:location][:building].to_s.empty?
1048
+
1049
+ building_id = JSS::Building.map_all_ids_to(:name).invert[machine_data[:location][:building]]
1050
+ scope_list.include? building_id
1051
+ end
1052
+
1053
+ # @param machine_data[Hash] See #fetch_machine_data
1054
+ # @param part[Symbol] either :target or :exclusion
1055
+ # @return [Boolean] Is the machine in any department listed in this part of the scope?
1056
+ #################
1057
+ def machine_in_scope_depts?(machine_data, part)
1058
+ scope_list = part == :target ? @targets[:departments] : @exclusions[:departments]
1059
+
1060
+ # nil if empty
1061
+ return if scope_list.empty?
1062
+ # false if no dept for the machine - it isn't in any dept
1063
+ return false if machine_data[:location][:department].to_s.empty?
1064
+
1065
+ dept_id = JSS::Department.map_all_ids_to(:name).invert[machine_data[:location][:department]]
1066
+
1067
+ scope_list.include? dept_id
1068
+ end
1069
+
1070
+ # @param machine_data[Hash] See #fetch_machine_data
1071
+ # @param part[Symbol] either :limitation or :exclusion
1072
+ # @return [Boolean] Is the machine in any NetworkSegment listed in this part of the scope?
1073
+ ##################
1074
+ def machine_in_scope_netsegs?(machine_data, part)
1075
+ scope_list = part == :limitation ? @limitations[:network_segments] : @exclusions[:network_segments]
1076
+
1077
+ # nil if no netsegs in scope part
1078
+ return if scope_list.empty?
1079
+
1080
+ ip = @target_class == JSS::Computer ? machine_data[:general][:last_reported_ip] : machine_data[:general][:ip_address]
1081
+ # false if no ip for machine - it isn't in a any of the segs
1082
+ return false if ip.to_s.empty?
1083
+
1084
+ mach_segs = JSS::NetworkSegment.network_segments_for_ip ip
1085
+
1086
+ # if the intersection is not empty, then the machine is in at least one of the net segs
1087
+ !(mach_segs & scope_list).empty?
1088
+ end
1089
+
1090
+ # @param machine_data[Hash] See #fetch_machine_data
1091
+ # @param part[Symbol] either :limitation or :exclusion
1092
+ # @return [Boolean] Is the user of this machine in the list of jamf/ldap users in this part of the scope?
1093
+ ##################
1094
+ def machine_in_scope_jamf_ldap_users_list?(machine_data, part)
1095
+ scope_list = part == :limitation ? @limitations[:jamf_ldap_users] : @exclusions[:jamf_ldap_users]
1096
+
1097
+ # nil if the list is empty
1098
+ return if scope_list.empty?
1099
+
1100
+ scope_list.include? machine_data[:location][:username]
1101
+ end
1102
+
1103
+ # @param machine_data[Hash] See #fetch_machine_data
1104
+ # @param part[Symbol] either :limitation or :exclusion
1105
+ # @return [Boolean] Is the user of this machine a member of any of the LDAP groups in in this part of the scope?
1106
+ ##################
1107
+ def machine_in_scope_ldap_usergroup_list?(machine_data, part)
1108
+ scope_list = part == :limitation ? @limitations[:ldap_user_groups] : @exclusions[:ldap_user_groups]
1109
+
1110
+ # nil if the list is empty
1111
+ return if scope_list.empty?
1112
+
1113
+ # loop thru them checking to see if the user is a member
1114
+ scope_list.each do |ldapgroup|
1115
+ server = JSS::LDAPServer.server_for_group ldapgroup
1116
+ # if the group doesn't exist in any LDAP the user isn't a part of it
1117
+ next unless server
1118
+
1119
+ # if the user name is in any group, return true
1120
+ return true if JSS::LDAPServer.check_membership server, machine_data[:location][:username], ldapgroup
1121
+ end
1122
+
1123
+ # if we're here, not in any group
1124
+ false
1125
+ end
1126
+
812
1127
  end # class Scope
813
1128
 
814
1129
  end # module Scopable