ecoportal-api 0.8.5 → 0.9.2

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +20 -20
  3. data/.rspec +3 -3
  4. data/.rubocop.yml +55 -55
  5. data/.travis.yml +5 -5
  6. data/.yardopts +10 -10
  7. data/CHANGELOG.md +257 -236
  8. data/Gemfile +6 -6
  9. data/LICENSE +21 -21
  10. data/README.md +34 -34
  11. data/Rakefile +27 -27
  12. data/bin/console +14 -14
  13. data/bin/setup +8 -8
  14. data/ecoportal-api.gemspec +36 -36
  15. data/lib/ecoportal/api/common/base_class.rb +33 -29
  16. data/lib/ecoportal/api/common/base_model.rb +195 -177
  17. data/lib/ecoportal/api/common/batch_operation.rb +119 -119
  18. data/lib/ecoportal/api/common/batch_response.rb +34 -34
  19. data/lib/ecoportal/api/common/client.rb +198 -196
  20. data/lib/ecoportal/api/common/doc_helpers.rb +29 -29
  21. data/lib/ecoportal/api/common/elastic_apm_integration.rb +112 -112
  22. data/lib/ecoportal/api/common/hash_diff.rb +41 -41
  23. data/lib/ecoportal/api/common/logging.rb +12 -12
  24. data/lib/ecoportal/api/common/response.rb +31 -31
  25. data/lib/ecoportal/api/common/wrapped_response.rb +54 -54
  26. data/lib/ecoportal/api/common.rb +18 -18
  27. data/lib/ecoportal/api/errors/base.rb +8 -8
  28. data/lib/ecoportal/api/errors/time_out.rb +8 -8
  29. data/lib/ecoportal/api/errors.rb +9 -9
  30. data/lib/ecoportal/api/internal/account.rb +99 -100
  31. data/lib/ecoportal/api/internal/login_provider.rb +9 -9
  32. data/lib/ecoportal/api/internal/login_providers.rb +33 -33
  33. data/lib/ecoportal/api/internal/people.rb +14 -14
  34. data/lib/ecoportal/api/internal/permissions.rb +14 -13
  35. data/lib/ecoportal/api/internal/person.rb +101 -53
  36. data/lib/ecoportal/api/internal/person_details.rb +9 -9
  37. data/lib/ecoportal/api/internal/person_schema.rb +10 -10
  38. data/lib/ecoportal/api/internal/person_schemas.rb +11 -11
  39. data/lib/ecoportal/api/internal/policy_group.rb +9 -9
  40. data/lib/ecoportal/api/internal/policy_groups.rb +32 -32
  41. data/lib/ecoportal/api/internal/preferences.rb +31 -31
  42. data/lib/ecoportal/api/internal/schema_field.rb +8 -8
  43. data/lib/ecoportal/api/internal/schema_field_value.rb +8 -8
  44. data/lib/ecoportal/api/internal.rb +31 -31
  45. data/lib/ecoportal/api/logger.rb +62 -62
  46. data/lib/ecoportal/api/v1/people.rb +218 -218
  47. data/lib/ecoportal/api/v1/person.rb +138 -135
  48. data/lib/ecoportal/api/v1/person_details.rb +94 -82
  49. data/lib/ecoportal/api/v1/person_schema.rb +53 -53
  50. data/lib/ecoportal/api/v1/person_schemas.rb +48 -48
  51. data/lib/ecoportal/api/v1/schema_field.rb +34 -34
  52. data/lib/ecoportal/api/v1/schema_field_value.rb +65 -65
  53. data/lib/ecoportal/api/v1.rb +49 -49
  54. data/lib/ecoportal/api/version.rb +5 -5
  55. data/lib/ecoportal/api.rb +16 -16
  56. metadata +3 -3
