eco-helpers 2.0.15 → 2.0.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ea76fb273e572c873b2f23348c54b56fd4e51cd39d9bf1109ddbc4594ba260f
4
- data.tar.gz: 56d64b1eb28202f4bd18997ff8854fdd6ae36c758217796f4739012f59d4ef5c
3
+ metadata.gz: 669f1a3e8d49a2499b02d925386477a8e52cc633c830072420484edcf8e4919d
4
+ data.tar.gz: 86b36286a089bfa03d3cb17d4c17648a4dcc5f1ed07145ee81565cd19d102c90
5
5
  SHA512:
6
- metadata.gz: bf49254f9b3f162f278d65f734fba3d3f683906cb1202df4d4cc4f7a90f2d663655e5168cf5bdea13d78b63d8ece32bcd22541655b001f3a9bfad429d89d2de8
7
- data.tar.gz: 3dcd85969e34079aa050546e427ebe0d28cb7ec358b121f066cd603af23c9c44bb05551ce8db061f1721832981c2b74c1a46aa095c031f9ea0fb8b29b1b65310
6
+ metadata.gz: 0a346a01757374cc004c12b5aadadf6b3c1daebba937c8d1c0cf597608297ab825d604af3a7f70f92528e28e0f009fd482abd31eb660c4abcf9d9796f55f69db
7
+ data.tar.gz: f912a967dfb21cb0e455b357c9f5ca28fae4de55cbacd060fd000add64992b86168a3ed38150d1ddaf9a264245da582a49c434d62d24bc28285d82b3f9a2e693
data/CHANGELOG.md CHANGED
@@ -1,12 +1,25 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [2.0.15] - 2021-04-xx
4
+ ## [2.0.16] - 2021-04-xx
5
5
 
6
6
  ### Added
7
- - Use case `Eco::API::UseCases::DefaultCases::SupersHierarchy`, invokable via `-supers-hiearchy`
7
+ - Use case `Eco::API::UseCases::DefaultCases::SupersCyclicIdentify`, invokable via `-identify-cyclic-supers`
8
+ - Use case `Eco::API::UseCases::DefaultCases::AbstractPolicyGroupAbilities`, invokable via `-abstract-policygroup-abilities`
9
+ - Option to run `one-off` scripts, without org configurations:
10
+ 1. `-api-key INTERNAL_API_KEY`
11
+ 2. `-enviro [live|pre.dev]`
12
+ 3. `-org NAME_OF_ORG`
13
+
8
14
  ### Changed
9
15
  ### Fixed
16
+
17
+
18
+ ## [2.0.15] - 2021-04-29
19
+
20
+ ### Added
21
+ - Use case `Eco::API::UseCases::DefaultCases::SupersHierarchy`, invokable via `-supers-hiearchy`
22
+ ### Fixed
10
23
  - `eco/cli/config/default/workflow.rb` prevent `rescue` looping
11
24
 
12
25
  ## [2.0.14] - 2021-04-15
@@ -17,7 +30,6 @@ All notable changes to this project will be documented in this file.
17
30
  - `Eco::API::Organization::PresetsFactory` added integrity validation for `person_*` abilities
18
31
  - `Eco::API::Session::Batch::Job` more debug info on erron handlers
19
32
 
20
- ### Changed
21
33
  ### Fixed
22
34
  - `Eco::API::Error.get_type` was almost always matching `Eco::API::Error::Unclassified` -> fixed
23
35
 
data/eco-helpers.gemspec CHANGED
@@ -36,5 +36,5 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency 'aws-sdk-ses', '>= 1.36.0', '< 2'
37
37
  spec.add_dependency 'dotenv', '>= 2.7.6', '< 2.8'
38
38
  spec.add_dependency 'net-sftp', '>= 3.0.0', '< 3.1'
39
-
39
+ #spec.add_dependency 'fuzzy_match' '>= 2.1.0', '< 2.2'
40
40
  end
