samanage 2.1.19 → 2.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +224 -0
  3. data/Gemfile +12 -7
  4. data/Gemfile.lock +43 -24
  5. data/Guardfile +5 -3
  6. data/changelog.md +92 -19
  7. data/lib/samanage.rb +33 -30
  8. data/lib/samanage/api.rb +67 -74
  9. data/lib/samanage/api/attachments.rb +12 -12
  10. data/lib/samanage/api/category.rb +9 -7
  11. data/lib/samanage/api/changes.rb +17 -16
  12. data/lib/samanage/api/comments.rb +6 -7
  13. data/lib/samanage/api/contracts.rb +17 -17
  14. data/lib/samanage/api/custom_fields.rb +6 -6
  15. data/lib/samanage/api/custom_forms.rb +13 -10
  16. data/lib/samanage/api/departments.rb +9 -9
  17. data/lib/samanage/api/groups.rb +21 -20
  18. data/lib/samanage/api/hardwares.rb +14 -14
  19. data/lib/samanage/api/incidents.rb +7 -8
  20. data/lib/samanage/api/mobiles.rb +14 -15
  21. data/lib/samanage/api/other_assets.rb +14 -14
  22. data/lib/samanage/api/problems.rb +17 -17
  23. data/lib/samanage/api/purchase_orders.rb +17 -17
  24. data/lib/samanage/api/releases.rb +14 -14
  25. data/lib/samanage/api/requester.rb +4 -2
  26. data/lib/samanage/api/sites.rb +10 -9
  27. data/lib/samanage/api/solutions.rb +15 -14
  28. data/lib/samanage/api/tasks.rb +39 -0
  29. data/lib/samanage/api/time_tracks.rb +8 -6
  30. data/lib/samanage/api/users.rb +32 -30
  31. data/lib/samanage/api/utils.rb +11 -9
  32. data/lib/samanage/api/vendors.rb +14 -13
  33. data/lib/samanage/error.rb +5 -4
  34. data/lib/samanage/language.rb +48 -46
  35. data/lib/samanage/url_builder.rb +27 -25
  36. data/lib/samanage/utils.rb +10 -8
  37. data/lib/samanage/version.rb +1 -1
  38. data/samanage.gemspec +11 -9
  39. data/spec/api/samanage_attachment_spec.rb +20 -19
  40. data/spec/api/samanage_category_spec.rb +12 -10
  41. data/spec/api/samanage_change_spec.rb +47 -44
  42. data/spec/api/samanage_comments_spec.rb +12 -10
  43. data/spec/api/samanage_contract_spec.rb +41 -35
  44. data/spec/api/samanage_custom_field_spec.rb +7 -5
  45. data/spec/api/samanage_custom_form_spec.rb +11 -9
  46. data/spec/api/samanage_department_spec.rb +20 -15
  47. data/spec/api/samanage_group_spec.rb +30 -28
  48. data/spec/api/samanage_hardware_spec.rb +44 -38
  49. data/spec/api/samanage_incident_spec.rb +79 -61
  50. data/spec/api/samanage_mobile_spec.rb +39 -34
  51. data/spec/api/samanage_other_asset_spec.rb +50 -44
  52. data/spec/api/samanage_problem_spec.rb +53 -46
  53. data/spec/api/samanage_purchase_order_spec.rb +43 -40
  54. data/spec/api/samanage_release_spec.rb +44 -40
  55. data/spec/api/samanage_site_spec.rb +18 -16
  56. data/spec/api/samanage_solution_spec.rb +16 -14
  57. data/spec/api/samanage_task_spec.rb +68 -0
  58. data/spec/api/samanage_time_tracks_spec.rb +41 -27
  59. data/spec/api/samanage_user_spec.rb +51 -46
  60. data/spec/api/samanage_util_spec.rb +13 -11
  61. data/spec/api/samanage_vendors_spec.rb +18 -16
  62. data/spec/samanage_api_spec.rb +27 -23
  63. data/spec/samanage_category_spec.rb +10 -8
  64. data/spec/samanage_language_spec.rb +12 -10
  65. data/spec/samanage_url_builder_spec.rb +11 -9
  66. data/spec/spec_helper.rb +6 -4
  67. metadata +5 -2
