ruby-jss 1.2.4a3 → 1.3.2

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

Potentially problematic release.


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

Files changed (248) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +180 -1
  3. data/README.md +4 -2
  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 +2 -1
  9. data/lib/jamf/api/abstract_classes/advanced_search.rb +1 -1
  10. data/lib/jamf/api/abstract_classes/collection_resource.rb +54 -38
  11. data/lib/jamf/api/abstract_classes/generic_reference.rb +1 -1
  12. data/lib/jamf/api/abstract_classes/json_object.rb +16 -10
  13. data/lib/jamf/api/abstract_classes/prestage.rb +111 -35
  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 +166 -69
  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 +87 -16
  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 +6 -4
  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 +5 -3
  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 +3 -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 +3 -3
  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 -1
  73. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +110 -18
  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 +9 -2
  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 +119 -0
  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 +59 -4
  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 +6 -8
  92. data/lib/jamf/exceptions.rb +6 -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 -3
  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 +5 -2
  119. data/lib/jss/api_connection.rb +3 -30
  120. data/lib/jss/api_object.rb +16 -3
  121. data/lib/jss/api_object/account.rb +1 -1
  122. data/lib/jss/api_object/advanced_search.rb +1 -1
  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/building.rb +1 -1
  127. data/lib/jss/api_object/categorizable.rb +1 -1
  128. data/lib/jss/api_object/category.rb +1 -1
  129. data/lib/jss/api_object/computer.rb +12 -6
  130. data/lib/jss/api_object/computer/application_installs.rb +1 -1
  131. data/lib/jss/api_object/computer_invitation.rb +1 -1
  132. data/lib/jss/api_object/configuration_profile.rb +4 -2
  133. data/lib/jss/api_object/configuration_profile/mobile_device_configuration_profile.rb +1 -1
  134. data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +1 -1
  135. data/lib/jss/api_object/creatable.rb +1 -1
  136. data/lib/jss/api_object/criteriable.rb +10 -5
  137. data/lib/jss/api_object/criteriable/criteria.rb +26 -10
  138. data/lib/jss/api_object/criteriable/criterion.rb +1 -1
  139. data/lib/jss/api_object/department.rb +1 -1
  140. data/lib/jss/api_object/directory_binding.rb +273 -0
  141. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  142. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  143. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  144. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  145. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  146. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  147. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  148. data/lib/jss/api_object/distribution_point.rb +96 -36
  149. data/lib/jss/api_object/dock_item.rb +137 -0
  150. data/lib/jss/api_object/ebook.rb +1 -1
  151. data/lib/jss/api_object/extendable.rb +67 -28
  152. data/lib/jss/api_object/extension_attribute.rb +1 -1
  153. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
  154. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
  155. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +1 -1
  156. data/lib/jss/api_object/group.rb +1 -1
  157. data/lib/jss/api_object/group/computer_group.rb +1 -1
  158. data/lib/jss/api_object/group/mobile_device_group.rb +1 -1
  159. data/lib/jss/api_object/group/user_group.rb +1 -1
  160. data/lib/jss/api_object/ibeacon.rb +1 -1
  161. data/lib/jss/api_object/ldap_server.rb +1 -1
  162. data/lib/jss/api_object/locatable.rb +1 -1
  163. data/lib/jss/api_object/mac_application.rb +1 -1
  164. data/lib/jss/api_object/management_history.rb +23 -22
  165. data/lib/jss/api_object/management_history/audit_event.rb +1 -1
  166. data/lib/jss/api_object/management_history/casper_imaging_log.rb +1 -1
  167. data/lib/jss/api_object/management_history/casper_remote_log.rb +1 -1
  168. data/lib/jss/api_object/management_history/computer_usage_log.rb +1 -1
  169. data/lib/jss/api_object/management_history/ebook.rb +1 -1
  170. data/lib/jss/api_object/management_history/hashlike.rb +1 -1
  171. data/lib/jss/api_object/management_history/mac_app_store_app.rb +1 -1
  172. data/lib/jss/api_object/management_history/mdm_command.rb +1 -1
  173. data/lib/jss/api_object/management_history/mobile_device_app.rb +1 -1
  174. data/lib/jss/api_object/management_history/policy_log.rb +1 -1
  175. data/lib/jss/api_object/management_history/screen_sharing_log.rb +1 -1
  176. data/lib/jss/api_object/management_history/user_location_change.rb +1 -1
  177. data/lib/jss/api_object/matchable.rb +1 -1
  178. data/lib/jss/api_object/mdm.rb +1 -1
  179. data/lib/jss/api_object/mobile_device.rb +29 -6
  180. data/lib/jss/api_object/mobile_device_application.rb +13 -1
  181. data/lib/jss/api_object/netboot_server.rb +1 -1
  182. data/lib/jss/api_object/network_segment.rb +153 -59
  183. data/lib/jss/api_object/package.rb +107 -42
  184. data/lib/jss/api_object/patch_policy.rb +1 -1
  185. data/lib/jss/api_object/patch_source.rb +1 -1
  186. data/lib/jss/api_object/patch_source/patch_external_source.rb +1 -1
  187. data/lib/jss/api_object/patch_source/patch_internal_source.rb +1 -1
  188. data/lib/jss/api_object/patch_title.rb +1 -1
  189. data/lib/jss/api_object/patch_title/version.rb +1 -1
  190. data/lib/jss/api_object/peripheral.rb +1 -1
  191. data/lib/jss/api_object/peripheral_type.rb +1 -1
  192. data/lib/jss/api_object/policy.rb +380 -5
  193. data/lib/jss/api_object/printer.rb +440 -0
  194. data/lib/jss/api_object/purchasable.rb +1 -1
  195. data/lib/jss/api_object/removable_macaddr.rb +1 -1
  196. data/lib/jss/api_object/restricted_software.rb +1 -1
  197. data/lib/jss/api_object/scopable.rb +1 -1
  198. data/lib/jss/api_object/scopable/scope.rb +257 -37
  199. data/lib/jss/api_object/script.rb +1 -1
  200. data/lib/jss/api_object/self_servable.rb +7 -7
  201. data/lib/jss/api_object/self_servable/icon.rb +1 -1
  202. data/lib/jss/api_object/sitable.rb +6 -2
  203. data/lib/jss/api_object/site.rb +1 -1
  204. data/lib/jss/api_object/software_update_server.rb +1 -1
  205. data/lib/jss/api_object/updatable.rb +1 -1
  206. data/lib/jss/api_object/uploadable.rb +1 -1
  207. data/lib/jss/api_object/user.rb +5 -3
  208. data/lib/jss/api_object/vppable.rb +1 -1
  209. data/lib/jss/api_object/webhook.rb +1 -1
  210. data/lib/jss/client.rb +1 -1
  211. data/lib/jss/client/jamf_binary.rb +1 -1
  212. data/lib/jss/client/jamf_helper.rb +1 -1
  213. data/lib/jss/client/management_action.rb +1 -1
  214. data/lib/jss/compatibility.rb +1 -1
  215. data/lib/jss/composer.rb +2 -2
  216. data/lib/jss/configuration.rb +1 -1
  217. data/lib/jss/db_connection.rb +1 -1
  218. data/lib/jss/exceptions.rb +1 -1
  219. data/lib/jss/ruby_extensions.rb +1 -1
  220. data/lib/jss/ruby_extensions/array.rb +1 -1
  221. data/lib/jss/ruby_extensions/filetest.rb +1 -1
  222. data/lib/jss/ruby_extensions/hash.rb +1 -1
  223. data/lib/jss/ruby_extensions/ipaddr.rb +1 -1
  224. data/lib/jss/ruby_extensions/pathname.rb +1 -1
  225. data/lib/jss/ruby_extensions/string.rb +1 -1
  226. data/lib/jss/ruby_extensions/string/backports.rb +1 -1
  227. data/lib/jss/ruby_extensions/string/conversions.rb +1 -1
  228. data/lib/jss/ruby_extensions/string/predicates.rb +14 -4
  229. data/lib/jss/ruby_extensions/time.rb +1 -1
  230. data/lib/jss/server.rb +1 -1
  231. data/lib/jss/utility.rb +9 -23
  232. data/lib/jss/validate.rb +1 -1
  233. data/lib/jss/version.rb +2 -2
  234. data/lib/jss/xml_workaround.rb +1 -1
  235. data/lib/ruby-jss.rb +1 -1
  236. data/test/bin/runtests +1 -1
  237. data/test/lib/testhelper.rb +1 -1
  238. data/test/lib/testhelper/auth.rb +1 -1
  239. data/test/lib/testhelper/patch_mgmt.rb +1 -1
  240. data/test/specs/api_connection_spec.rb +1 -1
  241. data/test/specs/patch01_source_spec.rb +1 -1
  242. data/test/specs/patch02_internal_source_spec.rb +1 -1
  243. data/test/specs/patch03_external_source_spec.rb +1 -1
  244. data/test/specs/patch04_titles_spec.rb +1 -1
  245. data/test/specs/patch05_policies_spec.rb +1 -1
  246. data/test/specs/patch06_cleanup_spec.rb +1 -1
  247. data/test/specs/policy_spec.rb +1 -1
  248. metadata +16 -4