@@ -15,6 +15,7 @@ module Eco
15
15
  # Reorders as follows:
16
16
  # 1. supervisors, people with no supervisor or where their supervisor not present
17
17
  # 2. subordinates
18
+ # @return [Array<Entry>] `values` sorted by supervisors/subordinates
18
19
  def sort_by_supervisors(values, supervisors_first: true)
19
20
  raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
20
21
  return [] unless values && values.is_a?(Enumerable)
@@ -32,6 +33,32 @@ module Eco
32
33
  roam.call(supervisors_tree(values))
33
34
  end
34
35
 
36
+ # Identifies all the cyclic supervisor chains
37
+ # @note as `supervisors_tree` will have any entry involved in a cycle at the top, it just checks all the top entries against their offspring
38
+ # @return [Array<Array>] the sets of entries that are cyclic
39
+ def identify_cyclic_chains(values)
40
+ raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
41
+ return [] unless values && values.is_a?(Enumerable)
42
+
43
+ identify = Proc.new do |top_sup, offspring, chain = [top_sup]|
44
+ next [] if offspring.empty?
45
+ offspring.each_with_object([]) do |(sup, subordinates), set|
46
+ break set unless set.empty?
47
+ if top_sup.supervisor_id == sup.id
48
+ set.concat(chain, [sup])
49
+ else
50
+ set = identify.call(top_sup, subordinates, chain | [sup])
51
+ end
52
+ end
53
+ end
54
+
55
+ supervisors_tree(values).each_with_object([]) do |(top_sup, offspring), sets|
56
+ if (set = identify.call(top_sup, offspring)) && !set.empty?
57
+ sets.push(set)
58
+ end
59
+ end
60
+ end
61
+
35
62
  def tree_to_str(tree, lev: 0)
36
63
  raise "Required Hash tree structure. Given: #{tree.class}" unless tree.is_a?(Hash)
37
64
  "".tap do |str|
@@ -20,8 +20,8 @@ module Eco
20
20
  begin
21
21
  @dir = Eco::Data::Files::Directory.new(value)
22
22
  @dir_path = @dir.create
23
- rescue
24
- logger.error("could not create or make any sense of directory '#{value}'")
23
+ rescue Exception => e
24
+ logger.error("could not create or make any sense of directory '#{value}': #{e.to_s}")
25
25
  end
26
26
  end
27
27
 
@@ -3,6 +3,27 @@ module Eco
3
3
  module Organization
4
4
 
5
5
  class PresetsFactory
6
+
7
+ class << self
8
+
9
+ def all_abilities(hash = {})
10
+ Hash[abilities.each_with_object(nil).to_a].merge(hash)
11
+ end
12
+
13
+ def abilities_model
14
+ @abilities_model ||= JSON.load(File.open(ABILITIES))
15
+ end
16
+
17
+ def integrity_model
18
+ @integrity_model ||= JSON.load(File.open(INTEGRITY))
19
+ end
20
+
21
+ def abilities
22
+ @abilities ||= abilities_model.keys
23
+ end
24
+
25
+ end
26
+
6
27
  ABILITIES = File.join(__dir__, 'presets_values.json')
7
28
  INTEGRITY = File.join(__dir__, 'presets_integrity.json')
8
29
  DEFAULT_CUSTOM = 'presets_custom.json'
@@ -111,7 +132,7 @@ module Eco
111
132
  end
112
133
 
113
134
  def integrity_model
114
- @integrity_model ||= JSON.load(File.open(INTEGRITY))
135
+ self.class.integrity_model
115
136
  end
116
137
 
117
138
  def value_exists?(ability, value)
@@ -129,7 +150,7 @@ module Eco
129
150
  end
130
151
 
131
152
  def abilities_model
132
- @abilities_model ||= JSON.load(File.open(ABILITIES))
153
+ self.class.abilities_model
133
154
  end
