ruby-jss 1.1.0b5 → 1.1.3

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9337d6314a79881c726e5b816872dffb2bccdc0f538a6f7b6407075f5be684a
4
- data.tar.gz: dd0d9d6210d1f8abab4bbf4046cc9ec59224e08e138e7b3d6a3122f13c4b2728
3
+ metadata.gz: 90a0bdaae94b5d0d1cb5ccad691ecf57daa75e205ceda668813655484ee232c8
4
+ data.tar.gz: 6c8e0211b2397df59d576b8fec2901f22003dd2d562c7a755209ebd0026493ca
5
5
  SHA512:
6
- metadata.gz: bf9e2ca6b9075436d09415eee9cf31c18f3fa88325f5c7c99ab4ca06f996fa0c8e1446b2a88d862dd1628b16b9a3a79676abcc118d07dd26b1fb553826255143
7
- data.tar.gz: 15361910ba0e772eecf502bc1d2ce644673b6a55cad00df60c207e495894a48cc67b593d05f8da32789974950984982eea568874762187bd126bb7f8fe47be56
6
+ metadata.gz: de40656a561b6624eaa28b4c851314de7bb4a84e151f656d1c021a784255c5c95ce76b2e7013553cc02f3094707934481e05059bf931b3fd9c659eedb8e05415
7
+ data.tar.gz: 8fdef7af00dc52b1ce253288415eade80d8d3812ed5470ad84f0e3c9292c95e32b1080b7c56e7457ce21e927bb0782e63124df1bb5efa2423e95694c620a148e
data/CHANGES.md CHANGED
@@ -4,19 +4,20 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## \[Unreleased]
7
+ ## \[1.1.3] - 2019-09-23
8
8
  ### Added
9
9
  - MobileDeviceExtensionAttribute now has a `.history` class method matching that of ComputerExtensionAttribute. Requires direct MySQL database access. Thanks @aurica!
10
10
  - JSS::AmbiguousError exception class
11
11
  - More caching of API data to improve general speed
12
12
  - The hashes created by `APIObject.map_all_ids_to(blah)`
13
13
  - ExtensionAttribute definitions when used by extendable classes
14
- - Implemented Ruby2.4's `String#casecmp?` in older Rubies
15
14
  - APIObject.fetch can take the search term `:random` and you'll get a randomly selected object. Example: `a_random_computer = JSS::Computer.fetch :random`
16
15
  - Keys of the hash returned by `Computer#hardware` are now available as instance methods on Computer objects. So as well as `a_computer.hardware[:total_ram]` you can also do `a_computer.total_ram`
17
16
  - Policy now recognizes the frequency Symbol `:once_per_user_per_computer`
18
17
  - Attribute reader :management_status added to Computer class
19
- - Implemented some useful String methods from newer versions of Ruby into older Rubies: casecmp?, delete_prefix, & delete_suffix
18
+ - Implemented some useful String methods from newer versions of Ruby into older Rubies: `casecmp?`, `delete_prefix`, & `delete_suffix`
19
+ - master_distribution_point class method in APIConnection & DistribtutionPoint now raise an error when no dist. point is 'master'
20
+ - The error states that the cloud dist. point may be the master, and there's no classic API access to it.
20
21
 
21
22
 
22
23
  ### Fixed
@@ -30,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
30
31
  - Script#name= now works again, no longer uses a constant from an ancient version. Thanks @shahn
31
32
  - Computer#asset_tag= now accepts nil to erase the value
32
33
  - APIConnection.my_distribution_point & DistributionPoint.my_distribution_point now return the master_distribution_point object if there isn't one assigned to the current network segment.
34
+ - RestClient no longer warns about calling 'to_i' on Responses when calling APIConnection#put_rsrc & #post_rsrc
33
35
 
34
36
  ### Changed
35
37
  - Monkey Patches are being moved to a better, more traceable technique, see https://www.justinweiss.com/articles/3-ways-to-monkey-patch-without-making-a-mess/
@@ -39,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
39
41
  - Removed deprecated VALID_DATA_KEYS constants from APIObject subclasses
40
42
  - Various changes in APIObject and its subclasses to try making `.fetch` and other lookup-methods faster.