@@ -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
@@ -482,7 +482,7 @@ module Jamf
482
482
  # have an alias without the 'is' so :isManaged will have
483
483
  # getters isManaged? and managed?
484
484
  #
485
- PREDICATE_RE = /^is([A-Z]\w*)$/.freeze
485
+ PREDICATE_RE = /^is([A-Z]\w+)$/.freeze
486
486
 
487
487
  # Public Class Methods
488
488
  #####################################
@@ -524,7 +524,7 @@ module Jamf
524
524
  #
525
525
  def self.attr_key_for_alias(als)
526
526
  validate_not_abstract
527
- self::OBJECT_MODEL.each { |k, deets| return k if k == als || deets[:aliases]&.include?(als) }
527
+ self::OBJECT_MODEL.each { |k, deets| return k if k == als || deets[:aliases].to_a.include?(als) }
528
528
  nil
529
529
  end
530
530
 
@@ -575,10 +575,11 @@ module Jamf
575
575
  else
576
576
  define_method(attr_name) { instance_variable_get("@#{attr_name}") }
577
577
 
578
- # all booleans get a predicate alias
579
- alias_method("#{attr_name}?", attr_name) if attr_def[:class] == :boolean
580
578
  end
581
579
 
580
+ # all booleans get predicate aliases
581
+ define_predicates(attr_name) if attr_def[:class] == :boolean
582
+
582
583
  return unless attr_def[:aliases]
583
584
 
584
585
  # aliases
@@ -586,6 +587,15 @@ module Jamf
586
587
  end # create getters
587
588
  private_class_method :create_getters
588
589
 