134
155
 
135
156
  def policy_groups
@@ -159,6 +159,8 @@ module Eco
159
159
  end
160
160
 
161
161
  def working_directory(mode: nil)
162
+ return files.working_directory if apis.active_api&.one_off?
163
+
162
164
  unless mode
163
165
  wd = files.working_directory
164
166
  return wd unless wd.to_s.strip.empty?
@@ -183,12 +185,21 @@ module Eco
183
185
  end
184
186
 
185
187
  def require(file = nil, match: nil)
186
- if match
187
- file_manager.dir.dir_files(pattern: match).each do |file|
188
- require_relative File.expand_path(file)
188
+ begin
189
+ if match
190
+ file_manager.dir.dir_files(pattern: match).each do |file|
191
+ require_relative File.expand_path(file)
192
+ end
193
+ else
194
+ target = File.expand_path(file_manager.dir.file(file))
195
+ require_relative target
196
+ end
197
+ rescue LoadError => e
198
+ if apis.active_api.one_off?
199
+ pp e.to_s
200
+ else
201
+ raise
189
202
  end
190
- else
191
- require_relative "#{File.expand_path(file_manager.dir.file(file))}"
192
203
  end
193
204
  end
194
205
  # @!endgroup
@@ -83,6 +83,10 @@ module Eco
83
83
  self["name"]
84
84
  end
85
85
 
86
+ def one_off?
87
+ name.is_a?(Symbol)
88
+ end
89
+
86
90
  def key
87
91
  self["key"]
88
92
  end
@@ -40,6 +40,20 @@ module Eco
40
40
  self
41
41
  end
42
42
 
43
+ # Method to support CLI one-off API requests
44
+ def one_off
45
+ if SCR.get_arg("-api-key")
46
+ key = SCR.get_arg("-api-key", with_param: true)
47
+ enviro = SCR.get_arg("-enviro") ? SCR.get_arg("-enviro", with_param: true) : "live"
48
+ host = "#{enviro}.ecoportal.com"
49
+ org = SCR.get_arg("-org") ? SCR.get_arg("-org", with_param: true) : raise("You should specify -org NAME when using -api-key")
50
+ org = org.downcase.split(/[^a-z]+/).join("_")
51
+ org = org.to_sym
52
+ add(org, key: key, host: host)
53
+ return org
54
+ end
55
+ end
56
+
43
57
  def active_api
44
58
  self["active-api"]
45
59
  end
@@ -14,6 +14,13 @@ module Eco
14
14
  end
15
15
 
16
16
  def working_directory
17
+ if config.apis.active_api&.one_off?
18
+ one_off_dir = File.join("one_off", config.apis.active_name.to_s)
19
+ unless full_path = Eco::Data::Files::Directory.new(one_off_dir).create
20
+ raise "Could not create the folder '#{full_path}'"
21
+ end
22
+ self["dir"] = one_off_dir
23
+ end
17
24
  self["dir"]
18
25
  end
19
26
 
@@ -9,7 +9,7 @@ module Eco
9
9
  end
10
10
 
11
11
  def cache
12
- self["cache"]
12
+ self["cache"] ||= "cache/people.json"
13
13
  end
14
14
 
15
15
  def partial_cache
@@ -35,7 +35,7 @@ module Eco
35
35
  end
36
36
 
37
37
  def requests_folder
38
- self["requests_folder"]
38
+ self["requests_folder"] ||= "requests"
39
39
  end
40
40
 
41
41
  # people to exclude from update feeds
@@ -9,6 +9,7 @@ module Eco
9
9
  end
10
10
  end
11
11
 
12
+ require_relative 'default_cases/abstract_policygroup_abilities_case.rb'
12
13
  require_relative 'default_cases/append_usergroups_case'
13
14
  require_relative 'default_cases/change_email_case'
14
15
  require_relative 'default_cases/codes_to_tags_case'
