ecoportal-api 0.4.3 → 0.5.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5441ef892224dc43af0a9060cf90725d93640cc98a66642565962ace69eefa00
4
- data.tar.gz: 5c53d8665f94cae4e06f86b72cc4807ed8862908f0999156fd792d38c8a46ed5
3
+ metadata.gz: 31190d7d5719d21b732605d97eccaad0c042f9fc3212fc5f181e6e18e6f12771
4
+ data.tar.gz: e7bb04368723c7da36ca8408b05088ed09753c9f9fa53722b32c3ef0df3f6e0e
5
5
  SHA512:
6
- metadata.gz: 0102b941ada369991d37a24676fedf97055633b3df0b4b0198f5dfef7007ddc289b53c1e36cdf4a0aae4afa995a26b05c26a3d2df5aecdcfeabe6e53bf108650
7
- data.tar.gz: e3d0401ba1d6d91508812f549677e23fc60667cb794d22cafe82fc5bda8c344b529cf248856c36f1d13dad9d4e0bc8a00d66844f628686b6b3442035521f1a12
6
+ metadata.gz: f10ac460fa44b8750825f46648f54d394b36b9a4bec95b138724dd79f278db4014540bb268fecf9e4a3e719b8eb03da1d398a15203776706643eaa9437ba9fe8
7
+ data.tar.gz: 67185025081f552f608ba0512fce293ef5a731d31fee2b2132e276eda04f85bd135b0f268936209af1e948ff066f537d7834c005a302ca251f75359d7cfeb758
@@ -0,0 +1,55 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5.1
3
+ Exclude:
4
+ - 'config/routes.rb'
5
+
6
+ Metrics/LineLength:
7
+ Enabled: false
8
+ Metrics/BlockLength:
9
+ ExcludedMethods: [context, describe]
10
+ Max: 50
11
+ Metrics/MethodLength:
12
+ Max: 50
13
+ Metrics/ClassLength:
14
+ Max: 200
15
+ Metrics/AbcSize:
16
+ Max: 30
17
+
18
+ ParameterLists:
19
+ Max: 5
20
+ CountKeywordArgs: false
21
+
22
+ Style/StringLiterals:
23
+ Enabled: false
24
+ Style/FrozenStringLiteralComment:
25
+ Enabled: false
26
+ Style/CommentedKeyword:
27
+ Enabled: false
28
+ Style/MultilineBlockChain:
29
+ Enabled: false
30
+ Style/Documentation:
31
+ Enabled: false
32
+ Style/StringLiteralsInInterpolation:
33
+ Enabled: false
34
+ Style/AndOr:
35
+ Enabled: false
36
+
37
+ Layout/SpaceInsideHashLiteralBraces:
38
+ Enabled: false
39
+ Layout/SpaceInsideBlockBraces:
40
+ Enabled: false
41
+ Layout/SpaceAroundOperators:
42
+ Enabled: false
43
+ Layout/ExtraSpacing:
44
+ AllowForAlignment: true
45
+ Layout/AccessModifierIndentation:
46
+ EnforcedStyle: indent
47
+ Layout/DotPosition:
48
+ EnforcedStyle: trailing
49
+ Layout/MultilineMethodCallIndentation:
50
+ EnforcedStyle: indented
51
+ Layout/IndentHash:
52
+ Enabled: false
53
+
54
+ Naming/VariableNumber:
55
+ EnforcedStyle: snake_case
@@ -0,0 +1,10 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ ## [0.5.6] - 2020-06-xx
5
+
6
+ ### Added
7
+ - this `CHANGELOG.md` file
8
+ - person model: `freemium` core property
9
+ ### Changed
10
+ ### Fixed
@@ -10,5 +10,5 @@ require "ecoportal/api"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
14
- IRB.start(__FILE__)
13
+ require "pry"
14
+ Pry.start(__FILE__)
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "ecoportal-api"
8
8
  spec.version = Ecoportal::API::VERSION
9
9
  spec.authors = ["Tapio Saarinen"]