@@ -1,34 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH << File.dirname(__FILE__)
2
- require 'httparty'
4
+ require "httparty"
3
5
 
4
- require 'samanage/api'
5
- require 'samanage/api/attachments'
6
- require 'samanage/api/category'
7
- require 'samanage/api/changes'
8
- require 'samanage/api/comments'
9
- require 'samanage/api/contracts'
10
- require 'samanage/api/custom_fields'
11
- require 'samanage/api/custom_forms'
12
- require 'samanage/api/departments'
13
- require 'samanage/api/groups'
14
- require 'samanage/api/hardwares'
15
- require 'samanage/api/incidents'
16
- require 'samanage/api/mobiles'
17
- require 'samanage/api/other_assets'
18
- require 'samanage/api/problems'
19
- require 'samanage/api/purchase_orders'
20
- require 'samanage/api/requester'
21
- require 'samanage/api/releases'
22
- require 'samanage/api/sites'
23
- require 'samanage/api/solutions'
24
- require 'samanage/api/time_tracks'
25
- require 'samanage/api/users'
26
- require 'samanage/api/utils'
27
- require 'samanage/api/vendors'
28
- require 'samanage/error'
29
- require 'samanage/language'
30
- require 'samanage/url_builder'
31
- require 'samanage/version'
6
+ require "samanage/api"
7
+ require "samanage/api/attachments"
8
+ require "samanage/api/category"
9
+ require "samanage/api/changes"
10
+ require "samanage/api/comments"
11
+ require "samanage/api/contracts"
12
+ require "samanage/api/custom_fields"
13
+ require "samanage/api/custom_forms"
14
+ require "samanage/api/departments"
15
+ require "samanage/api/groups"
16
+ require "samanage/api/hardwares"
17
+ require "samanage/api/incidents"
18
+ require "samanage/api/mobiles"
19
+ require "samanage/api/other_assets"
20
+ require "samanage/api/problems"
21
+ require "samanage/api/purchase_orders"
22
+ require "samanage/api/requester"
23
+ require "samanage/api/releases"
24
+ require "samanage/api/sites"
25
+ require "samanage/api/tasks"
26
+ require "samanage/api/solutions"
27
+ require "samanage/api/time_tracks"
28
+ require "samanage/api/users"
29
+ require "samanage/api/utils"
30
+ require "samanage/api/vendors"
31
+ require "samanage/error"
32
+ require "samanage/language"
33
+ require "samanage/url_builder"
34
+ require "samanage/version"
32
35
 
33
36
  module Samanage
34
37
  end
@@ -41,4 +44,4 @@ class Hash
41
44
  def except(*keys)
42
45
  dup.except!(*keys)
43
46
  end
44
- end
47
+ end
@@ -1,104 +1,101 @@
1
- require 'httparty'
2
- require 'open-uri'
1
+ # frozen_string_literal: true
2
+
3
+ require "httparty"
4
+ require "open-uri"
3
5
  module Samanage
4
6
  class Api
5
7
  include HTTParty