@@ -1,218 +1,218 @@
1
- module Ecoportal
2
- module API
3
- class V1
4
- # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
5
- class People
6
- extend Common::BaseClass
7
- include Enumerable
8
- include Common::DocHelpers
9
-
10
- JOB_TIMEOUT = 240
11
- DELAY_STATUS_CHECK = 5
12
-
13
- class_resolver :person_class, "Ecoportal::API::V1::Person"
14
-
15
- attr_reader :client
16
-
17
- # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
18
- # @return [People] an instance object ready to make people api requests.
19
- def initialize(client)
20
- @client = client
21
- end
22
-
23
- # Iterates all the people of the organization.
24
- # @note
25
- # - it ignores the key `cursor_id:` of `params:`.
26
- # - `each` is called by `to_a`
27
- # @param params [Hash]
28
- # @option params [String] :per_page the number of people you get per request.
29
- # @option params [String] :q some text to search. Omit this parameter to target all the people.
30
- # @param silent [Boolean] `false` to show percentage of progress.
31
- # @yield [person] does some stuff with the person.
32
- # @yieldparam person [Person]
33
- def each(params: {}, silent: false, &block)
34
- return to_enum(:each, params: params, silent: silent) unless block
35
- cursor_id = nil; results = 0
36
- puts "\n" unless silent
37
- loop do
38
- params.update(cursor_id: cursor_id) if cursor_id
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
48
- raise "Request failed - Status #{response.status}: #{body}" unless response.success?
49
-
50
- unless silent || (total = body["total_results"]) == 0
51
- results += body["results"].length
52
- percent = results * 100 / total
53
- msg = "People GET"
54
- msg += " (search=#{params[:q]})" if params.key?(:q)
55
- print "#{msg}: #{percent.round}% (of #{total})\r"
56
- $stdout.flush
57
- end
58
-
59
- body["results"].each do |person|
60
- yield person_class.new(person)
61
- end
62
- break unless (cursor_id = body["cursor_id"])
63
- end
64
- self
65
- end
66
-
67
- # Gets all the people via api requests.
68
- # @note it ignores the key `:cursor_id` in `params:`.
69
- # @param params [Hash]
70
- # @option params [Integer] :per_page the number of people you get per request.
71
- # @option params [String] :q some text to search.
72
- # @param silent [Boolean] `false` to show percentage of progress.
73
- # @return [Array<Person>] the array of people got via api.
74
- def get_all(params: {}, silent: false)
75
- each(params: params, silent: silent).to_a
76
- end
77
-
78
- # Gets a person via api.
79
- # @note if the request has `success?` the returned `object.result` gives an object with that `Person`.
80
- # @param doc [String, Hash, Person] data containing an `id` (internal or external) of the target person.
81
- # @return [Person] the person with `id` (internal or external) contained in `doc`.
82
- def get(doc)
83
- id = get_id(doc)
84
- response = client.get("/people/"+CGI.escape(id))
85
- body = body_data(response.body)
86
- return person_class.new(body) if response.success?
87
- raise "Could not get person #{id} - Error #{response.status}: #{body}"
88
- end
89
-
90
- # Requests an update of a person via api.
91
- # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
92
- # @return [Response] an object with the api response.
93
- def update(doc)
94
- body = get_body(doc)
95
- id = get_id(doc)
96
- client.patch("/people/"+CGI.escape(id), data: body)
97
- end
98
-
99
- # Requests to create a person via api.
100
- # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
101
- # @return [Response] an object with the api response.
102
- def create(doc)
103
- body = get_body(doc)
104
- client.post("/people", data: body)
105
- end
106
-
107
- # Requests to update an existing person or if it does not exist, to create it, via api.
108
- # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
109
- # @return [Response] an object with the api response.
110
- def upsert(doc)
111
- body = get_body(doc)
112
- id = get_id(doc)
113
- client.post("/people/"+CGI.escape(id), data: body)
114
- end
115
-
116
- # Requests to completelly remove from an organization an existing person via api.
117
- # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
118
- # @return [Response] an object with the api response.
119
- def delete(doc)
120
- id = get_id(doc)
121
- client.delete("/people/"+CGI.escape(id))
122
- end
123
-
124
- # Creates a `BatchOperation` and yields it to the given bock.
125
- # @yield [batch_op] adds multiple api requests for the current batch.
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
129
- def batch(job_mode: true, &block)
130
- return job(&block) if job_mode
131
- operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
132
- yield operation
133
- # The batch operation is responsible for logging the output
134
- client.post("/people/batch", data: operation.as_json).tap do |response|
135
- operation.process_response(response)
136
- end
137
- end
138
-
139
- # @return [Ecoportal::API::Common::Response] the results of the batch job
140
- def job
141
- operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
142
- yield operation
143
- job_id = create_job(operation)
144
- status = wait_for_job_completion(job_id)
145
-
146
- if status&.complete?
147
- job_result(job_id, operation)
148
- else
149
- msg = "Job `#{job_id}` not complete. Probably timeout after #{JOB_TIMEOUT} seconds. Current status: #{status}"
150
- raise API::Errors::TimeOut.new msg
151
- end
152
- end
153
-
154
- # Creates a new `Person` object.
155
- # @return [Person] new empty person object of the current version.
156
- def new
157
- person_class.new
158
- end
159
-
160
- private
161
-
162
- JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
163
- def job_status(job_id)
164
- response = client.get("/people/job/#{CGI.escape(job_id)}/status")
165
- body = response && body_data(response.body)
166
- raise "Status error (#{response.status}) - Errors: #{body}" unless response.success?
167
- JobStatus.new(
168
- body["id"],
169
- body["complete"],
170
- body["errored"],
171
- body["progress"]
172
- )
173
- end
174
-
175
- # @return [Ecoportal::API::Common::Response] the results of the batch job
176
- def job_result(job_id, operation)
177
- client.get("/people/job/#{CGI.escape(job_id)}").tap do |response|
178
- operation.process_response(response)
179
- end
180
- end
181
-
182
- def wait_for_job_completion(job_id)
183
- # timeout library is evil. So we make poor-man timeout.
184
- # https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
185
- before = Time.now
186
- while true
187
- status = job_status(job_id)
188
- break status if status.complete?
189
- break status if Time.now >= before + JOB_TIMEOUT
190
- sleep(DELAY_STATUS_CHECK)
191
- status
192
- end
193
- end
194
-
195
- # @return [String] the `id` of the created batch job
196
- def create_job(operation)
197
- job_id = nil
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
201
- end
202
- job_id
203
- end
204
-
205
- # Hook for other api versions to obtain the raw data of a response
206
- # @note this was introduced to allow `v2` to reuse this class
207
- def body_data(body)
208
- body
209
- end
210
-
211
- end
212
- end
213
- end
214
- end
215
-
216
- require 'ecoportal/api/v1/schema_field_value'
217
- require 'ecoportal/api/v1/person_details'
218
- require 'ecoportal/api/v1/person'
1
+ module Ecoportal
2
+ module API
3
+ class V1
4
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
5
+ class People
6
+ extend Common::BaseClass
7
+ include Enumerable
8
+ include Common::DocHelpers
9
+
10
+ JOB_TIMEOUT = 240
11
+ DELAY_STATUS_CHECK = 5
12
+
13
+ class_resolver :person_class, "Ecoportal::API::V1::Person"
14
+
15
+ attr_reader :client
16
+
17
+ # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
18
+ # @return [People] an instance object ready to make people api requests.
19
+ def initialize(client)
20
+ @client = client
21
+ end
22
+
23
+ # Iterates all the people of the organization.
24
+ # @note
25
+ # - it ignores the key `cursor_id:` of `params:`.
26
+ # - `each` is called by `to_a`
27
+ # @param params [Hash]
28
+ # @option params [String] :per_page the number of people you get per request.
29
+ # @option params [String] :q some text to search. Omit this parameter to target all the people.
30
+ # @param silent [Boolean] `false` to show percentage of progress.
31
+ # @yield [person] does some stuff with the person.
32
+ # @yieldparam person [Person]
33
+ def each(params: {}, silent: false, &block)
34
+ return to_enum(:each, params: params, silent: silent) unless block
35
+ cursor_id = nil; results = 0
36
+ puts "\n" unless silent
37
+ loop do
38
+ params.update(cursor_id: cursor_id) if cursor_id
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
48
+ raise "Request failed - Status #{response.status}: #{body}" unless response.success?
49
+
50
+ unless silent || (total = body["total_results"]) == 0
51
+ results += body["results"].length
52
+ percent = results * 100 / total
53
+ msg = "People GET"
54
+ msg += " (search=#{params[:q]})" if params.key?(:q)
55
+ print "#{msg}: #{percent.round}% (of #{total})\r"
56
+ $stdout.flush
57
+ end
58
+
59
+ body["results"].each do |person|
60
+ yield person_class.new(person)
61
+ end
62
+ break unless (cursor_id = body["cursor_id"])
63
+ end
64
+ self
65
+ end
66
+
67
+ # Gets all the people via api requests.
68
+ # @note it ignores the key `:cursor_id` in `params:`.
69
+ # @param params [Hash]
70
+ # @option params [Integer] :per_page the number of people you get per request.
71
+ # @option params [String] :q some text to search.
72
+ # @param silent [Boolean] `false` to show percentage of progress.
73
+ # @return [Array<Person>] the array of people got via api.
74
+ def get_all(params: {}, silent: false)
75
+ each(params: params, silent: silent).to_a
76
+ end
77
+
78
+ # Gets a person via api.
79
+ # @note if the request has `success?` the returned `object.result` gives an object with that `Person`.
80
+ # @param doc [String, Hash, Person] data containing an `id` (internal or external) of the target person.
81
+ # @return [Person] the person with `id` (internal or external) contained in `doc`.
82
+ def get(doc)
83
+ id = get_id(doc)
84
+ response = client.get("/people/"+CGI.escape(id))
85
+ body = body_data(response.body)
86
+ return person_class.new(body) if response.success?
87
+ raise "Could not get person #{id} - Error #{response.status}: #{body}"
88
+ end
89
+
90
+ # Requests an update of a person via api.
91
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
92
+ # @return [Response] an object with the api response.
93
+ def update(doc)
94
+ body = get_body(doc)
95
+ id = get_id(doc)
96
+ client.patch("/people/"+CGI.escape(id), data: body)
97
+ end
98
+
99
+ # Requests to create a person via api.
100
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
101
+ # @return [Response] an object with the api response.
102
+ def create(doc)
103
+ body = get_body(doc)
104
+ client.post("/people", data: body)
105
+ end
106
+
107
+ # Requests to update an existing person or if it does not exist, to create it, via api.
108
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
109
+ # @return [Response] an object with the api response.
110
+ def upsert(doc)
111
+ body = get_body(doc)
112
+ id = get_id(doc)
113
+ client.post("/people/"+CGI.escape(id), data: body)
114
+ end
115
+
116
+ # Requests to completelly remove from an organization an existing person via api.
117
+ # @param doc [Person, Hash] data that at least contains an `id` (internal or external) of the target person.
118
+ # @return [Response] an object with the api response.
119
+ def delete(doc)
120
+ id = get_id(doc)
121
+ client.delete("/people/"+CGI.escape(id))
122
+ end
123
+
124
+ # Creates a `BatchOperation` and yields it to the given bock.
125
+ # @yield [batch_op] adds multiple api requests for the current batch.
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
129
+ def batch(job_mode: true, &block)
130
+ return job(&block) if job_mode
131
+ operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
132
+ yield operation
133
+ # The batch operation is responsible for logging the output
134
+ client.post("/people/batch", data: operation.as_json).tap do |response|
135
+ operation.process_response(response)
136
+ end
137
+ end
138
+
139
+ # @return [Ecoportal::API::Common::Response] the results of the batch job
140
+ def job
141
+ operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
142
+ yield operation
143
+ job_id = create_job(operation)
144
+ status = wait_for_job_completion(job_id)
145
+
146
+ if status&.complete?
147
+ job_result(job_id, operation)
148
+ else
149
+ msg = "Job `#{job_id}` not complete. Probably timeout after #{JOB_TIMEOUT} seconds. Current status: #{status}"
150
+ raise API::Errors::TimeOut.new msg
151
+ end
152
+ end
153
+
154
+ # Creates a new `Person` object.
155
+ # @return [Person] new empty person object of the current version.
156
+ def new
157
+ person_class.new
158
+ end
159
+
160
+ private
161
+
162
+ JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
163
+ def job_status(job_id)
164
+ response = client.get("/people/job/#{CGI.escape(job_id)}/status")
165
+ body = response && body_data(response.body)
166
+ raise "Status error (#{response.status}) - Errors: #{body}" unless response.success?
167
+ JobStatus.new(
168
+ body["id"],
169
+ body["complete"],
170
+ body["errored"],
171
+ body["progress"]
172
+ )
173
+ end
174
+
175
+ # @return [Ecoportal::API::Common::Response] the results of the batch job
176
+ def job_result(job_id, operation)
177
+ client.get("/people/job/#{CGI.escape(job_id)}").tap do |response|
178
+ operation.process_response(response)
179
+ end
180
+ end
181
+
182
+ def wait_for_job_completion(job_id)
183
+ # timeout library is evil. So we make poor-man timeout.
184
+ # https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
185
+ before = Time.now
186
+ while true
187
+ status = job_status(job_id)
188
+ break status if status.complete?
189
+ break status if Time.now >= before + JOB_TIMEOUT
190
+ sleep(DELAY_STATUS_CHECK)
191
+ status
192
+ end
193
+ end
194
+
195
+ # @return [String] the `id` of the created batch job
196
+ def create_job(operation)
197
+ job_id = nil
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
201
+ end
202
+ job_id
203
+ end
204
+
205
+ # Hook for other api versions to obtain the raw data of a response
206
+ # @note this was introduced to allow `v2` to reuse this class
207
+ def body_data(body)
208
+ body
209
+ end
210
+
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ require 'ecoportal/api/v1/schema_field_value'
217
+ require 'ecoportal/api/v1/person_details'
218
+ require 'ecoportal/api/v1/person'