590
+ # create the default aliases for booleans
591
+ ##############################
592
+ def self.define_predicates(attr_name)
593
+ alias_method("#{attr_name}?", attr_name)
594
+ return unless attr_name.to_s =~ PREDICATE_RE
595
+
596
+ alias_method("#{Regexp.last_match(1).downcase}?", attr_name)
597
+ end
598
+
589
599
  # create setter(s) for an attribute, and any aliases needed
590
600
  ##############################
591
601
  def self.create_setters(attr_name, attr_def)
@@ -727,7 +737,7 @@ module Jamf
727
737
 
728
738
  attr_def[:aliases].each { |al| alias_method "#{al}_delete_if", "#{attr_name}_delete_if" }
729
739
  end # create_insert_setters
730
- private_class_method :create_delete_at_setters
740
+ private_class_method :create_delete_if_setters
731
741
 
732
742
  # Raise an exception if this is an abstract class
733
743
  # Used in class methods that are defined in abstract classes.
@@ -762,13 +772,9 @@ module Jamf
762
772
  #
763
773
  # Otherwise, the value is returned unchanged.
764
774
  #
765
- # If the attribute is defined as an identifier, it must be unique among
766
- # the other objects of this subclass in the JSS.
767
- #
768
775
  # This method only validates single values. When called from multi-value
769
776
  # setters, it is used for each value individually.
770
777
  #
771
- #
772
778
  # @param attr_name[Symbol], a top-level key from OBJECT_MODEL for this class
773
779
  #
774
780
  # @param value [Object] the value to validate for that attribute.
@@ -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")
@@ -235,17 +235,17 @@ module Jamf
235
235
  #
236
236
  def self.serials_for_prestage(prestage_ident, refresh = false, cnx: Jamf.cnx)
237
237
  id = valid_id prestage_ident, cnx: cnx
238
- raise Jamf::NoSuchItemError, "No #{self} matching '#{ident}'" unless id
238
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{prestage_ident}'" unless id
239
239
 
240
240
  serials_by_prestage_id(refresh, cnx: cnx).select { |_sn, psid| id == psid }.keys
241
241
  end
242
242
 
243
243
  # The id of the prestage to which the given serialNumber is assigned.
244
- # nil if not assigned
244
+ # nil if not assigned or not in DEP.
245
245
  #
246
246
  # NOTE: If a serial number isn't assigned to any prestage, it may really be
247
- # unassigned or it may not exist in your DEP. At the moment there's no way
248
- # via the JP-API to know the SNs in DEP that are not assigned
247
+ # unassigned or it may not exist in your DEP. To see if a SN exists in one
248
+ # of your Device Enrollment instances, use Jamf::DeviceEnrollment.include?
249
249
  #
250
250
  # @param sn [String] the serial number to look for
251
251
  #
@@ -263,8 +263,8 @@ module Jamf
263
263
  # given prestage if a prestage_ident is specified?
264
264
  #
265
265
  # NOTE: If a serial number isn't assigned to any prestage, it may really be
266
- # unassigned or it may not exist in your DEP. At the moment there's no way
267
- # via the JP-API to know the SNs in DEP but not assigned
266
+ # unassigned or it may not exist in your DEP. To see if a SN exists in one
267
+ # of your Device Enrollment instances, use Jamf::DeviceEnrollment.include?
268
268
  #
269
269
  # @param sn [String] the serial number to look for
270
270
  #
@@ -283,10 +283,10 @@ module Jamf
283
283
  return false unless assigned_id
284
284
 
285
285
  if prestage_ident
286
- id = valid_id prestage_ident, cnx: cnx
287
- raise Jamf::NoSuchItemError, "No #{self} matching '#{prestage_ident}'" unless id
286
+ psid = valid_id prestage_ident, cnx: cnx
287
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{prestage_ident}'" unless psid
288
288
 
289
- return id == assigned_id
289
+ return psid == assigned_id
290
290
  end
291
291
 
292
292
  true
@@ -305,13 +305,84 @@ module Jamf
305
305
  Jamf::DeviceEnrollment.device_sns(type: type, cnx: cnx) - serials_by_prestage_id(:refresh, cnx: cnx).keys
306
306
  end
307
307
 
308
- # @return [Array<String>] The serial numbers of devices that are not in DEP
308
+ # @return [Array<String>] The serial numbers of known hardware not in DEP
309
309
  # at all
310
310
  def self.sns_not_in_device_enrollment
311
311
  # type = self == Jamf::MobileDevicePrestage ? :mobiledevices : :computers
312
- nil # TODO: this, once MobileDevice is implemented
312
+ nil # TODO: this, once MobileDevice & Computer classes are implemented
313
313
  end
314
314
 