6
- attr_accessor :datacenter, :content_type, :base_url, :token, :custom_forms, :authorized, :admins, :max_retries, :sleep_time
8
+ attr_accessor :datacenter, :content_type, :base_url, :token, :custom_forms,
9
+ :authorized, :admins, :max_retries, :sleep_time
7
10
  PATHS = {
8
- attachment: 'attachments.json',
9
- category: 'categories.json',
10
- change: 'changes.json',
11
- contract: 'contracts.json',
12
- custom_fields: 'custom_fields.json',
13
- custom_forms: 'custom_forms.json',
14
- department: 'departments.json',
15
- group: 'groups.json',
16
- hardware: 'hardwares.json',
17
- incident: 'incidents.json',
18
- mobile: 'mobiles.json',
19
- other_asset: 'other_assets.json',
20
- problem: 'problems.json',
21
- purchase_order: 'purchase_orders.json',
22
- release: 'releases.json',
23
- site: 'sites.json',
24
- solution: 'solutions.json',
25
- user: 'users.json',
26
- vendor: 'vendors.json',
27
- }
11
+ attachment: "attachments.json",
12
+ category: "categories.json",
13
+ change: "changes.json",
14
+ contract: "contracts.json",
15
+ custom_fields: "custom_fields.json",
16
+ custom_forms: "custom_forms.json",
17
+ department: "departments.json",
18
+ group: "groups.json",
19
+ hardware: "hardwares.json",
20
+ incident: "incidents.json",
21
+ mobile: "mobiles.json",
22
+ other_asset: "other_assets.json",
23
+ problem: "problems.json",
24
+ purchase_order: "purchase_orders.json",
25
+ release: "releases.json",
26
+ site: "sites.json",
27
+ task: "tasks.json",
28
+ solution: "solutions.json",
29
+ user: "users.json",
30
+ vendor: "vendors.json"
31
+ }.freeze
28
32
  # Development mode forces authorization & pre-populates admins and custom forms / fields
29
33
  # datacenter should equal 'eu' or blank
30
- def initialize(token: , datacenter: nil, development_mode: false, max_retries: 3, content_type: 'json', sleep_time: 5)
34
+ def initialize(token:, datacenter: nil, development_mode: false,
35
+ max_retries: 3, content_type: "json", sleep_time: 5)
31
36
  self.token = token
32
- if !datacenter.nil? && datacenter.to_s.downcase != 'eu'
33
- datacenter = nil
34
- end
37
+ datacenter = nil if !datacenter.nil? && datacenter.to_s.downcase != "eu"
35
38
  self.datacenter ||= datacenter.to_s.downcase
36
- self.base_url = "https://api#{self.datacenter.to_s.downcase}.samanage.com/"
37
- self.content_type = content_type || 'json'
39
+ self.base_url = "https://api#{self.datacenter.to_s.downcase}.samanage.com/"
40
+ self.content_type = content_type || "json"
38
41
  self.admins = []
39
42
  self.max_retries = max_retries
40
43
  self.sleep_time = sleep_time
41
44
  if development_mode
42
- if self.authorized? != true
43
- self.authorize
44
- end
45
- self.custom_forms = self.organize_forms
46
- self.admins = self.list_admins
45
+ authorize if authorized? != true
46
+ self.custom_forms = organize_forms
47
+ self.admins = list_admins
47
48
  end
48
49
  end
49
50
 
50
51
  def authorized?
51
- self.authorized
52
+ authorized
52
53
  end
53
54
 
54
- # Check "oken against api.json"
55
+ # Check "oken against api.json"
55
56
  def authorize
56
- self.execute(path: "api.#{self.content_type}")
57
+ execute(path: "api.#{content_type}")
57
58
  self.authorized = true
58
59
  end
59
60
 
60
61
  # Calling execute without a method defaults to GET
61
- def execute(http_method: 'get', path: nil, payload: nil, verbose: nil, headers: {}, options: {}, multipart: false)
62
- if payload.class == Hash && self.content_type == 'json'
62
+ def execute(http_method: "get", path: nil, payload: nil, verbose: nil, headers: {}, options: {}, multipart: false)
63
+ if payload.class == Hash && content_type == "json"
63
64
  begin
64
- if path != 'attachments.json'
65
- payload = payload.to_json
66
- end
67
- rescue => e
65
+ payload = payload.to_json if path != "attachments.json"
66
+ rescue StandardError => e
68
67
  puts "Invalid JSON: #{payload.inspect}"
69
68
  raise Samanage::Error.new(error: e, response: nil, options: options)
70
69
  end
71
70
  end
72
- token = token ||= self.token
73
- unless verbose.nil?
74
- verbose = '?layout=long'
75
- end
71
+ verbose = "?layout=long" unless verbose.nil?
76
72
 
