ruby-jss 1.3.2 → 1.5.3

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +122 -0
  3. data/lib/jamf.rb +18 -16
  4. data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
  5. data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +109 -101
  6. data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +55 -30
  7. data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
  8. data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
  9. data/lib/jamf/api/connection.rb +13 -9
  10. data/lib/jamf/api/connection/api_error.rb +8 -8
  11. data/lib/jamf/api/connection/token.rb +36 -15
  12. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  13. data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
  14. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  15. data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
  16. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  17. data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
  20. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  21. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  22. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  23. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  24. data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
  25. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  26. data/lib/jamf/api/mixins/change_log.rb +201 -51
  27. data/lib/jamf/api/{resources/collection_resources/computer.rb → mixins/filterable.rb} +19 -17
  28. data/lib/jamf/api/mixins/pageable.rb +208 -0
  29. data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
  30. data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
  31. data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
  32. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
  33. data/lib/jamf/api/resources/collection_resources/department.rb +1 -3
  34. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
  35. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  36. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
  37. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  38. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  39. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  40. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  41. data/lib/jamf/validate.rb +63 -24
  42. data/lib/jamf/version.rb +1 -1
  43. data/lib/jss.rb +2 -1
  44. data/lib/jss/api_connection.rb +113 -406
  45. data/lib/jss/api_object.rb +10 -20
  46. data/lib/jss/api_object/advanced_search.rb +27 -26
  47. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  48. data/lib/jss/api_object/categorizable.rb +1 -1
  49. data/lib/jss/api_object/computer.rb +13 -0
  50. data/lib/jss/api_object/configuration_profile.rb +60 -4
  51. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  52. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  53. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  54. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  55. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  56. data/lib/jss/api_object/distribution_point.rb +2 -2
  57. data/lib/jss/api_object/dock_item.rb +102 -96
  58. data/lib/jss/api_object/ebook.rb +1 -2
  59. data/lib/jss/api_object/extendable.rb +1 -1
  60. data/lib/jss/api_object/extension_attribute.rb +4 -3
  61. data/lib/jss/api_object/group.rb +33 -2
  62. data/lib/jss/api_object/mac_application.rb +107 -8
  63. data/lib/jss/api_object/network_segment.rb +43 -12
  64. data/lib/jss/api_object/package.rb +1 -1
  65. data/lib/jss/api_object/patch_source.rb +10 -9
  66. data/lib/jss/api_object/policy.rb +217 -28
  67. data/lib/jss/api_object/printer.rb +10 -4
  68. data/lib/jss/api_object/scopable.rb +10 -15
  69. data/lib/jss/api_object/scopable/scope.rb +389 -73
  70. data/lib/jss/api_object/self_servable.rb +17 -9
  71. data/lib/jss/api_object/uploadable.rb +1 -1
  72. data/lib/jss/api_object/user.rb +42 -1
  73. data/lib/jss/api_object/vpp_account.rb +209 -0
  74. data/lib/jss/api_object/vppable.rb +169 -13
  75. data/lib/jss/exceptions.rb +3 -0
  76. data/lib/jss/server.rb +15 -0
  77. data/lib/jss/utility.rb +142 -37
  78. data/lib/jss/validate.rb +53 -10
  79. data/lib/jss/version.rb +1 -1
  80. metadata +45 -61
  81. data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
  82. data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
  83. data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
  84. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
  85. data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
  86. data/lib/jamf/api/json_objects/android_details.rb +0 -139
  87. data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
  88. data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
  89. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
  90. data/lib/jamf/api/json_objects/criterion.rb +0 -152
  91. data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
  92. data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
  93. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
  94. data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
  95. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
  96. data/lib/jamf/api/json_objects/ios_details.rb +0 -244
  97. data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
  98. data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
  99. data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
  100. data/lib/jamf/api/mixins/locatable.rb +0 -124
  101. data/lib/jamf/api/mixins/referable.rb +0 -92
  102. data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
  103. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
  104. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
  105. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +0 -45
  106. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
  107. data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
  108. data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
  109. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
  110. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
@@ -27,6 +27,6 @@
27
27
  module Jamf