41
43
  - All of the NetworkSegment-related methods in APIConnection have been moved back to NetworkSegment. The methods in APIConnection still work, but are marked deprecated and will go away eventually.
44
+ - Removed last call to deprecated `URI.encode`, replaced with `CGI.escape`
42
45
 
43
46
 
44
47
  ## \[1.0.4] - 2019-05-06
@@ -539,7 +539,8 @@ module JSS
539
539
  # Get an arbitrary JSS resource
540
540
  #
541
541
  # The first argument is the resource to get (the part of the API url
542
- # after the 'JSSResource/' )
542
+ # after the 'JSSResource/' ) The resource must be properly URL escaped
543
+ # beforehand. Note: URL.encode is deprecated, use CGI.escape
543
544
  #
544
545
  # By default we get the data in JSON, and parse it
545
546
  # into a ruby data structure (arrays, hashes, strings, etc)
@@ -559,11 +560,9 @@ module JSS
559
560
 
560
561
  raise JSS::InvalidDataError, 'format must be :json or :xml' unless %i[json xml].include? format
561
562
 
562
- # TODO: fix what rubocop is complaining about in the line below.
563
- # (I doubt we want to CGI.escape the whole resource)
564
- rsrc = URI.encode rsrc
565
563
  begin
566
564
  @last_http_response = @cnx[rsrc].get(accept: format)
565
+ @last_http_response.body
567
566
  rescue RestClient::ExceptionWithResponse => e
568
567
  handle_http_error e
569
568
  end
@@ -588,6 +587,7 @@ module JSS
588
587
 
589
588
  # send the data
590
589
  @last_http_response = @cnx[rsrc].put(xml, content_type: 'text/xml')
590
+ @last_http_response.body
591
591
  rescue RestClient::ExceptionWithResponse => e
592
592
  handle_http_error e
593
593
  end
@@ -607,7 +607,8 @@ module JSS
607
607
  xml.gsub!(/\r/, '
') if xml
608
608
 
609
609
  # send the data
610
- @last_http_response = @cnx[rsrc].post xml, content_type: 'text/xml', accept: :json
610
+ @last_http_response = @cnx[rsrc].post(xml, content_type: 'text/xml', accept: :json)
611
+ @last_http_response.body
611
612
  rescue RestClient::ExceptionWithResponse => e
612
613
  handle_http_error e
613
614
  end # post_rsrc
@@ -627,6 +628,7 @@ module JSS
627
628
 
628
629
  # delete the resource
629
630
  @last_http_response = @cnx[rsrc].delete
631
+ @last_http_response.body
630
632
  rescue RestClient::ExceptionWithResponse => e
631
633
  handle_http_error e
632
634
  end # delete_rsrc
@@ -886,17 +888,19 @@ module JSS
886
888
  @master_distribution_point = nil if refresh
887
889
  return @master_distribution_point if @master_distribution_point
888
890
 
889
- all_dps = JSS::DistributionPoint.all refresh, api: self
890
-
891
- @master_distribution_point =
892
- case all_dps.size
893
- when 0
894
- raise JSS::NoSuchItemError, 'No distribution points defined'
895
- when 1
896
- JSS::DistributionPoint.fetch id: all_dps.first[:id], api: self
897
- else
898
- JSS::DistributionPoint.fetch id: :master, api: self
891
+ JSS::DistributionPoint.all_ids.each do |dp_id|
892
+ dp = JSS::DistributionPoint.fetch id: dp_id, api: self
893
+ if dp.master?
894
+ @master_distribution_point = dp
895
+ break
899
896
  end
897
+ end
898
+
899
+ return @master_distribution_point if @master_distribution_point
900
+
901
+ # If we're here, the Cloud DP might be master, but there's no
902
+ # access to it in the API :/
903
+ raise JSS::NoSuchItemError, 'No Master Distribtion Point defined. It could be the Cloud Dist Point, which is not available in the classic API'
900
904
  end
901
905
 
902
906
  # Get the DistributionPoint instance for the machine running
@@ -912,9 +916,11 @@ module JSS
912
916
  return @my_distribution_point if @my_distribution_point
913
917
 
914
918
  my_net_seg_id = my_network_segments[0]
919
+
915
920
  if my_net_seg_id
916
921
  my_net_seg = JSS::NetworkSegment.fetch(id: my_net_seg_id, api: self)
917
- @my_distribution_point = JSS::DistributionPoint.fetch(name: my_net_seg.distribution_point)
922
+ my_dp_name = my_net_seg.distribution_point
923
+ @my_distribution_point = JSS::DistributionPoint.fetch(name: my_dp_name) if my_dp_name
918
924
  end # if my_net_seg_id
919
925
 
920
926
  @my_distribution_point ||= master_distribution_point refresh
@@ -586,7 +586,7 @@ module JSS
586
586
  all(refresh, api: api) if refresh
587
587
 
588
588
  # it its a valid id, return it
589
- return identifier if all_ids.include? identifier
589
+ return identifier if all_ids(api: api).include? identifier
590
590
 
591
591
  keys_to_check = lookup_keys(no_aliases: true)
592
592
  keys_to_check.delete :id # we've already checked :id
@@ -829,7 +829,7 @@ module JSS
829
829
 
830
830
  # does this lookup key have a fetch_rsrc_key?
831
831
  fetch_rsrc_key = fetch_rsrc_key(fetch_key)
832
- return new fetch_rsrc: "#{self::RSRC_BASE}/#{fetch_rsrc_key}/#{fetch_val}", api: api if fetch_rsrc_key
832
+ return new fetch_rsrc: "#{self::RSRC_BASE}/#{fetch_rsrc_key}/#{CGI.escape fetch_val.to_s}", api: api if fetch_rsrc_key
833
833
  end
834
834
 
835
835
  # if we'ere here, we need to get the id from either the lookup key/val or
@@ -1116,7 +1116,7 @@ module JSS
1116
1116
  def delete
1117
1117
  return nil unless @in_jss
1118
1118
  @api.delete_rsrc @rest_rsrc
1119
- @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}"
1119
+ @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name.to_s}"
1120
1120
  @id = nil
