eco-helpers 1.5.10 → 1.5.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +69 -1
  4. data/eco-helpers.gemspec +2 -2
  5. data/lib/eco/api/common/class_helpers.rb +45 -1
  6. data/lib/eco/api/common/loaders/error_handler.rb +2 -0
  7. data/lib/eco/api/common/loaders/parser.rb +4 -0
  8. data/lib/eco/api/common/loaders/use_case.rb +2 -0
  9. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +15 -2
  10. data/lib/eco/api/common/people/person_entry.rb +15 -3
  11. data/lib/eco/api/common/session/logger.rb +9 -1
  12. data/lib/eco/api/common/session/logger/cache.rb +91 -0
  13. data/lib/eco/api/common/session/logger/log.rb +48 -0
  14. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +9 -0
  15. data/lib/eco/api/microcases/people_cache.rb +7 -0
  16. data/lib/eco/api/microcases/people_load.rb +29 -21
  17. data/lib/eco/api/microcases/people_refresh.rb +6 -0
  18. data/lib/eco/api/microcases/people_search.rb +33 -8
  19. data/lib/eco/api/microcases/set_core_with_supervisor.rb +5 -3
  20. data/lib/eco/api/organization/tag_tree.rb +7 -0
  21. data/lib/eco/api/policies.rb +1 -0
  22. data/lib/eco/api/policies/default_policies.rb +12 -0
  23. data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +100 -0
  24. data/lib/eco/api/session.rb +13 -0
  25. data/lib/eco/api/session/batch/job.rb +17 -7
  26. data/lib/eco/api/session/config/api.rb +1 -1
  27. data/lib/eco/api/usecases.rb +1 -0
  28. data/lib/eco/api/usecases/ooze_samples.rb +11 -0
  29. data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +85 -0
  30. data/lib/eco/version.rb +1 -1
  31. metadata +11 -16
  32. data/lib/eco/api/usecases/backup/append_usergroups_case.rb +0 -36
  33. data/lib/eco/api/usecases/backup/create_case.rb +0 -104
  34. data/lib/eco/api/usecases/backup/create_details_case.rb +0 -31
  35. data/lib/eco/api/usecases/backup/create_details_with_supervisor_case.rb +0 -48
  36. data/lib/eco/api/usecases/backup/hris_case.rb +0 -124
  37. data/lib/eco/api/usecases/backup/set_default_tag_case.rb +0 -49
  38. data/lib/eco/api/usecases/backup/set_supervisor_case.rb +0 -41
  39. data/lib/eco/api/usecases/backup/transfer_account_case.rb +0 -90
  40. data/lib/eco/api/usecases/backup/update_case.rb +0 -112
  41. data/lib/eco/api/usecases/backup/update_details_case.rb +0 -64
  42. data/lib/eco/api/usecases/backup/upsert_case.rb +0 -114
@@ -13,6 +13,15 @@ module Ecoportal
13
13
  original_doc["details"] = JSON.parse(doc["details"])
14
14
  end
15
15
 
16
+ def identify
17
+ if entry
18
+ entry.to_s(:identify)
19
+ else
20
+ str_id = id ? "id: '#{id}'; " : ""
21
+ "#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
22
+ end
23
+ end
24
+
16
25
  end
17
26
  end
18
27
  end
@@ -6,7 +6,14 @@ module Eco
6
6
  # @return [Eco::API::Organization::People] the `People` object with the data.
7
7
  def people_cache(filename = enviro.config.people.cache)
8
8
  logger.info("Going to get all the people via API")
9
+
10
+ start = Time.now
9
11
  people = session.batch.get_people
12
+ secs = Time.now - start
13
+ cnt = people.count
14
+ per_sec = (cnt.to_f / secs).floor
15
+ logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
16
+
10
17
  file = file_manager.save_json(people, filename, :timestamp)
11
18
  logger.info("#{people.length} people loaded and saved locally to #{file}.")
12
19
  Eco::API::Organization::People.new(people)
@@ -18,27 +18,35 @@ module Eco
18
18
  def people_load(filename = enviro.config.people.cache, modifier: [:newest, :api])
19
19
  modifier = [modifier].flatten
20
20
  load_file = [:file, :newest].any? {|flag| modifier.include?(flag)}
