ruby-jss 1.3.3 → 1.6.0b1

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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +142 -0
  3. data/THANKS.md +3 -2
  4. data/lib/jamf.rb +18 -17
  5. data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
  6. data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +109 -101
  7. data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +55 -30
  8. data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
  9. data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
  10. data/lib/jamf/api/connection.rb +13 -9
  11. data/lib/jamf/api/connection/api_error.rb +8 -8
  12. data/lib/jamf/api/connection/token.rb +36 -15
  13. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  14. data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
  15. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  16. data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
  17. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  18. data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
  19. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  20. data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
  21. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  22. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  23. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  24. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  25. data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
  26. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  27. data/lib/jamf/api/mixins/change_log.rb +201 -51
  28. data/lib/jamf/api/{resources/collection_resources/computer.rb → mixins/filterable.rb} +19 -17
  29. data/lib/jamf/api/mixins/pageable.rb +208 -0
  30. data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
  31. data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
  32. data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
  33. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
  34. data/lib/jamf/api/resources/collection_resources/department.rb +1 -3
  35. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
  36. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  37. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
  38. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  39. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  40. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  41. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  42. data/lib/jamf/client.rb +3 -3
  43. data/lib/jamf/client/management_action.rb +2 -3
  44. data/lib/jamf/composer.rb +2 -2
  45. data/lib/jamf/utility.rb +35 -7
  46. data/lib/jamf/validate.rb +63 -24
  47. data/lib/jamf/version.rb +1 -1
  48. data/lib/jss.rb +2 -2
  49. data/lib/jss/api_connection.rb +114 -406
  50. data/lib/jss/api_object.rb +10 -20
  51. data/lib/jss/api_object/advanced_search.rb +27 -26
  52. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  53. data/lib/jss/api_object/categorizable.rb +1 -1
  54. data/lib/jss/api_object/computer.rb +13 -0
  55. data/lib/jss/api_object/configuration_profile.rb +61 -5
  56. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  57. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  58. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  59. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  60. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  61. data/lib/jss/api_object/distribution_point.rb +2 -2
  62. data/lib/jss/api_object/dock_item.rb +102 -96
  63. data/lib/jss/api_object/ebook.rb +1 -2
  64. data/lib/jss/api_object/extendable.rb +1 -1
  65. data/lib/jss/api_object/extension_attribute.rb +4 -3
  66. data/lib/jss/api_object/group.rb +33 -2
  67. data/lib/jss/api_object/mac_application.rb +107 -8
  68. data/lib/jss/api_object/network_segment.rb +45 -13
  69. data/lib/jss/api_object/patch_source.rb +10 -9
  70. data/lib/jss/api_object/policy.rb +267 -28
  71. data/lib/jss/api_object/printer.rb +10 -4
  72. data/lib/jss/api_object/scopable.rb +10 -15
  73. data/lib/jss/api_object/scopable/scope.rb +389 -73
  74. data/lib/jss/api_object/script.rb +242 -352
  75. data/lib/jss/api_object/self_servable.rb +17 -9
  76. data/lib/jss/api_object/uploadable.rb +1 -1
  77. data/lib/jss/api_object/user.rb +43 -2
  78. data/lib/jss/api_object/vpp_account.rb +209 -0
  79. data/lib/jss/api_object/vppable.rb +169 -13
  80. data/lib/jss/client/management_action.rb +1 -2
  81. data/lib/jss/composer.rb +2 -2
  82. data/lib/jss/exceptions.rb +3 -0
  83. data/lib/jss/server.rb +15 -0
  84. data/lib/jss/utility.rb +213 -45
  85. data/lib/jss/validate.rb +53 -10
  86. data/lib/jss/version.rb +1 -1
  87. metadata +50 -66
  88. data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
  89. data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
  90. data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
  91. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
  92. data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
  93. data/lib/jamf/api/json_objects/android_details.rb +0 -139
  94. data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
  95. data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
  96. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
  97. data/lib/jamf/api/json_objects/criterion.rb +0 -152
  98. data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
  99. data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
  100. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
  101. data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
  102. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
  103. data/lib/jamf/api/json_objects/ios_details.rb +0 -244
  104. data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
  105. data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
  106. data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
  107. data/lib/jamf/api/mixins/locatable.rb +0 -124
  108. data/lib/jamf/api/mixins/referable.rb +0 -92
  109. data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
  110. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
  111. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
  112. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +0 -45
  113. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
  114. data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
  115. data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
  116. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
  117. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