@@ -33,6 +34,7 @@ require_relative 'default_cases/restore_db_case'
33
34
  require_relative 'default_cases/set_default_tag_case'
34
35
  require_relative 'default_cases/set_supervisor_case'
35
36
  require_relative 'default_cases/supers_hierarchy_case'
37
+ require_relative 'default_cases/supers_cyclic_identify_case'
36
38
  require_relative 'default_cases/switch_supervisor_case'
37
39
  require_relative 'default_cases/to_csv_case'
38
40
  require_relative 'default_cases/to_csv_detailed_case'
@@ -0,0 +1,161 @@
1
+ class Eco::API::UseCases::DefaultCases::AbstractPolicyGroupAbilities < Eco::API::Common::Loaders::UseCase
2
+ name "abstract-policygroup-abilities"
3
+ type :export
4
+
5
+ attr_reader :session, :people, :options
6
+
7
+ def main(people, session, options, usecase)
8
+ @session = session; @options = options; @people = people
9
+
10
+ generate_csv!
11
+ exit(0)
12
+ end
13
+
14
+ private
15
+
16
+ def file
17
+ @file ||= options.dig(:output, :file) || "suggested_abilities.csv"
18
+ end
19
+
20
+ def generate_csv!
21
+ policy_groups.each_with_object({}) do |group, data|
22
+ data[group.id] ||= {}
23
+ data[group.id][:name] = group.name
24
+ data[group.id][:suggested] = group_suggestions(group.id)
25
+ data[group.id][:percents] = group_abilities(group.id)
26
+ end.yield_self do |data|
27
+ abilities_list = Eco::API::Organization::PresetsFactory.abilities
28
+ CSV.open(file, "w") do |csv|
29
+ csv << ["Type", "UserGroup", "ID", *abilities_list]
30
+ # Dump the final suggestions
31
+ data.each do |id, meta|
32
+ csv << ["Suggested", meta[:name], id, *meta[:suggested].values_at(*abilities_list)]
33
+ end
34
+ # Dump the percentaged levels of each ability
35
+ data.each do |id, meta|
36
+ analysis = meta[:percents].values_at(*abilities_list).each_with_object([]) do |levels, values|
37
+ values << levels.map do |level, percentil|
38
+ "#{level ? level : "null"} => #{percentil}"
39
+ end.join("\n")
40
+ end
41
+ csv << ["Analysis", meta[:name], id, *analysis]
42
+ end
43
+ end
44
+ puts "Generated file #{file}"
45
+ end
46
+ end
47
+
48
+ def policy_groups
49
+ @policy_groups ||= session.policy_groups
50
+ end
51
+
52
+ # Suggests 1 final set of abilities for a usergroup
53
+ def group_suggestions(id)
54
+ group_abilities(id).each_with_object({}) do |(key, levels), set|
55
+ data = levels.to_a.sort_by(&:last).reverse.first
56
+ set[key] = data ? data.shift : nil
57
+ end
58
+ end
59
+
60
+ # Cleans up each ability's levels by:
61
+ # 1. cutting at some minimum threshold percentage
62
+ # 2. directly selecting those greater than 70%
63
+ def group_abilities(id)
64
+ @group_abilities ||= {}
65
+ @group_abilities[id] ||= ability_levels_percent(id).each_with_object({}) do |(ability, levels), out|
66
+ outstanding = nil
67
+ levels.select do |level, percentil|
68
+ outstanding ||= level if percentil >= 75
69
+ percentil > 15
70
+ end.yield_self do |filtered|
71
+ out[ability] = outstanding ? filtered.slice(outstanding) : filtered
72
+ end
73
+ end
74
+ end
75
+
76
+ # With given the percentages of sets of abilities
77
+ # it abstracts the percentage of each level of each ability
78
+ def ability_levels_percent(id)
79
+ @ability_levels_percent ||= {}
80
+ @ability_levels_percent[id] ||= Eco::API::Organization::PresetsFactory.abilities.each_with_object({}) do |key, out|
81
+ out[key] ||= {}
82
+ ability_sets_percent(id).each_with_object(out[key]) do |(set, percentil), levels|
83
+ levels[set[key]] ||= 0
84
+ levels[set[key]] = (levels[set[key]] + percentil).round(2)
85
+ end
86
+ end
87
+ end
88
+
89
+ # Give a percentage to each set of abilities
90
+ def ability_sets_percent(id)
91
+ @ability_sets_percent ||= {}
92
+ @ability_sets_percent[id] ||= scoped_relevant_raw_data(id).yield_self do |data|
93
+ # Transform ability sets counter to percentage
94
+ total = data[:count]
95
+ abilities = data[:abilities]
96
+ data[:abilities].transform_values do |val|
97
+ percent(val, total)
98
+ end
99
+ end
100
+ end
101
+
102
+ # Get rid of data simingly irrelevant
103
+ def scoped_relevant_raw_data(id)
104
+ sp = single_percent(id)
105
+ sing = single(id); mult = multiple(id)
106
+
107
+ # Scope Relevant Raw Data
108
+ case
109
+ when sp >= 80
110
+ sing
111
+ when sp < 15
112
+ mult
113
+ else # combine
114
+ all_abilities = sing[:abilities].keys | mult[:abilities].keys
115
+ data = {count: sing[:count] + mult[:count], abilities: {}}
116
+ all_abilities.each_with_object(data) do |abilities, merged|
117
+ scount = sing[:abilities][abilities] || 0
118
+ mcount = mult[:abilities][abilities] || 0
119
+ merged[:abilities][abilities] = scount + mcount
120
+ end
121
+ end
122
+ end
123
+
124
+ def single_percent(id)
125
+ percent(single(id)[:count], count(id))
126
+ end
127
+
128
+ def single(id)
129
+ groups_abilities.dig(id, :single) || {count: 0, abilities: {}}
130
+ end
131
+
132
+ def multiple(id)
133
+ groups_abilities.dig(id, :multiple) || {count: 0, abilities: {}}
134
+ end
135
+
136
+ def count(id)
137
+ groups_abilities.dig(id, :count) || 0
138
+ end
139
+
140
+ def groups_abilities
141
+ @groups_abilities ||= people.users.each_with_object({}) do |user, groups|
142
+ abilities = Eco::API::Organization::PresetsFactory.all_abilities(user.account.permissions_custom)
143
+ ids = user.account.policy_group_ids
144
+ category = ids.count > 1 ? :multiple : :single
145
+
146
+ ids.each do |id|
147
+ groups[id] ||= {count: 0}
148
+ groups[id][:count] += 1
149
+ groups[id][category] ||= {count: 0, abilities: {}}
150
+ groups[id][category][:count] += 1
151
+ groups[id][category][:abilities][abilities] ||= 0
152
+ groups[id][category][:abilities][abilities] += 1
153
+ end
154
+ end
155
+ end
156
+
157
+ def percent(num, total)
158
+ (100 * num.to_f / total).round(2)
159
+ end
160
+
161
+ end
@@ -0,0 +1,72 @@
1
+ class Eco::API::UseCases::DefaultCases::SupersCyclicIdentify < Eco::API::Common::Loaders::UseCase
2
+ name "identify-cyclic-supers"
3
+ type :export
4
+
5
+ attr_reader :session, :people, :options
6
+
7
+ def main(people, session, options, usecase)
8
+ @session = session; @options = options; @people = people
9
+
10
+ save!(cyclic_sets)
11
+ exit(0)
12
+ end
13
+
14
+ private
15
+
16
+ def cyclic_sets
17
+ Eco::API::Common::People::SupervisorHelpers.identify_cyclic_chains(people)
18
+ end
19
+
20
+ def file
21
+ @file ||= options.dig(:output, :file) || "cyclic_supers.txt"
22
+ end
23
+
24
+ def save!(data)
25
+ if data.empty?
26
+ session.logger.info("There were no cyclic supervisors identified!!")
27
+ return
28
+ end
29
+
30
+ ext = File.extname(file).downcase.delete(".")
31
+
32
+ File.open(file, "w") do |fd|
33
+ if ext == "txt"
34
+ create_file(data, file: file, format: :txt)
35
+ elsif ext == "html"
36
+ puts "html is still not supported"
37
+ exit(1)
38
+ create_file(data, file: file, format: :html)
39
+ elsif ext == "json"
40
+ puts "json is still not supported"
41
+ exit(1)
42
+ create_file(data, file: file, format: :json)
43
+ end
44
+ end
45
+ end
46
+
47
+ def create_file(sets, file:, format: :txt)
48
+ File.open(file, "w") do |fd|
49
+ fd << sets_to_str(sets, format: format)
50
+ end
51
+ puts "Generated file #{file}"
52
+ end
53
+
54
+ def sets_to_str(sets, format: :txt)
55
+ raise "Required Array. Given: #{sets.class}" unless sets.is_a?(Array)
56
+ "".tap do |str|
57
+ sets.each do |set|
58
+ str << set_to_str(set, format: format)
59
+ end
60
+ end
61
+ end
62
+
63
+ def set_to_str(set, lev: 0, format: :txt)
64
+ raise "Required Array. Given: #{set.class}" unless set.is_a?(Array)
65
+ "".tap do |str|
66
+ entry = set.shift
67
+ str << "#{" " * lev}#{(lev > 0)? "+-#{lev}- " : ""}#{entry.name} (#{entry.external_id}|#{entry.email}|#{entry.id})\n"
68
+ str << set_to_str(set, lev: lev + 1, format: format) unless !set || set.empty?
69
+ end
70
+ end
71
+
72
+ end
data/lib/eco/cli.rb CHANGED
@@ -23,16 +23,6 @@ module Eco
23
23
  def run(session:)
