ruby-jss 1.2.4a3 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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