ecoportal-api 0.9.8 → 0.10.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.
@@ -1,11 +1,12 @@
1
+ # rubocop:disable Naming/PredicateName
1
2
  module Ecoportal
2
3
  module API
3
4
  module Common
4
5
  class BaseModel
5
- class UnlinkedModel < Exception
6
- def initialize (msg = "Something went wrong when linking the document.", from: nil, key: nil)
7
- msg += " From: #{from}." if from
8
- msg += " key: #{key}." if key
6
+ class UnlinkedModel < StandardError
7
+ def initialize(msg = "Something went wrong when linking the document.", from: nil, key: nil)
8
+ msg << " From: #{from}." if from
9
+ msg << " key: #{key}." if key
9
10
  super(msg)
10
11
  end
11
12
  end
@@ -25,10 +26,11 @@ module Ecoportal
25
26
  end
26
27
  end
27
28
 
28
- def embeds_one(method, key: method, nullable: false, klass:)
29
+ def embeds_one(method, klass:, key: method, nullable: false)
29
30
  method = method.to_s.freeze
30
31
  var = "@#{method}".freeze
31
32
  key = key.to_s.freeze
33
+
32
34
  define_method(method) do
33
35
  if instance_variable_defined?(var)
34
36
  value = instance_variable_get(var)
@@ -36,7 +38,9 @@ module Ecoportal
36
38
  return value if (value && doc[key]) || (!value && !doc[key])
37
39
  remove_instance_variable(var)
38
40
  end
41
+
39
42
  doc[key] ||= {} unless nullable
43
+
40
44
  return instance_variable_set(var, nil) unless doc[key]
41
45
 
42
46
  self.class.resolve_class(klass).new(
@@ -44,7 +48,6 @@ module Ecoportal
44
48
  ).tap {|obj| instance_variable_set(var, obj)}
45
49
  end
46
50
  end
47
-
48
51
  end
49
52
 
50
53
  attr_reader :_parent, :_key
@@ -52,28 +55,32 @@ module Ecoportal
52
55
  def initialize(doc = {}, parent: self, key: nil)
53
56
  @_parent = parent
54
57
  @_key = key
55
- if !_parent || !_key
56
- @doc = JSON.parse(doc.to_json)
57
- @original_doc = JSON.parse(@doc.to_json)
58
- @initial_doc = JSON.parse(@doc.to_json)
59
- end
58
+
59
+ return unless !_parent || !_key
60
+
61
+ @doc = JSON.parse(doc.to_json)
62
+ @original_doc = JSON.parse(@doc.to_json)
63
+ @initial_doc = JSON.parse(@doc.to_json)
60
64
  end
61
65
 
62
66
  def doc
63
- raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
67
+ raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
64
68
  return @doc if is_root?
69
+
65
70
  _parent.doc.dig(*[_key].flatten)
66
71
  end
67
72
 
68
73
  def original_doc
69
- raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
74
+ raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
70
75
  return @original_doc if is_root?
76
+
71
77
  _parent.original_doc&.dig(*[_key].flatten)
72
78
  end
73
79
 
74
80
  def initial_doc
75
- raise UnlinkedModel.new(from: "#{self.class}#initial_doc", key: _key) unless linked?
81
+ raise UnlinkedModel.new(from: "#{self.class}#initial_doc", key: _key) unless linked?
76
82
  return @initial_doc if is_root?
83
+
77
84
  _parent.initial_doc&.dig(*[_key].flatten)
78
85
  end
79
86
 
@@ -81,6 +88,7 @@ module Ecoportal
81
88
  # @return [Hash] `doc` before change
82
89
  def replace_doc!(new_doc)
83
90
  raise UnlinkedModel.new(from: "#{self.class}#replace_doc", key: _key) unless linked?
91
+
84
92
  @doc.tap do
85
93
  @doc = new_doc
86
94
  end
@@ -90,6 +98,7 @@ module Ecoportal
90
98
  # @return [Hash] `original_doc` before change
91
99
  def replace_original_doc!(new_doc)
92
100
  raise UnlinkedModel.new(from: "#{self.class}#replace_original_doc", key: _key) unless linked?
101
+
93
102
  @original_doc.tap do