24
24
  io = Eco::API::UseCases::BaseIO.new(session: session, options: options)
25
25
  session.workflow(io: io).run(io: io)
26
- #session.workflow(io: io) do |wf, io|
27
- # io = wf.run(:options, io: io)
28
- # io = wf.run(:load, io: io)
29
- # io = wf.run(:usecases, io: io)
30
- # io = wf.run(:launch_jobs, io: io)
31
- # io = wf.run(:post_launch, io: io)
32
- # io = wf.run(:report, io: io)
33
- # io = wf.run(:end, io: io)
34
- # io = wf.run(:close, io: io)
35
- #end
36
26
  end
37
27
 
38
28
  end
@@ -7,6 +7,18 @@ ASSETS.cli.config do |cnf|
7
7
  options.deep_merge!(output: {file: file})
8
8
  end
9
9
 
10
+ desc = "Draws the Cyclic Supervisors when identified (use option -to file.ext)"
11
+ cases.add("-identify-cyclic-supers", :export, desc, case_name: "identify-cyclic-supers") do |people, session, options|
12
+ file = (SCR.get_arg("-to") && SCR.get_file("-to", required: true, should_exist: false)) || "supers_hierarchy.txt"
13
+ options.deep_merge!(output: {file: file})
14
+ end
15
+
16
+ desc = "Abstracts the Abilities that each Usergroup should probably have (use option -to file.ext)"
17
+ cases.add("-abstract-policygroup-abilities", :export, desc, case_name: "abstract-policygroup-abilities") do |people, session, options|
18
+ file = (SCR.get_arg("-to") && SCR.get_file("-to", required: true, should_exist: false)) || "suggested_abilities.txt"
19
+ options.deep_merge!(output: {file: file})
20
+ end
21
+
10
22
  desc = "It exports to a CSV the (filtered) people"