315
+ # Assign one or more serialNumber to a prestage
316
+ # @return [Jamf::PrestageScope] the new scope for the prestage
317
+ def self.assign(*sns_to_assign, to_prestage:, cnx: Jamf.cnx)
318
+ prestage_id = valid_id to_prestage
319
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{to_prestage}'" unless prestage_id
320
+
321
+ # all sns_to_assign must be in DEP
322
+ not_in_dep = sns_to_assign - Jamf::DeviceEnrollment.device_sns
323
+ raise Jamf::UnsupportedError, "These SNs are not in any Device Enrollment instance: #{not_in_dep.join ', '}" unless not_in_dep.empty?
324
+
325
+ # all sns_to_assign must currently be unassigned.
326
+ already_assigned = sns_to_assign - unassigned_sns
327
+ raise Jamf::UnsupportedError, "These SNs are already assigned to a prestage: #{already_assigned.join ', '}" unless already_assigned.empty?
328
+
329
+ # upcase all sns
330
+ sns_to_assign.map!(&:to_s)
331
+ sns_to_assign.map!(&:upcase)
332
+
333
+ # get the prestage name
334
+ prestage_name = map_all(:id, to: :displayName)[prestage_id]
335
+
336
+ scope_rsrc = "#{self::RSRC_VERSION}/#{self::RSRC_PATH}/#{prestage_id}/#{SCOPE_RSRC}"
337
+ scope = Jamf::PrestageScope.new cnx.get(scope_rsrc)
338
+
339
+ # add the new sns to the existing ones
340
+ new_scope_sns = scope.assignments.map(&:serialNumber)
341
+ new_scope_sns += sns_to_assign
342
+ new_scope_sns.uniq!
343
+
344
+ update_scope(prestage_name, scope_rsrc, new_scope_sns, scope.versionLock, cnx)
345
+ end # self.assign
346
+
347
+ # Unassign one or more serialNumber from a prestage
348
+ # @return [Jamf::PrestageScope] the new scope for the prestage
349
+ def self.unassign(*sns_to_unassign, from_prestage:, cnx: Jamf.cnx)
350
+ prestage_id = valid_id from_prestage
351
+ raise Jamf::NoSuchItemError, "No #{self} matching '#{from_prestage}'" unless prestage_id
352
+
353
+ # upcase all sns
354
+ sns_to_unassign.map!(&:to_s)
355
+ sns_to_unassign.map!(&:upcase)
356
+
357
+ # get the prestage name
358
+ prestage_name = map_all(:id, to: :displayName)[prestage_id]
359
+
360
+ scope_rsrc = "#{self::RSRC_VERSION}/#{self::RSRC_PATH}/#{prestage_id}/#{SCOPE_RSRC}"
361
+ scope = Jamf::PrestageScope.new cnx.get(scope_rsrc)
362
+
363
+ new_scope_sns = scope.assignments.map(&:serialNumber)
364
+ new_scope_sns -= sns_to_unassign
365
+
366
+ update_scope(prestage_name, scope_rsrc, new_scope_sns, scope.versionLock, cnx)
367
+ end # self.unassign
368
+
369
+ # Provate Class Methods
370
+ #####################################
371
+
372
+ # used by assign and unassign
373
+ def self.update_scope(prestage_name, scope_rsrc, new_scope_sns, vlock, cnx)
374
+ assignment_data = {
375
+ serialNumbers: new_scope_sns,
376
+ versionLock: vlock
377
+ }
378
+ Jamf::PrestageScope.new cnx.put(scope_rsrc, assignment_data)
379
+ rescue Jamf::Connection::APIError => e
380
+ raise Jamf::VersionLockError, "The #{self} '#{prestage_name}' was modified by another process during this operation. Please try again" if e.status == 409
381
+
382
+ raise e
383
+ end
384
+ private_class_method :update_scope
385
+
315
386
  # Instance Methods
316
387
  #####################################
317
388
 
@@ -351,19 +422,24 @@ module Jamf
351
422
 
352
423
  # Assign
353
424
  def assign(*sns_to_assign)
354
- sns_to_assign.map!(&:to_s)
355
- new_scope_sns = assigned_sns
356
- new_scope_sns += sns_to_assign
357
- new_scope_sns.uniq!
358
- update_scope(new_scope_sns)
425
+ @scope = self.class.assign(sns_to_assign, to_prestage: @id, cnx: @cnx)
426
+ @versionLock = @scope.versionLock
427
+
428
+ # sns_to_assign.map!(&:to_s)
429
+ # new_scope_sns = assigned_sns
430
+ # new_scope_sns += sns_to_assign
431
+ # new_scope_sns.uniq!
432
+ # update_scope(new_scope_sns)
359
433
  end
360
434
  alias add assign
361
435
 
362
436
  def unassign(*sns_to_unassign)
363
- sns_to_unassign.map!(&:to_s)
364
- new_scope_sns = assigned_sns
365
- new_scope_sns -= sns_to_unassign
366
- update_scope(new_scope_sns)
437
+ @scope = self.class.unassign(sns_to_unassign, from_prestage: @id, cnx: @cnx)
438
+ @versionLock = @scope.versionLock
439
+ # sns_to_unassign.map!(&:to_s)
440
+ # new_scope_sns = assigned_sns
441
+ # new_scope_sns -= sns_to_unassign
442
+ # update_scope(new_scope_sns)
367
443
  end
368
444
  alias remove unassign
369
445
 
@@ -382,20 +458,20 @@ module Jamf
382
458
  @scope_rsrc ||= "#{self.class::RSRC_VERSION}/#{self.class::RSRC_PATH}/#{@id}/#{SCOPE_RSRC}"
383
459
  end
384
460
 