77
73
  headers = {
78
- 'Accept' => "application/vnd.samanage.v2.1+#{self.content_type}#{verbose}",
79
- 'Content-Type' => "application/#{self.content_type}",
80
- 'X-Samanage-Authorization' => 'Bearer ' + self.token
74
+ "Accept" => "application/vnd.samanage.v2.1+#{content_type}#{verbose}",
75
+ "Content-Type" => "application/#{content_type}",
76
+ "X-Samanage-Authorization" => "Bearer " + self.token
81
77
  }.merge(headers)
82
78
  options = options.except(:verbose)
83
- full_path = self.base_url + path
79
+ full_path = base_url + path
84
80
  retries = 0
85
81
  begin
86
82
  case http_method.to_s.downcase
87
- when 'get'
83
+ when "get"
88
84
  api_call = self.class.get(full_path, headers: headers, query: options)
89
- when 'post'
85
+ when "post"
90
86
  api_call = self.class.post(full_path, multipart: multipart, body: payload, headers: headers, query: options)
91
- when 'put'
87
+ when "put"
92
88
  api_call = self.class.put(full_path, body: payload, headers: headers, query: options)
93
- when 'delete'
89
+ when "delete"
94
90
  api_call = self.class.delete(full_path, body: payload, headers: headers, query: options)
95
91
  else
96
- raise Samanage::Error.new(response: {response: 'Unknown HTTP method'}, options: options)
92
+ raise Samanage::Error.new(response: { response: "Unknown HTTP method" }, options: options)
97
93
  end
98
- rescue Errno::ECONNREFUSED, Net::OpenTimeout, Errno::ETIMEDOUT, Net::ReadTimeout, OpenSSL::SSL::SSLError, Errno::ENETDOWN, Errno::ECONNRESET, Errno::ENOENT, EOFError, Net::HTTPTooManyRequests, SocketError => e
94
+ rescue Errno::ECONNREFUSED, Net::OpenTimeout, Errno::ETIMEDOUT, Net::ReadTimeout, OpenSSL::SSL::SSLError,
95
+ Errno::ENETDOWN, Errno::ECONNRESET, Errno::ENOENT, EOFError, Net::HTTPTooManyRequests, SocketError => e
99
96
  retries += 1
100
- if retries < self.max_retries
101
- puts "[Warning] #{e.class}: #{e} - Retry: #{retries}/#{self.max_retries}"
97
+ if retries < max_retries
98
+ puts "[Warning] #{e.class}: #{e} - Retry: #{retries}/#{max_retries}"
102
99
  sleep sleep_time
103
100
  retry
104
101
  else
@@ -106,10 +103,10 @@ module Samanage
106
103
  response = e.class
107
104
  raise Samanage::InvalidRequest.new(error: error, response: response, options: options)
108
105
  end
109
- rescue => e
106
+ rescue StandardError => e
110
107
  retries += 1
111
- if retries < self.max_retries
112
- puts "[Warning] #{e.class}: #{e} - Retry: #{retries}/#{self.max_retries}"
108
+ if retries < max_retries
109
+ puts "[Warning] #{e.class}: #{e} - Retry: #{retries}/#{max_retries}"
113
110
  sleep sleep_time
114
111
  retry
115
112
  else
@@ -119,14 +116,14 @@ module Samanage
119
116
  end
120
117
  end
121
118
 
122
- response = Hash.new
119
+ response = {}
123
120
  response[:code] = api_call.code.to_i
124
121
  response[:json] = api_call.body
125
122
  response[:response] = api_call
126
123
  response[:headers] = api_call.headers
127
- response[:total_pages] = api_call.headers['X-Total-Pages'].to_i
124
+ response[:total_pages] = api_call.headers["X-Total-Pages"].to_i
128
125
  response[:total_pages] = 1 if response[:total_pages] == 0
129
- response[:total_count] = api_call.headers['X-Total-Count'].to_i
126
+ response[:total_count] = api_call.headers["X-Total-Count"].to_i
130
127
 