21
- people = case
22
- when filename && load_file
23
- if file = people_load_filename(filename, newest: modifier.include?(:newest))
24
- file_manager.load_json(file).tap do |people|
25
- logger.info("#{people&.length} people loaded from file #{file}") if people.is_a?(Array)
26
- end
27
- else
28
- logger.error("could not find the file #{file_manager.dir.file(filename)}")
29
- exit unless modifier.include?(:api)
30
- people_load(modifier: modifier - [:newest, :file])
31
- end
32
- when modifier.include?(:api)
33
- logger.info("Going to get all the people via API")
34
- session.batch.get_people.tap do |people|
35
- if modifier.include?(:save) && people && people.length > 0
36
- file = file_manager.save_json(people, filename, :timestamp)
37
- logger.info("#{people.length } people saved to file #{file}.")
38
- end
39
- end
40
- end
41
- Eco::API::Organization::People.new(people)
21
+ case
22
+ when filename && load_file
23
+ if file = people_load_filename(filename, newest: modifier.include?(:newest))
24
+ file_manager.load_json(file).tap do |people|
25
+ logger.info("#{people&.length} people loaded from file #{file}") if people.is_a?(Array)
26
+ end
27
+ else
28
+ logger.error("could not find the file #{file_manager.dir.file(filename)}")
29
+ exit unless modifier.include?(:api)
30
+ people_load(modifier: modifier - [:newest, :file])
31
+ end
32
+ when modifier.include?(:api)
33
+ logger.info("Going to get all the people via API")
34
+
35
+ start = Time.now
36
+ session.batch.get_people.tap do |people|
37
+ secs = Time.now - start
38
+ cnt = people.count
39
+ per_sec = (cnt.to_f / secs).floor
40
+ logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
41
+
42
+ if modifier.include?(:save) && people && people.length > 0
43
+ file = file_manager.save_json(people, filename, :timestamp)
44
+ logger.info("#{people.length } people saved to file #{file}.")
45
+ end
46
+ end
47
+ end.yield_self do |people|
48
+ Eco::API::Organization::People.new(people)
49
+ end
42
50
  end
43
51
 
44
52
  private
@@ -18,7 +18,13 @@ module Eco
18
18
  msg = "Going to refresh #{people.length} people with server data"
19
19
  msg += " (including #{created} that were created)" if created > 0
20
20
  logger.info(msg)
21
+
22
+ start = Time.now
21
23
  entries = session.batch.get_people(people, silent: true)
24
+ secs = Time.now - start
25
+ cnt = entries.count
26
+ per_sec = (cnt.to_f / secs).floor
27
+ logger.info("Re-loaded #{cnt} people (out of #{people.length}) in #{secs} seconds (#{per_sec} people/sec)")
22
28
 
23
29
  missing = people.length - entries.length
24
30
  logger.error("Missed to obtain #{missing} people during the refresh") if missing > 0
@@ -11,24 +11,49 @@ module Eco
11
11
  # @return [Eco::API::Organization::People] the `People` object with the found persons.
12
12
  def people_search(data, options: {}, silent: true)
13
13
  session.logger.info("Going to api get #{data.length} entries...")
14
- status = session.batch.search(data, silent: silent)
15
- people = Eco::API::Organization::People.new(status.people)
16
- session.logger.info("... could get #{people.length} people (out of #{data.length} entries)")
14
+
15
+ start = Time.now
16
+ people = session.batch.search(data, silent: silent).yield_self do |status|
17
+ secs = Time.now - start
18
+ Eco::API::Organization::People.new(status.people).tap do |people|
19
+ cnt = people.count
20
+ per_sec = (cnt.to_f / secs).floor
21
+ msg = "... could get #{cnt} people (out of #{data.length} entries) in #{secs} seconds (#{per_sec} people/sec)"
22
+ session.logger.info(msg)
23
+ end
24
+ end
17
25
 
18
26
  # get the supervisors of found people (current supervisors)
19
27
  supers = people_search_prepare_supers_request(people)
20
28
  if supers.length > 0
21
29
  session.logger.info(" Going to api get #{supers.length} current supervisors...")
22
- status = session.batch.search(supers, silent: silent)
23
- people = people.merge(status.people, strict: micro.strict_search?(options))
30
+ start = Time.now
31
+ people = session.batch.search(supers, silent: silent).yield_self do |status|
32
+ secs = Time.now - start
33
+ found = status.people
34
+ cnt = found.count
35
+ per_sec = (cnt.to_f / secs).floor
36
+ msg = "... could find #{cnt} current supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
37
+ session.logger.info(msg)
38
+ people.merge(found, strict: micro.strict_search?(options))
39
+ end
24
40
  end