94
103
  @original_doc = new_doc
95
104
  end
@@ -115,7 +124,8 @@ module Ecoportal
115
124
 
116
125
  # It consolidates all the changes carried by `doc` by setting it as `original_doc`.
117
126
  def consolidate!
118
- raise UnlinkedModel.new(from: "#{self.class}#consolidate!", key: _key) unless linked?
127
+ raise UnlinkedModel.new(from: "#{self.class}#consolidate!", key: _key) unless linked?
128
+
119
129
  new_doc = JSON.parse(doc.to_json)
120
130
  if is_root?
121
131
  @original_doc = new_doc
@@ -130,18 +140,19 @@ module Ecoportal
130
140
  # i.e. `parent.reset!("child")` # when parent.child is `nil`
131
141
  # 2. In such a case, only immediate childs are allowed to be reset
132
142
  # @param key [String, Array<String>, nil] if given, it only resets the specified property
133
- def reset!(key = nil)
134
- raise "'key' should be a String. Given #{key}" unless !key || key.is_a?(String)
135
- raise UnlinkedModel.new(from: "#{self.class}#reset!", key: _key) unless linked?
143
+ def reset!(key = nil) # rubocop:disable Metrics/AbcSize>
144
+ msg = "'key' should be a String. Given #{key}"
145
+ raise ArgumentError, msg unless !key || key.is_a?(String)
146
+ raise UnlinkedModel.new(from: "#{self.class}#reset!", key: _key) unless linked?
136
147
 
137
148
  if key
138
- if self.respond_to?(key) && child = self.send(key) && child.is_a?(Ecoportal::API::Common::BaseModel)
149
+ if respond_to?(key) && (child = send(key)) && child.is_a?(Ecoportal::API::Common::BaseModel)
139
150
  child.reset!
140
151
  else
141
152
  new_doc = original_doc && original_doc[key]
142
153
  dig_set(doc, [key], new_doc && JSON.parse(new_doc.to_json))
143
154
  # regenerate object if new_doc is null
144
- self.send(key) if !new_doc && self.respond_to?(key)
155
+ send(key) if !new_doc && respond_to?(key)
145
156
  end
146
157
  else
147
158
  new_doc = JSON.parse(original_doc.to_json)
@@ -179,17 +190,17 @@ module Ecoportal
179
190
  end
180
191
 
181
192
  def set_uniq_array_keep_order(key, value)
182
- unless value.is_a?(Array)
183
- raise "#{key}= needs to be passed an Array, got #{value.class}"
184
- end
185
- ini_vals = (original_doc && original_doc[key]) || []
193
+ msg = "#{key}= needs to be passed an Array, got #{value.class}"
194
+ raise ArgumentError, msg unless value.is_a?(Array)
186
195
 
196
+ ini_vals = (original_doc && original_doc[key]) || []
187
197
  value = value.uniq
188
198
  # preserve original order to avoid false updates
189
199
  doc[key] = ((ini_vals & value) + (value - ini_vals)).compact
190
200
  end
191
-
192
201
  end
193
202
  end
194
203
  end
195
204
  end
205
+
206
+ # rubocop:enable Naming/PredicateName
@@ -28,19 +28,21 @@ module Ecoportal
28
28
  log(:info) { "Processing batch responses" }
29
29
 
30
30
  body_data(response.body).each.with_index do |subresponse, idx|
31
- callback = @operations[idx][:callback]
32
31
  status = subresponse["status"]
33
- body = subresponse["response"]
34
32
  method = @operations[idx][:method]
33
+ body = subresponse["response"]
34
+ callback = @operations[idx][:callback]
35
35
 
36
36
  if status == 200 && method == "GET"
37
37
  batch_response = BatchResponse.new(status, body, @wrapper.new(body))
38
38
  log_batch_response(@operations[idx], batch_response)
39
- callback && callback.call(batch_response, batch_response.result)
39
+
40
+ callback&.call(batch_response, batch_response.result)
40
41
  else
41
42
  batch_response = BatchResponse.new(status, body)
42
43
  log_batch_response(@operations[idx], batch_response)
43
- callback && callback.call(batch_response)
44
+
45
+ callback&.call(batch_response)
44
46
  end