131
128
  # Error cases
132
129
  case response[:code]
@@ -135,16 +132,14 @@ module Samanage
135
132
  response[:data] = JSON.parse(api_call.body)
136
133
  rescue JSON::ParserError => e
137
134
  response[:data] = api_call.body
138
- if !path.match('send_activation_email')
139
- puts "[Warning] #{e.class}: #{e}"
140
- end
135
+ puts "[Warning] #{e.class}: #{e}" unless path.match?("send_activation_email")
141
136
  end
142
137
  response
143
138
  when 401
144
139
  response[:data] = api_call.body
145
140
  error = response[:response]
146
141
  self.authorized = false
147
- raise Samanage::AuthorizationError.new(error: error,response: response, options: options)
142
+ raise Samanage::AuthorizationError.new(error: error, response: response, options: options)
148
143
  when 404
149
144
  response[:data] = api_call.body
150
145
  error = response[:response]
@@ -160,18 +155,16 @@ module Samanage
160
155
  end
161
156
  end
162
157
 
163
-
164
158
  def set_params(options:)
165
159
  options[:audit_archive] = options[:audit_archive] || options[:audit_archives] if options[:audit_archives]
166
160
  URI.encode_www_form(options.except(:verbose))
167
161
  end
168
162
 
169
-
170
163
  # Return all admins in the account
171
164
  def list_admins
