ecoportal-api 0.8.5 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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'