25
41
 
26
42
  # get the supervisors referred in the input data (future supervisors)
27
43
  supers = people_search_prepare_supers_request(data, people)
28
44
  if supers.length > 0
29
- session.logger.info(" Going to api get #{supers.length} supervisors as per entries...")
30
- status = session.batch.search(supers, silent: silent)
31
- people = people.merge(status.people, strict: micro.strict_search?(options))
45
+ session.logger.info(" Going to api get #{supers.length} supervisors as per input entries...")
46
+ start = Time.now
47
+
48
+ people = session.batch.search(supers, silent: silent).yield_self do |status|
49
+ secs = Time.now - start
50
+ found = status.people
51
+ cnt = found.count
52
+ per_sec = (cnt.to_f / secs).floor
53
+ msg = "... could find #{cnt} input supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
54
+ session.logger.info(msg)
55
+ people.merge(found, strict: micro.strict_search?(options))
56
+ end
32
57
  end
33
58
 
34
59
  session.logger.info("Finally got #{people.length} people (out of #{data.length} entries)")
@@ -11,9 +11,11 @@ module Eco
11
11
  def set_core_with_supervisor(entry, person, people, supers_job, options)
12
12
  unless options.dig(:exclude, :core) && !person.new?
13
13
  micro.set_core(entry, person, options)
14
- micro.set_supervisor(entry.supervisor_id, person, people, options) do |unkown_id|
15
- # delay setting supervisor if does not exit
16
- supers_job.add(person) {|person| person.supervisor_id = unkown_id}
14
+ if entry.supervisor_id?
15
+ micro.set_supervisor(entry.supervisor_id, person, people, options) do |unkown_id|
16
+ # delay setting supervisor if does not exit
17
+ supers_job.add(person) {|person| person.supervisor_id = unkown_id}
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -68,6 +68,13 @@ module Eco
68
68
  tags - tags(depth: depth)
69
69
  end
70
70
 
71
+ # Verifies if a tag exists in the subtree(s).
72
+ # @param key [String] tag to verify.
73
+ # @return [Boolean]
74
+ def subtag?(key)
75
+ subtags.include?(key&.upcase)
76
+ end
77
+
71
78
  # Verifies if a tag exists in the tree.
72
79
  # @param key [String] tag to verify.
73
80
  # @return [Boolean]
@@ -36,3 +36,4 @@ module Eco
36
36
  end
37
37
 
38
38
  require_relative 'policies/policy'