28
28
 
29
29
  ### The version of the Jamf module
30
- VERSION = '0.0.1'.freeze
30
+ VERSION = '0.0.6a1'.freeze
31
31
 
32
32
  end # module
data/lib/jss.rb CHANGED
@@ -58,7 +58,8 @@ module JSS
58
58
 
59
59
  ###################
60
60
  ### Gems
61
- require 'rest-client'
61
+ require 'faraday'
62
+ require 'faraday_middleware'
62
63
  require 'plist'
63
64
  require 'immutable-struct'
64
65
  require 'recursive-open-struct'
@@ -25,18 +25,6 @@
25
25
  ###
26
26
  module JSS
27
27
 
28
- # Constants
29
- #####################################
30
-
31
- # Module Variables
32
- #####################################
33
-
34
- # Module Methods
35
- #####################################
36
-
37
- # Classes
38
- #####################################
39
-
40
28
  # Instances of this class represent a REST connection to a JSS API.
41
29
  #
42
30
  # For most cases, a single connection to a single JSS is all you need, and
@@ -227,42 +215,6 @@ module JSS
227
215
  # # the variable 'prod2_victim_md' now contains a JSS::MobileDevice queried
228
216
  # # through the connection 'production_api2'.
229
217
  #
230
- # == Using the APIConnection itself to make API calls.
231
- #
232
- # Rather than passing an APIConnection into another method, you can call
233
- # similar methods on the connection itself. For example, these two calls
234
- # have the same result as the two examples above:
235
- #
236
- # prod2_computer_sns = production_api2.all :Computer, only: :serial_numbers
237
- # prod2_victim_md = production_api2.fetch :MobileDevice, id: 832
238
- #
239
- # Here are the API calls you can make directly from an APIConnection object.
240
- # They behave practically identically to the same methods in the APIObject
241
- # subclasses, since they just call those methods, passing themselves in as the
242
- # APIConnection to use.
243
- #
244
- # - {#all} The 'list' methods of the various APIObject classes. Use the 'only:'
245
- # parameter to specify one of the sub-list-methods, like #all_ids or
246
- # #all_laptops, e.g. `my_connection.all :computers, only: :id`
247
- # - {#map_all_ids} the equivalent of #map_all_ids_to in the APIObject classes
248
- # - {#valid_id} given a class and an identifier (like macaddress or udid)
249
- # return a valid id or nil
250
- # - {#exist?} given a class and an identifier (like macaddress or udid) does
251
- # the identifier exist for the class in the JSS
252
- # - {#match} list items in the JSS matching a query
253
- # (if the object is {Matchable})
254
- # - {#fetch} retrieve an object from the JSS
255
- # - {#make} instantiate an object to be created in the JSS
256
- # - {#computer_checkin_settings} same as {Computer.checkin_settings}
257
- # - {#computer_inventory_collection_settings} same as {Computer.inventory_collection_settings}
258
- # - {#computer_application_usage} same as {Computer.application_usage}
259
- # - {#computer_management_data} same as {Computer.management_data}
260
- # - {#master_distribution_point} same as {DistributionPoint.master_distribution_point}
261
- # - {#my_distribution_point} same as {DistributionPoint.my_distribution_point}
262
- # - {#network_ranges} same as {NetworkSegment.network_ranges}
263
- # - {#network_segments_for_ip} same as {NetworkSegment.segments_for_ip}
264
- # - {#my_network_segments} same as {NetworkSegment.my_network_segments}
265
- #
266
218
  # == Low-level use of APIConnection instances.
267
219
  #
268
220
  # For most cases, using APIConnection instances as mentioned above
@@ -271,7 +223,7 @@ module JSS
271
223
  # {#get_rsrc}, {#put_rsrc}, {#post_rsrc}, & {#delete_rsrc}
272
224
  # documented below.
273
225
  #
274
- # For even lower-level work, you can access the underlying RestClient::Resource
226
+ # For even lower-level work, you can access the underlying Faraday::Connection
275
227
  # inside the APIConnection via the connection's {#cnx} attribute.
276
228
  #
277
229
  # APIConnection instances also have a {#server} attribute which contains an