1121
1121
  @in_jss = false
1122
1122
  @need_to_update = false
@@ -1444,7 +1444,7 @@ module JSS
1444
1444
  @init_data = args
1445
1445
  @name = args[:name]
1446
1446
  @in_jss = false
1447
- @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}"
1447
+ @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name.to_s}"
1448
1448
  @need_to_update = true
1449
1449
  end
1450
1450
 
@@ -96,11 +96,10 @@ module JSS
96
96
  def self.application_installs(appname, fields: [], version: nil, ids_only: false, api: JSS.api)
97
97
  fields = [fields] unless fields.is_a? Array
98
98
 
99
- rsrc = "#{COMPUTER_APPLICATIONS_RSRC}/#{appname}"
100
- rsrc << "/version/#{version}" if version
101
- rsrc << "/inventory/#{fields.join ','}" unless ids_only || fields.empty?
99
+ rsrc = "#{COMPUTER_APPLICATIONS_RSRC}/#{CGI.escape appname.to_s}"
100
+ rsrc << "/version/#{CGI.escape version.to_s}" if version
101
+ rsrc << "/inventory/#{CGI.escape fields.join(',')}" unless ids_only || fields.empty?
102
102
 
103
- # get_rsrc will URI.encode the rsrc
104
103
  result = api.get_rsrc(rsrc)[:computer_applications]
105
104
 
106
105
  return result[:unique_computers].map { |c| c[:id] } if ids_only
@@ -103,7 +103,7 @@ module JSS
103
103
  orig_id = @id
104
104
  @id = nil
105
105
  orig_rsrc = @rest_rsrc
106
- @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape new_name}"
106
+ @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape new_name.to_s}"
107
107
  orig_api = @api
108
108
  @api = api
109
109
 
@@ -323,7 +323,7 @@ module JSS
323
323
  # drop down below to try the password for mounting.
324
324
  # we'll escape all the chars that aren't unreserved
325
325
  # reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]")
326
- user_pass = "#{CGI.escape @http_username}:#{CGI.escape ro_pw}@"
326
+ user_pass = "#{CGI.escape @http_username.to_s}:#{CGI.escape ro_pw.to_s}@"
327
327
  url = @http_url.sub "://#{@ip_address}", "://#{user_pass}#{@ip_address}"
328
328
  else
329
329
  url = @http_url
@@ -410,7 +410,7 @@ module JSS
410
410
 