45
47
  end
46
48
  end
@@ -48,9 +50,9 @@ module Ecoportal
48
50
  def get(doc, &block)
49
51
  id = get_id(doc)
50
52
  @operations << {
51
- path: @base_path + "/" + CGI::escape(id),
53
+ path: "#{@base_path}/#{CGI.escape(id)}",
52
54
  method: "GET",
53
- callback: block_given? && block
55
+ callback: block
54
56
  }
55
57
  end
56
58
 
@@ -58,10 +60,10 @@ module Ecoportal
58
60
  id = get_id(doc)
59
61
  body = get_body(doc)
60
62
  @operations << {
61
- path: @base_path + "/" + CGI::escape(id),
63
+ path: "#{@base_path}/#{CGI.escape(id)}",
62
64
  method: "PATCH",
63
65
  body: body,
64
- callback: block_given? && block
66
+ callback: block
65
67
  }
66
68
  end
67
69
 
@@ -69,19 +71,19 @@ module Ecoportal
69
71
  id = get_id(doc)
70
72
  body = get_body(doc)
71
73
  @operations << {
72
- path: @base_path + "/" + CGI::escape(id),
74
+ path: "#{@base_path}/#{CGI.escape(id)}",
73
75
  method: "POST",
74
76
  body: body,
75
- callback: block_given? && block
77
+ callback: block
76
78
  }
77
79
  end
78
80
 
79
81
  def delete(doc, &block)
80
82
  id = get_id(doc)
81
83
  @operations << {
82
- path: @base_path + "/" + CGI::escape(id),
84
+ path: "#{@base_path}/#{CGI.escape(id)}",
83
85
  method: "DELETE",
84
- callback: block_given? && block
86
+ callback: block
85
87
  }
86
88
  end
87
89
 
@@ -91,7 +93,7 @@ module Ecoportal
91
93
  path: @base_path,
92
94
  method: "POST",
93
95
  body: body,
94
- callback: block_given? && block
96
+ callback: block
95
97
  }
96
98
  end
97
99
 
@@ -104,14 +106,15 @@ module Ecoportal
104
106
  end
105
107
 
106
108
  def log_batch_response(operation, response)
107
- level = response.success?? :debug : :warn
108
109
  log(:info) { "BATCH #{operation[:method]} #{operation[:path]}" }
109
110
  log(:info) { "Status #{response.status}" }
111
+
112
+ level = response.success?? :debug : :warn
110
113
  log(level) { "Response: #{JSON.pretty_generate(response.body)}" }
111
114
  end
112
115
 
113
116
  def log(level, &block)
114
- @logger.send(level, &block) if @logger
117
+ @logger&.send(level, &block)
115
118
  end
116
119
  end
117
120
  end
@@ -2,7 +2,6 @@ module Ecoportal
2
2
  module API
3
3
  module Common
4
4
  class BatchResponse
5
-
6
5
  attr_reader :status, :body, :result
7
6
 
8
7
  def initialize(status, body, result = nil)
@@ -15,10 +14,8 @@ module Ecoportal
15
14
  status.success?
16
15
  end
17
16
 
18
- def each
19
- [*@result].each do |doc|
20
- yield doc
21
- end
17
+ def each(&block)
18
+ [*@result].each(&block)
22
19
  end
23
20
 
24
21
  def print_pretty
@@ -3,11 +3,16 @@ module Ecoportal
3
3
  module API
4
4
  module Common
5
5
  # @note