@@ -94,7 +94,7 @@ module JSS
94
94
  #
95
95
  def self.set_mgmt_action_ncprefs_flags(user, flags, hup: true)
96
96
  plist = Pathname.new "/Users/#{user}/Library/Preferences/#{NCPREFS_DOMAIN}.plist"
97
- prefs = JSS.parse_plist plist
97
+ prefs = Jamf.parse_plist plist
98
98
  mgmt_action_setting = prefs['apps'].select { |a| a['bundle-id'] == MGMT_ACTION_BUNDLE_ID }.first
99
99
  if mgmt_action_setting
100
100
  orig_flags = mgmt_action_setting['flags']
@@ -103,8 +103,7 @@ module JSS
103
103
  orig_flags = flags
104
104
  prefs['apps'] << { 'bundle-id' => MGMT_ACTION_BUNDLE_ID, 'flags' => flags }
105
105
  end
106
- # system "/usr/bin/defaults write #{NCPREFS_DOMAIN} '#{prefs.to_plist}'"
107
- plist.open('w') { |f| f.write prefs.to_plist }
106
+ plist.open('w') { |f| f.write Jamf.xml_plist_from(prefs) }
108
107
  system HUP_NOTIF_CTR_CMD if hup
109
108
  orig_flags
110
109
  end
data/lib/jamf/composer.rb CHANGED
@@ -126,7 +126,7 @@ module Jamf
126
126
  ###
127
127
  comp_plist_out = Pathname.new "/tmp/#{PKG_BUNDLE_ID_PFX}-#{pkg_filename}.plist"
128
128
  system "#{PKGBUILD} --analyze --root '#{root}' '#{comp_plist_out}'"
129
- comp_plist = Plist.parse_xml comp_plist_out.read
129
+ comp_plist = Jamf.parse_plist comp_plist_out
130
130
 
131
131
  ### if the plist is empty, there are no bundles in the pkg
132
132
  if comp_plist[0].nil?
@@ -141,7 +141,7 @@ module Jamf
141
141
  bndl['BundleHasStrictIdentifier'] = false
142
142
  end
143
143
  ### write out the edits
144
- comp_plist_out.open('w') { |f| f.write comp_plist.to_plist }
144
+ comp_plist_out.open('w') { |f| f.write Jamf.xml_plist_from(comp_plist) }
145
145
  comp_plist_arg = "--component-plist '#{comp_plist_out}'"
146
146
  end
147
147
 
data/lib/jamf/utility.rb CHANGED
@@ -187,19 +187,26 @@ module Jamf
187
187
  { stringform: valstr, arrayform: valarr }
188
188
  end # to_s_and_a
189
189
 
190
- # Parse a plist into a Ruby data structure.
191
- # This enhances Plist::parse_xml taking file paths, as well as XML Strings
192
- # and reading the files regardless of binary/XML format.
190
+ # Parse a plist into a Ruby data structure. The plist parameter may be
191
+ # a String containing an XML plist, or a path to a plist file, or it may be
192
+ # a Pathname object pointing to a plist file. The plist files may be XML or
193
+ # binary.
193
194
  #
194
195
  # @param plist[Pathname, String] the plist XML, or the path to a plist file
195
196
  #
197
+ # @param symbol_keys[Boolean] should any Hash keys in the result be converted
198
+ # into Symbols rather than remain as Strings?
199
+ #
196
200
  # @return [Object] the parsed plist as a ruby hash,array, etc.
197
201
  #
198
- def self.parse_plist(plist)
202
+ def self.parse_plist(plist, symbol_keys: false)
203
+ require 'cfpropertylist'
204
+
199
205
  # did we get a string of xml, or a string pathname?
200
206
  case plist
201
207
  when String
202
- return Plist.parse_xml plist if plist.include? '</plist>'
208
+ return CFPropertyList.native_types(CFPropertyList::List.new(data: plist).value, symbol_keys) if plist.include? '</plist>'
209
+
203
210
  plist = Pathname.new plist