172
- admin_role_id = self.execute(path: "roles.json")[:data].select{|role| role['name'] == 'Administrator'}.first['id']
173
- self.admins.push(
174
- self.execute(path: "users.json?role=#{admin_role_id}")[:data].map{|u| u['email']}
165
+ admin_role_id = execute(path: "roles.json")[:data].select { |role| role["name"] == "Administrator" }.first["id"]
166
+ admins.push(
167
+ execute(path: "users.json?role=#{admin_role_id}")[:data].map { |u| u["email"] }
175
168
  ).flatten
176
169
  end
177
170
  end
@@ -3,16 +3,16 @@
3
3
  module Samanage
4
4
  class Api
5
5
  def download_attachment(attachment: {}, filename: nil, path: nil)
6
- attachable_type = attachment['attachable_type']
7
- attachable_id = attachment['attachable_id'].to_s
8
- filename ||= attachment['filename']
9
- url = attachment['url']
6
+ attachable_type = attachment["attachable_type"]
7
+ attachable_id = attachment["attachable_id"].to_s
8
+ filename ||= attachment["filename"]
9
+ url = attachment["url"]
10
10
 
11
11
  file_path = path || File.join(Dir.pwd, attachable_type, attachable_id)
12
12
  FileUtils.mkpath(file_path) unless File.directory?(file_path)
13
13
 
14
14
  exact_path = File.join(file_path, filename)
15
- downloaded_attachment = File.open(exact_path, 'wb+') do |file|
15
+ downloaded_attachment = File.open(exact_path, "wb+") do |file|
16
16
  file << URI.parse(url).read
17
17
  end
18
18
  downloaded_attachment
@@ -24,17 +24,17 @@ module Samanage
24
24
  return
25
25
  end
26
26
  req = execute(
27
- path: 'attachments.json',
28
- http_method: 'post',
27
+ path: "attachments.json",
28
+ http_method: "post",
29
29
  multipart: true,
30
30
  payload: {
31
- 'file[attachable_type]' => attachable_type,
32
- 'file[attachable_id]' => attachable_id,
33
- 'file[attachment]' => File.open(filepath, 'rb')
31
+ "file[attachable_type]" => attachable_type,
32
+ "file[attachable_id]" => attachable_id,
33
+ "file[attachment]" => File.open(filepath, "rb")
34
34
  },
35
35
  headers: {
36
- 'Content-Type' => 'multipart/form-data',
37
- 'X-Samanage-Authorization' => 'Bearer ' + token
36
+ "Content-Type" => "multipart/form-data",
37
+ "X-Samanage-Authorization" => "Bearer " + token
38
38
  }
39
39
  )
40
40
  req
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Samanage
2
4
  class Api
3
5
  def get_categories(path: PATHS[:category], options: {})
4
- path = 'categories.json'
6
+ path = "categories.json"
5
7
  self.execute(path: path, options: options)
6
8
  end
7
9
 
@@ -9,18 +11,18 @@ module Samanage
9
11
  # Samanage categories are not paginated
10
12
  # - to break into subcategories, add
11
13
  def collect_categories(options: {})
12
- request = self.execute(http_method: 'get', path: "categories.json", options: options)
14
+ request = self.execute(http_method: "get", path: "categories.json", options: options)
13
15
  request[:data]
14
16
  end
15
17
 
16
18
  def create_category(payload: nil, options: {})
17
- self.execute(path: PATHS[:category], http_method: 'post', payload: payload, options: options)
19
+ self.execute(path: PATHS[:category], http_method: "post", payload: payload, options: options)
18
20
  end
19
21
 
20
- def delete_category(id: )
21
- self.execute(path: "categories/#{id}", http_method: 'delete', options: options)
22
+ def delete_category(id:)
23
+ self.execute(path: "categories/#{id}", http_method: "delete", options: options)
22
24
  end
23
25
 
24
- alias_method :categories, :collect_categories
26
+ alias_method :categories, :collect_categories
25
27
  end
26
- end
28
+ end
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Samanage
2
4
  class Api
3
-
4
5
  # Default get change path
5
6
  def get_changes(path: PATHS[:change], options: {})
6
- path = 'changes.json?'
7
+ path = "changes.json?"
7
8
  self.execute(path: path, options: options)
8
9
  end
9
10
 
10
11
 
11
- # Returns all changes.
12
- # Options:
12
+ # Returns all changes.
13
+ # Options:
13
14
  # - audit_archives: true
14
15
  # - layout: 'long'
15
16
  def collect_changes(options: {})
@@ -17,10 +18,10 @@ module Samanage
17
18
  total_pages = self.get_changes(options: options)[:total_pages]
18
19
  1.upto(total_pages) do |page|
19
20
  options[:page] = page
20
-
21
+
21
22
  puts "Collecting Changes page: #{page}/#{total_pages}" if options[:verbose]
22
23
  path = "changes.json?"
23
- request = self.execute(http_method: 'get', path: path, options: options)
24
+ request = self.execute(http_method: "get", path: path, options: options)
24
25
  request[:data].each do |change|
25
26
  if block_given?
26
27
  yield change
@@ -34,29 +35,29 @@ module Samanage
34
35
 
35
36
  # Create an change given json
36
37
  def create_change(payload: nil, options: {})
37
- self.execute(path: PATHS[:change], http_method: 'post', payload: payload)
38
+ self.execute(path: PATHS[:change], http_method: "post", payload: payload)
38
39
  end
39
40
 
40
41
  # Find change by ID
41
- def find_change(id: , options: {})
42
+ def find_change(id:, options: {})
42
43
  path = "changes/#{id}.json"
43
- if options[:layout] == 'long'
44
- path += '?layout=long'
44
+ if options[:layout] == "long"
45
+ path += "?layout=long"
45
46
  end
46
47
  self.execute(path: path)
47
48
  end
48
49
 
49
50
  # Update an change given id and json
50
- def update_change(payload: , id: , options: {})
51
+ def update_change(payload:, id:, options: {})
51
52
  path = "changes/#{id}.json"
52
- self.execute(path: path, http_method: 'put', payload: payload)
53
+ self.execute(path: path, http_method: "put", payload: payload)
53
54
  end
54
55
 
55
- def delete_change(id: )
56
- self.execute(path: "changes/#{id}.json", http_method: 'delete')
56
+ def delete_change(id:)
57
+ self.execute(path: "changes/#{id}.json", http_method: "delete")
57
58
  end
58
59
 
59
60
 
60
- alias_method :changes, :collect_changes
61
+ alias_method :changes, :collect_changes
61
62
  end
62
- end
63
+ end