6
- # - You can see the documentation of the `HTTP` module in [the repository](https://github.com/httprb/http)
7
- # - it does `extend` the module `Chainable` ([chainable.rb](https://github.com/httprb/http/blob/master/lib/http/chainable.rb)),
8
- # - where all the http requests are dev by using `HTTP::Client#request` ([client.rb](https://github.com/httprb/http/blob/master/lib/http/client.rb))
9
- # - which calls `build_request` (new `HTTP::Request`) and `perform` (new `HTTP::Connection`)
10
- # - to return `HTTP::Response` ([response.rb](https://github.com/httprb/http/blob/master/lib/http/response.rb))
6
+ # - You can see the documentation of the `HTTP` module in
7
+ # [the repository](https://github.com/httprb/http)
8
+ # - it does `extend` the module `Chainable`
9
+ # ([chainable.rb](https://github.com/httprb/http/blob/master/lib/http/chainable.rb)),
10
+ # - where all the http requests are dev by using `HTTP::Client#request`
11
+ # ([client.rb](https://github.com/httprb/http/blob/master/lib/http/client.rb))
12
+ # - which calls `build_request` (new `HTTP::Request`) and `perform`
13
+ # (new `HTTP::Connection`)
14
+ # - to return `HTTP::Response`
15
+ # ([response.rb](https://github.com/httprb/http/blob/master/lib/http/response.rb))
11
16
  # @attr_reader logger [Logger] the logger.
12
17
  # @attr_reader host [String] the remote target server.
13
18
  class Client
@@ -31,15 +36,17 @@ module Ecoportal
31
36
  @logger = logger
32
37
  @host = host
33
38
  @response_logging_enabled = response_logging
39
+
34
40
  if host.match(/^localhost|^127\.0\.0\.1/)
35
41
  @base_uri = "http://#{host}/api/"
36
42
  else
37
43
  @base_uri = "https://#{host}/api/"
38
44
  end
39
45
  log(:info) { "#{version} client initialized pointing at #{host}" }
40
- if @api_key.nil? || @api_key.match(/\A\W*\z/)
41
- log(:error) { "Api-key missing!" }
42
- end
46
+
47
+ return unless @api_key.nil? || @api_key.match(/\A\W*\z/)
48
+
49
+ log(:error) { "Api-key missing!" }
43
50
  end
44
51
 
45
52
  # Logger interface.
@@ -52,7 +59,7 @@ module Ecoportal
52
59
  # @yield [] generates the message.
53
60
  # @yieldreturn [String] the generated message.
54
61
  def log(level, &block)
55
- logger.send(level, &block) if logger
62
+ logger&.send(level, &block)
56
63
  end
57
64
 
58
65
  # Sends an http `GET` request against the api version using `path` to complete the base url,
@@ -127,18 +134,18 @@ module Ecoportal
127
134
  Ecoportal::API::Common::Response.new(response)
128
135
  end
129
136
 
130
- # Creates a HTTP object adding the `X-ApiKey` or `X-ECOPORTAL-API-KEY` param to the header, depending on the API version.
137
+ # Creates a HTTP object adding the `X-ApiKey` or `X-ECOPORTAL-API-KEY` param
138
+ # to the header, depending on the API version.
131
139
  # @note It configures HTTP so it only allows body data in json format.
132
140
  # @return [HTTP] HTTP object.
133
141
  def base_request
134
- @base_request ||= begin
142
+ @base_request ||=
135
143
  case @version
136
144
  when "v2"
137
145
  HTTP.headers("X-ECOPORTAL-API-KEY" => @api_key).accept(:json)
138
146
  else
139
147
  HTTP.headers("X-ApiKey" => @api_key).accept(:json)
140
148
  end
141
- end
142
149
  end
143
150
 
144
151
  # Full URl builder of the request
@@ -151,19 +158,23 @@ module Ecoportal
151
158
  private
152
159
 
153
160
  def instrument(method, path, data = nil, &block)
154
- raise "Expected block" unless block
161
+ raise "Expected block" unless block_given?
162
+
155
163
  start_time = Time.now.to_f
156
164
  log(:info) { "#{method} #{url_for(path)}" }
157
165
  log(:debug) { "Data: #{JSON.pretty_generate(data)}" }
158
166
 
159
167
  with_retry(&block).tap do |result|
160
168
  end_time = Time.now.to_f
161
- log(result.success?? :info : :warn) do
162
- "Took %.2fs, Status #{result.status}" % (end_time - start_time)
163
- end
164
- log(result.success?? :debug : :warn) do
169
+ log(result.success?? :info : :warn) {
170
+ "Took %.2fs, Status #{result.status}" % (end_time - start_time) # rubocop:disable Style/FormatString
171
+ }
172
+
173
+ next unless @response_logging_enabled
174
+
175
+ log(result.success?? :debug : :warn) {
165
176
  "Response: #{JSON.pretty_generate(result.body)}"
166
- end if @response_logging_enabled
177
+ }
167
178
  end