411
411
  username = access == :ro ? @read_only_username : @read_write_username
412
412
 
413
- safe_pw = CGI.escape password
413
+ safe_pw = CGI.escape password.to_s
414
414
 
415
415
  @mount_url = "#{@connection_type.downcase}://#{username}:#{safe_pw}@#{@ip_address}/#{@share_name}"
416
416
  @mnt_cmd = case @connection_type.downcase
@@ -463,6 +463,7 @@ module JSS
463
463
  #### aliases
464
464
  alias hostname ip_address
465
465
  alias umount unmount
466
+ alias master? is_master
466
467
 
467
468
  # Private Instance Methods
468
469
  ######################################
@@ -159,7 +159,7 @@ module JSS
159
159
  def self.check_membership(ldap_server, user, group, api: JSS.api)
160
160
  ldap_server_id = valid_id ldap_server
161
161
  raise JSS::NoSuchItemError, "No LDAPServer matching #{ldap_server}" unless ldap_server_id
162
- rsrc = "#{RSRC_BASE}/id/#{ldap_server_id}/group/#{CGI.escape group}/user/#{CGI.escape user}"
162
+ rsrc = "#{RSRC_BASE}/id/#{ldap_server_id}/group/#{CGI.escape group.to_s}/user/#{CGI.escape user.to_s}"
163
163
  member_check = api.get_rsrc rsrc
164
164
  return false if member_check[:ldap_users].empty?
165
165
  true
@@ -302,7 +302,7 @@ module JSS
302
302
  #
303
303
  def find_user(user, exact = false)
304
304
  raise JSS::NoSuchItemError, 'LDAPServer not yet saved in the JSS' unless @in_jss
305
- raw = api.get_rsrc("#{RSRC_BASE}/id/#{@id}/user/#{user}")[:ldap_users]
305
+ raw = api.get_rsrc("#{RSRC_BASE}/id/#{@id}/user/#{CGI.escape user.to_s}")[:ldap_users]
306
306
  exact ? raw.select { |u| u[:username] == user } : raw
307
307
  end
308
308
 
@@ -314,7 +314,7 @@ module JSS
314
314
  #
315
315
  def find_group(group, exact = false)
316
316
  raise JSS::NoSuchItemError, 'LDAPServer not yet saved in the JSS' unless @in_jss
317
- raw = api.get_rsrc("#{RSRC_BASE}/id/#{@id}/group/#{group}")[:ldap_groups]
317
+ raw = api.get_rsrc("#{RSRC_BASE}/id/#{@id}/group/#{CGI.escape group.to_s}")[:ldap_groups]
318
318
  exact ? raw.select { |u| u[:groupname] == group } : raw
319
319
  end
320
320
 
@@ -88,7 +88,7 @@ module JSS
88
88
  ###
89
89
  def match(term, api: JSS.api )
90
90
  raise JSS::InvalidDataError, "Match term may not be empty" if term.to_s.empty?
91
- rsrc = "#{self::RSRC_BASE}/#{JSS::Matchable::MATCH_RSRC}/#{term}"
91
+ rsrc = "#{self::RSRC_BASE}/#{JSS::Matchable::MATCH_RSRC}/#{CGI.escape term.to_s}"
92
92
  api.get_rsrc(rsrc)[self::RSRC_LIST_KEY]
93
93
  end
94
94
 
@@ -899,7 +899,7 @@ module JSS
899
899
  raise JSS::InvaldDatatError, 'Incorrect password for http access to distribution point.' unless mdp.check_pw(:http, ro_pw)
900
900
  # insert the name and pw into the uri
901
901
  # reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]") # we'll escape all the chars that aren't unreserved