39
+ require_relative 'policies/default_policies'
@@ -0,0 +1,12 @@
1
+ module Eco
2
+ module API
3
+ class Policies
4
+ class DefaultPolicies < Eco::API::Policies
5
+ autoloads_children_of "Eco::API::Common::Loaders::Policy"
6
+ autoload_namespace "Eco::API::Policies::DefaultPolicies"
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative 'default_policies/99_user_access_policy'
@@ -0,0 +1,100 @@
1
+ class Eco::API::Policies::DefaultPolicies::UserAccess < Eco::API::Common::Loaders::Policy
2
+ name "default-user-access"
3
+
4
+ attr_reader :session, :options
5
+ attr_accessor :account_removed_count
6
+
7
+ def main(people, session, options, policy, job)
8
+ @session = session; @options = options
9
+
10
+ self.account_removed_count = 0
11
+
12
+ people.each do |person|
13
+ remove_account_when_no_email!(person) if person.email.to_s.empty?
14
+ person.account.policy_group_ids = [defid] if no_policy_group_ids?(person)
15
+ refresh_abilities!(person.account)
16
+ end
17
+
18
+ warn_account_removal!
19
+ end
20
+
21
+ private
22
+
23
+ def warn_account_removal!
24
+ if account_removed_count > 0
25
+ msg = "Removed account to #{account_removed_count} people"
26
+ session.logger.warn(msg)
27
+ end
28
+ end
29
+
30
+ def remove_account_when_no_email!(person)
31
+ if person.account
32
+ account_removed_count += 1 if had_account?(person)
33
+ person.account = nil
34
+ end
35
+ end
36
+
37
+ def had_account?(person)
38
+ return false if person.new?
39
+ return false if person.account_added?
40
+ return !!person.original_doc["account"]
41
+ end
42
+
43
+ def provision_basic_level!(person)
44
+ if account = person.account
45
+
46
+ unless options.dig(:exclude, :abilities)
47
+ account.permissions_custom = session.new_preset(person)
48
+
49
+ if no_abilities?(person)
50
+ account.permissions_custom = min_abilities
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+
57
+ def refresh_abilities!(account)
58
+ return nil unless account
59
+
60
+ end
61
+
62
+ def no_policy_group_ids?(person)
63
+ (account = person.account) && account.policy_group_ids.empty?
64
+ end
65
+
66
+ def no_abilities?(person)
67
+ person.account.permissions_custom &&
68
+ person.account.permissions_custom.values.all?(&:nil?)
69
+ end
70
+
71
+ def min_abilities
72
+ {
73
+ "files" => "upload",
74
+ "data" => nil,
75
+ "reports" => nil,
76
+ "pages" => "create",
77
+ "page_editor" => "basic",
78
+ "registers" => "view",
79
+ "organization" => nil,
80
+ "person_core" => "attach",
81
+ "person_core_edit" => nil,
82
+ "person_core_create" => nil,
83
+ "person_details" => "view",
84
+ "person_account" => nil
85
+ }
86
+ end
87
+
88
+ def defid
89
+ @defid ||= policy_groups.to_id(default_group)
90
+ end
91
+
92
+ def default_group
93
+ session.config.people.default_usergroup
94
+ end
95
+
96
+ def policy_groups
97
+ session.policy_groups
98
+ end
99
+
100
+ end
@@ -187,6 +187,8 @@ module Eco
187
187
  end
188
188
 
189
189
  # Does merge `Eco::API::UseCases::DefaultCases` with the custom cases.
190
+ # @note
191
+ # - the order matters, as a default usecase can be redefined by a custom one with same name
190
192
  # @return [Eco::API::UseCases]
191
193
  def usecases
192
194
  @usecases ||= config.usecases.dup.tap do |cases|
@@ -195,6 +197,17 @@ module Eco
195
197
  end
196
198
  end
197
199
 
200
+ # Does merge `Eco::API::Policies::DefaultPolicies` with the custom policies.
201
+ # @note
202
+ # - the default policies are added at the end (meaning they will run after the custom policies)
203
+ # @return [Eco::API::Policies]
204
+ def policies
205
+ @policies ||= config.policies.dup.tap do |policies|
206
+ default_policies = Eco::API::Policies::DefaultPolicies.new
207
+ policies.merge(default_policies)
208
+ end
209
+ end
210
+
198
211
  # Set of helpers to simplify your code
199
212
  # @see Eco::API::MicroCases
200
213
  # @return [Eco::API::MicroCases]
@@ -71,12 +71,6 @@ module Eco
71
71
  @subjobs ||= Eco::API::Session::Batch::Jobs.new(enviro, name: "childs-of:#{self.name}")
72
72
  end
73
73
 
74
- def subjobs_add(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase, &block)
75
- dup(name, usecase: usecase).tap do |subjob|
76
- subjobs.add(subjob, &block)
77
- end
78
- end
79
-
80
74
  # @return [Boolean] `true` if the current batch job is a result of an error_handler
81
75
  def error_handler?
82
76
  usecase? && usecase.is_a?(Eco::API::Error::Handler)
@@ -211,6 +205,7 @@ module Eco
211
205
  end
212
206
 
213
207
  msg << status.errors.message unless !status
208
+ msg << subjobs_summary
214
209
  end
215
210
  end.join("\n")
216
211
  end
@@ -238,7 +233,7 @@ module Eco
238
233
  # Applies the changes introduced by api policies
239
234
  def apply_policies(pre_queue)
240
235
  people(pre_queue).tap do |entries|
241
- policies = session.config.policies
236
+ policies = session.policies
242
237
  unless policies.empty? || options.dig(:skip, :api_policies)
243
238
  policies.launch(people: entries, session: session, options: options, job: self)
244
239
  end
@@ -307,6 +302,21 @@ module Eco
307
302
  file_manager.save_json(requests, file, :timestamp)
308
303
  end
309
304
 