168
179
  end
169
180
 
@@ -190,9 +201,11 @@ module Ecoportal
190
201
  puts "re-attempting (remaining: #{remaining} attempts out of #{attempts})"
191
202
 
192
203
  log_unexpected_server_error(response)
204
+
193
205
  msg = "Got server error (#{response.status}): #{response.body}\n"
194
206
  msg += "Going to retry (#{i} out of #{attempts})"
195
207
  log(:error) { msg }
208
+
196
209
  sleep(delay) if i < attempts
197
210
  end
198
211
  response
@@ -13,7 +13,7 @@ module Ecoportal
13
13
  end
14
14
  end.join.to_s
15
15
 
16
- @body = JSON.parse(@src_body) rescue nil
16
+ @body = JSON.parse(@src_body) rescue nil # rubocop:disable Style/RescueModifier
17
17
  end
18
18
 
19
19
  def success?
@@ -10,26 +10,24 @@ module Ecoportal
10
10
  @response = response
11
11
  @klass = klass
12
12
 
13
- if @response.success?
14
- @result =
15
- if @response.body.is_a?(Array)
16
- @response.body.map do |doc|
17
- @klass.new(doc)
18
- end
19
- else
20
- @klass.new(@response.body)
13
+ return unless @response.success?
14
+
15
+ @result =
16
+ if @response.body.is_a?(Array)
17
+ @response.body.map do |doc|
18
+ @klass.new(doc)
21
19
  end
22
- end
20
+ else
21
+ @klass.new(@response.body)
22
+ end
23
23
  end
24
24
 
25
25
  def body
26
26
  response.body.to_s
27
27
  end
28
28
 
29
- def each
30
- [*result].each do |doc|
31
- yield doc
32
- end
29
+ def each(&block)
30
+ [*result].each(&block)
33
31
  end
34
32
 
35
33
  def status
@@ -41,13 +39,10 @@ module Ecoportal
41
39
  end
42
40
 
43
41
  def print_pretty
44
- if success?
45
- each(&:print_pretty)
46
- else
47
- puts "Request failed."
48
- end
49
- end
42
+ return each(&:print_pretty) if success?
50
43
 
44
+ "Request failed."
45
+ end
51
46
  end
52
47
  end
53
48
  end
@@ -2,13 +2,14 @@ module Ecoportal
2
2
  module API
3
3
  class Internal
4
4
  class Account < Common::BaseModel
5
- PROPERTIES = [
6
- "user_id", "policy_group_ids", "default_tag", "prefilter",
7
- "permissions_custom", "permissions_merged", "preferences",
8
- "login_provider_ids", "starred_ids", "landing_page_id",
9
- "accept_eula", "send_invites", "force_send_invites"
10
- ]
11
- passthrough *PROPERTIES.map(&:to_sym)
5
+ PROPERTIES = %w[
6
+ user_id policy_group_ids default_tag prefilter
7
+ permissions_custom permissions_merged preferences
8
+ login_provider_ids starred_ids landing_page_id
9
+ accept_eula send_invites force_send_invites
10
+ ].freeze
11
+
12
+ passthrough(*PROPERTIES.map(&:to_sym))
12
13
 
13
14
  class_resolver :preferences_class, "Ecoportal::API::Internal::Preferences"
14
15
  class_resolver :permissions_class, "Ecoportal::API::Internal::Permissions"
@@ -23,11 +24,11 @@ module Ecoportal
23
24
  # @return [String, nil] the value set in `default_tag`
24
25
  def default_tag=(value)
25
26
  unless !value || value.is_a?(String)
26
- raise ArgumentError.new("default_tag= needs to be passed a String or nil, got #{value.class}")
27
+ raise ArgumentError, "default_tag= needs to be passed a String or nil, got #{value.class}"
27
28
  end
28
29
  if value
29
30
  unless value.match(Ecoportal::API::V1::Person::VALID_TAG_REGEX)
30
- raise ArgumentError.new("Invalid default tag #{value.inspect}")
31
+ raise ArgumentError, "Invalid default tag #{value.inspect}"
31
32
  end