11
23
  cases.add("-people-to-csv", :export, desc) do |people, session, options|
12
24
  file = SCR.get_file("-people-to-csv", required: true, should_exist: false)
@@ -5,6 +5,29 @@ module Eco
5
5
  module Files
6
6
  class Directory
7
7
 
8
+ class << self
9
+ def create(path, includes_file: false)
10
+ return true if Files.file_exists?(path)
11
+
12
+ parts = Files.split(File.expand_path(path))
13
+ filename = parts.pop if includes_file
14
+
15
+ return true if Files.dir_exists?(File.join(*parts))
16
+
17
+ subpath = nil
18
+ begin
19
+ parts.each do |curr|
20
+ subpath = subpath ? File.join(subpath, curr) : curr
21
+ Dir.mkdir(subpath) unless Files.dir_exists?(subpath)
22
+ end
23
+ rescue Exception => e
24
+ pp e
25
+ return false
26
+ end
27
+ true
28
+ end
29
+ end
30
+
8
31
  attr_reader :dir_path
9
32
 
10
33
  def initialize(dir_path = Dir.pwd)
@@ -14,12 +37,14 @@ module Eco
14
37
  end
15
38
 
16
39
  def exists?
17
- Files.dir_exists(@dir_path)
40
+ Files.dir_exists?(@dir_path)
18
41
  end