305
+ # Adds a job tied to the current job
306
+ # Used with error handlers that need their own job to run
307
+ def subjobs_add(name = "ad-hoc:job-from:#{self.name}", usecase: self.usecase, &block)
308
+ dup(name, usecase: usecase).tap do |subjob|
309
+ subjobs.add(subjob, &block)
310
+ end
311
+ end
312
+
313
+ def subjobs_summary
314
+ return "" unless subjobs.count > 0
315
+ [].tap do |msg|
316
+ subjobs.map {|subjob| msg << subjob.summary}
317
+ end.join("\n")
318
+ end
319
+
310
320
  end
311
321
  end
312
322
  end
@@ -142,7 +142,7 @@ module Eco
142
142
  when :v1
143
143
  klass.new(external_key, host: host, logger: logger)
144
144
  when :v2
145
- klass.new(user_key: user_key, org_key: external_key, logger: logger)
145
+ klass.new(user_key: user_key, org_key: external_key, host: host, logger: logger)
146
146
  end.tap do |api|
147
147
  unless !api || log_connection?
148
148
  @logger.info("Created api#{self.version(version)} connection on '#{name}' enviro, pointing to '#{host}' in '#{mode}' mode")
@@ -160,3 +160,4 @@ require_relative 'usecases/use_case_chain'
160
160
  require_relative 'usecases/base_io'
161
161
  require_relative 'usecases/use_case_io'
162
162
  require_relative 'usecases/default_cases'
163
+ require_relative 'usecases/ooze_samples'
@@ -0,0 +1,11 @@
1
+ module Eco
2
+ module API
3
+ class UseCases
4
+ class OozeSamples
5
+
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ require_relative 'ooze_samples/ooze_update_case'
@@ -0,0 +1,85 @@
1
+ class Eco::API::UseCases::OozeSamples::OozeUpdateCase < Eco::API::Common::Loaders::UseCase
2
+ name "single-ooze-case"
3
+ type :other
4
+
5
+ attr_reader :session, :options, :usecase
6
+
7
+ SAVE_PATCH = "ooze_patch_update.json"
8
+
9
+ def main(session, options, usecase)
10
+ @session = session; @options = options; @usecase = usecase
11
+ yield
12
+ end_script!
13
+ end
14
+
15
+ private
16
+
17
+ def end_script!
18
+ exit_if_no_changes!
19
+ backup_patch!
20
+ launch_request unless options[:simulate]
21
+ exit(0)
22
+ end
23
+
24
+ def ooze_id
25
+ options.dig(:source, :ooze_id)
26
+ end
27
+
28
+ def ooze
29
+ @ooze ||= apiv2.pages.get(ooze_id).tap do |ooze|
30
+ if ooze
31
+ logger.info("Got ooze '#{ooze_id}': '#{ooze.name}'")
32
+ else
33
+ logger.error("Could not get ooze '#{ooze_id}'")
34
+ exit(1)
35
+ end
36
+ end
37
+ end
38
+
39
+ def launch_request
40
+ prompt_to_confirm!
41
+
42
+ apiv2.pages.update(ooze).tap do |response|
43
+ if response.success?
44
+ logger.info("All went OK")
45
+ else
46
+ logger.error(response.body)
47
+ end
48
+ end
49
+ end
50
+
51
+ def exit_if_no_changes!
52
+ unless changes = !!patch_doc["page"]
53
+ logger.warn "No Changes!!"
54
+ exit(0)
55
+ end
56
+ end
57
+
58
+ def apiv2
59
+ @apiv2 ||= session.api(version: :oozes)
60
+ end
61
+
62
+ def patch_doc(renew: false)
63
+ return @patch_doc if @patch_doc && !renew
64
+ @patch_doc = apiv2.pages.get_body(ooze)
65
+ end
66
+
67
+ def backup_patch!
68
+ # store the request
69
+ File.open(SAVE_PATCH, "w") do |file|
70
+ #file << (patch_doc || {}).to_json
71
+ file << JSON.pretty_generate(patch_doc || {})
72
+ end
73
+ puts "Saved patch at: #{File.expand_path(SAVE_PATCH)}"
74
+ end
75
+
76
+ def logger
77
+ session.logger
78
+ end
79
+
80
+ def prompt_to_confirm!
81
+ print "\nDo you want to proceed (y/N)? "
82
+ exit(1) unless $stdin.gets.chomp.to_s.downcase == "y"
83
+ end
84
+
85
+ end