eco-helpers 1.5.13 → 2.0.4

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +71 -0
  3. data/eco-helpers.gemspec +31 -29
  4. data/lib/eco/api.rb +1 -1
  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/person_entry.rb +15 -3
  10. data/lib/eco/api/common/people/person_parser.rb +10 -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/policies.rb +1 -0
  20. data/lib/eco/api/policies/default_policies.rb +12 -0
  21. data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +88 -0
  22. data/lib/eco/api/session.rb +13 -0
  23. data/lib/eco/api/session/batch.rb +0 -3
  24. data/lib/eco/api/session/batch/job.rb +17 -7
  25. data/lib/eco/api/session/config/workflow.rb +1 -0
  26. data/lib/eco/api/usecases.rb +1 -0
  27. data/lib/eco/api/usecases/ooze_samples.rb +11 -0
  28. data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +131 -0
  29. data/lib/eco/version.rb +1 -1
  30. metadata +42 -47
  31. data/lib/eco/api/usecases/backup/append_usergroups_case.rb +0 -36
  32. data/lib/eco/api/usecases/backup/create_case.rb +0 -104
  33. data/lib/eco/api/usecases/backup/create_details_case.rb +0 -31
  34. data/lib/eco/api/usecases/backup/create_details_with_supervisor_case.rb +0 -48
  35. data/lib/eco/api/usecases/backup/hris_case.rb +0 -124
  36. data/lib/eco/api/usecases/backup/set_default_tag_case.rb +0 -49
  37. data/lib/eco/api/usecases/backup/set_supervisor_case.rb +0 -41
  38. data/lib/eco/api/usecases/backup/transfer_account_case.rb +0 -90
  39. data/lib/eco/api/usecases/backup/update_case.rb +0 -112
  40. data/lib/eco/api/usecases/backup/update_details_case.rb +0 -64
  41. data/lib/eco/api/usecases/backup/upsert_case.rb +0 -114
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f83b4bc20ff8289dbc743531ceaf75350fefbefa687c3f88ae09325b762e1fd1
4
- data.tar.gz: b6ecd929fc1494ba657755020eac2cd92bdfe1ad4b4e5beb454c2bcaea165b77
3
+ metadata.gz: 28b5de98751cc76d2642fa0ac4d08a2567ce937095bed3d567c728ccc8503580
4
+ data.tar.gz: a69fb97c974f2241f563c203689eca6c8b584b84634a606de037cf529fa595ba
5
5
  SHA512:
6
- metadata.gz: 0fbb3710424b72248a2abefb0a0c8682a6fa4e97c69b50af951298c867582e4e857b5db25fd0afe1ba0a6379f6ba85e751a48c1bed1b091ad0a180f1d52f73df
7
- data.tar.gz: 16157a6f8f6118574bec5ca59716b9c52b860b89acab5a7d56bc720b34339de80b747543da684ddd68b23c694f0a67e6af82396f95c1b3811bcf203e7cadb7ee
6
+ metadata.gz: 75b8a884c4dbcaf27898cb9ea046e91e492eebf6d54d93b69c4b8303fefde9f25daf548aea2b7fea37ec2087a38596f5d506909a0295accae0bac2ccfe7751d2
7
+ data.tar.gz: dbdd106ad836cef111d8293e338adcc6b79d5cc37f6e61995569e73f1749a7dc896c9fa77192a1a27ffe07d185ce5057461cc45b99598321f1d30bc8c4cf25a0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,77 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [2.0.4] - 2021-02-23
5
+
6
+ ### Added
7
+ ### Changed
8
+ - `Eco::API::Common::People::PersonParser#defined_attrs` to include virtual attributes
9
+
10
+ ### Fixed
11
+
12
+ ## [2.0.3] - 2021-02-23
13
+
14
+ ### Added
15
+ - `Eco::API::UseCases::OozeSamples::OozeUpdateCase`: added integration to update page instances (non-templates)
16
+
17
+ ### Changed
18
+ ### Fixed
19
+ - `Eco::API::Policies::DefaultPolicies::UserAccess` complete default policy code.
20
+
21
+ ## [2.0.2] - 2021-02-22
22
+
23
+ ### Added
24
+ ### Changed
25
+ - upgraded dependencies with `ecoportal-api`
26
+
27
+ ### Fixed
28
+
29
+
30
+ ## [2.0.1] - 2021-02-22
31
+
32
+ ### Added
33
+ ### Changed
34
+ - upgraded dependencies with `ecoportal-api-oozes` to `ecoportal-api-v2`
35
+
36
+ ### Fixed
37
+
38
+ ## [1.5.15] - 2021-02-17
39
+
40
+ ### Added
41
+ - `Eco::API::Common::ClassHelpers` added support for class methods inheritance
42
+ - this is key to be able to define usecase models to inherit from
43
+ - `Eco::API::UseCases::OozeSamples::OozeUpdateCase`: added this sample to inherit from (simplifying use cases code)
44
+ - `Eco::API::Common::ClassHelpers` added inheritable attribute values
45
+ - added benchmarking to people loaders:
46
+ - `Eco::API::MicroCases#people_load`
47
+ - `Eco::API::MicroCases#people_cache`
48
+ - `Eco::API::MicroCases#people_search`
49
+ - `Eco::API::MicroCases#refresh`
50
+
51
+ ### Changed
52
+ ### Fixed
53
+ - `Eco::API::Policies::DefaultPolicies::UserAccess` typos in default api policy
54
+
55
+ ## [1.5.14] - 2021-02-05
56
+
57
+ ### Added
58
+ - `Eco::API::Policies::DefaultPolicies` policies that are run always (after the custom policies)
59
+ - `Eco::API::Policies::DefaultPolicies::UserAccess`:
60
+ - remove account if there's no `email`
61
+ - provision min user level to those with account (if no usergroup and no abilities)
62
+ - `Eco::API::Session#policies` which merges the default policies to be added/run after the custom policies
63
+ - `Eco::API::Common::Session::Logger`: add caching of logs
64
+ - `Eco::API::Common::Session::Logger::Cache` new class to manage cached logs
65
+ - `Eco::API::Common::Session::Logger::Log` new class to have a trace on logs
66
+ - `Eco::API::Session::Batch::Job#summary` added subjobs (error handlers) summary
67
+
68
+ ### Changed
69
+ - `Eco::API::Session::Batch::Job#launch` it will also run the default api policies before feedback and query launch
70
+ - `Eco::API::Common::People::PersonEntry` add error log when wrong email error is detected
71
+ - previously it would have crashed
72
+
73
+ ### Fixed
74
+
4
75
  ## [1.5.13] - 2021-02-01
5
76
 
6
77
  ### Added
data/eco-helpers.gemspec CHANGED
@@ -3,37 +3,39 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require "./lib/eco/version"
5
5
 
6
- Gem::Specification.new do |s|
7
- s.name = "eco-helpers"
8
- s.version = Eco::VERSION
9
- s.platform = Gem::Platform::RUBY
10
- s.authors = ["Oscar Segura"]
11
- s.email = ["oscar@ecoportal.co.nz"]
12
- s.date = %q{2018-09-05}
13
- s.summary = %q{eco-helpers to manage people api cases}
14
- s.homepage = "https://www.ecoportal.com"
15
- s.licenses = %w[MIT]
16
- s.required_ruby_version = '>= 2.4.4'
17
-
18
- s.files = `git ls-files -z`.split("\x0").reject do |f|
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "eco-helpers"
8
+ spec.version = Eco::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Oscar Segura"]
11
+ spec.email = ["oscar@ecoportal.co.nz"]
12
+ spec.date = %q{2018-09-05}
13
+ spec.summary = %q{eco-helpers to manage people api cases}
14
+ spec.homepage = "https://www.ecoportal.com"
15
+ spec.licenses = %w[MIT]
16
+
17
+ spec.required_ruby_version = '>= 2.4.4'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
20
  f.match(%r{^(test|spec|features)/})
20
21
  end
21
22
 