385
- def update_scope(new_scope_sns)
386
- assignment_data = {
387
- serialNumbers: new_scope_sns,
388
- versionLock: @scope.versionLock
389
- }
390
- begin
391
- @scope = Jamf::PrestageScope.new @cnx.put(scope_rsrc, assignment_data)
392
- rescue Jamf::Connection::APIError => e
393
- raise Jamf::VersionLockError, "The #{self.class} '#{name}' has been modified since it was fetched. Please refetch and try again" if e.status == 409
394
-
395
- raise e
396
- end # begin
397
- @versionLock = @scope.versionLock
398
- end
461
+ # def update_scope(new_scope_sns)
462
+ # assignment_data = {
463
+ # serialNumbers: new_scope_sns,
464
+ # versionLock: @scope.versionLock
465
+ # }
466
+ # begin
467
+ # @scope = Jamf::PrestageScope.new @cnx.put(scope_rsrc, assignment_data)
468
+ # rescue Jamf::Connection::APIError => e
469
+ # raise Jamf::VersionLockError, "The #{self.class} '#{name}' has been modified since it was fetched. Please refetch and try again" if e.status == 409
470
+ #
471
+ # raise e
472
+ # end # begin
473
+ # @versionLock = @scope.versionLock
474
+ # end
399
475
 
400
476
  end # class
401
477
 
@@ -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
  #
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
  #
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")
@@ -48,7 +48,7 @@ module Jamf
48
48
  RSRC_BASE = 'uapi'.freeze
49
49
 
50
50
  # The API version must be this or higher
51
- MIN_API_VERSION = Gem::Version.new('1.0')
51
+ MIN_JAMF_VERSION = Gem::Version.new('10.15.0')
52
52
 
53
53
  HTTPS_SCHEME = 'https'.freeze
54
54
 
@@ -77,17 +77,17 @@ module Jamf
77
77
  DFT_SSL_VERSION = 'TLSv1_2'.freeze
78
78
 
79
79
  # refresh token if less than this many seconds until
80
- # expiration. Default is 30 minutes if not specified
81
- DFT_TOKEN_REFRESH = 60 * 30
80
+ # expiration. Default is 5 minutes if not specified
81
+ DFT_TOKEN_REFRESH = 300
82
82
 
83
83
  # pre-existing tokens must have this many seconds before
84
84
  # before they expire
85
85
  TOKEN_REUSE_MIN_LIFE = 60
86
86
 
87
- HTTP_ACCEPT_HEADER = 'Accept'
88
- HTTP_CONTENT_TYPE_HEADER = 'Content-Type'
87
+ HTTP_ACCEPT_HEADER = 'Accept'.freeze
88
+ HTTP_CONTENT_TYPE_HEADER = 'Content-Type'.freeze
89
89
 
90
- MIME_JSON = 'application/json'
90
+ MIME_JSON = 'application/json'.freeze
91
91
 
92
92
  SLASH = '/'.freeze
93
93
 
@@ -111,6 +111,7 @@ module Jamf
111
111
  @login_time
112
112
  @keep_alive
113
113
  @token_refresh
114
+ @pw_fallback
114
115
  ].freeze
115
116
 
116
117
  # Attributes
@@ -140,6 +141,10 @@ module Jamf
140
141
  # @return [String, nil]
141
142
  attr_reader :base_url
142
143
 
144
+ # @return [Boolean] if token refresh/keepaliave fails, try to get a new one
145
+ # with the passwd used with .connect. Defaults to true
146
+ attr_reader :pw_fallback
147
+
143
148
  # @return [Boolean]
144
149
  attr_reader :connected
145
150
  alias connected? connected
@@ -227,14 +232,13 @@ module Jamf
227
232
  # ### Tokens
228
233
  # Instead of a user and password, you may specify a valid 'token:', either:
229
234
  #
230
- # A Jamf::Connection::Token object, which can be extracted from an active
235
+ # A Jamf::Connection::Token object, which can be extracted from an active
231
236
  # Jamf::Connection via its #token method
232
237
  #
233
238
  # or
234
239
  #
235
240
  # A token string e.g. "eyJhdXR...6EKoo" from any source can also be used.
236
241
  #
237
- #
238
242
  # Any values available via Jamf.config will be used if they are not provided
239
243
  # in the parameters.
240
244
  #
@@ -251,6 +255,19 @@ module Jamf
251
255
  #
252
256
  # @param token: [Jamf::Connection::Token, String] An existing, valid token.
253
257
  # When used, there's no need to provide user: or pw:.
258
+ # NOTE if using pw_fallback:true (the default) while providing a token
259
+ # you will also need to provide the password for the token user in the pw:
260
+ # parameter, or be prompted for it. If you don't have the pw for the
261
+ # token user, be sure to set pw_fallback to false.
262
+ #
263
+ # @param token_refresh: [Integer] Refresh the token this many seconds before
264
+ # it expires. Must be >= DFT_TOKEN_REFRESH
265
+ #
266
+ # @pararm pw_fallback: [Boolean] Default is true. Use the password provided
267
+ # to refresh the token if regular refresh doesn't work (e.g. token is expired).
268
+ # NOTE: This causes the password to be kept in memory. If you don't want
269
+ # this, explicitly set pw_fallback to false, however long-running processes
270
+ # may lose connection if token refresh fails for any reason.
254
271
  #
255
272
  # @param open_timeout: [Integer] The number of seconds for initial contact
256
273
  # with the host.
@@ -268,7 +285,8 @@ module Jamf
268
285
  # This sets all the instance vars to nil, and flushes/creates the caches
269
286
  disconnect
270
287
 
271
- # This sets @token, and adds host, port, user to params from a Token object
288
+ # If there's a Token object in :token, this sets @token,
289
+ # and adds host, port, user from that token
272
290
  parse_token params
273
291
 
274
292
  # Get host, port, user and pw from a URL, add to params if needed