204
211
  when Pathname
205
212
  true
@@ -208,11 +215,32 @@ module Jamf
208
215
  end # case plist
209
216
 
210
217
  # if we're here, its a Pathname
211
- raise Jamf::MissingDataError, "No such file: #{plist}" unless plist.file?
218
+ raise JSS::MissingDataError, "No such file: #{plist}" unless plist.file?
212
219
 
213
- Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}`.force_encoding('UTF-8')
220
+ CFPropertyList.native_types(CFPropertyList::List.new(file: plist).value, symbol_keys)
214
221
  end # parse_plist
215
222
 
223
+ # Convert any ruby data to an XML plist.
224
+ #
225
+ # NOTE: Binary data is tricky. Easiest way is to pass in a
226
+ # Pathname or IO object (anything that responds to `read` and
227
+ # returns a bytestring)
228
+ # and then the CFPropertyList.guess method will read it and
229
+ # convert it to a Plist <data> element with base64 encoded
230
+ # data.
231
+ # For more info, see CFPropertyList.guess
232
+ #
233
+ # @param data [Object] the data to be converted, usually a Hash
234
+ #
235
+ # @return [String] the object converted into an XML plist
236
+ #
237
+ def self.xml_plist_from(data)
238
+ require 'cfpropertylist'
239
+ plist = CFPropertyList::List.new
240
+ plist.value = CFPropertyList.guess(data, convert_unknown_to_string: true)
241
+ plist.to_str(CFPropertyList::List::FORMAT_XML)
242
+ end
243
+
216
244
  # TODO: Sill needed in Jamf API?
217
245
  #
218
246
  # Converts anything that responds to #to_s to a Time, or nil
data/lib/jamf/validate.rb CHANGED
@@ -37,7 +37,7 @@ module Jamf
37
37
  module Validate
38
38
 
39
39
  # The regular expression that matches a valid MAC address.
40
- MAC_ADDR_RE = /^[a-f0-9]{2}(:[a-f0-9]{2}){5}$/i
40
+ MAC_ADDR_RE = /^[a-f0-9]{2}(:[a-f0-9]{2}){5}$/i.freeze
41
41
 
42
42
  # Validate the format and content of a MAC address
43
43
  #
@@ -50,6 +50,7 @@ module Jamf
50
50
  def self.mac_address(val, msg = nil)
51
51
  msg ||= "Not a valid MAC address: '#{val}'"
52
52
  raise Jamf::InvalidDataError, msg unless val =~ MAC_ADDR_RE
53
+
53
54
  val
54
55
  end
55
56
 
@@ -68,10 +69,11 @@ module Jamf
68
69
  ok = false unless parts.size == 4
69
70
  parts.each { |p| ok = false unless p.j_integer? && p.to_i < 256 && p.to_i >= 0 }
70
71
  raise Jamf::InvalidDataError, msg unless ok
72
+
71
73
  val
72
74
  end
73
75
 
74
- # Does a give JSONObject class have a given JSON attribute?
76
+ # Does a given JSONObject class have a given JSON attribute?
75
77
  #
76
78
  # @param klass [<JSONObject] A class descended from JSONObject
77
79
  #
@@ -83,9 +85,24 @@ module Jamf
83
85
  raise "#{klass} is not a descendent of JSONObject" unless klass < Jamf::JSONObject
84
86
 
85
87
  raise Jamf::NoSuchItemError, "No attribute #{attr_name} for class #{klass}" unless klass::OBJECT_MODEL.key? attrib
88
+
86
89
  attr_name
87
90
  end
88
91
 
92
+ # Does a value exist in a given enum array?
93
+ #
94
+ # @param klass [<JSONObject] A class descended from JSONObject
95
+ #
96
+ # @param attr_name [Symbol] The attribute to validate
97
+ #
98
+ # @return [Symbol] The valid attribute
99
+ #
100
+ def self.in_enum(val, enum)
101
+ raise Jamf::InvalidDataError, "Value must be one of: #{enum.join ', '}" unless enum.include? val
102
+
103
+ val
104
+ end
105
+
89
106
  # Validate that a value doesn't already exist for a given identifier of
90
107
  # a given CollectionResource class
91
108
  #
@@ -116,14 +133,12 @@ module Jamf
116
133
  raise Jamf::AlreadyExistsError, msg
117
134
  end
118
135
 
136
+ TRUE_FALSE = [true, false].freeze
137
+
119
138
  # Confirm that the given value is a boolean value, accepting
120
- # Strings and Symbols, returning real booleans as needed
121
- #
122
- # Accepted True values: true, 'true', :true, 'yes', :yes
123
- #
124
- # Accepted False values: false, 'false', :false, 'no', :no
125
- #
126
- # all Strings and Symbols are case insensitive
139
+ # strings and symbols and returning real booleans as needed
140
+ # Accepts: true, false, 'true', 'false', 'yes', 'no', 't','f', 'y', or 'n'
141
+ # as strings or symbols, case insensitive
127
142
  #
128
143
  # @param val [Boolean,String,Symbol] The value to validate
129
144
  #
@@ -131,14 +146,36 @@ module Jamf
131
146
  #
132
147
  # @return [Boolean] the valid boolean
133
148
  #
134
- def self.boolean(val, msg = nil)
135
- msg ||= 'Value must be boolean true or false'
136
- return true if val.to_s =~ /^(true|yes)$/i
137
- return false if val.to_s =~ /^(false|no)$/i
149
+ def self.boolean(val, msg = 'Value must be true or false, or equivalent string or symbol')
150
+ return val if TRUE_FALSE.include? val
151
+ return true if val.to_s =~ /^(t(rue)?|y(es)?)$/i
152
+ return false if val.to_s =~ /^(f(alse)?|no?)$/i
138
153
 
139
154
  raise Jamf::InvalidDataError, msg
140
155
  end
141
156
 
157
+ # Confirm that a value provided is an integer or a string version
158
+ # of an integer, and return the string version
159
+ #
160
+ # The JPAPI specs say that all IDs are integers in strings
161
+ # tho, the endpoints are still implementing that in different versions.
162
+ #
163
+ # @param val[Object] the value to validate
164
+ #
165
+ # @param msg[String] A custom error message when the value is invalid
166
+ #
167
+ # @return [String] the valid integer-in-a-string
168
+ #
169
+ def self.j_id(val, msg = 'Value must be an Integer or an Integer in a String, e.g. "42"')
170
+ case val
171
+ when Integer
172
+ return val.to_s
173
+ when String
174
+ return val if val.j_integer?
175
+ end
176
+ raise Jamf::InvalidDataError, msg
177
+ end
178
+
142
179
  # Confirm that a value is an Integer or a String representation of an
143
180
  # Integer. Return the integer, or raise an error
144
181
  #
@@ -148,10 +185,10 @@ module Jamf
148
185
  #
149
186
  # @return [Integer] the valid integer
150
187
  #
151
- def self.integer(val, msg = nil)
152
- msg ||= 'Value must be an Integer'
188
+ def self.integer(val, msg = 'Value must be an Integer')
153
189
  val = val.to_i if val.is_a?(String) && val.j_integer?
154
190
  raise Jamf::InvalidDataError, msg unless val.is_a? Integer
191
+
155
192
  val
156
193
  end
157
194
 
@@ -164,10 +201,10 @@ module Jamf
164
201
  #
165
202
  # @return [Float] the valid float
166
203
  #
167
- def self.float(val, msg = nil)
168
- msg ||= 'Value must be a Floating Point number'
204
+ def self.float(val, msg = 'Value must be a Floating Point number')
169
205
  val = val.to_f if val.is_a?(String) && val.j_float?
170
- raise Jamf::InvalidDataError, msg unless val.is_a? Flot
206
+ raise Jamf::InvalidDataError, msg unless val.is_a? Float
207
+
171
208
  val
172
209
  end
173
210
 
@@ -180,11 +217,12 @@ module Jamf
180
217
  #
181
218
  # @return [String] the valid String
182
219
  #
183
- def self.string(val, msg = nil)
184
- msg ||= 'Value must be a String'
220
+ def self.string(val, msg = 'Value must be a String')
185
221
  return Jamf::BLANK if val.nil?
222
+
186
223
  val = val.to_s if val.is_a? Symbol
187
224
  raise Jamf::InvalidDataError, msg unless val.is_a? String
225
+
188
226
  val
189
227
  end
190
228
 
@@ -197,10 +235,10 @@ module Jamf
197
235
  #
198
236
  # @return [String] the valid non-empty string
199
237
  #
200
- def self.non_empty_string(val, msg = nil)
201
- msg ||= 'value must be a non-empty String'
238
+ def self.non_empty_string(val, msg = 'value must be a non-empty String')
202
239
  val = val.to_s if val.is_a? Symbol
203
240
  raise Jamf::InvalidDataError, msg unless val.is_a?(String) && !val.empty?
241
+
204
242
  val
205
243
  end
206
244
 
@@ -214,11 +252,12 @@ module Jamf
214
252
  #
215
253
  # @return [String] the validated string
216
254
  #
217
- def self.script_contents(val, msg = nil)
218
- msg ||= "value must be a String starting with '#!'"
255
+ def self.script_contents(val, msg = "value must be a String starting with '#!'")
219
256
  raise Jamf::InvalidDataError, msg unless val.is_a?(String) && val.start_with?(SCRIPT_SHEBANG)
257
+
220
258
  val
221
259
  end
260
+
222
261
  end # module validate
223
262
 
224
263
  end # module JSS
data/lib/jamf/version.rb CHANGED
@@ -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,8 +58,8 @@ module JSS
58
58
 
59
59
  ###################
60
60
  ### Gems
61
- require 'rest-client'
62
- require 'plist'
61
+ require 'faraday'
62
+ require 'faraday_middleware'
63
63
  require 'immutable-struct'
64
64
  require 'recursive-open-struct'
65
65
 
@@ -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/, '&#13;')
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 &#13;
618
- xml.gsub!(/\r/, '&#13;') if xml
589
+ xml&.gsub!(/\r/, '&#13;')
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,69 @@ 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
+ Regexp.last_match(1) || @last_http_response.body =~ %r{<p>Error: (.*?)</p>}
926
+ msg = Regexp.last_match(1)
927
+ when 400
1204
928
  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
929
+ @last_http_response.body =~ %r{>Bad Request</p>\n<p>(.*?)</p>\n<p>You can get technical detail}m
930
+ msg = Regexp.last_match(1)
931
+ when 401
932
+ err = JSS::AuthorizationError
933
+ msg = 'You are not authorized to do that.'
934
+ when (500..599)
935
+ err = JSS::APIRequestError
936
+ msg = 'There was an internal server error'
1208
937
  else
1209
938
  err = JSS::APIRequestError
1210
- msg_matcher = %r{<body.*?>(.*?)</body>}m
939
+ msg = "There was a error processing your request, status: #{@last_http_response.status}"
1211
940
  end
1212
- exception.http_body =~ msg_matcher
1213
- msg = Regexp.last_match(1)
1214
- msg ||= exception.http_body
1215
941
  raise err, msg
1216
942
  end
1217
943
 
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
944
+ # create the faraday connection object
945
+ def create_connection(pw)
946
+ Faraday.new(@rest_url, ssl: @ssl_options) do |cnx|
947
+ cnx.basic_auth @user, pw
948
+ cnx.options[:timeout] = @timeout
949
+ cnx.options[:open_timeout] = @open_timeout
950
+ cnx.adapter Faraday::Adapter::NetHttp
951
+ end
952
+ end
1249
953
 
1250
954
  end # class APIConnection
1251
955
 
956
+ # JSS MODULE METHODS
957
+ ######################
958
+
1252
959
  # Create a new APIConnection object and use it for all
1253
960
  # future API calls. If connection options are provided,
1254
961
  # they are passed to the connect method immediately, otherwise
@@ -1276,6 +983,7 @@ module JSS
1276
983
  #
1277
984
  def self.use_api_connection(connection)
1278
985
  raise 'API connections must be instances of JSS::APIConnection' unless connection.is_a? JSS::APIConnection
986
+
1279
987
  @api = connection
1280
988
  end
1281
989