22
- #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
- #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
- s.require_paths = ["lib"]
25
-
26
- s.add_development_dependency "bundler", ">= 2.1.3", "< 2.2"
27
- s.add_development_dependency "rspec", ">= 3.9", "< 4"
28
- s.add_development_dependency "rake", ">= 12.3.0", "< 13"
29
- s.add_development_dependency "yard", ">= 0.9.18", "< 0.10"
30
- s.add_development_dependency "redcarpet", ">= 3.5.0", "< 3.6"
31
-
32
- s.add_dependency 'ecoportal-api', '>= 0.7.4', '< 0.8'
33
- s.add_dependency 'ecoportal-api-oozes', '>= 0.7.3', '< 0.8'
34
- s.add_dependency 'aws-sdk-s3', '>= 1.64.0', '< 2'
35
- s.add_dependency 'aws-sdk-ses', '>= 1.29.0', '< 2'
36
- s.add_dependency 'dotenv', '>= 2.7.0', '< 2.8'
37
- s.add_dependency 'net-sftp', '>= 2.1.2', '< 2.2'
23
+ #spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ #spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_development_dependency "bundler", ">= 2.2.11", "< 2.3"
28
+ spec.add_development_dependency "rspec", ">= 3.10.0", "< 3.11"
29
+ spec.add_development_dependency "rake", ">= 13.0.3", "< 13.1"
30
+ spec.add_development_dependency "yard", ">= 0.9.26", "< 0.10"
31
+ spec.add_development_dependency "redcarpet", ">= 3.5.1", "< 3.6"
32
+
33
+ spec.add_dependency 'ecoportal-api', '>= 0.8.1', '< 0.9'
34
+ #spec.add_dependency 'ecoportal-api', '>= 0.7.5', '< 0.8'
35
+ spec.add_dependency 'ecoportal-api-v2', '>= 0.8.3', '< 0.9'
36
+ spec.add_dependency 'aws-sdk-s3', '>= 1.83.0', '< 2'
37
+ spec.add_dependency 'aws-sdk-ses', '>= 1.36.0', '< 2'
38
+ spec.add_dependency 'dotenv', '>= 2.7.6', '< 2.8'
39
+ spec.add_dependency 'net-sftp', '>= 3.0.0', '< 3.1'
38
40
 
39
41
  end
data/lib/eco/api.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'ecoportal/api'
2
- require 'ecoportal/api-oozes'
2
+ require 'ecoportal/api-v2'
3
3
 
4
4
  module Eco
5
5
  module API
@@ -3,7 +3,7 @@ module Eco
3
3
  module Common
4
4
  module ClassHelpers
5
5
 
6
- # Creates an class and instance object methods with name `name` to resolve `klass` name
6
+ # Creates a class and instance object methods with name `name` to resolve `klass` name
7
7
  def class_resolver(name, klass)
8
8
  define_singleton_method(name) { resolve_class(klass) }
9
9
  define_method(name) { self.class.resolve_class(klass) }
@@ -39,6 +39,15 @@ module Eco
39
39
  end.join("")
40
40
  end
41
41
 
42
+ # Helper to create an instance variable `name`
43
+ # @param [String, Symbol] the name of the variable
44
+ # @reutrn [String] the name of the created instance variable
45
+ def instance_variable_name(name)
46
+ str = name.to_s
47
+ str = "@#{str}" unless str.start_with?("@")
48
+ str
49
+ end
50
+
42
51
  # If the class for `name` exists, it returns it. Otherwise it generates it.
43
52
  # @param name [String, Symbol] the name of the new class
44
53
  # @param inherits [Class] the parent class to _inherit_ from
@@ -92,6 +101,41 @@ module Eco
92
101
  descendants(parent_class: parent_class, direct: direct).length > 0
93
102
  end
94
103
 
104
+ # Keeps track on class instance variables that should be inherited by child classes.
105
+ # @note
106
+ # - subclasses will inherit the value as is at that moment
107
+ # - any change afterwards will be only on the specific class (in line with class instance variables)
108
+ # - adapted from https://stackoverflow.com/a/10729812/4352306
109
+ # TODO: this separates the logic of the method to the instance var. Think if would be possible to join them somehow.
110
+ def inheritable_class_vars(*vars)
111
+ @inheritable_class_vars ||= [:inheritable_class_vars]
112
+ @inheritable_class_vars += vars
113
+ end
114
+
115
+ # Builds the attr_reader and attr_writer of `attrs` and registers the associated instance variable as inheritable.
116
+ def inheritable_attrs(*attrs)
117
+ attrs.each do |attr|
118
+ class_eval %(
119
+ class << self; attr_accessor :#{attr} end
120
+ )
121
+ end
122
+ inheritable_class_vars(*attrs)
123
+ end
124
+
125
+ # This callback method is called whenever a subclass of the current class is created.
126
+ # @note
127
+ # - values of the instance variables are copied as they are (no dups or clones)
128
+ # - the above means: avoid methods that change the state of the mutable object on it
129
+ # - mutating methods would reflect the changes on other classes as well
130
+ # - therefore, `freeze` will be called on the values that are inherited.
131
+ def inherited(subclass)
132
+ inheritable_class_vars.each do |var|
133
+ instance_var = instance_variable_name(var)
134
+ value = instance_variable_get(instance_var)
135
+ subclass.instance_variable_set(instance_var, value.freeze)
136
+ end
137
+ end
138
+
95
139
  end