@@ -277,6 +295,8 @@ module Jamf
277
295
  # apply defaults from config, client, and then this class.
278
296
  apply_connection_defaults params
279
297
 
298
+ # Once we're here, all params have been parsed & defaulted into the
299
+ # params hash, so
280
300
  # make sure we have the minimum needed params for a connection
281
301
  verify_basic_params params
282
302
 
@@ -285,15 +305,20 @@ module Jamf
285
305
 
286
306
  # if no @token already, get one from from
287
307
  # either a token string or a pw
288
- @token ||=
308
+ unless @token
289
309
  if params[:token].is_a? String
290
- tk = token_from :token_string, params[:token]
310
+ @token = token_from :token_string, params[:token]
291
311
  # get the user from the token
292
- @user = tk.user
293
- tk
312
+ @user = @toke.user
313
+ # if @pw_fallback, the pw must be acquired, since it isn't in
314
+ # the token
315
+ @pw = acquire_password(params[:pw]) if @pw_fallback
294
316
  else
295
- token_from :pw, acquire_password(params[:pw])
317
+ pw = acquire_password(params[:pw])
318
+ @token = token_from :pw, pw
319
+ @pw = pw if @pw_fallback
296
320
  end
321
+ end
297
322
 
298
323
  # Now get some values from our token
299
324
  @base_url = @token.base_url
@@ -303,46 +328,56 @@ module Jamf
303
328
  @rest_cnx = create_connection
304
329
 
305
330
  # make sure versions are good
306
- validate_api_version
331
+ validate_jamf_version
307
332
 
308
333
  @connected = true
309
334
 
310
335
  # start keepalive if needed
311
- @keep_alive = params[:keep_alive].nil? ? false : params[:keep_alive]
312
336
  start_keep_alive if @keep_alive
313
337
 
314
338
  # return our string output
315
339
  to_s
316
340
  end # connect
317
341
 
342
+ # reset all values to nil or empty
318
343
  def disconnect
319
- # reset everything except the name & timeouts
320
344
  @connected = false
345
+ @name = NOT_CONNECTED
321
346
  @login_time = nil
347
+
348
+ stop_keep_alive
349
+
322
350
  @host = nil
323
351
  @port = nil
324
352
  @user = nil
325
- @token = nil
353
+ @timeout = nil
354
+ @open_timeout = nil
326
355
  @base_url = nil
356
+ @token = nil
327
357
  @rest_cnx = nil
328
358
  @ssl_options = {}
329
359
  @keep_alive = nil
360
+ @token_refresh = nil
361
+ @pw_fallback = nil
362
+ @pw = nil
363
+
330
364
  flushcache
331
365
  end
332
366
 
333
- # Same as disconnect, but invalidates the token
367
+ # Same as disconnect, but invalidates the token on the server first
334
368
  def logout
335
369
  @token.destroy
336
370
  disconnect
337
371
  end
338
372
 
373
+ # Get a resource
339
374
  def get(rsrc)
340
375
  validate_connected
341
376
  resp = @rest_cnx.get rsrc
342
377
  @last_http_response = resp
343
378
  return resp.body if resp.success?
344
379
 
345
- raise Jamf::Connection::APIError.new(resp)
380
+ raise Jamf::Connection::APIError, resp
346
381
  end
347
382
 
348
383
  # GET a rsrc without doing any JSON parsing, using
@@ -353,7 +388,7 @@ module Jamf
353
388
  @last_http_response = resp
354
389
  return resp.body if resp.success?
355
390
 
356
- raise Jamf::Connection::APIError.new(resp)
391
+ raise Jamf::Connection::APIError, resp
357
392
  end
358
393
 
359
394
  def post(rsrc, data)
@@ -364,7 +399,7 @@ module Jamf
364
399
  @last_http_response = resp
365
400
  return resp.body if resp.success?
366
401
 
367
- raise Jamf::Connection::APIError.new(resp)
402
+ raise Jamf::Connection::APIError, resp
368
403
  end
369
404
 
370
405
  def put(rsrc, data)
@@ -375,7 +410,7 @@ module Jamf
375
410
  @last_http_response = resp
376
411
  return resp.body if resp.success?
377
412
 
378
- raise Jamf::Connection::APIError.new(resp)
413
+ raise Jamf::Connection::APIError, resp
379
414
  end
380
415
 
381
416
  def patch(rsrc, data)
@@ -386,7 +421,7 @@ module Jamf
386
421
  @last_http_response = resp
387
422
  return resp.body if resp.success?
388
423
 
389
- raise Jamf::Connection::APIError.new(resp)
424
+ raise Jamf::Connection::APIError, resp
390
425
  end
391
426
 
392
427
  def delete(rsrc)
@@ -395,7 +430,7 @@ module Jamf
395
430
  @last_http_response = resp
396
431
  return resp.body if resp.success?
397
432
 
398
- raise Jamf::Connection::APIError.new(resp)
433
+ raise Jamf::Connection::APIError, resp
399
434
  end
400
435
 
401
436
  # A useful string about this connection
@@ -403,13 +438,50 @@ module Jamf
403
438
  # @return [String]
404
439
  #
405
440
  def to_s
406
- "Jamf::Connection: https://#{@user}@#{@host}:#{@port}"
441
+ str =
442
+ if connected?
443
+ "#{@base_url}, Token expires: #{@token ? @token.expires : '<token missing>'}"
444
+ else
445
+ NOT_CONNECTED
446
+ end
447
+ "Jamf::Connection '#{@name == NOT_CONNECTED ? object_id : @name}': #{str}"
448
+ end
449
+
450
+ # Reset the name
451
+ def name=(new_name)
452
+ @name = new_name.to_s
407
453
  end