32
33
  value = value.upcase
33
34
  end
@@ -89,7 +90,7 @@ module Ecoportal
89
90
  end
90
91
 
91
92
  def as_update(ref = :last, ignore: [])
92
- super(ref, ignore: ignore | ["user_id", "permissions_merged", "prefilter"])
93
+ super(ref, ignore: ignore | %w[user_id permissions_merged prefilter])
93
94
  end
94
95
  end
95
96
  end
@@ -3,12 +3,12 @@ module Ecoportal
3
3
  class Internal < V1
4
4
  include Common::Logging
5
5
 
6
- VERSION = "v0"
7
- class_resolver :people_class, "Ecoportal::API::Internal::People"
8
- class_resolver :person_schemas_class, "Ecoportal::API::Internal::PersonSchemas"
6
+ VERSION = "v0".freeze
7
+ class_resolver :people_class, "Ecoportal::API::Internal::People"
8
+ class_resolver :person_schemas_class, "Ecoportal::API::Internal::PersonSchemas"
9
9
 
10
- class_resolver :policy_groups_class, "Ecoportal::API::Internal::PolicyGroups"
11
- class_resolver :login_providers_class, "Ecoportal::API::Internal::LoginProviders"
10
+ class_resolver :policy_groups_class, "Ecoportal::API::Internal::PolicyGroups"
11
+ class_resolver :login_providers_class, "Ecoportal::API::Internal::LoginProviders"
12
12
 
13
13
  # Obtain specific object for policy groups api requests.
14
14
  # @return [PolicyGroups] an instance object ready to make policy groups api requests.
@@ -1,24 +1,26 @@
1
1
  module Ecoportal
2
2
  module API
3
3
  class Logger
4
- TIMESTAMP_PATTERN = "%Y-%m-%dT%H:%M:%S"
5
- STDOUT_FORMAT_PROC = proc do |severity, datetime, progname, msg|
6
- prefix = "%5s > " % severity
4
+ TIMESTAMP_PATTERN = "%Y-%m-%dT%H:%M:%S".freeze
5
+
6
+ STDOUT_FORMAT_PROC = proc do |severity, _datetime, _progname, msg|
7
+ prefix = "%5s > " % severity # rubocop:disable Style/FormatString
7
8
  msg.lines.map.with_index do |line, idx|
8
9
  if idx.zero?
9
10
  prefix + line.chomp
10
11
  else
11
- " "*prefix.length + line.chomp
12
+ (" " * prefix.length) + line.chomp
12
13
  end
13
14
  end.join("\n")+"\n"
14
15
  end
15
- FILE_FORMAT_PROC = proc do |severity, datetime, progname, msg|
16
- prefix = "%5s(%s) > " % [severity, datetime.strftime(TIMESTAMP_PATTERN)]
16
+
17
+ FILE_FORMAT_PROC = proc do |severity, datetime, _progname, msg|
18
+ prefix = "%5s(%s) > " % [severity, datetime.strftime(TIMESTAMP_PATTERN)] # rubocop:disable Style/FormatString, Style/FormatStringToken
17
19
  msg.lines.map.with_index do |line, idx|
18
20
  if idx.zero?
19
21
  prefix + line.chomp
20
22
  else
21
- " "*prefix.length + line.chomp
23
+ (" " * prefix.length) + line.chomp
22
24
  end
23
25
  end.join("\n")+"\n"
24
26
  end
@@ -34,7 +36,7 @@ module Ecoportal
34
36
  @file = make_file_logger(file_level, output_file)
35
37
  end
36
38
 
37
- %w(unknown fatal error warn info debug).each do |type|
39
+ %w[unknown fatal error warn info debug].each do |type|
38
40
  define_method(type) do |&block|
39
41
  @console.send(type, &block)
40
42
  @file&.send(type, &block)
@@ -44,7 +46,7 @@ module Ecoportal
44
46
  private
45
47
 
46
48
  def make_stdout_logger(level)
47
- ::Logger.new(STDOUT).tap do |logger|
49
+ ::Logger.new($stdout).tap do |logger|
48
50
  logger.formatter = STDOUT_FORMAT_PROC
49
51
  logger.level = level
50
52
  end