96
140
  end
97
141
  end
@@ -16,6 +16,8 @@ module Eco
16
16
  end
17
17
  end
18
18
 
19
+ inheritable_class_vars :error
20
+
19
21
  def initialize(handlers)
20
22
  raise "Expected Eco::API::Policies. Given #{handlers.class}" unless handlers.is_a?(Eco::API::Error::Handlers)
21
23
  handlers.on(self.error, &self.method(:main))
@@ -60,6 +60,8 @@ module Eco
60
60
  end
61
61
  end
62
62
 
63
+ private
64
+
63
65
  # Helper to obtain the current internal named attributes of the data
64
66
  # @param source_data [Array<String>, Hash] if `Array` those are already the `keys`, if `Hash` it gets the `keys`
65
67
  # @return [Array<String>] `keys` of `source_data`
@@ -76,6 +78,8 @@ module Eco
76
78
 
77
79
  end
78
80
 
81
+ inheritable_class_vars :attribute
82
+
79
83
  def initialize(person_parser)
80
84
  raise "Expected Eco::API::Common::People::PersonParser. Given #{policies.class}" unless person_parser.is_a?(Eco::API::Common::People::PersonParser)
81
85
  person_parser.define_attribute(self.attribute, dependencies: self.class.dependencies) do |attr_parser|
@@ -14,6 +14,8 @@ module Eco
14
14
  end
15
15
  end
16
16
 
17
+ inheritable_class_vars :type
18
+
17
19
  def initialize(usecases)
18
20
  raise "Expected Eco::API::UseCases. Given #{usecases.class}" unless usecases.is_a?(Eco::API::UseCases)
19
21
  usecases.define(self.name, type: self.type, &self.method(:main))
@@ -170,14 +170,25 @@ module Eco
170
170
  end
171
171
 
172
172
  # Setter to fill in all the `core` properties of the `Person` that are present in the `Entry`.
173
- # @note it only sets those core properties defined in the entry.
174
- # Meaning that if an core property is not present in the entry, this will not be set on the target person.
173
+ # @note
174
+ # 1. it only sets those core properties defined in the entry.
175
+ # Meaning that if an core property is not present in the entry, this will not be set on the target person.
176
+ # 2. if there's an incorrect email exception, it blanks the email and logs a warning message
175
177
  # @param person [Ecoportal::API::V1::Person] the person we want to set the core values to.
176
178
  # @param exclude [String, Array<String>] core attributes that should not be set/changed to the person.
177
179
  def set_core(person, exclude: nil)
178
180
  scoped_attrs = @emap.core_attrs - into_a(exclude)
179
181
  @final_entry.slice(*scoped_attrs).each do |attr, value|
180
- set_part(person, attr, value)
182
+ begin
183
+ set_part(person, attr, value)
184
+ rescue Exception => e
185
+ if attr == "email"
186
+ logger.error(e.to_s + " - setting blank email instead.")
187
+ set_part(person, attr, nil)
188
+ else
189
+ raise
190
+ end
191
+ end
181
192
  end
182
193
  end
183
194
 
@@ -460,6 +471,7 @@ module Eco
460
471
  obj.send("#{attr}=", value)
461
472
  end
462
473
  rescue Exception => e
474
+ # add more info to the error
463
475
  raise e.append_message " -- Entry #{to_s(:identify)}"
464
476
  end
465
477
  end
@@ -99,9 +99,16 @@ module Eco
99
99
  # - the list is sorted according `CORE_ATTRS` + `ACCOUNT_ATTRS` + schema attrs
100
100
  # @return [Array<String>] list of all attribute defined parsers.
101
101
  def defined_attrs
102
- defined = @parsers.keys
103
- defined = (all_attrs || defined) && defined
104
- defined - (defined - all_attrs)
102
+ defined = @parsers.keys
103
+ defined = (all_attrs | defined) & defined
104
+ defined - symbol_keys
105
+ end
106
+
107
+ # Symbol keys are type or import parsers (that do not belong to the model)
108
+ # @note this was introduced to boost virtual fields to treat in different phases of the parsing process
109
+ # @return [Array<Symbol>] all the parsers defined as Symbol
110
+ def symbol_keys
111
+ @parsers.keys.filter {|k| k.is_a?(Symbol)}
105
112
  end
