ruby-jss 1.4.1 → 1.5.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +38 -0
  3. data/lib/jamf.rb +10 -3
  4. data/lib/jamf/api/abstract_classes/collection_resource.rb +329 -150
  5. data/lib/jamf/api/abstract_classes/generic_reference.rb +9 -1
  6. data/lib/jamf/api/abstract_classes/json_object.rb +106 -82
  7. data/lib/jamf/api/abstract_classes/prestage.rb +54 -29
  8. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +21 -0
  9. data/lib/jamf/api/abstract_classes/resource.rb +4 -4
  10. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  11. data/lib/jamf/api/connection.rb +13 -9
  12. data/lib/jamf/api/connection/api_error.rb +8 -8
  13. data/lib/jamf/api/connection/token.rb +16 -15
  14. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +14 -1
  15. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  16. data/lib/jamf/api/json_objects/device_enrollment_device_sync_state.rb +81 -0
  17. data/lib/jamf/api/json_objects/locale.rb +59 -0
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  20. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  21. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  22. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  23. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  24. data/lib/jamf/api/mixins/change_log.rb +201 -51
  25. data/lib/jamf/api/mixins/filterable.rb +51 -0
  26. data/lib/jamf/api/mixins/pageable.rb +208 -0
  27. data/lib/jamf/api/mixins/sortable.rb +59 -0
  28. data/lib/jamf/api/resources/collection_resources/building.rb +19 -8
  29. data/lib/jamf/api/resources/collection_resources/category.rb +5 -3
  30. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +11 -4
  31. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +10 -10
  32. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  33. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +24 -22
  34. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  35. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  36. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +14 -14
  37. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  38. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  39. data/lib/jamf/validate.rb +63 -24
  40. data/lib/jamf/version.rb +1 -1
  41. data/lib/jss.rb +2 -1
  42. data/lib/jss/api_connection.rb +110 -370
  43. data/lib/jss/api_object.rb +3 -19
  44. data/lib/jss/api_object/categorizable.rb +1 -1
  45. data/lib/jss/api_object/configuration_profile.rb +34 -3
  46. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  47. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  48. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  49. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  50. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  51. data/lib/jss/api_object/distribution_point.rb +2 -2
  52. data/lib/jss/api_object/dock_item.rb +102 -96
  53. data/lib/jss/api_object/extendable.rb +1 -1
  54. data/lib/jss/api_object/group.rb +33 -2
  55. data/lib/jss/api_object/network_segment.rb +43 -12
  56. data/lib/jss/api_object/patch_source.rb +10 -9
  57. data/lib/jss/api_object/printer.rb +10 -4
  58. data/lib/jss/api_object/scopable.rb +10 -15
  59. data/lib/jss/exceptions.rb +3 -0
  60. data/lib/jss/server.rb +15 -0
  61. data/lib/jss/version.rb +1 -1
  62. metadata +37 -22
@@ -27,6 +27,6 @@
27
27
  module Jamf
28
28
 
29
29
  ### The version of the Jamf module
30
- VERSION = '0.0.3'.freeze
30
+ VERSION = '0.0.5'.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
@@ -271,7 +259,7 @@ module JSS
271
259
  # {#get_rsrc}, {#put_rsrc}, {#post_rsrc}, & {#delete_rsrc}
272
260
  # documented below.
273
261
  #
274
- # For even lower-level work, you can access the underlying RestClient::Resource
262
+ # For even lower-level work, you can access the underlying Faraday::Connection
275
263
  # inside the APIConnection via the connection's {#cnx} attribute.
276
264
  #
277
265
  # APIConnection instances also have a {#server} attribute which contains an
@@ -330,6 +318,12 @@ module JSS
330
318
  # values for the format param of get_rsrc
331
319
  GET_FORMATS = %i[json xml].freeze
332
320
 
321
+ HTTP_ACCEPT_HEADER = 'Accept'.freeze
322
+ HTTP_CONTENT_TYPE_HEADER = 'Content-Type'.freeze
323
+
324
+ MIME_JSON = 'application/json'.freeze
325
+ MIME_XML = 'application/xml'.freeze
326
+
333
327
  # Attributes
334
328
  #####################################
335
329
 
@@ -337,7 +331,7 @@ module JSS
337
331
  attr_reader :user
338
332
  alias jss_user user
339
333
 
340
- # @return [RestClient::Resource] the underlying connection resource
334
+ # @return [Faraday::Connection] the underlying connection resource
341
335
  attr_reader :cnx
342
336
 
343
337
  # @return [Boolean] are we connected right now?
@@ -359,7 +353,7 @@ module JSS
359
353
  # @return [String] the protocol being used: http or https
360
354
  attr_reader :protocol
361
355
 
362
- # @return [RestClient::Response] The response from the most recent API call
356
+ # @return [Faraday::Response] The response from the most recent API call
363
357
  attr_reader :last_http_response
364
358
 
365
359
  # @return [String] The base URL to to the current REST API
@@ -453,8 +447,6 @@ module JSS
453
447
  # @option args :use_ssl[Boolean] should the connection be made over SSL? Defaults to true.