@@ -330,6 +282,12 @@ module JSS
330
282
  # values for the format param of get_rsrc
331
283
  GET_FORMATS = %i[json xml].freeze
332
284
 
285
+ HTTP_ACCEPT_HEADER = 'Accept'.freeze
286
+ HTTP_CONTENT_TYPE_HEADER = 'Content-Type'.freeze
287
+
288
+ MIME_JSON = 'application/json'.freeze
289
+ MIME_XML = 'application/xml'.freeze
290
+
333
291
  # Attributes
334
292
  #####################################
335
293
 
@@ -337,7 +295,7 @@ module JSS
337
295
  attr_reader :user
338
296
  alias jss_user user
339
297
 
340
- # @return [RestClient::Resource] the underlying connection resource
298
+ # @return [Faraday::Connection] the underlying connection resource
341
299
  attr_reader :cnx
342
300
 
343
301
  # @return [Boolean] are we connected right now?
@@ -359,7 +317,7 @@ module JSS
359
317
  # @return [String] the protocol being used: http or https
360
318
  attr_reader :protocol
361
319
 
362
- # @return [RestClient::Response] The response from the most recent API call
320
+ # @return [Faraday::Response] The response from the most recent API call
363
321
  attr_reader :last_http_response
364
322
 
365
323
  # @return [String] The base URL to to the current REST API
@@ -428,6 +386,7 @@ module JSS
428
386
  @name = args.delete :name
429
387
  @name ||= :unknown
430
388
  @connected = false
389
+ @object_list_cache = {}
431
390
  connect args unless args.empty?
432
391
  end # init
433
392
 
@@ -453,8 +412,6 @@ module JSS
453
412
  # @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true.
454
413
  #
455
414
  # @option args :verify_cert[Boolean] should HTTPS SSL certificates be verified. Defaults to true.
456
- # If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the
457
- # validity of the SSL cert. just set this explicitly to false.
458
415
  #
459
416
  # @option args :user[String] a JSS user who has API privs, required if not defined in JSS::CONFIG
460
417
  #
@@ -476,6 +433,8 @@ module JSS
476
433
 
477
434
  args[:no_port_specified] = args[:port].to_s.empty?
478
435
  args = apply_connection_defaults args
436
+ @timeout = args[:timeout]
437
+ @open_timeout = args[:open_timeout]
479
438
 
480
439
  # ensure an integer
481
440
  args[:port] &&= args[:port].to_i
@@ -494,7 +453,7 @@ module JSS
494
453
  args[:password] = acquire_password args
495
454
 
496
455
  # heres our connection
497
- @cnx = RestClient::Resource.new(@rest_url.to_s, args)
456
+ @cnx = create_connection args[:password]
498
457
 
499
458
  verify_server_version
500
459
 
@@ -543,8 +502,7 @@ module JSS
543
502
  @connected = false
544
503
  end # disconnect
545
504
 
546
- # Get an arbitrary JSS resource
547
- #
505
+ # Get a JSS resource
548
506
  # The first argument is the resource to get (the part of the API url
549
507
  # after the 'JSSResource/' ) The resource must be properly URL escaped
550
508
  # beforehand. Note: URL.encode is deprecated, use CGI.escape
@@ -572,14 +530,19 @@ module JSS
572
530
  validate_connected
573
531
  raise JSS::InvalidDataError, 'format must be :json or :xml' unless GET_FORMATS.include? format
574
532
 
575
- begin
576
- @last_http_response = @cnx[rsrc].get(accept: format)
577
- return JSON.parse(@last_http_response.body, symbolize_names: true) if format == :json && !raw_json
533
+ @last_http_response =
534
+ @cnx.get(rsrc) do |req|
535
+ req.headers[HTTP_ACCEPT_HEADER] = format == :json ? MIME_JSON : MIME_XML
536
+ end
578
537
 
579
- @last_http_response.body
580
- rescue RestClient::ExceptionWithResponse => e
581
- handle_http_error e
538
+ unless @last_http_response.success?
539
+ handle_http_error
540
+ return
582
541
  end