408
454
 
455
+ # Are we keeping the connection alive?
409
456
  def keep_alive?
410
- !@keep_alive_thread.nil?
457
+ return false unless @keep_alive_thread
458
+
459
+ @keep_alive_thread.alive?
460
+ end
461
+
462
+ # @return [Jamf::Timestamp, nil]
463
+ def next_refresh
464
+ return unless keep_alive?
465
+
466
+ @token.expires - @token_refresh
467
+ end
468
+
469
+ # @return [Float, nil]
470
+ def secs_to_refresh
471
+ return unless keep_alive?
472
+
473
+ next_refresh - Time.now
411
474
  end
412
475
 
476
+ # @return [String, nil] e.g. "1 week 6 days 23 hours 49 minutes 56 seconds"
477
+ def time_to_refresh
478
+ return unless keep_alive?
479
+ return 0 if secs_to_refresh.negative?
480
+
481
+ Jamf.humanize_secs secs_to_refresh
482
+ end
483
+
484
+ # Turn keepalive on or offs
413
485
  def keep_alive=(bool)
414
486
  bool ? start_keep_alive : stop_keep_alive
415
487
  end
@@ -422,8 +494,12 @@ module Jamf
422
494
  @token_refresh = secs
423
495
  end
424
496
 
425
- def api_version
426
- @token.api_version
497
+ def jamf_version
498
+ @token.jamf_version
499
+ end
500
+
501
+ def jamf_build
502
+ @token.jamf_build
427
503
  end
428
504
 
429
505
  # Flush the collection and/or ea cache for the given class,
@@ -458,18 +534,17 @@ module Jamf
458
534
  ####################################
459
535
  private
460
536
 
461
-
462
537
  # raise exception if not connected
463
538
  def validate_connected
464
539
  raise Jamf::InvalidConnectionError, 'Not Connected. Use .connect first.' unless connected?
465
540
  end
466
541
 
467
542
  # raise exception if API version is too low.
468
- def validate_api_version
469
- vers = api_version
470
- return if Gem::Version.new(vers) >= MIN_API_VERSION
543
+ def validate_jamf_version
544
+ vers = jamf_version
545
+ return if Gem::Version.new(vers) >= MIN_JAMF_VERSION
471
546
 
472
- raise Jamf::InvalidConnectionError, "API version '#{vers}' too low, must be >= '#{MIN_API_VERSION}'"
547
+ raise Jamf::InvalidConnectionError, "API version '#{vers}' too low, must be >= '#{MIN_JAMF_VERSION}'"
473
548
  end
474
549
 
475
550
  ##### Parse Params
@@ -499,7 +574,7 @@ module Jamf
499
574
  raise "Cannot use token: it expires in less than #{TOKEN_REUSE_MIN_LIFE} seconds" if token.secs_remaining < TOKEN_REUSE_MIN_LIFE
500
575
  end
501
576
 
502
- # Get host, port, user and pw from a URL, unless they are already in the params
577
+ # Get host, port, user and pw from a URL, overriding any already in the params
503
578
  #
504
579
  # @return [String, nil] the pw if present
505
580
  #
@@ -509,27 +584,29 @@ module Jamf
509
584
  url = URI.parse url.to_s
510
585
  raise ArgumentError, 'Invalid url, scheme must be https' unless url.scheme == HTTPS_SCHEME
511
586
 
512
- params[:host] ||= url.host
513
- params[:port] ||= url.port
514
- params[:user] ||= url.user if url.user
515
- params[:pw] ||= url.password if url.password
587
+ params[:host] = url.host
588
+ params[:port] = url.port
589
+ params[:user] = url.user if url.user
590
+ params[:pw] = url.password if url.password
516
591
  end
517
592
 
518
- # Apply defaults from the Jamf.config,
519
- # then from the Jamf::Client,
593
+ # Apply defaults to the unset params for the #connect method
594
+ # First apply them from from the Jamf.config,
595
+ # then from the Jamf::Client (read from the jamf binary config),
520
596
  # then from the Jamf module defaults
521
- # to the unset params for the #connect method
522
597
  #
523
598
  # @param params[Hash] The params for #connect
524
599
  #
525
600
  # @return [Hash] The params with defaults applied
526
601
  #
527
602
  def apply_connection_defaults(params)
528
- # if no port given, either directly or via URL, and the host
529
- # is a jamfcloud host, always set the port to 443
530
- # This should happen before the config is applied, so
531
- # on-prem users can still get to jamfcoud without specifying the port
532
- params[:port] = JAMFCLOUD_PORT if params[:port].nil? && params[:host].to_s.end_with?(JAMFCLOUD_DOMAIN)
603
+ # must have a host, but accept legacy :server as well as :host
604
+ params[:host] ||= params[:server]
605
+
606
+ # if we have no port set by this point, set to cloud port
607
+ # if host is a cloud host. But leave port nil for other hosts
608
+ # (will be set via client defaults or module defaults)
609
+ params[:port] ||= JAMFCLOUD_PORT if params[:host].to_s.end_with?(JAMFCLOUD_DOMAIN)
533
610
 
534
611
  apply_defaults_from_config(params)
535
612
 
@@ -583,11 +660,12 @@ module Jamf
583
660
  # @return [Hash] The params with defaults applied