106
113
 
107
114
  # Returns a list of all the internal attributes of the model that have a parser defined & that should be active.
@@ -5,9 +5,12 @@ module Eco
5
5
  class Logger
6
6
  DEFAULT_TIMESTAMP_PATTERN = '%Y-%m-%dT%H:%M:%S'
7
7
 
8
+ attr_reader :cache
9
+
8
10
  def initialize(console_level: nil, file_level: ::Logger::DEBUG, log_file: nil, timestamp_console: false, enviro: nil)
9
11
  raise "Required Environment object (enviro:). Given: #{enviro}" if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
10
12
  @enviro = enviro
13
+ @cache = Logger::Cache.new
11
14
 
12
15
  timestamp_console = fetch_timestamp_console(timestamp_console)
13
16
  @console_logger = ::Logger.new(STDOUT).tap do |_logger|
@@ -21,7 +24,9 @@ module Eco
21
24
  if log_file = fetch_log_file(log_file)
22
25
  @file_logger = ::Logger.new(log_file).tap do |_logger|
23
26
  _logger.formatter = proc do |severity, datetime, progname, msg|
24
- "#{severity.to_s[0]}: #{datetime.strftime(DEFAULT_TIMESTAMP_PATTERN)} > #{msg}\n"
27
+ "#{severity.to_s[0]}: #{datetime.strftime(DEFAULT_TIMESTAMP_PATTERN)} > #{msg}\n".tap do |formatted|
28
+ cache.add(severity, datetime, msg, formatted)
29
+ end
25
30
  end
26
31
  _logger.level = fetch_file_level(file_level)
27
32
  end
@@ -107,3 +112,6 @@ module Eco
107
112
  end
108
113
  end
109
114
  end
115
+
116
+ require_relative "logger/cache"
117
+ require_relative "logger/log"
@@ -0,0 +1,91 @@
1
+ module Eco
2
+ module API
3
+ module Common
4
+ module Session
5
+ class Logger
6
+ class Cache
7
+ LEVELS = ["UNKNOWN", "FATAL", "ERROR", "WARN", "INFO", "DEBUG"]
8
+
9
+ def initialize
10
+ reset
11
+ end
12
+
13
+ def level(level)
14
+ cache[to_level(level)] ||= []
15
+ end
16
+
17
+ def add(level, datetime, message, formatted)
18
+ Logger::Log.new(level, datetime, message, formatted).tap do |log|
19
+ self.level(level).push(log)
20
+ end
21
+ end
22
+
23
+ def cache
24
+ @cache ||= {}
25
+ end
26
+
27
+ def reset(level: nil, start_time: nil, end_time: nil)
28
+ where(start_time, end_time) do |cond|
29
+ to_levels(level).map do |lev|
30
+ self.level(lev).reject(&cond)
31
+ end
32
+ end
33
+ self
34
+ end
35
+
36
+ def logs(level: nil, start_time: nil, end_time: nil)
37
+ where(start_time, end_time) do |cond|
38
+ to_levels(level).map do |lev|
39
+ self.level(lev).select(&cond)
40
+ end.flatten
41
+ end.sort
42
+ end
43
+
44
+ private
45
+
46
+ def where(start_time, end_time)
47
+ tstart = to_datetime(start_time)
48
+ tend = to_datetime(end_time)
49
+ condition = Proc.new do |log|
50
+ next true unless tstart || tend
51
+ log.after?(tstart) && log.before?(tend)
52
+ end
53
+
54
+ yield(condition)
55
+ end
56
+
57
+ def to_datetime(value)
58
+ return nil unless value
59
+ Time.parse(value)
60
+ end
61
+
62
+ def to_levels(value)
63
+ levels = [value].flatten.map {|v| to_level(v)}.compact
64
+ levels = levels.empty?? LEVELS : levels
65
+ end
66
+
67
+ def to_level(value)
68
+ nil_or_upcase(value).tap do |out|
69
+ valid_level!(out)
70
+ end
71
+ end
72
+
73
+ def valid_level!(str)
74
+ return true if !str
75
+ unless LEVELS.any? {|lev| str == lev}
76
+ raise "Unknown level #{str}. Should be one of #{LEVELS}"
77
+ end
78
+ end
79
+
80
+ def nil_or_upcase(value)
81
+ value = value.to_s.upcase if value
82
+ return yield(value) if block_given?
83
+ value
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end