10
- spec.email = ["tapio@ecoportal.co.nz"]
10
+ spec.email = ["tapio@ecoportal.co.nz", "rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
11
11
 
12
12
  spec.summary = %q{A collection of helpers for interacting with the ecoPortal MS's various APIs}
13
13
  spec.homepage = "https://www.ecoportal.com"
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rspec", "~> 3.0"
26
26
  spec.add_development_dependency "yard", "~> 0.9", ">= 0.9.18"
27
27
  spec.add_development_dependency "redcarpet", "~> 3.4", ">= 3.4.0"
28
+ spec.add_development_dependency "pry"
28
29
 
29
30
  spec.add_dependency 'http', '~> 3'
30
31
  spec.add_dependency 'hash-polyfill', '~> 0'
@@ -3,17 +3,15 @@ module Ecoportal
3
3
  class Internal
4
4
  class Account < Common::BaseModel
5
5
  passthrough :policy_group_ids, :landing_page_id, :permissions_preset, :permissions_custom,
6
- :preferences, :prefilter, :filter_tags, :login_provider_ids, :starred_ids, :accept_eula,
6
+ :preferences, :prefilter, :login_provider_ids, :starred_ids, :accept_eula,
7
7
  :send_invites, :default_tag
8
8
 
9
9
  class_resolver :preferences_class, "Ecoportal::API::Internal::Preferences"
10
10
  class_resolver :permissions_class, "Ecoportal::API::Internal::Permissions"
11
-
11
+
12
12
  embeds_one :permissions, key: "permissions_custom", klass: :permissions_class
13
13
  embeds_one :preferences, klass: :preferences_class
14
14
 
15
- VALID_TAG_REGEX = /^[A-Za-z0-9 &_'\/-]+$/
16
-
17
15
  # Sets the `permissions_preset`.
18
16
  # @note basically the same as `permissions_preset=` but when `"custom"`, it's changed to `nil`
19
17
  # @param value [nil, String] preset name.
@@ -28,22 +26,6 @@ module Ecoportal
28
26
  self.permissions_preset.nil? ? "custom" : self.permissions_preset
29
27
  end
30
28
 
31
- # Validates the string tags of the array, and sets the `filter_tags` property of the account.
32
- # @note all is set in upper case.
33
- # @raise [Exception] if there was any invalid string tag.
34
- # @param value [Array<String>] array of tags.
35
- def filter_tags=(value)
36
- unless value.is_a?(Array)
37
- raise "filter_tags= needs to be passed an Array, got #{value.class}"
38
- end
39
- doc["filter_tags"] = value.map do |tag|
40
- unless tag.match(VALID_TAG_REGEX)
41
- raise "Invalid filter tag #{tag.inspect}"
42
- end
43
- tag.upcase
44
- end
45
- end
46
-
47
29
  def as_json
48
30
  super.tap do |hash|
49
31
  if preset == "custom"
@@ -25,10 +25,7 @@ module Ecoportal
25
25
  when Internal::Account
26
26
  doc["account"] = JSON.parse(value.to_json)
27
27
  when Hash
28
- # TODO:
29
- # => missing send_invites
30
- # => better use an Internal::Account::PROPERTIES const for this kind of stuff
31
- doc["account"] = value.slice(%w[policy_group_ids landing_page_id permissions_preset permissions_custom preferences prefilter filter_tags login_provider_ids starred_ids])
28
+ doc["account"] = value.slice(*%w[policy_group_ids default_tag landing_page_id permissions_preset permissions_custom preferences prefilter login_provider_ids starred_ids])
32
29
  else
33
30
  # TODO
34
31
  raise "Invalid set on account: Need nil, Account or Hash; got #{value.class}"
@@ -7,7 +7,16 @@ module Ecoportal
7
7
  :show_shortcuts,
8
8
  :show_coming_soon,
9
9
  :show_recently_visited_forms,
10
- :show_tasks
10
+ :show_tasks,
11
+ :show_task_bubbles,
12
+ :kiosk_enabled,
13
+ :kiosk_workflow_message,
14
+ :kiosk_create_button_label,
15
+ :kiosk_create_button_help,
16
+ :kiosk_return_button_label,
17
+ :kiosk_return_button_help,
18
+ :kiosk_dashboard_button_label,
19
+ :kiosk_dashboard_button_help
11
20
  ].each do |field|
12
21
  define_method(field) do
13
22
  if doc.key?(field)
@@ -7,7 +7,10 @@ module Ecoportal
7
7
  include Enumerable
8
8
  include Common::DocHelpers
9
9
 
10
- class_resolver :person_class, "Ecoportal::API::V1::Person"
10
+ JOB_TIMEOUT = 60
11
+ DELAY_STATUS_CHECK = 5
12
+
13
+ class_resolver :person_class, "Ecoportal::API::V1::Person"
11
14
 
12
15
  attr_reader :client
13
16
 
@@ -19,7 +22,7 @@ module Ecoportal
19
22
 
20
23
  # Iterates all the people of the organization.
21
24
  # @note
22
- # - it ignores the key `results_from:` of `params:`.
25
+ # - it ignores the key `cursor_id:` of `params:`.
23
26
  # - `each` is called by `to_a`
24
27
  # @param params [Hash]
25
28
  # @option params [String] :per_page the number of people you get per request.
@@ -28,15 +31,15 @@ module Ecoportal
28
31
  # @yieldparam person [Person]
29
32
  def each(params: {}, &block)
30
33
  return to_enum(:each) unless block
31
- results_from = nil
34
+ cursor_id = nil
32
35
  loop do
33
- params.update(results_from: results_from) if results_from
36
+ params.update(cursor_id: cursor_id) if cursor_id
34
37
  response = client.get("/people", params: params)
35
38
  raise "Request failed." unless response.success?
36
39
  response.body["results"].each do |person|
37
40
  yield person_class.new(person)
38
41
  end
39
- break unless (results_from = response.body["next_results_from"])
42
+ break unless (cursor_id = response.body["cursor_id"])
40
43
  end
41
44
  self
42
45
  end
@@ -56,7 +59,7 @@ module Ecoportal
56
59
  # @param doc [String, Hash, Person] data containing an `id` (internal or external) of the target person.
57
60
  # @return [WrappedResponse] an object with the api response.
58
61
  def get(doc)
59
- response = client.get("/people/"+CGI::escape(get_id(doc)))
62
+ response = client.get("/people/"+CGI.escape(get_id(doc)))
60
63
  Common::WrappedResponse.new(response, person_class)
61
64
  end
62
65
 
@@ -66,7 +69,7 @@ module Ecoportal
66
69
  def update(doc)
67
70
  body = get_body(doc)
68
71
  id = get_id(doc)
69
- client.patch("/people/"+CGI::escape(id), data: body)
72
+ client.patch("/people/"+CGI.escape(id), data: body)
70
73
  end
71
74
 
72
75
  # Requests to create a person via api.
@@ -83,7 +86,7 @@ module Ecoportal
83
86
  def upsert(doc)
84
87
  body = get_body(doc)
85
88
  id = get_id(doc)
86
- client.post("/people/"+CGI::escape(id), data: body)
89
+ client.post("/people/"+CGI.escape(id), data: body)
87
90
  end
88
91
 
89
92
  # Requests to completelly remove from an organization an existing person via api.
@@ -91,13 +94,14 @@ module Ecoportal
91
94
  # @return [Response] an object with the api response.
92
95
  def delete(doc)
93
96
  id = get_id(doc)
94
- client.delete("/people/"+CGI::escape(id))
97
+ client.delete("/people/"+CGI.escape(id))
95
98
  end
96
99
 
97
100
  # Creates a `BatchOperation` and yields it to the given bock.
98
101
  # @yield [batch_op] adds multiple api requests for the current batch.
99
102
  # @yieldparam batch_op [BatchOperation]
100
- def batch
103
+ def batch(job_mode: true, &block)
104
+ return job(&block) if job_mode
101
105
  operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
102
106
  yield operation
103
107
  # The batch operation is responsible for logging the output
@@ -108,12 +112,72 @@ module Ecoportal
108
112
  end
109
113
  end
110
114
 
115
+ def job
116
+ operation = Common::BatchOperation.new("/people", person_class, logger: client.logger)
117
+ yield operation
118
+ # The batch operation is responsible for logging the output
119
+ job_id = create_job(operation)
120
+ status = wait_for_job_completion(job_id)
121
+
122
+ if status&.complete?
123
+ operation.process_response job_result(job_id, operation)
124
+ else
125
+ raise "Job `#{job_id}` not complete. Probably timeout after #{JOB_TIMEOUT} seconds. Current status: #{status}"
126
+ end
127
+ end
128
+
111
129
  # Creates a new `Person` object.
112
130
  # @return [Person] new empty person object of the current version.
113
131
  def new
114
132
  person_class.new
115
133
  end
116
134
 
135
+ private
136
+
137
+ JobStatus = Struct.new(:id, :complete?, :errored?, :progress)
138
+ def job_status(job_id)
139
+ response = client.get("/people/job/#{CGI.escape(job_id)}/status")
140
+
141
+ raise "Status error" unless response.success?
142
+ JobStatus.new(
143
+ response.body["id"],
144
+ response.body["complete"],
145
+ response.body["errored"],
146
+ response.body["progress"]
147
+ )
148
+ end
149
+
150
+ def job_result(job_id, operation)
151
+ # The batch operation is responsible for logging the output
152
+ client.without_response_logging do
153
+ client.get("/people/job/#{CGI.escape(job_id)}").tap do |response|
154
+ operation.process_response(response)
155
+ end
156
+ end
157
+ end
158
+
159
+ def wait_for_job_completion(job_id)
160
+ # timeout library is evil. So we make poor-man timeout.
161
+ # https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
162
+ before = Time.now
163
+ while true
164
+ status = job_status(job_id)
165
+ break status if status.complete?
166
+ break status if Time.now >= before + JOB_TIMEOUT
167
+ sleep(DELAY_STATUS_CHECK)
168
+ status
169
+ end
170
+ end
171
+
172
+ def create_job(operation)
173
+ job_id = nil
174
+ client.without_response_logging do
175
+ client.post("/people/job", data: operation.as_json).tap do |response|
176
+ job_id = response.body["id"]
177
+ end
178
+ end
179
+ job_id
180
+ end
117
181
  end
118
182
  end
119
183
  end
@@ -8,12 +8,14 @@ module Ecoportal
8
8
  # @attr_reader subordinates [Integer] the number of people this person is supervisor of.
9
9
  # @attr details [PersonDetails, nil] the details of the person or `nil` if missing.
10
10
  class Person < Common::BaseModel
11
- passthrough :id, :external_id, :name, :email, :supervisor_id, :subordinates
11
+ passthrough :id, :external_id, :name, :email, :supervisor_id, :subordinates, :filter_tags, :freemium
12
12
 
13
13
  class_resolver :person_schema_class, "Ecoportal::API::V1::PersonSchema"
14
14
  class_resolver :person_details_class, "Ecoportal::API::V1::PersonDetails"
15
15
  embeds_one :details, nullable: true, klass: :person_details_class
16
16
 
17
+ VALID_TAG_REGEX = /^[A-Za-z0-9 &_'\/-]+$/
18
+
17
19
  # Gets the supervisor (`Person`) of this person, with given his `supervisor_id`.
18
20
  #
19
21
  # **Example Usage**:
@@ -39,6 +41,22 @@ module Ecoportal
39
41
  self.supervisor_id = person&.id || person&.external_id
40
42
  end
41
43
 
44
+ # Validates the string tags of the array, and sets the `filter_tags` property of the account.
45
+ # @note all is set in upper case.
46
+ # @raise [Exception] if there was any invalid string tag.
47
+ # @param value [Array<String>] array of tags.
48
+ def filter_tags=(value)
49
+ unless value.is_a?(Array)
50
+ raise "filter_tags= needs to be passed an Array, got #{value.class}"
51
+ end
52
+ doc["filter_tags"] = value.map do |tag|
53
+ unless tag.match(VALID_TAG_REGEX)
54
+ raise "Invalid filter tag #{tag.inspect}"
55
+ end
56
+ tag.upcase
57
+ end
58
+ end
59
+
42
60
  def as_json
43
61
  super.merge "details" => details&.as_json
44
62
  end
@@ -1,5 +1,5 @@
1
1
  module Ecoportal
2
2
  module API
3
- VERSION = "0.4.3"
3
+ VERSION = "0.5.6"
4
4
  end
5
5
  end
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.4.3
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tapio Saarinen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-12 00:00:00.000000000 Z
11
+ date: 2020-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -92,6 +92,20 @@ dependencies:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
94
  version: '3.4'
95
+ - !ruby/object:Gem::Dependency
96
+ name: pry
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
95
109
  - !ruby/object:Gem::Dependency
96
110
  name: http
97
111
  requirement: !ruby/object:Gem::Requirement
@@ -123,14 +137,19 @@ dependencies:
123
137
  description:
124
138
  email:
125
139
  - tapio@ecoportal.co.nz
140
+ - rien@ecoportal.co.nz
141
+ - oscar@ecoportal.co.nz
142
+ - bozydar@ecoportal.co.nz
126
143
  executables: []
127
144
  extensions: []
128
145
  extra_rdoc_files: []
129
146
  files:
130
147
  - ".gitignore"
131
148
  - ".rspec"
149
+ - ".rubocop.yml"
132
150
  - ".travis.yml"
133
151
  - ".yardopts"
152
+ - CHANGELOG.md
134
153
  - Gemfile
135
154
  - Gemfile.lock
136
155
  - LICENSE