584
661
  #
585
662
  def apply_module_defaults(params)
586
- # if we have no port set by this point, assume on-prem
663
+ # if we have no port set by this point, assume on-prem.
587
664
  params[:port] ||= ON_PREM_SSL_PORT
588
665
  params[:timeout] ||= DFT_TIMEOUT
589
666
  params[:open_timeout] ||= DFT_OPEN_TIMEOUT
590
667
  params[:ssl_version] ||= DFT_SSL_VERSION
668
+ params[:token_refresh] ||= DFT_TOKEN_REFRESH
591
669
  # if we have a TTY, pw defaults to :prompt
592
670
  params[:pw] ||= :prompt if STDIN.tty?
593
671
  end
@@ -603,32 +681,38 @@ module Jamf
603
681
  # and is already parsed
604
682
  return if @token
605
683
 
606
- # must have a host, but accept legacy :server as well as :host
607
- params[:host] ||= params[:server]
684
+ # must have a host
608
685
  raise Jamf::MissingDataError, 'No Jamf :host specified, or in configuration.' unless params[:host]
609
686
 
610
687
  # no need for user or pass if using a token string
611
688
  return if params[:token].is_a? String
612
689
 
690
+ # must have user and pw
613
691
  raise Jamf::MissingDataError, 'No Jamf :user specified, or in configuration.' unless params[:user]
614
692
  raise Jamf::MissingDataError, "No :pw specified for user '#{params[:user]}'" unless params[:pw]
615
693
  end
616
694
 
695
+ # Turn the connection parameters into instance vars
617
696
  def parse_connect_params(params)
618
697
  @host = params[:host]
619
698
  @port = params[:port]
620
- @port ||= @host.end_with?(JAMFCLOUD_DOMAIN) ? JAMFCLOUD_PORT : ON_PREM_SSL_PORT
621
699
  @user = params[:user]
622
- @token_refresh = params[:token_refresh] || DFT_TOKEN_REFRESH
623
- @timeout = params[:timeout] || DFT_TIMEOUT
624
- @open_timeout = params[:open_timeout] || DFT_TIMEOUT
700
+
701
+ @keep_alive = params[:keep_alive].nil? ? false : params[:keep_alive]
702
+ @pw_fallback = params[:pw_fallback].nil? ? true : params[:pw_fallback]
703
+ @token_refresh = params[:token_refresh].to_i
704
+
705
+ @timeout = params[:timeout]
706
+ @open_timeout = params[:open_timeout]
625
707
  @base_url = URI.parse "https://#{@host}:#{@port}/#{RSRC_BASE}"
708
+
626
709
  # ssl opts for faraday
627
710
  # TODO: implement all of faraday's options
628
711
  @ssl_options = {
629
712
  verify: params[:verify_cert],
630
713
  version: params[:ssl_version]
631
714
  }
715
+
632
716
  @name = "#{@user}@#{@host}:#{@port}" if @name == NOT_CONNECTED
633
717
  end
634
718
 
@@ -659,16 +743,18 @@ module Jamf
659
743
  # @return [String] The password for the connection
660
744
  #
661
745
  def acquire_password(param_pw)
662
- if param_pw == :prompt
663
- Jamf.prompt_for_password "Enter the password for Jamf user #{@user}@#{@host}:"
664
- elsif param_pw.is_a?(Symbol) && param_pw.to_s.start_with?('stdin')
665
- param_pw.to_s =~ /^stdin(\d+)$/
666
- line = Regexp.last_match(1)
667
- line ||= 1
668
- Jamf.stdin line
669
- else
670
- param_pw
671
- end # if
746
+ pw =
747
+ if param_pw == :prompt
748
+ Jamf.prompt_for_password "Enter the password for Jamf user #{@user}@#{@host}:"
749
+ elsif param_pw.is_a?(Symbol) && param_pw.to_s.start_with?('stdin')
750
+ param_pw.to_s =~ /^stdin(\d+)$/
751
+ line = Regexp.last_match(1)
752
+ line ||= 1
753
+ Jamf.stdin line
754
+ else
755
+ param_pw
756
+ end # if
757
+ pw
672
758
  end # acquire pw
673
759
 
674
760
  # create the faraday connection object
@@ -702,9 +788,16 @@ module Jamf
702
788
  Thread.new do
703
789
  loop do
704
790
  sleep 60
705
- next if @token.secs_remaining > @token_refresh
706
-
707
- @token.keep_alive
791
+ begin
792
+ next if @token.secs_remaining > @token_refresh
793
+
794
+ @token.refresh @pw
795
+ # make sure faraday uses the new token
796
+ @rest_cnx.headers[:authorization] = @token.auth_token
797
+ rescue
798
+ # TODO: Some kind of error reporting
799
+ next
800
+ end
708
801
  end # loop
709
802
  end # thread
710
803
  end
@@ -717,7 +810,7 @@ module Jamf
717
810
  def stop_keep_alive
718
811
  return unless @keep_alive_thread
719
812
 
720
- @keep_alive_thread.kill
813
+ @keep_alive_thread.kill if @keep_alive_thread.alive?
721
814
  @keep_alive_thread = nil
722
815
  end
723
816
 
@@ -763,4 +856,8 @@ module Jamf
763
856
  @active_connection = connection
764
857
  end
765
858
 
859
+ def self.disconnect
860
+ @active_connection.disconnect if @active_connection
861
+ end
862
+
766
863
  end # module Jamf