454
448
  #
455
449
  # @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
450
  #
459
451
  # @option args :user[String] a JSS user who has API privs, required if not defined in JSS::CONFIG
460
452
  #
@@ -494,7 +486,7 @@ module JSS
494
486
  args[:password] = acquire_password args
495
487
 
496
488
  # heres our connection
497
- @cnx = RestClient::Resource.new(@rest_url.to_s, args)
489
+ @cnx = create_connection args[:password]
498
490
 
499
491
  verify_server_version
500
492
 
@@ -543,8 +535,7 @@ module JSS
543
535
  @connected = false
544
536
  end # disconnect
545
537
 
546
- # Get an arbitrary JSS resource
547
- #
538
+ # Get a JSS resource
548
539
  # The first argument is the resource to get (the part of the API url
549
540
  # after the 'JSSResource/' ) The resource must be properly URL escaped
550
541
  # beforehand. Note: URL.encode is deprecated, use CGI.escape
@@ -572,14 +563,19 @@ module JSS
572
563
  validate_connected
573
564
  raise JSS::InvalidDataError, 'format must be :json or :xml' unless GET_FORMATS.include? format
574
565
 
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
566
+ @last_http_response =
567
+ @cnx.get(rsrc) do |req|
568
+ req.headers[HTTP_ACCEPT_HEADER] = format == :json ? MIME_JSON : MIME_XML
569
+ end
578
570
 
579
- @last_http_response.body
580
- rescue RestClient::ExceptionWithResponse => e
581
- handle_http_error e
571
+ unless @last_http_response.success?
572
+ handle_http_error
573
+ return
582
574
  end
575
+
576
+ return JSON.parse(@last_http_response.body, symbolize_names: true) if format == :json && !raw_json
577
+
578
+ @last_http_response.body
583
579
  end
584
580
 
585
581
  # Update an existing JSS resource
