ruby-jss 1.4.1 → 1.5.1

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

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