19
42
 
20
43
  def create
21
- succeed = Directory.create(File.expand_path(@dir_path)) unless self.exists?
22
- self.full_path if succeed
44
+ return self.full_path if self.exists?
45
+ if succeed = Directory.create(File.expand_path(@dir_path))
46
+ return self.full_path
47
+ end
23
48
  end
24
49
 
25
50
  def full_path
@@ -57,23 +82,6 @@ module Eco
57
82
  File.join(*args)
58
83
  end
59
84
 
60
- def self.create(path, includes_file: false)
61
- return true if Files.file_exists?(path)
62
- parts = Files.split(File.expand_path(path))
63
- filename = parts.pop if includes_file
64
- return true if Files.dir_exists?(File.join(*parts))
65
- subpath = nil
66
- begin
67
- parts.each do |curr|
68
- subpath = subpath ? File.join(subpath, curr) : curr
69
- Dir.mkdir(subpath) unless Files.dir_exists?(subpath)
70
- end
71
- rescue Exception => e
72
- pp e
73
- end
74
- false
75
- end
76
-
77
85
  private
78
86
 
79
87
  def file_pattern(value)
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = "2.0.15"
2
+ VERSION = "2.0.16"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.15
4
+ version: 2.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -375,6 +375,7 @@ files:
375
375
  - lib/eco/api/usecases/base_case.rb
376
376
  - lib/eco/api/usecases/base_io.rb
377
377
  - lib/eco/api/usecases/default_cases.rb
378
+ - lib/eco/api/usecases/default_cases/abstract_policygroup_abilities_case.rb
378
379
  - lib/eco/api/usecases/default_cases/append_usergroups_case.rb
379
380
  - lib/eco/api/usecases/default_cases/change_email_case.rb
380
381
  - lib/eco/api/usecases/default_cases/codes_to_tags_case.rb
@@ -399,6 +400,7 @@ files:
399
400
  - lib/eco/api/usecases/default_cases/restore_db_case.rb
400
401
  - lib/eco/api/usecases/default_cases/set_default_tag_case.rb
401
402
  - lib/eco/api/usecases/default_cases/set_supervisor_case.rb
403
+ - lib/eco/api/usecases/default_cases/supers_cyclic_identify_case.rb
402
404
  - lib/eco/api/usecases/default_cases/supers_hierarchy_case.rb
403
405
  - lib/eco/api/usecases/default_cases/switch_supervisor_case.rb
404
406
  - lib/eco/api/usecases/default_cases/to_csv_case.rb