ecoportal-api 0.8.2 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -1
- data/ecoportal-api.gemspec +3 -1
- data/lib/ecoportal/api/common/base_model.rb +54 -16
- data/lib/ecoportal/api/common/client.rb +40 -15
- data/lib/ecoportal/api/common/elastic_apm_integration.rb +112 -0
- data/lib/ecoportal/api/common/hash_diff.rb +8 -7
- data/lib/ecoportal/api/common.rb +1 -0
- data/lib/ecoportal/api/errors/base.rb +8 -0
- data/lib/ecoportal/api/errors/time_out.rb +8 -0
- data/lib/ecoportal/api/errors.rb +9 -0
- data/lib/ecoportal/api/internal/account.rb +34 -39
- data/lib/ecoportal/api/internal/permissions.rb +4 -3
- data/lib/ecoportal/api/internal/person.rb +8 -2
- data/lib/ecoportal/api/v1/people.rb +27 -21
- data/lib/ecoportal/api/v1/person.rb +6 -6
- data/lib/ecoportal/api/v1/person_details.rb +12 -1
- data/lib/ecoportal/api/v1/schema_field_value.rb +16 -19
- data/lib/ecoportal/api/version.rb +1 -1
- data/lib/ecoportal/api.rb +2 -0
- metadata +49 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4364abf59cd6460788d315eb5012df5e8ad254a208e8af7314a766463eb35ed0
|
4
|
+
data.tar.gz: d71fe7e38402e827aea0f95c6a0c379e191e525d597ab8b225990f48c6879764
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e055587b4aafbfabf25996cf4e67d85b0a0d9be936d4b0bdae194b431e4f2bb12b09fc99562d594cf355767aae3081a1fbea70d10a48dc204ce839284bbf0256
|
7
|
+
data.tar.gz: 5cd7284e455af271f1642775844636fd0ea11b590c0036d3b4a43868a9ffd6ece97ceebb9a3d6dfcdae7891dd65dedd0df9dac5944578cb18484b07342640c3e
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,92 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [0.8.
|
4
|
+
## [0.8.5] - 2022-02-28
|
5
|
+
|
6
|
+
### Added
|
7
|
+
- `Ecoportal::API::V1::PersonDetails#[]` to raise a specific error type to allow handling
|
8
|
+
- `Ecoportal::API::V1::PersonDetails.key?` to allow to check if a field exists
|
9
|
+
- `Ecoportal::API::Internal::Account#force_send_invites` support for back-end new method
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
- `Ecoportal::API::V1::People#get` fixed typo
|
13
|
+
- `Ecoportal::API::Common::BaseModel` `#original_doc` and `#initial_doc` maybe empty for the parent object
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
- `Ecoportal::API::V1::People#each` limited the `GET` retries to `5`
|
17
|
+
- `Ecoportal::API::Internal::Account#default_tag=`
|
18
|
+
- Controls input type to be `String` or `nil`
|
19
|
+
- Inherent `upcase`
|
20
|
+
|
21
|
+
## [0.8.4] - 2021-11-05
|
22
|
+
|
23
|
+
### Added
|
24
|
+
- `Ecoportal::API::Internal::Permissions` added abilities
|
25
|
+
- `visitor_management`, `cross_register_reporting` and `broadcast_notifications`
|
26
|
+
- Some yardocs too
|
27
|
+
- Some callbacks are done in a non-obvious way and the returned object type was not documented
|
28
|
+
- For this reason, some yardocs have been added to some of the parts that have been worked on.
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
- `Ecoportal::API::V1::People#create_job`
|
32
|
+
- **Removed** call to `BatchOperation#process_response`
|
33
|
+
- The method was is already called by `job_result`
|
34
|
+
- As a consequence there was a double up of `callbacks`
|
35
|
+
- **Fixed** line in wrong position
|
36
|
+
- `Ecoportal::API::V1::People#batch`
|
37
|
+
- `Ecoportal::API::Common::ElasticApmIntegration#unexpected_server_error?`
|
38
|
+
- No code or code lesser than 100 is a server error as well
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
- `Ecoportal::API::Common::Client`: changed
|
42
|
+
- Logging the **response** of batches or batch jobs can be handy when debugging the back-end
|
43
|
+
- **removed** method `#without_response_logging`
|
44
|
+
- This change entailed to remove dependencies in `Ecoportal::API::V1::People`
|
45
|
+
- Specifically in methods `#batch`, `#job_result` and `#create_job`
|
46
|
+
- `@response_logging_enabled` to be set in initialization stage (added parameter for `.new`)
|
47
|
+
|
48
|
+
## [0.8.3] - 2021-05-24
|
49
|
+
|
50
|
+
### Added
|
51
|
+
- `Ecoportal::API::Errors` namespace
|
52
|
+
- `Ecoportal::API::Errors::Base` base error class.
|
53
|
+
- `Ecoportal::API::Errors::TimeOut` error when an api request fails with time out.
|
54
|
+
- This serves the purpose to allow a client script to re-start the process where it stopped by capturing this specific Error
|
55
|
+
- `Ecoportal::API::Common::BaseModel::UnlinkedModel` added more description to track down the source of the error.
|
56
|
+
- `Ecoportal::API::Common::BaseModel#reset!` added parameter `key`, which should try to recover `doc[key]` from `original_doc[key]`
|
57
|
+
- Thanks to this, you are supposed to be able to do things like:
|
58
|
+
- `person.account = nil && person.reset!("account")`
|
59
|
+
- `person.name = nil && person.reset!("name")`
|
60
|
+
- `Ecoportal::API::V1::People#job` methods to provide more information on failure.
|
61
|
+
- Specific changes due to eP **release `1.5.9.70`** (_Policy Group Abilities_)
|
62
|
+
- `Ecoportal::API::Internal::Account#permissions_merged`
|
63
|
+
- `Ecoportal::API::Internal::Permissions#person_abilities` (new ability)
|
64
|
+
- `Ecoportal::API::Internal::Account#user_id`
|
65
|
+
|
66
|
+
### Fixed
|
67
|
+
- `Ecoportal::API::Internal::Account`: consistency in setting arrays (`uniq!` & `compact`)
|
68
|
+
- `#policy_group_ids=`, `#login_provider_ids=`, `#starred_ids=`
|
69
|
+
- `Ecoportal::API::Common::HashDiff.diff` was including empty `{}` objects
|
70
|
+
- This change sacrifices the case `account: {}` (which will be also removed from `as_update`), but it should be fine.
|
71
|
+
|
72
|
+
### Changed
|
73
|
+
- `Ecoportal::API::V1::People#job` to raise specific error on time out `API::Errors::TimeOut`
|
74
|
+
- Specific changes due to eP **release `1.5.9.70`** (_Policy Group Abilities_)
|
75
|
+
- `Ecoportal::API::Internal::Account` **removed** methods: `#permissions_preset`, `#preset` and `#preset=`
|
76
|
+
- `Ecoportal::API::Internal::Person#account=` added support for `user_id` which should remain unchanged when existing
|
77
|
+
- **remove** from `as_update` **read-only** data
|
78
|
+
- `Ecoportal::API::Common::HashDiff.diff` added parameter `:ignore` (`Array`)
|
79
|
+
- `Ecoportal::API::Common::BaseModel#as_update` added parameter `:ignore`
|
80
|
+
- `Ecoportal::API::V1::Person#as_update` added method, which ignores `subordinates`
|
81
|
+
- `Ecoportal::API::Internal::Person#as_update` added method, which ignores `user_id`, `permissions_merged` and `prefilter`
|
82
|
+
- `Ecoportal::API::Internal::Account#as_update` added method, which ignores `user_id`, `permissions_merged` and `prefilter`
|
83
|
+
- `Ecoportal::API::Common::Client` native support for `elastic-apm`
|
84
|
+
- Via new module `Ecoportal::API::Common::ElasticApmIntegration` with method `log_unexpected_server_error`, which will only log an `UnexpectedServerError` to _ElasticAPM_ if
|
85
|
+
1. There's a correct configuration: environmental variables `ELASTIC_APM_KEY` and `ELASTIC_APM_ACCOUNT_ID` are defined
|
86
|
+
2. The `Response` from the server gave `code` in the range `5xx` (which are those under server responsibility)
|
87
|
+
- `Ecoportal::API::Common::Client` added retry logics when `response.status == 5xx`
|
88
|
+
|
89
|
+
## [0.8.2] - 2021-02-24
|
5
90
|
|
6
91
|
### Added
|
7
92
|
|
data/ecoportal-api.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", ">= 2.2.
|
25
|
+
spec.add_development_dependency "bundler", ">= 2.2.17", "< 2.3"
|
26
26
|
spec.add_development_dependency "rspec", ">= 3.10.0", "< 3.11"
|
27
27
|
spec.add_development_dependency "rake", ">= 13.0.3", "< 13.1"
|
28
28
|
spec.add_development_dependency "yard", ">= 0.9.26", "< 0.10"
|
@@ -30,5 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "pry" , "~> 0.14"
|
31
31
|
|
32
32
|
spec.add_dependency 'http', '~> 4.4.1', "< 5"
|
33
|
+
spec.add_dependency 'dotenv', '>= 2.7.6', "< 2.8"
|
34
|
+
spec.add_dependency 'elastic-apm', '>= 4.0.0', "< 4.1"
|
33
35
|
spec.add_dependency 'hash-polyfill', '~> 0'
|
34
36
|
end
|
@@ -3,7 +3,9 @@ module Ecoportal
|
|
3
3
|
module Common
|
4
4
|
class BaseModel
|
5
5
|
class UnlinkedModel < Exception
|
6
|
-
def initialize (msg = "Something went wrong when linking the document.")
|
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
|
7
9
|
super(msg)
|
8
10
|
end
|
9
11
|
end
|
@@ -28,7 +30,12 @@ module Ecoportal
|
|
28
30
|
var = "@#{method}".freeze
|
29
31
|
key = key.to_s.freeze
|
30
32
|
define_method(method) do
|
31
|
-
|
33
|
+
if instance_variable_defined?(var)
|
34
|
+
value = instance_variable_get(var)
|
35
|
+
return value unless nullable
|
36
|
+
return value if (value && doc[key]) || (!value && !doc[key])
|
37
|
+
remove_instance_variable(var)
|
38
|
+
end
|
32
39
|
doc[key] ||= {} unless nullable
|
33
40
|
return instance_variable_set(var, nil) unless doc[key]
|
34
41
|
|
@@ -53,21 +60,21 @@ module Ecoportal
|
|
53
60
|
end
|
54
61
|
|
55
62
|
def doc
|
56
|
-
raise UnlinkedModel.new unless linked?
|
63
|
+
raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
|
57
64
|
return @doc if is_root?
|
58
65
|
_parent.doc.dig(*[_key].flatten)
|
59
66
|
end
|
60
67
|
|
61
68
|
def original_doc
|
62
|
-
raise UnlinkedModel.new unless linked?
|
69
|
+
raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
|
63
70
|
return @original_doc if is_root?
|
64
|
-
_parent.original_doc
|
71
|
+
_parent.original_doc&.dig(*[_key].flatten)
|
65
72
|
end
|
66
73
|
|
67
74
|
def initial_doc
|
68
|
-
raise UnlinkedModel.new unless linked?
|
75
|
+
raise UnlinkedModel.new(from: "#{self.class}#initial_doc", key: _key) unless linked?
|
69
76
|
return @initial_doc if is_root?
|
70
|
-
_parent.initial_doc
|
77
|
+
_parent.initial_doc&.dig(*[_key].flatten)
|
71
78
|
end
|
72
79
|
|
73
80
|
def as_json
|
@@ -78,18 +85,19 @@ module Ecoportal
|
|
78
85
|
doc.to_json(*args)
|
79
86
|
end
|
80
87
|
|
81
|
-
def as_update(ref = :last)
|
88
|
+
def as_update(ref = :last, ignore: [])
|
82
89
|
new_doc = as_json
|
83
90
|
ref_doc = ref == :total ? initial_doc : original_doc
|
84
|
-
Common::HashDiff.diff(new_doc, ref_doc)
|
91
|
+
Common::HashDiff.diff(new_doc, ref_doc, ignore: ignore)
|
85
92
|
end
|
86
93
|
|
87
94
|
def dirty?
|
88
95
|
as_update != {}
|
89
96
|
end
|
90
97
|
|
98
|
+
# It consolidates all the changes carried by `doc` by setting it as `original_doc`.
|
91
99
|
def consolidate!
|
92
|
-
raise UnlinkedModel.new unless linked?
|
100
|
+
raise UnlinkedModel.new(from: "#{self.class}#consolidate!", key: _key) unless linked?
|
93
101
|
new_doc = JSON.parse(doc.to_json)
|
94
102
|
if is_root?
|
95
103
|
@original_doc = new_doc
|
@@ -98,13 +106,32 @@ module Ecoportal
|
|
98
106
|
end
|
99
107
|
end
|
100
108
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
109
|
+
# It removes all the changes carried by `doc` by restoring `original_doc` into `doc`.
|
110
|
+
# @note
|
111
|
+
# 1. When there are nullable properties, it may be required to apply `reset!` from the parent
|
112
|
+
# i.e. `parent.reset!("child")` # when parent.child is `nil`
|
113
|
+
# 2. In such a case, only immediate childs are allowed to be reset
|
114
|
+
# @param key [String, Array<String>, nil] if given, it only resets the specified property
|
115
|
+
def reset!(key = nil)
|
116
|
+
raise "'key' should be a String. Given #{key}" unless !key || key.is_a?(String)
|
117
|
+
raise UnlinkedModel.new(from: "#{self.class}#reset!", key: _key) unless linked?
|
118
|
+
|
119
|
+
if key
|
120
|
+
if self.respond_to?(key) && child = self.send(key) && child.is_a?(Ecoportal::API::Common::BaseModel)
|
121
|
+
child.reset!
|
122
|
+
else
|
123
|
+
new_doc = original_doc && original_doc[key]
|
124
|
+
dig_set(doc, [key], new_doc && JSON.parse(new_doc.to_json))
|
125
|
+
# regenerate object if new_doc is null
|
126
|
+
self.send(key) if !new_doc && self.respond_to?(key)
|
127
|
+
end
|
106
128
|
else
|
107
|
-
|
129
|
+
new_doc = JSON.parse(original_doc.to_json)
|
130
|
+
if is_root?
|
131
|
+
@doc = new_doc
|
132
|
+
else
|
133
|
+
dig_set(_parent.doc, [_key].flatten, new_doc)
|
134
|
+
end
|
108
135
|
end
|
109
136
|
end
|
110
137
|
|
@@ -133,6 +160,17 @@ module Ecoportal
|
|
133
160
|
end
|
134
161
|
end
|
135
162
|
|
163
|
+
def set_uniq_array_keep_order(key, value)
|
164
|
+
unless value.is_a?(Array)
|
165
|
+
raise "#{key}= needs to be passed an Array, got #{value.class}"
|
166
|
+
end
|
167
|
+
ini_vals = (original_doc && original_doc[key]) || []
|
168
|
+
|
169
|
+
value = value.uniq
|
170
|
+
# preserve original order to avoid false updates
|
171
|
+
doc[key] = ((ini_vals & value) + (value - ini_vals)).compact
|
172
|
+
end
|
173
|
+
|
136
174
|
end
|
137
175
|
end
|
138
176
|
end
|
@@ -10,6 +10,9 @@ module Ecoportal
|
|
10
10
|
# - to return `HTTP::Response` ([response.rb](https://github.com/httprb/http/blob/master/lib/http/response.rb))
|
11
11
|
# @attr_reader logger [Logger] the logger.
|
12
12
|
class Client
|
13
|
+
include Common::ElasticApmIntegration
|
14
|
+
DELAY_REQUEST_RETRY = 5
|
15
|
+
|
13
16
|
attr_accessor :logger
|
14
17
|
|
15
18
|
# @note the `api_key` will be automatically added as parameter `X-ApiKey` in the header of the http requests.
|
@@ -17,11 +20,14 @@ module Ecoportal
|
|
17
20
|
# @param version [String] it is part of the base url and will determine the api version we query against.
|
18
21
|
# @param host [String] api server domain.
|
19
22
|
# @param logger [Logger] an object with `Logger` interface to generate logs.
|
23
|
+
# @param response_logging [Boolean] whether or not batch responses should be logged
|
20
24
|
# @return [Client] an object that holds the configuration of the api connection.
|
21
|
-
def initialize(api_key:, version: "v1", host: "live.ecoportal.com", logger: nil)
|
25
|
+
def initialize(api_key:, version: "v1", host: "live.ecoportal.com", logger: nil, response_logging: false)
|
22
26
|
@version = version
|
23
27
|
@api_key = api_key
|
24
28
|
@logger = logger
|
29
|
+
@host = host
|
30
|
+
@response_logging_enabled = response_logging
|
25
31
|
if host.match(/^localhost|^127\.0\.0\.1/)
|
26
32
|
@base_uri = "http://#{host}/api/"
|
27
33
|
else
|
@@ -31,7 +37,6 @@ module Ecoportal
|
|
31
37
|
if @api_key.nil? || @api_key.match(/\A\W*\z/)
|
32
38
|
log(:error) { "Api-key missing!" }
|
33
39
|
end
|
34
|
-
@response_logging_enabled = true
|
35
40
|
end
|
36
41
|
|
37
42
|
# Logger interface.
|
@@ -106,7 +111,7 @@ module Ecoportal
|
|
106
111
|
# basic HTTP connection to the block.
|
107
112
|
# @yield [http] launch specific http request.
|
108
113
|
# @yieldparam http [HTTP] the http connection.
|
109
|
-
# @yieldreturn [Common::Response] the basic custom
|
114
|
+
# @yieldreturn [Common::Response] the basic custom response object.
|
110
115
|
# @return [Common::Reponse] the basic custom response object.
|
111
116
|
def request
|
112
117
|
wrap_response yield(base_request)
|
@@ -140,22 +145,15 @@ module Ecoportal
|
|
140
145
|
@base_uri+@version+path
|
141
146
|
end
|
142
147
|
|
143
|
-
def without_response_logging(&block)
|
144
|
-
begin
|
145
|
-
@response_logging_enabled = false
|
146
|
-
yield self
|
147
|
-
ensure
|
148
|
-
@response_logging_enabled = true
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
148
|
private
|
153
149
|
|
154
|
-
def instrument(method, path, data = nil)
|
150
|
+
def instrument(method, path, data = nil, &block)
|
151
|
+
raise "Expected block" unless block
|
155
152
|
start_time = Time.now.to_f
|
156
|
-
log(:info)
|
153
|
+
log(:info) { "#{method} #{url_for(path)}" }
|
157
154
|
log(:debug) { "Data: #{JSON.pretty_generate(data)}" }
|
158
|
-
|
155
|
+
|
156
|
+
with_retry(&block).tap do |result|
|
159
157
|
end_time = Time.now.to_f
|
160
158
|
log(result.success?? :info : :warn) do
|
161
159
|
"Took %.2fs, Status #{result.status}" % (end_time - start_time)
|
@@ -165,6 +163,33 @@ module Ecoportal
|
|
165
163
|
end if @response_logging_enabled
|
166
164
|
end
|
167
165
|
end
|
166
|
+
|
167
|
+
# Helper to ensure unexpected server errors do not bring client scripts immediately down
|
168
|
+
def with_retry(attempts = 3, delay = DELAY_REQUEST_RETRY, error_safe: true, &block)
|
169
|
+
response = nil
|
170
|
+
attempts.times do |i|
|
171
|
+
remaining = attempts - i - 1
|
172
|
+
begin
|
173
|
+
response = block.call
|
174
|
+
rescue HTTP::ConnectionError => e
|
175
|
+
raise unless error_safe && remaining > 0
|
176
|
+
log(:error) { "Got connection error: #{e.message}" }
|
177
|
+
response = with_retry(remaining, error_safe: error_safe, &block)
|
178
|
+
rescue IOError => e
|
179
|
+
raise unless error_safe && remaining > 0
|
180
|
+
log(:error) { "Got IO error: #{e.message}" }
|
181
|
+
response = with_retry(remaining, error_safe: error_safe, &block)
|
182
|
+
end
|
183
|
+
return response unless unexpected_server_error?(response.status)
|
184
|
+
log_unexpected_server_error(response)
|
185
|
+
msg = "Got server error (#{response.status}): #{response.body}\n"
|
186
|
+
msg += "Going to retry (#{i} out of #{attempts})"
|
187
|
+
log(:error) { msg }
|
188
|
+
sleep(delay) if i < attempts
|
189
|
+
end
|
190
|
+
response
|
191
|
+
end
|
192
|
+
|
168
193
|
end
|
169
194
|
end
|
170
195
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'elastic-apm'
|
2
|
+
module Ecoportal
|
3
|
+
module API
|
4
|
+
module Common
|
5
|
+
module ElasticApmIntegration
|
6
|
+
|
7
|
+
class UnexpectedServerError < StandardError
|
8
|
+
def initialize(code, msg)
|
9
|
+
super("Code: #{code} -- Error: #{msg}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
APM_SERVICE_NAME = 'ecoportal-api-gem'
|
14
|
+
|
15
|
+
# Log only errors that are only server's responsibility
|
16
|
+
def log_unexpected_server_error(response)
|
17
|
+
raise "Expecting Ecoportal::API::Common::Response. Given: #{response.class}" unless response.is_a?(Common::Response)
|
18
|
+
return nil unless elastic_apm_service
|
19
|
+
return nil unless unexpected_server_error?(response.status)
|
20
|
+
if ElasticAPM.running?
|
21
|
+
ElasticAPM.report(UnexpectedServerError.new(response.status, response.body))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def unexpected_server_error?(code)
|
28
|
+
!code || ((code >= 500) && (code <= 599)) || (code <= 99)
|
29
|
+
end
|
30
|
+
|
31
|
+
# finalizer to stop the agent
|
32
|
+
close_elastic_apm = Proc.new do |id|
|
33
|
+
begin
|
34
|
+
if ElasticAPM.running?
|
35
|
+
puts "Stopping ElasticAPM service"
|
36
|
+
ElasticAPM.stop
|
37
|
+
end
|
38
|
+
rescue StandardError => e
|
39
|
+
# Silent
|
40
|
+
end
|
41
|
+
end
|
42
|
+
ObjectSpace.define_finalizer("ElasticAPM", close_elastic_apm)
|
43
|
+
|
44
|
+
def elastic_apm_service
|
45
|
+
return false if @disable_apm
|
46
|
+
begin
|
47
|
+
ElasticAPM.start(**elastic_apm_options) unless ElasticAPM.running?
|
48
|
+
rescue StandardError => e
|
49
|
+
@disable_apm = true
|
50
|
+
puts "ElasticAPM services not available: #{e}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def elastic_apm_options
|
55
|
+
{
|
56
|
+
service_name: APM_SERVICE_NAME,
|
57
|
+
server_url: elastic_apm_url,
|
58
|
+
secret_token: elastic_apm_key,
|
59
|
+
environment: environment,
|
60
|
+
#http_compression: false,
|
61
|
+
transaction_sample_rate: 0.1,
|
62
|
+
transaction_max_spans: 100,
|
63
|
+
span_frames_min_duration: "5ms"
|
64
|
+
}.tap do |options|
|
65
|
+
options.merge!({
|
66
|
+
log_level: Logger::DEBUG,
|
67
|
+
log_path: File.join(__dir__, "elastic_apm.log")
|
68
|
+
}) if false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def elastic_apm_url
|
73
|
+
@elastic_apm_url ||= "https://".tap do |url|
|
74
|
+
url << "#{elastic_apm_account_id}"
|
75
|
+
url << ".#{elastic_apm_base_url}"
|
76
|
+
url << ":#{elastic_apm_port}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def elastic_apm_key
|
81
|
+
@elastic_apm_key ||= ENV['ELASTIC_APM_KEY']
|
82
|
+
end
|
83
|
+
|
84
|
+
def elastic_apm_account_id
|
85
|
+
@elastic_apm_account_id ||= ENV['ELASTIC_APM_ACCOUNT_ID']
|
86
|
+
end
|
87
|
+
|
88
|
+
def elastic_apm_base_url
|
89
|
+
@elastic_apm_base_url ||= "apm.#{elastic_apm_region}.aws.cloud.es.io"
|
90
|
+
end
|
91
|
+
|
92
|
+
def elastic_apm_region
|
93
|
+
@elastic_apm_region ||= ENV['ELASTIC_APM_REGION'] || "ap-southeast-2"
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def elastic_apm_port
|
98
|
+
@elastic_apm_port ||= ENV['ELASTIC_APM_PORT'] || "443"
|
99
|
+
end
|
100
|
+
|
101
|
+
def environment
|
102
|
+
@environment ||= "unknown".tap do |value|
|
103
|
+
if instance_variable_defined?(:@host) && env = @host.gsub(".ecoportal.com", '')
|
104
|
+
value.clear << env
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -5,15 +5,16 @@ module Ecoportal
|
|
5
5
|
ID_KEYS = %w[id]
|
6
6
|
|
7
7
|
class << self
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
def diff(a, b, ignore: [])
|
10
10
|
case a
|
11
11
|
when Hash
|
12
12
|
{}.tap do |diffed|
|
13
13
|
a.each do |key, a_value|
|
14
|
-
b_value
|
15
|
-
|
16
|
-
|
14
|
+
b_value = b && b[key]
|
15
|
+
no_changes = (a_value == b_value) || ignore.include?(key)
|
16
|
+
next if !ID_KEYS.include?(key) && no_changes
|
17
|
+
diffed[key] = diff(a_value, b_value, ignore: ignore)
|
17
18
|
diffed.delete(key) if diffed[key] == {}
|
18
19
|
end
|
19
20
|
# All keys are IDs, so it's actually blank
|
@@ -22,10 +23,10 @@ module Ecoportal
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
when Array
|
25
|
-
return a unless a.length == b.length
|
26
|
+
return a unless b.is_a?(Array) && a.length == b.length
|
26
27
|
a.map.with_index do |a_value, idx|
|
27
28
|
b_value = b[idx]
|
28
|
-
diff(a_value, b_value)
|
29
|
+
diff(a_value, b_value, ignore: ignore)
|
29
30
|
end.reject do |el|
|
30
31
|
el == {}
|
31
32
|
end
|
data/lib/ecoportal/api/common.rb
CHANGED
@@ -10,6 +10,7 @@ require 'ecoportal/api/common/hash_diff'
|
|
10
10
|
require 'ecoportal/api/common/base_model'
|
11
11
|
require 'ecoportal/api/common/doc_helpers'
|
12
12
|
require 'ecoportal/api/common/logging'
|
13
|
+
require 'ecoportal/api/common/elastic_apm_integration'
|
13
14
|
require 'ecoportal/api/common/client'
|
14
15
|
require 'ecoportal/api/common/response'
|
15
16
|
require 'ecoportal/api/common/wrapped_response'
|
@@ -2,29 +2,43 @@ module Ecoportal
|
|
2
2
|
module API
|
3
3
|
class Internal
|
4
4
|
class Account < Common::BaseModel
|
5
|
-
|
6
|
-
|
7
|
-
|
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)
|
8
12
|
|
9
13
|
class_resolver :preferences_class, "Ecoportal::API::Internal::Preferences"
|
10
14
|
class_resolver :permissions_class, "Ecoportal::API::Internal::Permissions"
|
11
15
|
|
12
16
|
embeds_one :permissions, key: "permissions_custom", klass: :permissions_class
|
17
|
+
embeds_one :perms_merged, key: "permissions_merged", klass: :permissions_class
|
13
18
|
embeds_one :preferences, klass: :preferences_class
|
14
19
|
|
20
|
+
# Sets the `default_tag` of the user
|
21
|
+
# @note it upcases the value
|
22
|
+
# @param value [String, nil] the tag
|
23
|
+
# @return [String, nil] the value set in `default_tag`
|
24
|
+
def default_tag=(value)
|
25
|
+
unless !value || value.is_a?(String)
|
26
|
+
raise ArgumentError.new("default_tag= needs to be passed a String or nil, got #{value.class}")
|
27
|
+
end
|
28
|
+
if value
|
29
|
+
unless value.match(Ecoportal::API::V1::Person::VALID_TAG_REGEX)
|
30
|
+
raise ArgumentError.new("Invalid default tag #{value.inspect}")
|
31
|
+
end
|
32
|
+
value = value.upcase
|
33
|
+
end
|
34
|
+
doc["default_tag"] = value
|
35
|
+
end
|
36
|
+
|
15
37
|
# Sets the `policy_group_ids`
|
16
38
|
# @note it preserves the original order
|
17
39
|
# @param value [Array<String>] the policy group ids to be set.
|
18
40
|
def policy_group_ids=(value)
|
19
|
-
|
20
|
-
raise "policy_group_ids= needs to be passed an Array, got #{value.class}"
|
21
|
-
end
|
22
|
-
|
23
|
-
value.uniq!
|
24
|
-
ini_ids = (original_doc && original_doc["policy_group_ids"]) || []
|
25
|
-
# preserve original order to avoid false updates
|
26
|
-
doc["policy_group_ids"] = (ini_ids & value) + (value - ini_ids)
|
27
|
-
doc["policy_group_ids"].compact
|
41
|
+
set_uniq_array_keep_order("policy_group_ids", value)
|
28
42
|
end
|
29
43
|
|
30
44
|
# @return [Array<String>] the policy group ids of this user.
|
@@ -34,10 +48,7 @@ module Ecoportal
|
|
34
48
|
|
35
49
|
# Sets the `login_provider_ids`
|
36
50
|
def login_provider_ids=(value)
|
37
|
-
|
38
|
-
raise "login_provider_ids= needs to be passed an Array, got #{value.class}"
|
39
|
-
end
|
40
|
-
doc["login_provider_ids"] = value.compact
|
51
|
+
set_uniq_array_keep_order("login_provider_ids", value)
|
41
52
|
end
|
42
53
|
|
43
54
|
# @return [Array<String>] the login provider ids of this user.
|
@@ -47,10 +58,7 @@ module Ecoportal
|
|
47
58
|
|
48
59
|
# Sets the `starred_ids`
|
49
60
|
def starred_ids=(value)
|
50
|
-
|
51
|
-
raise "starred_ids= needs to be passed an Array, got #{value.class}"
|
52
|
-
end
|
53
|
-
doc["starred_ids"] = value.compact
|
61
|
+
set_uniq_array_keep_order("starred_ids", value)
|
54
62
|
end
|
55
63
|
|
56
64
|
# @return [Array<String>] the starred page ids of this user.
|
@@ -58,20 +66,6 @@ module Ecoportal
|
|
58
66
|
doc["starred_ids"] ||= []
|
59
67
|
end
|
60
68
|
|
61
|
-
# Sets the `permissions_preset`.
|
62
|
-
# @note basically the same as `permissions_preset=` but when `"custom"`, it's changed to `nil`
|
63
|
-
# @param value [nil, String] preset name.
|
64
|
-
def preset=(value)
|
65
|
-
self.permissions_preset = value == "custom" ? nil : value
|
66
|
-
end
|
67
|
-
|
68
|
-
# Gets the `permissions_preset`.
|
69
|
-
# @note basically the same as `permissions_preset` but when 'nil', it returns `"custom"` instead
|
70
|
-
# @return [nil, String] preset name.
|
71
|
-
def preset
|
72
|
-
self.permissions_preset.nil? ? "custom" : self.permissions_preset
|
73
|
-
end
|
74
|
-
|
75
69
|
# It preserves the values of keys that are not defined in `value`.
|
76
70
|
# @param value [Hash] the abilities that you want to update.
|
77
71
|
def permissions_custom=(value)
|
@@ -88,15 +82,16 @@ module Ecoportal
|
|
88
82
|
|
89
83
|
def as_json
|
90
84
|
super.tap do |hash|
|
91
|
-
|
92
|
-
|
93
|
-
else
|
94
|
-
hash.delete "permissions_custom"
|
95
|
-
end
|
85
|
+
hash["permissions_custom"] = permissions.as_json
|
86
|
+
hash["permissions_merged"] = perms_merged.as_json
|
96
87
|
hash["preferences"] = preferences.as_json
|
97
88
|
end
|
98
89
|
end
|
99
90
|
|
91
|
+
def as_update(ref = :last, ignore: [])
|
92
|
+
super(ref, ignore: ignore | ["user_id", "permissions_merged", "prefilter"])
|
93
|
+
end
|
94
|
+
|
100
95
|
end
|
101
96
|
end
|
102
97
|
end
|
@@ -3,9 +3,10 @@ module Ecoportal
|
|
3
3
|
class Internal
|
4
4
|
class Permissions < Common::BaseModel
|
5
5
|
passthrough :files, :data, :reports
|
6
|
-
passthrough :organization, :
|
7
|
-
passthrough :
|
8
|
-
passthrough :
|
6
|
+
passthrough :organization, :pages, :page_editor, :registers, :tasks
|
7
|
+
passthrough :person_core, :person_core_create, :person_core_edit
|
8
|
+
passthrough :person_details, :person_account, :person_abilities
|
9
|
+
passthrough :visitor_management, :broadcast_notifications, :cross_register_reporting
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -11,10 +11,14 @@ module Ecoportal
|
|
11
11
|
super.update("account" => account&.as_json)
|
12
12
|
end
|
13
13
|
|
14
|
+
def as_update(ref = :last, ignore: [])
|
15
|
+
super(ref, ignore: ignore | ["user_id", "permissions_merged", "prefilter"])
|
16
|
+
end
|
17
|
+
|
14
18
|
# Sets the Account to the person, depending on the paramter received:
|
15
19
|
# - `nil`: blanks the account.
|
16
20
|
# - `Account`: sets a copy of the object param as account.
|
17
|
-
# - `Hash`: slices the properties of `Account
|
21
|
+
# - `Hash`: slices the properties of `Account` (keeping the value of `user_id` if there was already account).
|
18
22
|
# @note this method does not make dirty the account (meaning that `as_json` will be an empty hash `{}`)
|
19
23
|
# @param value [nil, Account, Hash] value to be set.
|
20
24
|
# @return [nil, Account] the resulting `Account` set to the person.
|
@@ -25,7 +29,9 @@ module Ecoportal
|
|
25
29
|
when Internal::Account
|
26
30
|
doc["account"] = JSON.parse(value.to_json)
|
27
31
|
when Hash
|
28
|
-
|
32
|
+
user_id = account.user_id if account
|
33
|
+
doc["account"] = value.slice(*Internal::Account::PROPERTIES)
|
34
|
+
doc["account"]["user_id"] = user_id if user_id
|
29
35
|
else
|
30
36
|
# TODO
|
31
37
|
raise "Invalid set on account: Need nil, Account or Hash; got #{value.class}"
|
@@ -36,8 +36,15 @@ module Ecoportal
|
|
36
36
|
puts "\n" unless silent
|
37
37
|
loop do
|
38
38
|
params.update(cursor_id: cursor_id) if cursor_id
|
39
|
-
response =
|
40
|
-
|
39
|
+
body = nil; response = nil; count = 5
|
40
|
+
loop do
|
41
|
+
response = client.get("/people", params: params)
|
42
|
+
body = response && body_data(response.body)
|
43
|
+
break if response.success? || count <= 0
|
44
|
+
puts "Request failed - Status #{response.status}: #{body}"
|
45
|
+
count -= 1
|
46
|
+
sleep(0.5)
|
47
|
+
end
|
41
48
|
raise "Request failed - Status #{response.status}: #{body}" unless response.success?
|
42
49
|
|
43
50
|
unless silent || (total = body["total_results"]) == 0
|
@@ -77,7 +84,7 @@ module Ecoportal
|
|
77
84
|
response = client.get("/people/"+CGI.escape(id))
|
78
85
|
body = body_data(response.body)
|
79
86
|
return person_class.new(body) if response.success?
|
80
|
-
raise "Could not get person #{id} - Error #{
|
87
|
+
raise "Could not get person #{id} - Error #{response.status}: #{body}"
|
81
88
|
end
|
82
89
|
|
83
90
|
# Requests an update of a person via api.
|
@@ -117,29 +124,30 @@ module Ecoportal
|
|
117
124
|
# Creates a `BatchOperation` and yields it to the given bock.
|
118
125
|
# @yield [batch_op] adds multiple api requests for the current batch.
|
119
126
|
# @yieldparam batch_op [BatchOperation]
|
127
|
+
# @param job_mode [Boolean] whether or not it should use batch jobs
|
128
|
+
# @return [Ecoportal::API::Common::Response] the results of the batch
|
120
129
|
def batch(job_mode: true, &block)
|
121
130
|
return job(&block) if job_mode
|
122
131
|
operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
|
123
132
|
yield operation
|
124
133
|
# The batch operation is responsible for logging the output
|
125
|
-
client.
|
126
|
-
|
127
|
-
operation.process_response(response)
|
128
|
-
end
|
134
|
+
client.post("/people/batch", data: operation.as_json).tap do |response|
|
135
|
+
operation.process_response(response)
|
129
136
|
end
|
130
137
|
end
|
131
138
|
|
139
|
+
# @return [Ecoportal::API::Common::Response] the results of the batch job
|
132
140
|
def job
|
133
141
|
operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
|
134
142
|
yield operation
|
135
|
-
# The batch operation is responsible for logging the output
|
136
143
|
job_id = create_job(operation)
|
137
144
|
status = wait_for_job_completion(job_id)
|
138
145
|
|
139
146
|
if status&.complete?
|
140
|
-
|
147
|
+
job_result(job_id, operation)
|
141
148
|
else
|
142
|
-
|
149
|
+
msg = "Job `#{job_id}` not complete. Probably timeout after #{JOB_TIMEOUT} seconds. Current status: #{status}"
|
150
|
+
raise API::Errors::TimeOut.new msg
|
143
151
|
end
|
144
152
|
end
|
145
153
|
|
@@ -154,8 +162,8 @@ module Ecoportal
|
|
154
162
|
JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
|
155
163
|
def job_status(job_id)
|
156
164
|
response = client.get("/people/job/#{CGI.escape(job_id)}/status")
|
157
|
-
body = body_data(response.body)
|
158
|
-
raise "Status error" unless response.success?
|
165
|
+
body = response && body_data(response.body)
|
166
|
+
raise "Status error (#{response.status}) - Errors: #{body}" unless response.success?
|
159
167
|
JobStatus.new(
|
160
168
|
body["id"],
|
161
169
|
body["complete"],
|
@@ -164,12 +172,10 @@ module Ecoportal
|
|
164
172
|
)
|
165
173
|
end
|
166
174
|
|
175
|
+
# @return [Ecoportal::API::Common::Response] the results of the batch job
|
167
176
|
def job_result(job_id, operation)
|
168
|
-
|
169
|
-
|
170
|
-
client.get("/people/job/#{CGI.escape(job_id)}").tap do |response|
|
171
|
-
operation.process_response(response)
|
172
|
-
end
|
177
|
+
client.get("/people/job/#{CGI.escape(job_id)}").tap do |response|
|
178
|
+
operation.process_response(response)
|
173
179
|
end
|
174
180
|
end
|
175
181
|
|
@@ -186,12 +192,12 @@ module Ecoportal
|
|
186
192
|
end
|
187
193
|
end
|
188
194
|
|
195
|
+
# @return [String] the `id` of the created batch job
|
189
196
|
def create_job(operation)
|
190
197
|
job_id = nil
|
191
|
-
client.
|
192
|
-
|
193
|
-
|
194
|
-
end
|
198
|
+
client.post("/people/job", data: operation.as_json).tap do |response|
|
199
|
+
job_id = body_data(response.body)["id"] if response.success?
|
200
|
+
raise "Could not create job - Error (#{response.status}): #{body_data(response.body)}" unless job_id
|
195
201
|
end
|
196
202
|
job_id
|
197
203
|
end
|
@@ -64,12 +64,8 @@ module Ecoportal
|
|
64
64
|
raise "Invalid filter tag #{tag.inspect}"
|
65
65
|
end
|
66
66
|
tag.upcase
|
67
|
-
end
|
68
|
-
|
69
|
-
ini_tags = (original_doc && original_doc["filter_tags"]) || []
|
70
|
-
# preserve original order to avoid false updates
|
71
|
-
doc["filter_tags"] = (ini_tags & end_tags) + (end_tags - ini_tags)
|
72
|
-
doc["filter_tags"].compact
|
67
|
+
end
|
68
|
+
set_uniq_array_keep_order("filter_tags", end_tags)
|
73
69
|
end
|
74
70
|
|
75
71
|
# @return [Array<String>] the filter tags of this person.
|
@@ -81,6 +77,10 @@ module Ecoportal
|
|
81
77
|
super.merge "details" => details&.as_json
|
82
78
|
end
|
83
79
|
|
80
|
+
def as_update(ref = :last, ignore: [])
|
81
|
+
super(ignore: ignore | ["subordinates"])
|
82
|
+
end
|
83
|
+
|
84
84
|
# Sets the PersonDetails to the person, depending on the paramter received:
|
85
85
|
# - `nil`: blanks the details.
|
86
86
|
# - `PersonDetails`: sets a copy of the object param as details.
|
@@ -2,6 +2,9 @@ module Ecoportal
|
|
2
2
|
module API
|
3
3
|
class V1
|
4
4
|
class PersonDetails < Common::BaseModel
|
5
|
+
class MissingId < StandardError
|
6
|
+
end
|
7
|
+
|
5
8
|
passthrough :schema_id
|
6
9
|
|
7
10
|
class_resolver :schema_field_value_class, "Ecoportal::API::V1::SchemaFieldValue"
|
@@ -43,16 +46,24 @@ module Ecoportal
|
|
43
46
|
end
|
44
47
|
|
45
48
|
# Sets the value to one specific field of the PersonDetails.
|
49
|
+
# @raise MisssingId if the `id` or `alt_id` is missing.
|
46
50
|
# @param id [String] the `id` or the `alt_id` of the target field.
|
47
51
|
# @return [void]
|
48
52
|
def []=(id, value)
|
49
53
|
if field = get_field(id)
|
50
54
|
field.value = value
|
51
55
|
else
|
52
|
-
raise "details[#{id.inspect}] is missing. Did you forget to load the schema?"
|
56
|
+
raise MissingId.new("details[#{id.inspect}] is missing. Did you forget to load the schema?")
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
60
|
+
# Checks if an `id` or `alt_id` exists
|
61
|
+
# @param id [String] the `id` or the `alt_id` of the target field.
|
62
|
+
# @return [Boolean] `true` if it exists, `false` otherwise
|
63
|
+
def key?(id)
|
64
|
+
@fields_by_id.key?(id) || @fields_by_alt_id.key?(id)
|
65
|
+
end
|
66
|
+
|
56
67
|
protected
|
57
68
|
|
58
69
|
# Rebuilds the internal `id` and `alt_id` references to the fields.
|
@@ -6,25 +6,24 @@ module Ecoportal
|
|
6
6
|
passthrough :id, :alt_id, :type, :name, :shared, :multiple
|
7
7
|
|
8
8
|
def value
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
9
|
+
case type
|
10
|
+
when "text", "phone_number", "number", "boolean", "select"
|
11
|
+
doc["value"]
|
12
|
+
when "date"
|
13
|
+
if doc["value"]
|
14
|
+
maybe_multiple(doc["value"]) do |v|
|
15
|
+
Date.iso8601(v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
else
|
19
|
+
raise "Unknown type #{type}"
|
20
|
+
end
|
22
21
|
end
|
23
22
|
|
24
23
|
def value=(value)
|
25
24
|
case type
|
26
25
|
when "text", "phone_number", "select"
|
27
|
-
doc["value"] =
|
26
|
+
doc["value"] = maybe_multiple(value) do |v|
|
28
27
|
v&.to_s
|
29
28
|
end
|
30
29
|
when "number"
|
@@ -33,23 +32,21 @@ module Ecoportal
|
|
33
32
|
raise "Invalid number type #{v.class}"
|
34
33
|
end
|
35
34
|
end
|
36
|
-
doc["value"] =
|
35
|
+
doc["value"] = value
|
37
36
|
when "boolean"
|
38
|
-
doc["value"] =
|
37
|
+
doc["value"] = !!value
|
39
38
|
when "date"
|
40
39
|
maybe_multiple(value) do |v|
|
41
40
|
unless v.nil? || v.respond_to?(:to_date)
|
42
41
|
raise "Invalid date type #{v.class}"
|
43
42
|
end
|
44
43
|
end
|
45
|
-
|
46
|
-
doc["value"] = maybe_multiple(@value) do |v|
|
44
|
+
doc["value"] = maybe_multiple(value) do |v|
|
47
45
|
v&.to_date&.to_s
|
48
46
|
end
|
49
47
|
else
|
50
48
|
raise "Unknown type #{type}"
|
51
49
|
end
|
52
|
-
@value
|
53
50
|
end
|
54
51
|
|
55
52
|
def maybe_multiple(value)
|
data/lib/ecoportal/api.rb
CHANGED
@@ -2,6 +2,7 @@ require "cgi"
|
|
2
2
|
require "logger"
|
3
3
|
require "hash-polyfill"
|
4
4
|
require "ecoportal/api/version"
|
5
|
+
require "dotenv/load"
|
5
6
|
|
6
7
|
module Ecoportal
|
7
8
|
module API
|
@@ -10,5 +11,6 @@ end
|
|
10
11
|
|
11
12
|
require "ecoportal/api/logger"
|
12
13
|
require "ecoportal/api/common"
|
14
|
+
require "ecoportal/api/errors"
|
13
15
|
require "ecoportal/api/v1"
|
14
16
|
require "ecoportal/api/internal"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecoportal-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tapio Saarinen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.2.
|
19
|
+
version: 2.2.17
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '2.3'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 2.2.
|
29
|
+
version: 2.2.17
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '2.3'
|
@@ -144,6 +144,46 @@ dependencies:
|
|
144
144
|
- - "<"
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '5'
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: dotenv
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 2.7.6
|
154
|
+
- - "<"
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '2.8'
|
157
|
+
type: :runtime
|
158
|
+
prerelease: false
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 2.7.6
|
164
|
+
- - "<"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '2.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: elastic-apm
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 4.0.0
|
174
|
+
- - "<"
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '4.1'
|
177
|
+
type: :runtime
|
178
|
+
prerelease: false
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 4.0.0
|
184
|
+
- - "<"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '4.1'
|
147
187
|
- !ruby/object:Gem::Dependency
|
148
188
|
name: hash-polyfill
|
149
189
|
requirement: !ruby/object:Gem::Requirement
|
@@ -189,10 +229,14 @@ files:
|
|
189
229
|
- lib/ecoportal/api/common/batch_response.rb
|
190
230
|
- lib/ecoportal/api/common/client.rb
|
191
231
|
- lib/ecoportal/api/common/doc_helpers.rb
|
232
|
+
- lib/ecoportal/api/common/elastic_apm_integration.rb
|
192
233
|
- lib/ecoportal/api/common/hash_diff.rb
|
193
234
|
- lib/ecoportal/api/common/logging.rb
|
194
235
|
- lib/ecoportal/api/common/response.rb
|
195
236
|
- lib/ecoportal/api/common/wrapped_response.rb
|
237
|
+
- lib/ecoportal/api/errors.rb
|
238
|
+
- lib/ecoportal/api/errors/base.rb
|
239
|
+
- lib/ecoportal/api/errors/time_out.rb
|
196
240
|
- lib/ecoportal/api/internal.rb
|
197
241
|
- lib/ecoportal/api/internal/account.rb
|
198
242
|
- lib/ecoportal/api/internal/login_provider.rb
|
@@ -237,7 +281,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
281
|
- !ruby/object:Gem::Version
|
238
282
|
version: '0'
|
239
283
|
requirements: []
|
240
|
-
rubygems_version: 3.
|
284
|
+
rubygems_version: 3.3.5
|
241
285
|
signing_key:
|
242
286
|
specification_version: 4
|
243
287
|
summary: A collection of helpers for interacting with the ecoPortal MS's various APIs
|