@@ -597,10 +593,18 @@ module JSS
597
593
  xml.gsub!(/\r/, '
')
598
594
 
599
595
  # send the data
600
- @last_http_response = @cnx[rsrc].put(xml, content_type: 'text/xml')
596
+ @last_http_response =
597
+ @cnx.put(rsrc) do |req|
598
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
599
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
600
+ req.body = xml
601
+ end
602
+ unless @last_http_response.success?
603
+ handle_http_error
604
+ return
605
+ end
606
+
601
607
  @last_http_response.body
602
- rescue RestClient::ExceptionWithResponse => e
603
- handle_http_error e
604
608
  end
605
609
 
606
610
  # Create a new JSS resource
@@ -611,17 +615,24 @@ module JSS
611
615
  #
612
616
  # @return [String] the xml response from the server.
613
617
  #
614
- def post_rsrc(rsrc, xml = '')
618
+ def post_rsrc(rsrc, xml)
615
619
  validate_connected
616
620
 
617
621
  # convert CRs & to 
618
- xml.gsub!(/\r/, '
') if xml
622
+ xml&.gsub!(/\r/, '
')
619
623
 
620
624
  # send the data
621
- @last_http_response = @cnx[rsrc].post(xml, content_type: 'text/xml', accept: :json)
625
+ @last_http_response =
626
+ @cnx.post(rsrc) do |req|
627
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
628
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
629
+ req.body = xml
630
+ end
631
+ unless @last_http_response.success?
632
+ handle_http_error
633
+ return
634
+ end
622
635
  @last_http_response.body
623
- rescue RestClient::ExceptionWithResponse => e
624
- handle_http_error e
625
636
  end # post_rsrc
626
637
 
627
638
  # Delete a resource from the JSS
@@ -630,18 +641,23 @@ module JSS
630
641
  #
631
642
  # @return [String] the xml response from the server.
632
643
  #
633
- def delete_rsrc(rsrc, xml = nil)
644
+ def delete_rsrc(rsrc)
634
645
  validate_connected
635
646
  raise MissingDataError, 'Missing :rsrc' if rsrc.nil?
636
647
 
637
- # payload?
638
- return delete_with_payload rsrc, xml if xml
639
-
640
648
  # delete the resource
641
- @last_http_response = @cnx[rsrc].delete
649
+ @last_http_response =
650
+ @cnx.delete(rsrc) do |req|
651
+ req.headers[HTTP_CONTENT_TYPE_HEADER] = MIME_XML
652
+ req.headers[HTTP_ACCEPT_HEADER] = MIME_XML
653
+ end
654
+
655
+ unless @last_http_response.success?
656
+ handle_http_error
657
+ return
658
+ end
659
+
642
660
  @last_http_response.body
643
- rescue RestClient::ExceptionWithResponse => e
644
- handle_http_error e
645
661
  end # delete_rsrc
646
662
 
647
663
  # Test that a given hostname & port is a JSS API server
@@ -657,25 +673,8 @@ module JSS
657
673
  # ssl_options like :OP_NO_SSLv2 and :OP_NO_SSLv3 will take time to figure out..
658
674
  return true if `/usr/bin/curl -s 'https://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
659
675
  return true if `/usr/bin/curl -s 'http://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
660
- false
661
676
 
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
677
+ false
679
678
  end
680
679
 
681
680
  # The server to which we are connected, or will
@@ -686,267 +685,13 @@ module JSS
686
685
  #
687
686
  def hostname
688
687
  return @server_host if @server_host
688
+
689
689
  srvr = JSS::CONFIG.api_server_name
690
690
  srvr ||= JSS::Client.jss_server
691
691
  srvr
692
692
  end
693
693
  alias host hostname
694
694
 
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
695
  # Empty all cached lists from this connection
951
696
  # then run garbage collection to clear any available memory
952
697
  #
@@ -1052,6 +797,7 @@ module JSS
1052
797
  #
1053
798
  def apply_defaults_from_client(args)
1054
799
  return unless JSS::Client.installed?
800
+
1055
801
  # these settings can come from the jamf binary config, if this machine is a JSS client.
1056
802
  args[:server] ||= JSS::Client.jss_server
1057
803
  args[:port] ||= JSS::Client.jss_port.to_i
@@ -1105,11 +851,13 @@ module JSS
1105
851
  # keep this basic level of info available for basic authentication
1106
852
  # and JSS version checking.
1107
853
  begin
1108
- @server = JSS::Server.new get_rsrc('jssuser')[:user], self
1109
- rescue RestClient::Unauthorized
854
+ data = get_rsrc('jssuser')
855
+ rescue JSS::AuthorizationError
1110
856
  raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{@user}@#{@server_host}:#{@port}'."
1111
857
  end
1112
858
 
859
+ @server = JSS::Server.new data[:user], self
860
+
1113
861
  min_vers = JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
1114
862
  return if @server.version >= min_vers # we're good...
1115
863
 
@@ -1178,77 +926,68 @@ module JSS
1178
926
  if SSL_PORTS.include? args[:port]
1179
927
  args[:use_ssl] = true unless args[:use_ssl] == false
1180
928
  end
929
+ return unless args[:use_ssl]
930
+
1181
931
  # 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
932
+ args[:verify_ssl] = args[:verify_cert] != false
933
+
934
+ # ssl version if not specified
935
+ args[:ssl_version] ||= DFT_SSL_VERSION
936
+
937
+ @ssl_options = {
938
+ verify: args[:verify_ssl],
939
+ version: args[:ssl_version]
940
+ }
1183
941
  end
1184
942
 
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
943
+ # Parses the @last_http_response
944
+ # and raises a JSS::APIError with a useful error message.
1191
945
  #
1192
946
  # @return [void]
1193
947
  #
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
948
+ def handle_http_error
949
+ return if @last_http_response.success?
950
+
951
+ case @last_http_response.status
952
+ when 404
953
+ err = JSS::NoSuchItemError
954
+ msg = 'Not Found'
955
+ when 409
1201
956
  err = JSS::ConflictError
1202
- msg_matcher = /<p>Error:(.*?)(<|$)/m
1203
- when RestClient::BadRequest
957
+ @last_http_response.body =~ /<p>(The server has not .*?)(<|$)/m
958
+ msg = Regexp.last_match(1)
959
+ when 400
1204
960
  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
961
+ @last_http_response.body =~ %r{>Bad Request</p>\n<p>(.*?)</p>\n<p>You can get technical detail}m
962
+ msg = Regexp.last_match(1)
963
+ when 401
964
+ err = JSS::AuthorizationError
965
+ msg = 'You are not authorized to do that.'
966
+ when (500..599)
967
+ err = JSS::APIRequestError
968
+ msg = 'There was an internal server error'
1208
969
  else
1209
970
  err = JSS::APIRequestError
1210
- msg_matcher = %r{<body.*?>(.*?)</body>}m
971
+ msg = "There was a error processing your request, status: #{@last_http_response.status}"
1211
972
  end
1212
- exception.http_body =~ msg_matcher
1213
- msg = Regexp.last_match(1)
1214
- msg ||= exception.http_body
1215
973
  raise err, msg
1216
974
  end
1217
975
 
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
976
+ # create the faraday connection object
977
+ def create_connection(pw)
978
+ Faraday.new(@rest_url, ssl: @ssl_options) do |cnx|
979
+ cnx.basic_auth @user, pw
980
+ cnx.options[:timeout] = @timeout
981
+ cnx.options[:open_timeout] = @open_timeout
982
+ cnx.adapter Faraday::Adapter::NetHttp
983
+ end
984
+ end
1249
985
 
1250
986
  end # class APIConnection
1251
987
 
988
+ # JSS MODULE METHODS
989
+ ######################
990
+
1252
991
  # Create a new APIConnection object and use it for all
1253
992
  # future API calls. If connection options are provided,
1254
993
  # they are passed to the connect method immediately, otherwise
@@ -1276,6 +1015,7 @@ module JSS
1276
1015
  #
1277
1016
  def self.use_api_connection(connection)
1278
1017
  raise 'API connections must be instances of JSS::APIConnection' unless connection.is_a? JSS::APIConnection
1018
+
1279
1019
  @api = connection
1280
1020
  end
1281
1021