902
- src_path = src_path.sub(%r{(https?://)(\S)}, "#{Regexp.last_match(1)}#{CGI.escape mdp.http_username}:#{CGI.escape ro_pw}@#{Regexp.last_match(2)}")
902
+ src_path = src_path.sub(%r{(https?://)(\S)}, "#{Regexp.last_match(1)}#{CGI.escape mdp.http_username.to_s}:#{CGI.escape ro_pw.to_s}@#{Regexp.last_match(2)}")
903
903
  end
904
904
 
905
905
  # or with filesharing?
@@ -510,7 +510,7 @@ module JSS
510
510
  # TODO: prepare for more cases where the POST rsrc is
511
511
  # different from the PUT/GET/DELETE.
512
512
  orig_rsrc = @rest_rsrc
513
- @rest_rsrc = "#{RSRC_BY_PATCH_TITLE}#{patch_title_id}"
513
+ @rest_rsrc = "#{RSRC_BY_PATCH_TITLE}#{CGI.escape patch_title_id.to_s}"
514
514
  super
515
515
  @rest_rsrc = orig_rsrc
516
516
  refetch_version_info
@@ -184,7 +184,7 @@ module JSS
184
184
  @name = new_val
185
185
 
186
186
  ### if our REST resource is based on the name, update that too
187
- @rest_rsrc = "#{RSRC_BASE}/name/#{CGI.escape @name}" if @rest_rsrc.include? '/name/'
187
+ @rest_rsrc = "#{RSRC_BASE}/name/#{CGI.escape @name.to_s}" if @rest_rsrc.include? '/name/'
188
188
  @need_to_update = true
189
189
  end # name=
190
190
 
@@ -81,7 +81,7 @@ module JSS
81
81
  raise JSS::AlreadyExistsError, "A #{self.class::RSRC_OBJECT_KEY} named '#{newname}' already exsists in the JSS" \
82
82
  if self.class.all_names(:refresh, api: @api).include? newname
83
83
  @name = newname
84
- @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}" if @rest_rsrc.include? '/name/'
84
+ @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name.to_s}" if @rest_rsrc.include? '/name/'
85
85
  @need_to_update = true
86
86
  end # name=(newname)
87
87
 
@@ -21,11 +21,15 @@
21
21
  # KIND, either express or implied. See the Apache License for the specific
22
22
  # language governing permissions and limitations under the Apache License.
23
23
 
24
-
25
24
  require 'jss/ruby_extensions/string/conversions.rb'
26
25
  require 'jss/ruby_extensions/string/predicates.rb'
27
26
  require 'jss/ruby_extensions/string/backports.rb'
28
27
 
29
- String.include JSSRubyExtensions::String::Predicates
30
- String.include JSSRubyExtensions::String::Conversions
31
- String.include JSSRubyExtensions::String::BackPorts
28
+ # include the modules loaded above
29
+ class String
30
+
31
+ include JSSRubyExtensions::String::Predicates
32
+ include JSSRubyExtensions::String::Conversions
33
+ include JSSRubyExtensions::String::BackPorts
34
+
35
+ end
@@ -27,6 +27,6 @@
27
27
  module JSS
28
28
 
29
29
  ### The version of ruby-jss
30
- VERSION = '1.1.0b5'.freeze
30
+ VERSION = '1.1.3'.freeze
31
31
 
32
32
  end # module
@@ -2,8 +2,8 @@
2
2
 
3
3
  For years, I've attempted to use some ruby testing framework to automate testing of ruby-jss.
4
4
 
5
- Every time I've run into walls because unit testing suites are designed for unit testing, and that's not really what we need to do. Yes we need to test individual methods of classes and so on, but when working with a REST API, there's a lot of
6
- scaffolding that needs to happen before tests can even start - and that scaffolding itself is testing the code. And the details of the scaffolding will vary in different environments.
5
+ Every time I've run into walls because unit testing suites are designed for unit testing, and that's not really what we need to do. Yes we need to test individual methods of classes and so on, but when working with a REST API, there's a lot of
6
+ scaffolding that needs to happen before tests can even start - and that scaffolding itself is testing the code. And the details of the scaffolding will vary in different environments. We need to run integration tests.
7
7
 
8
8
  For example, the tests *must* be very interactive from the start - you have to tell them what server to connect with, what credentials to use, and so on.
9
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-jss
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0b5
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Lasell
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-09-11 00:00:00.000000000 Z
12
+ date: 2019-09-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: plist
@@ -288,9 +288,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
288
288
  version: 2.0.0
289
289
  required_rubygems_version: !ruby/object:Gem::Requirement
290
290
  requirements:
291
- - - ">"
291
+ - - ">="
292
292
  - !ruby/object:Gem::Version
293
- version: 1.3.1
293
+ version: '0'
294
294
  requirements: []
295
295
  rubyforge_project:
296
296
  rubygems_version: 2.7.8