542
+
543
+ return JSON.parse(@last_http_response.body, symbolize_names: true) if format == :json && !raw_json
544
+
545
+ @last_http_response.body
583
546
  end
584
547
 
585
548
  # Update an existing JSS resource
@@ -597,10 +560,18 @@ module JSS
597
560
  xml.gsub!(/\r/, '
')
598
561
 
599
562
  # send the data
600
- @last_http_response = @cnx[rsrc].put(xml, content_type: 'text/xml')
563
+ @last_http_response =
564
+ @cnx.put(rsrc) do |req|
565
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
566
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
567
+ req.body = xml
568
+ end
569
+ unless @last_http_response.success?
570
+ handle_http_error
571
+ return
572
+ end
573
+
601
574
  @last_http_response.body
602
- rescue RestClient::ExceptionWithResponse => e
603
- handle_http_error e
604
575
  end
605
576
 
606
577
  # Create a new JSS resource
@@ -611,17 +582,24 @@ module JSS
611
582
  #
612
583
  # @return [String] the xml response from the server.
613
584
  #
614
- def post_rsrc(rsrc, xml = '')
585
+ def post_rsrc(rsrc, xml)
615
586
  validate_connected
616
587
 
617
588
  # convert CRs & to 
618
- xml.gsub!(/\r/, '
') if xml
589
+ xml&.gsub!(/\r/, '
')
619
590
 
620
591
  # send the data
621
- @last_http_response = @cnx[rsrc].post(xml, content_type: 'text/xml', accept: :json)
592
+ @last_http_response =
593
+ @cnx.post(rsrc) do |req|
594
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
595
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
596
+ req.body = xml
597
+ end
598
+ unless @last_http_response.success?
599
+ handle_http_error
600
+ return
601
+ end
622
602
  @last_http_response.body
623
- rescue RestClient::ExceptionWithResponse => e
624
- handle_http_error e
625
603
  end # post_rsrc
626
604
 
627
605
  # Delete a resource from the JSS
@@ -630,18 +608,23 @@ module JSS
630
608
  #
631
609
  # @return [String] the xml response from the server.
632
610
  #
633
- def delete_rsrc(rsrc, xml = nil)
611
+ def delete_rsrc(rsrc)
634
612
  validate_connected
635
613
  raise MissingDataError, 'Missing :rsrc' if rsrc.nil?
636
614
 
637
- # payload?
638
- return delete_with_payload rsrc, xml if xml
639
-
640
615
  # delete the resource
641
- @last_http_response = @cnx[rsrc].delete
616
+ @last_http_response =
617
+ @cnx.delete(rsrc) do |req|
618
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
619
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
620
+ end
621
+
622
+ unless @last_http_response.success?
623
+ handle_http_error
624
+ return
625
+ end
626
+
642
627
  @last_http_response.body
643
- rescue RestClient::ExceptionWithResponse => e
644
- handle_http_error e
645
628
  end # delete_rsrc
646
629
 
647
630
  # Test that a given hostname & port is a JSS API server
@@ -657,25 +640,8 @@ module JSS
657
640
  # ssl_options like :OP_NO_SSLv2 and :OP_NO_SSLv3 will take time to figure out..
658
641
  return true if `/usr/bin/curl -s 'https://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
659
642
  return true if `/usr/bin/curl -s 'http://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
660
- false
661
643
 
662
- # # try ssl first
663
- # # NOTE: doesn't work if we can't disallow SSLv3 or force TLSv1
664
- # # See cheat above.
665
- # begin
666
- # return true if open("https://#{server}:#{port}/#{TEST_PATH}", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read.include? TEST_CONTENT
667
- #
668
- # rescue
669
- # # then regular http
670
- # begin
671
- # return true if open("http://#{server}:#{port}/#{TEST_PATH}").read.include? TEST_CONTENT
672
- # rescue
673
- # # any errors = no API
674
- # return false
675
- # end # begin
676
- # end # begin
677
- # # if we're here, no API
678
- # false
644
+ false
679
645
  end
680
646
 
681
647
  # The server to which we are connected, or will
@@ -686,267 +652,13 @@ module JSS
686
652
  #
687
653
  def hostname
688
654
  return @server_host if @server_host
655
+
689
656
  srvr = JSS::CONFIG.api_server_name
690
657
  srvr ||= JSS::Client.jss_server
691
658
  srvr
692
659
  end
693
660
  alias host hostname
694
661
 
695
- #################
696
-
697
- # Call one of the 'all*' methods on a JSS::APIObject subclass
698
- # using this APIConnection.
699
- #
700
- #
701
- # @deprecated please use the .all class method of the desired class
702
- #
703
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
704
- # see {JSS.api_object_class}
705
- #
706
- # @param refresh[Boolean] Should the data be re-read from the API?
707
- #
708
- # @param only[String,Symbol] Limit the output to subset or data. All
709
- # APIObject subclasses can take :ids or :names, which calls the .all_ids
710
- # and .all_names methods. Some subclasses can take other options, e.g.
711
- # MobileDevice can take :udids
712
- #
713
- # @return [Array] The list of items for the class
714
- #
715
- def all(class_name, refresh = false, only: nil)
716
- the_class = JSS.api_object_class(class_name)
717
- list_method = only ? :"all_#{only}" : :all
718
-
719
- raise ArgumentError, "Unknown identifier: #{only} for #{the_class}" unless
720
- the_class.respond_to? list_method
721
-
722
- the_class.send list_method, refresh, api: self
723
- end
724
-
725
- # Call the 'map_all_ids_to' method on a JSS::APIObject subclass
726
- # using this APIConnection.
727
- #
728
- # @deprecated please use the .map_all_ids_to class method of the desired class
729
- #
730
- #
731
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
732
- # see {JSS.api_object_class}
733
- #
734
- # @param refresh[Boolean] Should the data be re-read from the API?
735
- #
736
- # @param to[String,Symbol] the value to which the ids should be mapped
737
- #
738
- # @return [Hash] The ids for the class keyed to the requested identifier
739
- #
740
- def map_all_ids(class_name, refresh = false, to: nil)
741
- raise "'to:' value must be provided for mapping ids." unless to
742
- the_class = JSS.api_object_class(class_name)
743
- the_class.map_all_ids_to to, refresh, api: self
744
- end
745
-
746
- # Call the 'valid_id' method on a JSS::APIObject subclass
747
- # using this APIConnection. See {JSS::APIObject.valid_id}
748
- #
749
- # @deprecated please use the .valid_id class method of the desired class
750
- #
751
- #
752
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass,
753
- # see {JSS.api_object_class}
754
- #
755
- # @param identifier[String,Symbol] the value to which the ids should be mapped
756
- #
757
- # @param refresh[Boolean] Should the data be re-read from the API?
758
- #
759
- # @return [Integer, nil] the id of the matching object of the class,
760
- # or nil if there isn't one
761
- #
762
- def valid_id(class_name, identifier, refresh = true)
763
- the_class = JSS.api_object_class(class_name)
764
- the_class.valid_id identifier, refresh, api: self
765
- end
766
-
767
- # Call the 'exist?' method on a JSS::APIObject subclass
768
- # using this APIConnection. See {JSS::APIObject.exist?}
769
- #
770
- # @deprecated please use the .exist class method of the desired class
771
- #
772
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
773
- # see {JSS.api_object_class}
774
- #
775
- # @param identifier[String,Symbol] the value to which the ids should be mapped
776
- #
777
- # @param refresh[Boolean] Should the data be re-read from the API?
778
- #
779
- # @return [Boolean] Is there an object of this class in the JSS matching
780
- # this indentifier?
781
- #
782
- def exist?(class_name, identifier, refresh = false)
783
- !valid_id(class_name, identifier, refresh).nil?
784
- end
785
-
786
- # Call {Matchable.match} for the given class.
787
- #
788
- # See {Matchable.match}
789
- #
790
- # @deprecated Please use the .match class method of the desired class
791
- #
792
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
793
- # see {JSS.api_object_class}
794
- #
795
- # @return (see Matchable.match)
796
- #
797
- def match(class_name, term)
798
- the_class = JSS.api_object_class(class_name)
799
- raise JSS::UnsupportedError, "Class #{the_class} is not matchable" unless the_class.respond_to? :match
800
- the_class.match term, api: self
801
- end
802
-
803
- # Retrieve an object of a given class from the API
804
- # See {APIObject.fetch}
805
- #
806
- # @deprecated Please use the .fetch class method of the desired class
807
- #
808
- #
809
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
810
- # see {JSS.api_object_class}
811
- #
812
- # @return [APIObject] The ruby-instance of the object.
813
- #
814
- def fetch(class_name, arg)
815
- the_class = JSS.api_object_class(class_name)
816
- the_class.fetch arg, api: self
817
- end
818
-
819
- # Make a ruby instance of a not-yet-existing APIObject
820
- # of the given class
821
- # See {APIObject.make}
822
- #
823
- # @deprecated Please use the .make class method of the desired class
824
- #
825
- # @param class_name[String,Symbol] The name of a JSS::APIObject subclass
826
- # see {JSS.api_object_class}
827
- #
828
- # @return [APIObject] The un-created ruby-instance of the object.
829
- #
830
- def make(class_name, **args)
831
- the_class = JSS.api_object_class(class_name)
832
- args[:api] = self
833
- the_class.make args
834
- end
835
-
836
- # Call {JSS::Computer.checkin_settings} q.v., passing this API
837
- # connection
838
- # @deprecated Please use JSS::Computer.checkin_settings
839
- #
840
- def computer_checkin_settings
841
- JSS::Computer.checkin_settings api: self
842
- end
843
-
844
- # Call {JSS::Computer.inventory_collection_settings} q.v., passing this API
845
- # connection
846
- # @deprecated Please use JSS::Computer.inventory_collection_settings
847
- #
848
- def computer_inventory_collection_settings
849
- JSS::Computer.inventory_collection_settings api: self
850
- end
851
-
852
- # Call {JSS::Computer.application_usage} q.v., passing this API
853
- # connection
854
- # @deprecated Please use JSS::Computer.application_usage
855
- #
856
- def computer_application_usage(ident, start_date, end_date = nil)
857
- JSS::Computer.application_usage ident, start_date, end_date, api: self
858
- end
859
-
860
- # Call {JSS::Computer.management_data} q.v., passing this API
861
- # connection
862
- #
863
- # @deprecated Please use JSS::Computer.management_data
864
- #
865
- def computer_management_data(ident, subset: nil, only: nil)
866
- JSS::Computer.management_data ident, subset: subset, only: only, api: self
867
- end
868
-
869
- # Call {JSS::Computer.history} q.v., passing this API
870
- # connection
871
- #
872
- # @deprecated Please use JSS::Computer.management_history or its
873
- # convenience methods. @see JSS::ManagementHistory
874
- #
875
- def computer_history(ident, subset: nil)
876
- JSS::Computer.history ident, subset, api: self
877
- end
878
-
879
- # Call {JSS::Computer.send_mdm_command} q.v., passing this API
880
- # connection
881
- #
882
- # @deprecated Please use JSS::Computer.send_mdm_command or its
883
- # convenience methods. @see JSS::MDM
884
- #
885
- def send_computer_mdm_command(targets, command, passcode = nil)
886
- opts = passcode ? { passcode: passcode } : {}
887
- JSS::Computer.send_mdm_command targets, command, opts: opts, api: self
888
- end
889
-
890
- # Get the DistributionPoint instance for the master
891
- # distribution point in the JSS. If there's only one
892
- # in the JSS, return it even if not marked as master.
893
- #
894
- # @param refresh[Boolean] re-read from the API?
895
- #
896
- # @return [JSS::DistributionPoint]
897
- #
898
- def master_distribution_point(refresh = false)
899
- JSS::DistributionPoint.master_distribution_point refresh, api: self
900
- end
901
-
902
- # Get the DistributionPoint instance for the machine running
903
- # this code, based on its IP address. If none is defined for this IP address,
904
- # use the result of master_distribution_point
905
- #
906
- # @param refresh[Boolean] should the distribution point be re-queried?
907
- #
908
- # @return [JSS::DistributionPoint]
909
- #
910
- def my_distribution_point(refresh = false)
911
- JSS::DistributionPoint.my_distribution_point refresh, api: self
912
- end
913
-
914
- # @deprecated
915
- #
916
- # @see {JSS::NetworkSegment.network_ranges}
917
- #
918
- def network_ranges(refresh = false)
919
- JSS::NetworkSegment.network_ranges refresh, api: self
920
- end # def network_segments
921
-
922
- # @deprecated
923
- #
924
- # @see {JSS::NetworkSegment.network_segments_for_ip}
925
- #
926
- def network_segments_for_ip(ip, refresh = false)
927
- JSS::NetworkSegment.network_segments_for_ip ip, refresh, api: self
928
- end
929
-
930
- # @deprecated
931
- #
932
- # @see {JSS::NetworkSegment.my_network_segments}
933
- #
934
- def my_network_segments
935
- network_segments_for_ip JSS::Client.my_ip_address
936
- end
937
-
938
- # Send an MDM command to one or more mobile devices managed by
939
- # this JSS
940
- #
941
- # see {JSS::MobileDevice.send_mdm_command}
942
- #
943
- # @deprecated Please use JSS::MobileDevice.send_mdm_command or its
944
- # convenience methods. @see JSS::MDM
945
- #
946
- def send_mobiledevice_mdm_command(targets, command, data = {})
947
- JSS::MobileDevice.send_mdm_command(targets, command, opts: data, api: self)
948
- end
949
-
950
662
  # Empty all cached lists from this connection
951
663
  # then run garbage collection to clear any available memory
952
664
  #
@@ -1052,6 +764,7 @@ module JSS
1052
764
  #
1053
765
  def apply_defaults_from_client(args)
1054
766
  return unless JSS::Client.installed?
767
+
1055
768
  # these settings can come from the jamf binary config, if this machine is a JSS client.
1056
769
  args[:server] ||= JSS::Client.jss_server
1057
770
  args[:port] ||= JSS::Client.jss_port.to_i
@@ -1105,11 +818,13 @@ module JSS
1105
818
  # keep this basic level of info available for basic authentication
1106
819
  # and JSS version checking.
1107
820
  begin
1108
- @server = JSS::Server.new get_rsrc('jssuser')[:user], self
1109
- rescue RestClient::Unauthorized
821
+ data = get_rsrc('jssuser')
822
+ rescue JSS::AuthorizationError
1110
823
  raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{@user}@#{@server_host}:#{@port}'."
1111
824
  end
1112
825
 
826
+ @server = JSS::Server.new data[:user], self
827
+
1113
828
  min_vers = JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
1114
829
  return if @server.version >= min_vers # we're good...
1115
830
 
@@ -1178,77 +893,68 @@ module JSS
1178
893
  if SSL_PORTS.include? args[:port]
1179
894
  args[:use_ssl] = true unless args[:use_ssl] == false
1180
895
  end
896
+ return unless args[:use_ssl]
897
+
1181
898
  # if verify_cert is anything but false, we will verify
1182
- args[:verify_ssl] = args[:verify_cert] == false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
899
+ args[:verify_ssl] = args[:verify_cert] != false
900
+
901
+ # ssl version if not specified
902
+ args[:ssl_version] ||= DFT_SSL_VERSION
903
+
904
+ @ssl_options = {
905
+ verify: args[:verify_ssl],
906
+ version: args[:ssl_version]
907
+ }
1183
908
  end
1184
909
 
1185
- # Parses the HTTP body of a RestClient::ExceptionWithResponse
1186
- # (the parent of all HTTP error responses) and its subclasses
1187
- # and re-raises a JSS::APIError with a more
1188
- # useful error message.
1189
- #
1190
- # @param exception[RestClient::ExceptionWithResponse] the exception to parse
910
+ # Parses the @last_http_response
911
+ # and raises a JSS::APIError with a useful error message.
1191
912
  #
1192
913
  # @return [void]
1193
914
  #
1194
- def handle_http_error(exception)
1195
- @last_http_response = exception.response
1196
- case exception
1197
- when RestClient::ResourceNotFound
1198
- # other methods catch this and report more details
1199
- raise exception
1200
- when RestClient::Conflict
915
+ def handle_http_error
916
+ return if @last_http_response.success?
917
+
918
+ case @last_http_response.status
919
+ when 404
920
+ err = JSS::NoSuchItemError
921
+ msg = 'Not Found'
922
+ when 409
1201
923
  err = JSS::ConflictError
1202
- msg_matcher = /<p>Error:(.*?)(<|$)/m
1203
- when RestClient::BadRequest
924
+ @last_http_response.body =~ /<p>(The server has not .*?)(<|$)/m
925
+ msg = Regexp.last_match(1)
926
+ when 400
1204
927
  err = JSS::BadRequestError
1205
- msg_matcher = %r{>Bad Request</p>\n<p>(.*?)</p>\n<p>You can get technical detail}m
1206
- when RestClient::Unauthorized
1207
- raise
928
+ @last_http_response.body =~ %r{>Bad Request</p>\n<p>(.*?)</p>\n<p>You can get technical detail}m
929
+ msg = Regexp.last_match(1)
930
+ when 401
931
+ err = JSS::AuthorizationError
932
+ msg = 'You are not authorized to do that.'
933
+ when (500..599)
934
+ err = JSS::APIRequestError
935
+ msg = 'There was an internal server error'
1208
936
  else
1209
937
  err = JSS::APIRequestError
1210
- msg_matcher = %r{<body.*?>(.*?)</body>}m
938
+ msg = "There was a error processing your request, status: #{@last_http_response.status}"
1211
939
  end
1212
- exception.http_body =~ msg_matcher
1213
- msg = Regexp.last_match(1)
1214
- msg ||= exception.http_body
1215
940
  raise err, msg
1216
941
  end
1217
942
 
1218
- # RestClient::Resource#delete doesn't take an HTTP payload,
1219
- # but some JSS API resources require it (notably, logflush).
1220
- #
1221
- # This method uses RestClient::Request#execute
1222
- # to do the same thing that RestClient::Resource#delete does, but
1223
- # adding the payload.
1224
- #
1225
- # @param rsrc[String] the sub-resource we're DELETEing
1226
- #
1227
- # @param payload[String] The XML to be passed with the DELETE
1228
- #
1229
- # @param additional_headers[Type] See RestClient::Request#execute
1230
- #
1231
- # @param &block[Type] See RestClient::Request#execute
1232
- #
1233
- # @return [String] the XML response from the server.
1234
- #
1235
- def delete_with_payload(rsrc, payload, additional_headers = {}, &block)
1236
- headers = (@cnx.options[:headers] || {}).merge(additional_headers)
1237
- @last_http_response = RestClient::Request.execute(
1238
- @cnx.options.merge(
1239
- method: :delete,
1240
- url: @cnx[rsrc].url,
1241
- payload: payload,
1242
- headers: headers
1243
- ),
1244
- &(block || @block)
1245
- )
1246
- rescue RestClient::ExceptionWithResponse => e
1247
- handle_http_error e
1248
- end # delete_with_payload
943
+ # create the faraday connection object
944
+ def create_connection(pw)
945
+ Faraday.new(@rest_url, ssl: @ssl_options) do |cnx|
946
+ cnx.basic_auth @user, pw
947
+ cnx.options[:timeout] = @timeout
948
+ cnx.options[:open_timeout] = @open_timeout
949
+ cnx.adapter Faraday::Adapter::NetHttp
950
+ end
951
+ end
1249
952
 
1250
953
  end # class APIConnection
1251
954
 
955
+ # JSS MODULE METHODS
956
+ ######################
957
+
1252
958
  # Create a new APIConnection object and use it for all
1253
959
  # future API calls. If connection options are provided,
1254
960
  # they are passed to the connect method immediately, otherwise
@@ -1276,6 +982,7 @@ module JSS
1276
982
  #
1277
983
  def self.use_api_connection(connection)
1278
984
  raise 'API connections must be instances of JSS::APIConnection' unless connection.is_a? JSS::APIConnection
985
+
1279
986
  @api = connection
1280
987
  end
1281
988