forest_liana 7.2.0 → 7.4.0

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +3 -0
  3. data/app/controllers/forest_liana/associations_controller.rb +4 -0
  4. data/app/controllers/forest_liana/base_controller.rb +1 -0
  5. data/app/controllers/forest_liana/resources_controller.rb +8 -0
  6. data/app/controllers/forest_liana/router.rb +1 -0
  7. data/app/controllers/forest_liana/scopes_controller.rb +1 -0
  8. data/app/controllers/forest_liana/smart_actions_controller.rb +4 -0
  9. data/app/controllers/forest_liana/stats_controller.rb +2 -0
  10. data/app/services/forest_liana/intercom_attributes_getter.rb +1 -0
  11. data/app/services/forest_liana/intercom_conversation_getter.rb +1 -0
  12. data/app/services/forest_liana/intercom_conversations_getter.rb +1 -0
  13. data/app/services/forest_liana/ip_whitelist.rb +1 -0
  14. data/app/services/forest_liana/permissions_checker.rb +8 -1
  15. data/app/services/forest_liana/permissions_getter.rb +1 -0
  16. data/app/services/forest_liana/resources_getter.rb +1 -0
  17. data/app/services/forest_liana/schema_adapter.rb +4 -1
  18. data/app/services/forest_liana/search_query_builder.rb +1 -0
  19. data/app/services/forest_liana/stripe_invoices_getter.rb +1 -0
  20. data/app/services/forest_liana/stripe_payments_getter.rb +1 -0
  21. data/app/services/forest_liana/stripe_sources_getter.rb +1 -0
  22. data/app/services/forest_liana/stripe_subscriptions_getter.rb +1 -0
  23. data/config/initializers/httpclient.rb +11 -0
  24. data/config/initializers/logger.rb +8 -1
  25. data/lib/forest_liana/bootstrapper.rb +3 -1
  26. data/lib/forest_liana/collection.rb +1 -0
  27. data/lib/forest_liana/engine.rb +3 -0
  28. data/lib/forest_liana/schema_file_updater.rb +1 -0
  29. data/lib/forest_liana/version.rb +1 -1
  30. data/lib/forest_liana.rb +2 -0
  31. data/spec/config/initializers/logger_spec.rb +37 -0
  32. data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +28 -0
  33. data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +38 -0
  34. metadata +135 -134
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9661846cededb74e730dcd16808b9a34f13e4094467efad90d069c3eccb89e31
4
- data.tar.gz: 7c7da61924546e78660f9e6674ddc15fb787432793fca4866e53681a0b4d463c
3
+ metadata.gz: adc1d7ec157183e6001f0c62980ae41cac6812a06e4fb8d1d5189609e478c2c6
4
+ data.tar.gz: 21ccd896ff434a672683d6d384aa70e80b531c95189294551c3466a5ead3a5b6
5
5
  SHA512:
6
- metadata.gz: 602f195379f0e5175aaccd55eff08a49da25a6f720a68cca54fce1a40cc46d3b2e878b42fa85512a43b2de94fba9fe9476e01d6a267a572c6a4f2d73e4b182d3
7
- data.tar.gz: 5dac79fb17eaddc9bece92948109934cf043e61a6afb0e697b423419e45c7ffac05b4cb6575650eceb9b3cdcd006c334ab984954e01b37a836047dd0c1f0f493
6
+ metadata.gz: ce716a35923e78b2d00f066aa717e2a4fcd62506fe9073d370cbf30af90b1474a26cf940cd0a2aed1cf959b6c93cfe9314268e4a9ed048042ec3f04b9a227826
7
+ data.tar.gz: 5bb96fed2cc7218d162d4f0ac9df00b6270efa909deaab5ed84289cebe41606b36230423844584b9d65efd7b19588f06f42f90798d6515a05c0a2e2c2755011d
@@ -5,6 +5,7 @@ module ForestLiana
5
5
  begin
6
6
  params[:data][:attributes]
7
7
  rescue => error
8
+ FOREST_REPORTER.report error
8
9
  FOREST_LOGGER.error "Smart Action hook request error: #{error}"
9
10
  {}
10
11
  end
@@ -19,6 +20,7 @@ module ForestLiana
19
20
  begin
20
21
  collection.actions.find {|action| ActiveSupport::Inflector.parameterize(action.name) == params[:action_name]}
21
22
  rescue => error
23
+ FOREST_REPORTER.report error
22
24
  FOREST_LOGGER.error "Smart Action get action retrieval error: #{error}"
23
25
  nil
24
26
  end
@@ -57,6 +59,7 @@ module ForestLiana
57
59
  rescue ForestLiana::Errors::SmartActionInvalidFieldError => invalid_field_error
58
60
  FOREST_LOGGER.warn invalid_field_error.message
59
61
  rescue ForestLiana::Errors::SmartActionInvalidFieldHookError => invalid_hook_error
62
+ FOREST_REPORTER.report invalid_hook_error
60
63
  FOREST_LOGGER.error invalid_hook_error.message
61
64
  return render status: 500, json: { error: invalid_hook_error.message }
62
65
  end
@@ -18,6 +18,7 @@ module ForestLiana
18
18
  format.csv { render_csv(getter, @association.klass) }
19
19
  end
20
20
  rescue => error
21
+ FOREST_REPORTER.report error
21
22
  FOREST_LOGGER.error "Association Index error: #{error}\n#{format_stacktrace(error)}"
22
23
  internal_server_error
23
24
  end
@@ -30,6 +31,7 @@ module ForestLiana
30
31
 
31
32
  render serializer: nil, json: { count: getter.records_count }
32
33
  rescue => error
34
+ FOREST_REPORTER.report error
33
35
  FOREST_LOGGER.error "Association Index Count error: #{error}\n#{format_stacktrace(error)}"
34
36
  internal_server_error
35
37
  end
@@ -47,6 +49,7 @@ module ForestLiana
47
49
  head :no_content
48
50
  end
49
51
  rescue => error
52
+ FOREST_REPORTER.report error
50
53
  FOREST_LOGGER.error "Association Update error: #{error}\n#{format_stacktrace(error)}"
51
54
  internal_server_error
52
55
  end
@@ -59,6 +62,7 @@ module ForestLiana
59
62
 
60
63
  head :no_content
61
64
  rescue => error
65
+ FOREST_REPORTER.report error
62
66
  FOREST_LOGGER.error "Association Associate error: #{error}\n#{format_stacktrace(error)}"
63
67
  internal_server_error
64
68
  end
@@ -30,6 +30,7 @@ module ForestLiana
30
30
  }])
31
31
  render(serializer: nil, json: error_data, status: exception.status)
32
32
  rescue => exception
33
+ FOREST_REPORTER.report exception
33
34
  FOREST_LOGGER.error(exception)
34
35
  FOREST_LOGGER.error(exception.backtrace.join("\n"))
35
36
  render(serializer: nil, json: nil, status: :internal_server_error)
@@ -47,6 +47,7 @@ module ForestLiana
47
47
  }])
48
48
  render(serializer: nil, json: error_data, status: error.status)
49
49
  rescue => error
50
+ FOREST_REPORTER.report error
50
51
  FOREST_LOGGER.error "Records Index error: #{error}\n#{format_stacktrace(error)}"
51
52
  internal_server_error
52
53
  end
@@ -79,6 +80,7 @@ module ForestLiana
79
80
  }])
80
81
  render(serializer: nil, json: error_data, status: error.status)
81
82
  rescue => error
83
+ FOREST_REPORTER.report error
82
84
  FOREST_LOGGER.error "Records Index Count error: #{error}\n#{format_stacktrace(error)}"
83
85
  internal_server_error
84
86
  end
@@ -96,6 +98,7 @@ module ForestLiana
96
98
  rescue ActiveRecord::RecordNotFound
97
99
  render serializer: nil, json: { status: 404 }, status: :not_found
98
100
  rescue => error
101
+ FOREST_REPORTER.report error
99
102
  FOREST_LOGGER.error "Record Show error: #{error}\n#{format_stacktrace(error)}"
100
103
  internal_server_error
101
104
  end
@@ -119,6 +122,7 @@ module ForestLiana
119
122
  creator.record.errors), status: 400
120
123
  end
121
124
  rescue => error
125
+ FOREST_REPORTER.report error
122
126
  FOREST_LOGGER.error "Record Create error: #{error}\n#{format_stacktrace(error)}"
123
127
  internal_server_error
124
128
  end
@@ -142,6 +146,7 @@ module ForestLiana
142
146
  updater.record.errors), status: 400
143
147
  end
144
148
  rescue => error
149
+ FOREST_REPORTER.report error
145
150
  FOREST_LOGGER.error "Record Update error: #{error}\n#{format_stacktrace(error)}"
146
151
  internal_server_error
147
152
  end
@@ -162,6 +167,7 @@ module ForestLiana
162
167
 
163
168
  head :no_content
164
169
  rescue => error
170
+ FOREST_REPORTER.report error
165
171
  FOREST_LOGGER.error "Record Destroy error: #{error}\n#{format_stacktrace(error)}"
166
172
  internal_server_error
167
173
  end
@@ -175,6 +181,7 @@ module ForestLiana
175
181
 
176
182
  head :no_content
177
183
  rescue => error
184
+ FOREST_REPORTER.report error
178
185
  FOREST_LOGGER.error "Records Destroy error: #{error}\n#{format_stacktrace(error)}"
179
186
  internal_server_error
180
187
  end
@@ -190,6 +197,7 @@ module ForestLiana
190
197
  render serializer: nil, json: { status: 404 }, status: :not_found
191
198
  end
192
199
  rescue => error
200
+ FOREST_REPORTER.report error
193
201
  FOREST_LOGGER.error "Find Collection error: #{error}\n#{format_stacktrace(error)}"
194
202
  render serializer: nil, json: { status: 404 }, status: :not_found
195
203
  end
@@ -39,6 +39,7 @@ class ForestLiana::Router
39
39
 
40
40
  controller.action(action.to_sym).call(env)
41
41
  rescue NoMethodError => exception
42
+ FOREST_REPORTER.report exception
42
43
  FOREST_LOGGER.error "Routing error: #{exception}\n#{exception.backtrace.join("\n\t")}"
43
44
  ForestLiana::BaseController.action(:route_not_found).call(env)
44
45
  end
@@ -12,6 +12,7 @@ module ForestLiana
12
12
  ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
13
13
  return render serializer: nil, json: { status: 200 }, status: :ok
14
14
  rescue => error
15
+ FOREST_REPORTER.report error
15
16
  FOREST_LOGGER.error "Error during scope cache invalidation: #{error.message}"
16
17
  render serializer: nil, json: {status: 500 }, status: :internal_server_error
17
18
  end
@@ -12,6 +12,7 @@ module ForestLiana
12
12
  begin
13
13
  params[:data][:attributes]
14
14
  rescue => error
15
+ FOREST_REPORTER.report error
15
16
  FOREST_LOGGER.error "Smart Action execution error: #{error}"
16
17
  {}
17
18
  end
@@ -47,6 +48,7 @@ module ForestLiana
47
48
  # target records are out of scope
48
49
  render serializer: nil, json: { error: 'Smart Action: target record not found' }, status: :bad_request
49
50
  rescue => error
51
+ FOREST_REPORTER.report error
50
52
  FOREST_LOGGER.error "Smart Action: #{error}\n#{format_stacktrace(error)}"
51
53
  render serializer: nil, json: { error: 'Smart Action: failed to evaluate permissions' }, status: :internal_server_error
52
54
  end
@@ -70,6 +72,7 @@ module ForestLiana
70
72
  render serializer: nil, json: { status: 400 }, status: :bad_request
71
73
  end
72
74
  rescue => error
75
+ FOREST_REPORTER.report error
73
76
  FOREST_LOGGER.error "Smart Action execution error: #{error}"
74
77
  render serializer: nil, json: { status: 400 }, status: :bad_request
75
78
  end
@@ -85,6 +88,7 @@ module ForestLiana
85
88
  end
86
89
  resource
87
90
  rescue => error
91
+ FOREST_REPORTER.report error
88
92
  FOREST_LOGGER.error "Find Collection error: #{error}\n#{format_stacktrace(error)}"
89
93
  render serializer: nil, json: { status: 404 }, status: :not_found
90
94
  end
@@ -60,6 +60,7 @@ module ForestLiana
60
60
  render json: { errors: [{ status: 422, detail: error.message }] },
61
61
  status: :unprocessable_entity, serializer: nil
62
62
  rescue => error
63
+ FOREST_REPORTER.report error
63
64
  FOREST_LOGGER.error "Live Query error: #{error.message}"
64
65
  render json: { errors: [{ status: 422, detail: error.message }] },
65
66
  status: :unprocessable_entity, serializer: nil
@@ -110,6 +111,7 @@ module ForestLiana
110
111
 
111
112
  return head :forbidden unless checker.is_authorized?
112
113
  rescue => error
114
+ FOREST_REPORTER.report error
113
115
  FOREST_LOGGER.error "Stats execution error: #{error}"
114
116
  render serializer: nil, json: { status: 400 }, status: :bad_request
115
117
  end
@@ -18,6 +18,7 @@ module ForestLiana
18
18
  @record = user
19
19
  rescue Intercom::ResourceNotFound
20
20
  rescue Intercom::UnexpectedError => exception
21
+ FOREST_REPORTER.report exception
21
22
  FOREST_LOGGER.error "Cannot retrieve the Intercom attributes: #{exception.message}"
22
23
  end
23
24
  end
@@ -14,6 +14,7 @@ module ForestLiana
14
14
  rescue Intercom::ResourceNotFound
15
15
  @record = nil
16
16
  rescue Intercom::UnexpectedError => exception
17
+ FOREST_REPORTER.report exception
17
18
  FOREST_LOGGER.error "Cannot retrieve the Intercom conversation: #{exception.message}"
18
19
  @record = nil
19
20
  end
@@ -31,6 +31,7 @@ module ForestLiana
31
31
  rescue Intercom::ResourceNotFound
32
32
  @records = []
33
33
  rescue Intercom::UnexpectedError => exception
34
+ FOREST_REPORTER.report exception
34
35
  FOREST_LOGGER.error "Cannot retrieve the Intercom conversations: #{exception.message}"
35
36
  @records = []
36
37
  end
@@ -21,6 +21,7 @@ module ForestLiana
21
21
  false
22
22
  end
23
23
  rescue => exception
24
+ FOREST_REPORTER.report exception
24
25
  FOREST_LOGGER.error 'Cannot retrieve the IP Whitelist from the Forest server.'
25
26
  FOREST_LOGGER.error 'Which was caused by:'
26
27
  ForestLiana::Errors::ExceptionHelper.recursively_print(exception, margin: ' ', is_error: true)
@@ -159,9 +159,16 @@ module ForestLiana
159
159
 
160
160
  def segment_query_allowed?
161
161
  segments_queries_permissions = get_segments_in_permissions
162
-
162
+ # NOTICE: The segmentQuery should be in the segments_queries_permissions
163
163
  return false unless segments_queries_permissions
164
164
 
165
+ # Handle UNION queries made by the FRONT to display available actions on details view
166
+ unionQueries = @collection_list_parameters[:segmentQuery].split('/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION ');
167
+ if unionQueries.length > 1
168
+ # Are unionQueries all included only in the allowed queries
169
+ return unionQueries.all? { |unionQuery| segments_queries_permissions.select { |query| query.gsub(/;\s*/i, '') === unionQuery }.length > 0 };
170
+ end
171
+
165
172
  # NOTICE: @query_request_info matching an existing segment query
166
173
  return segments_queries_permissions.include? @collection_list_parameters[:segmentQuery]
167
174
  end
@@ -47,6 +47,7 @@ module ForestLiana
47
47
  raise "Forest API returned an #{ForestLiana::Errors::HTTPErrorHelper.format(response)}"
48
48
  end
49
49
  rescue => exception
50
+ FOREST_REPORTER.report exception
50
51
  FOREST_LOGGER.error 'Cannot retrieve the permissions from the Forest server.'
51
52
  FOREST_LOGGER.error 'Which was caused by:'
52
53
  ForestLiana::Errors::ExceptionHelper.recursively_print(exception, margin: ' ', is_error: true)
@@ -179,6 +179,7 @@ module ForestLiana
179
179
  )
180
180
  rescue => error
181
181
  error_message = "Live Query Segment: #{error.message}"
182
+ FOREST_REPORTER.report error
182
183
  FOREST_LOGGER.error(error_message)
183
184
  raise ForestLiana::Errors::LiveQueryError.new(error_message)
184
185
  end
@@ -261,6 +261,7 @@ module ForestLiana
261
261
  FOREST_LOGGER.warn "The association \"#{association.name.to_s}\" " \
262
262
  "does not seem to exist for model \"#{@model.name}\"."
263
263
  rescue => exception
264
+ FOREST_REPORTER.report exception
264
265
  FOREST_LOGGER.error "An error occured trying to add " \
265
266
  "\"#{association.name.to_s}\" association:\n#{exception}"
266
267
  end
@@ -350,10 +351,12 @@ module ForestLiana
350
351
  type = 'Number'
351
352
  when :json, :jsonb, :hstore
352
353
  type = 'Json'
353
- when :string, :text, :citext, :uuid
354
+ when :string, :text, :citext
354
355
  type = 'String'
355
356
  when :time
356
357
  type = 'Time'
358
+ when :uuid
359
+ type = 'Uuid'
357
360
  end
358
361
 
359
362
  is_array = (column.respond_to?(:array) && column.array == true)
@@ -31,6 +31,7 @@ module ForestLiana
31
31
  begin
32
32
  @records = field[:search].call(@records, @search)
33
33
  rescue => exception
34
+ FOREST_REPORTER.report exception
34
35
  FOREST_LOGGER.error "Cannot search properly on Smart Field:\n" \
35
36
  "#{exception}"
36
37
  end
@@ -50,6 +50,7 @@ module ForestLiana
50
50
  d
51
51
  end
52
52
  rescue ::Stripe::InvalidRequestError => error
53
+ FOREST_REPORTER.report error
53
54
  FOREST_LOGGER.error "Stripe error: #{error.message}"
54
55
  @records = []
55
56
  end
@@ -48,6 +48,7 @@ module ForestLiana
48
48
  d
49
49
  end
50
50
  rescue ::Stripe::InvalidRequestError => error
51
+ FOREST_REPORTER.report error
51
52
  FOREST_LOGGER.error "Stripe error: #{error.message}"
52
53
  @records = []
53
54
  end
@@ -46,6 +46,7 @@ module ForestLiana
46
46
  d
47
47
  end
48
48
  rescue ::Stripe::InvalidRequestError => error
49
+ FOREST_REPORTER.report error
49
50
  FOREST_LOGGER.error "Stripe error: #{error.message}"
50
51
  @records = []
51
52
  end
@@ -43,6 +43,7 @@ module ForestLiana
43
43
  d
44
44
  end
45
45
  rescue ::Stripe::InvalidRequestError => error
46
+ FOREST_REPORTER.report error
46
47
  FOREST_LOGGER.error "Stripe error: #{error.message}"
47
48
  @records = []
48
49
  end
@@ -0,0 +1,11 @@
1
+ require 'httpclient'
2
+
3
+ class HTTPClient
4
+ alias original_initialize initialize
5
+
6
+ def initialize(*args, &block)
7
+ original_initialize(*args, &block)
8
+ # NOTICE: Force use of the default system CA certs (instead of the 6 year old bundled ones).
9
+ @session_manager&.ssl_config&.set_default_paths
10
+ end
11
+ end
@@ -18,12 +18,19 @@ module ForestLiana
18
18
  displayed_message = "[#{datetime.to_s(:db)}] Forest 🌳🌳🌳 " \
19
19
  "#{message}\n"
20
20
  "\e[#{logger_colors[severity.to_sym]}m#{displayed_message}\033[0m"
21
- end
21
+ end
22
22
  logger
23
23
  end
24
24
  end
25
25
  end
26
26
  end
27
+
28
+ class Reporter
29
+ def self.report (error)
30
+ ForestLiana.reporter.report error if ForestLiana.reporter
31
+ end
32
+ end
27
33
  end
28
34
 
29
35
  FOREST_LOGGER = ForestLiana::Logger.log
36
+ FOREST_REPORTER = ForestLiana::Reporter
@@ -82,7 +82,8 @@ module ForestLiana
82
82
  @collections_sent = content['collections']
83
83
  @meta_sent = content['meta']
84
84
  generate_action_hooks
85
- rescue JSON::JSONError
85
+ rescue JSON::JSONError => error
86
+ FOREST_REPORTER.report error
86
87
  FOREST_LOGGER.error "The content of .forestadmin-schema.json file is not a correct JSON."
87
88
  FOREST_LOGGER.error "The schema cannot be synchronized with Forest Admin servers."
88
89
  end
@@ -122,6 +123,7 @@ module ForestLiana
122
123
  end
123
124
  end
124
125
  rescue => exception
126
+ FOREST_REPORTER.report exception
125
127
  FOREST_LOGGER.error "Cannot fetch properly model #{model.name}:\n" \
126
128
  "#{exception}"
127
129
  end
@@ -91,6 +91,7 @@ module ForestLiana::Collection
91
91
  begin
92
92
  object.instance_eval(&block)
93
93
  rescue => exception
94
+ FOREST_REPORTER.report exception
94
95
  FOREST_LOGGER.error "Cannot retrieve the " + name.to_s + " value because of an " \
95
96
  "internal error in the getter implementation: " + exception.message
96
97
  nil
@@ -37,6 +37,7 @@ module ForestLiana
37
37
  end
38
38
  nil
39
39
  rescue => exception
40
+ FOREST_REPORTER.report exception
40
41
  exception
41
42
  end
42
43
  end
@@ -51,6 +52,7 @@ module ForestLiana
51
52
  ActiveRecord::Base.connection_pool.with_connection { |connection| connection.active? }
52
53
  rescue => error
53
54
  database_available = false
55
+ FOREST_REPORTER.report error
54
56
  FOREST_LOGGER.error "No Apimap sent to Forest servers, it seems that the database is not accessible:\n#{error}"
55
57
  end
56
58
  database_available
@@ -75,6 +77,7 @@ module ForestLiana
75
77
 
76
78
  config.after_initialize do |app|
77
79
  if error
80
+ FOREST_REPORTER.report error
78
81
  FOREST_LOGGER.error "Impossible to set the whitelisted Forest " \
79
82
  "domains for CORS constraint:\n#{error}"
80
83
  end
@@ -102,6 +102,7 @@ module ForestLiana
102
102
  rescue ForestLiana::Errors::SmartActionInvalidFieldError => invalid_field_error
103
103
  FOREST_LOGGER.warn invalid_field_error.message
104
104
  rescue ForestLiana::Errors::SmartActionInvalidFieldHookError => invalid_hook_error
105
+ FOREST_REPORTER.report invalid_hook_error
105
106
  FOREST_LOGGER.error invalid_hook_error.message
106
107
  end
107
108
  action['fields'] = action['fields'].map { |field| field.slice(*KEYS_ACTION_FIELD) }
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "7.2.0"
2
+ VERSION = "7.4.0"
3
3
  end
data/lib/forest_liana.rb CHANGED
@@ -28,6 +28,7 @@ module ForestLiana
28
28
  mattr_accessor :names_overriden
29
29
  mattr_accessor :meta
30
30
  mattr_accessor :logger
31
+ mattr_accessor :reporter
31
32
  # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
32
33
  mattr_accessor :names_old_overriden
33
34
 
@@ -40,6 +41,7 @@ module ForestLiana
40
41
  self.names_overriden = {}
41
42
  self.meta = {}
42
43
  self.logger = nil
44
+ self.reporter = nil
43
45
 
44
46
  @config_dir = 'lib/forest_liana/**/*.rb'
45
47
 
@@ -27,4 +27,41 @@ module ForestLiana
27
27
  end
28
28
  end
29
29
  end
30
+
31
+ describe Reporter do
32
+ describe 'self.reporter' do
33
+ describe 'with a reporter provided' do
34
+ it 'should report the error' do
35
+ class SampleReporter
36
+ def report(error)
37
+ end
38
+ end
39
+
40
+ spier = spy('sampleReporter')
41
+
42
+ ForestLiana.reporter = spier
43
+ FOREST_REPORTER.report(Exception.new "sample error")
44
+
45
+ expect(spier).to have_received(:report)
46
+ ForestLiana.reporter = nil
47
+ end
48
+ end
49
+
50
+ describe 'without any reporter provided' do
51
+ it 'should not report the error' do
52
+ class ErrorReporter
53
+ def report(error)
54
+ expect(false).to be_truthy
55
+ end
56
+ end
57
+
58
+ spier = spy('errorReporter')
59
+
60
+ FOREST_REPORTER.report(Exception.new "sample error")
61
+
62
+ expect(spier).not_to have_received(:export)
63
+ end
64
+ end
65
+ end
66
+ end
30
67
  end
@@ -481,6 +481,14 @@ module ForestLiana
481
481
  end
482
482
  end
483
483
 
484
+ context 'when user has no segments and param segmentQuery is there' do
485
+ let(:segmentQuery) { 'SELECT * FROM products;' }
486
+ let(:collection_list_parameters) { { :user_id => "1", :segmentQuery => segmentQuery } }
487
+ it 'should be authorized' do
488
+ expect(subject.is_authorized?).to be false
489
+ end
490
+ end
491
+
484
492
  context 'when segments are defined' do
485
493
  let(:segments_permissions) { ['SELECT * FROM products;', 'SELECT * FROM sellers;'] }
486
494
  let(:collection_list_parameters) { { :user_id => "1", :segmentQuery => segmentQuery } }
@@ -499,6 +507,26 @@ module ForestLiana
499
507
  end
500
508
  end
501
509
 
510
+ context 'when received union segments NOT passing validation' do
511
+ let(:segmentQuery) { 'SELECT * FROM sellers/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2' }
512
+ it 'should return false' do
513
+ expect(subject.is_authorized?).to be false
514
+ end
515
+ end
516
+
517
+ context 'when received union segments passing validation' do
518
+ let(:segmentQuery) { 'SELECT * FROM sellers/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT * FROM products' }
519
+ it 'should return true' do
520
+ expect(subject.is_authorized?).to be true
521
+ end
522
+ end
523
+ context 'when received union segments with UNION inside passing validation' do
524
+ let(:segmentQuery) { 'SELECT COUNT(*) AS value FROM products/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2' }
525
+ let(:segments_permissions) { ['SELECT COUNT(*) AS value FROM products;', 'SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2;', 'SELECT * FROM products;', 'SELECT * FROM sellers;'] }
526
+ it 'should return true' do
527
+ expect(subject.is_authorized?).to be true
528
+ end
529
+ end
502
530
  end
503
531
 
504
532
  context 'when user has not the required permission' do
@@ -458,6 +458,14 @@ module ForestLiana
458
458
  end
459
459
  end
460
460
 
461
+ context 'when user has no segments queries permissions and param segmentQuery is there' do
462
+ let(:segmentQuery) { 'SELECT * FROM products;' }
463
+ let(:collection_list_parameters) { { :user_id => "1", :segmentQuery => segmentQuery } }
464
+ it 'should be authorized' do
465
+ expect(subject.is_authorized?).to be false
466
+ end
467
+ end
468
+
461
469
  context 'when segments are defined' do
462
470
  let(:default_rendering_id) { 1 }
463
471
  let(:segments_permissions) {
@@ -484,6 +492,36 @@ module ForestLiana
484
492
  expect(subject.is_authorized?).to be false
485
493
  end
486
494
  end
495
+
496
+ context 'when received union segments NOT passing validation' do
497
+ let(:segmentQuery) { 'SELECT * FROM sellers/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2' }
498
+ it 'should return false' do
499
+ expect(subject.is_authorized?).to be false
500
+ end
501
+ end
502
+
503
+ context 'when received union segments passing validation' do
504
+ let(:segmentQuery) { 'SELECT * FROM sellers/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT * FROM products' }
505
+ it 'should return true' do
506
+ expect(subject.is_authorized?).to be true
507
+ end
508
+ end
509
+
510
+ context 'when received union segments with UNION inside passing validation' do
511
+ let(:segmentQuery) { 'SELECT COUNT(*) AS value FROM products/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2' }
512
+ let(:segments_permissions) {
513
+ {
514
+ default_rendering_id => {
515
+ collection_name => {
516
+ 'segments' => ['SELECT COUNT(*) AS value FROM products;', 'SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2;', 'SELECT * FROM products;', 'SELECT * FROM sellers;']
517
+ }
518
+ }
519
+ }
520
+ }
521
+ it 'should return true' do
522
+ expect(subject.is_authorized?).to be true
523
+ end
524
+ end
487
525
  end
488
526
  end
489
527
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 7.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-10 00:00:00.000000000 Z
11
+ date: 2021-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -302,6 +302,7 @@ files:
302
302
  - config/initializers/arel-helpers.rb
303
303
  - config/initializers/error-messages.rb
304
304
  - config/initializers/errors.rb
305
+ - config/initializers/httpclient.rb
305
306
  - config/initializers/logger.rb
306
307
  - config/initializers/time_formats.rb
307
308
  - config/routes.rb
@@ -509,171 +510,171 @@ signing_key:
509
510
  specification_version: 4
510
511
  summary: Official Rails Liana for Forest
511
512
  test_files:
512
- - test/services/forest_liana/operator_date_interval_parser_test.rb
513
- - test/services/forest_liana/schema_adapter_test.rb
514
- - test/forest_liana_test.rb
515
- - test/routing/route_test.rb
516
- - test/dummy/bin/rake
517
- - test/dummy/bin/bundle
513
+ - test/test_helper.rb
514
+ - test/dummy/config.ru
518
515
  - test/dummy/bin/setup
516
+ - test/dummy/bin/bundle
517
+ - test/dummy/bin/rake
519
518
  - test/dummy/bin/rails
520
- - test/dummy/config/boot.rb
521
- - test/dummy/config/secrets.yml
522
- - test/dummy/config/routes.rb
523
- - test/dummy/config/environments/test.rb
524
- - test/dummy/config/environments/development.rb
525
- - test/dummy/config/environments/production.rb
526
- - test/dummy/config/locales/en.yml
527
- - test/dummy/config/initializers/inflections.rb
528
- - test/dummy/config/initializers/cookies_serializer.rb
529
- - test/dummy/config/initializers/wrap_parameters.rb
530
- - test/dummy/config/initializers/mime_types.rb
531
- - test/dummy/config/initializers/assets.rb
532
- - test/dummy/config/initializers/session_store.rb
533
- - test/dummy/config/initializers/filter_parameter_logging.rb
534
- - test/dummy/config/initializers/backtrace_silencers.rb
535
- - test/dummy/config/application.rb
536
- - test/dummy/config/database.yml
537
- - test/dummy/config/environment.rb
538
519
  - test/dummy/Rakefile
539
520
  - test/dummy/db/schema.rb
540
- - test/dummy/db/migrate/20150608131430_create_integer_field.rb
541
- - test/dummy/db/migrate/20181111162121_create_references_table.rb
542
- - test/dummy/db/migrate/20160628173505_add_timestamps.rb
543
- - test/dummy/db/migrate/20150608130516_create_date_field.rb
544
- - test/dummy/db/migrate/20150608131610_create_float_field.rb
545
- - test/dummy/db/migrate/20150608132159_create_boolean_field.rb
521
+ - test/dummy/db/migrate/20150612112520_create_has_and_belongs_to_many_field.rb
546
522
  - test/dummy/db/migrate/20150623115554_create_has_many_class_name_field.rb
547
- - test/dummy/db/migrate/20150608131603_create_decimal_field.rb
548
- - test/dummy/db/migrate/20150609114636_create_belongs_to_class_name_field.rb
549
- - test/dummy/db/migrate/20150616150629_create_polymorphic_field.rb
550
- - test/dummy/db/migrate/20170614141921_create_serialize_field.rb
551
- - test/dummy/db/migrate/20150814081918_create_has_many_through_field.rb
552
- - test/dummy/db/migrate/20150608133038_create_belongs_to_field.rb
553
- - test/dummy/db/migrate/20150608133044_create_has_one_field.rb
523
+ - test/dummy/db/migrate/20150608130516_create_date_field.rb
554
524
  - test/dummy/db/migrate/20150608132621_create_string_field.rb
555
525
  - test/dummy/db/migrate/20160627172810_create_owner.rb
526
+ - test/dummy/db/migrate/20170614141921_create_serialize_field.rb
527
+ - test/dummy/db/migrate/20150608131430_create_integer_field.rb
528
+ - test/dummy/db/migrate/20150608133038_create_belongs_to_field.rb
529
+ - test/dummy/db/migrate/20150608131610_create_float_field.rb
530
+ - test/dummy/db/migrate/20160628173505_add_timestamps.rb
556
531
  - test/dummy/db/migrate/20150608150016_create_has_many_field.rb
557
- - test/dummy/db/migrate/20150612112520_create_has_and_belongs_to_many_field.rb
532
+ - test/dummy/db/migrate/20150608131603_create_decimal_field.rb
533
+ - test/dummy/db/migrate/20150616150629_create_polymorphic_field.rb
534
+ - test/dummy/db/migrate/20150609114636_create_belongs_to_class_name_field.rb
535
+ - test/dummy/db/migrate/20181111162121_create_references_table.rb
558
536
  - test/dummy/db/migrate/20160627172951_create_tree.rb
559
- - test/dummy/public/500.html
537
+ - test/dummy/db/migrate/20150608133044_create_has_one_field.rb
538
+ - test/dummy/db/migrate/20150814081918_create_has_many_through_field.rb
539
+ - test/dummy/db/migrate/20150608132159_create_boolean_field.rb
560
540
  - test/dummy/public/422.html
561
- - test/dummy/public/404.html
562
541
  - test/dummy/public/favicon.ico
563
- - test/dummy/config.ru
564
- - test/dummy/app/models/reference.rb
565
- - test/dummy/app/models/belongs_to_field.rb
566
- - test/dummy/app/models/has_many_class_name_field.rb
567
- - test/dummy/app/models/decimal_field.rb
568
- - test/dummy/app/models/owner.rb
569
- - test/dummy/app/models/integer_field.rb
570
- - test/dummy/app/models/boolean_field.rb
542
+ - test/dummy/public/500.html
543
+ - test/dummy/public/404.html
544
+ - test/dummy/README.rdoc
545
+ - test/dummy/config/secrets.yml
546
+ - test/dummy/config/environments/test.rb
547
+ - test/dummy/config/environments/production.rb
548
+ - test/dummy/config/environments/development.rb
549
+ - test/dummy/config/boot.rb
550
+ - test/dummy/config/routes.rb
551
+ - test/dummy/config/locales/en.yml
552
+ - test/dummy/config/application.rb
553
+ - test/dummy/config/database.yml
554
+ - test/dummy/config/environment.rb
555
+ - test/dummy/config/initializers/cookies_serializer.rb
556
+ - test/dummy/config/initializers/wrap_parameters.rb
557
+ - test/dummy/config/initializers/inflections.rb
558
+ - test/dummy/config/initializers/session_store.rb
559
+ - test/dummy/config/initializers/assets.rb
560
+ - test/dummy/config/initializers/backtrace_silencers.rb
561
+ - test/dummy/config/initializers/mime_types.rb
562
+ - test/dummy/config/initializers/filter_parameter_logging.rb
563
+ - test/dummy/app/helpers/application_helper.rb
564
+ - test/dummy/app/views/layouts/application.html.erb
565
+ - test/dummy/app/controllers/application_controller.rb
571
566
  - test/dummy/app/models/date_field.rb
572
- - test/dummy/app/models/serialize_field.rb
573
- - test/dummy/app/models/has_many_field.rb
574
- - test/dummy/app/models/tree.rb
575
567
  - test/dummy/app/models/belongs_to_class_name_field.rb
576
- - test/dummy/app/models/has_and_belongs_to_many_field.rb
577
568
  - test/dummy/app/models/float_field.rb
578
- - test/dummy/app/models/has_one_field.rb
569
+ - test/dummy/app/models/has_many_through_field.rb
570
+ - test/dummy/app/models/decimal_field.rb
571
+ - test/dummy/app/models/serialize_field.rb
572
+ - test/dummy/app/models/has_and_belongs_to_many_field.rb
573
+ - test/dummy/app/models/has_many_field.rb
574
+ - test/dummy/app/models/owner.rb
579
575
  - test/dummy/app/models/polymorphic_field.rb
576
+ - test/dummy/app/models/tree.rb
580
577
  - test/dummy/app/models/string_field.rb
581
- - test/dummy/app/models/has_many_through_field.rb
582
- - test/dummy/app/assets/config/manifest.js
583
- - test/dummy/app/assets/stylesheets/application.css
578
+ - test/dummy/app/models/belongs_to_field.rb
579
+ - test/dummy/app/models/integer_field.rb
580
+ - test/dummy/app/models/has_one_field.rb
581
+ - test/dummy/app/models/boolean_field.rb
582
+ - test/dummy/app/models/has_many_class_name_field.rb
583
+ - test/dummy/app/models/reference.rb
584
584
  - test/dummy/app/assets/javascripts/application.js
585
- - test/dummy/app/controllers/application_controller.rb
586
- - test/dummy/app/views/layouts/application.html.erb
587
- - test/dummy/app/helpers/application_helper.rb
588
- - test/dummy/README.rdoc
589
- - test/fixtures/has_many_through_field.yml
590
- - test/fixtures/has_many_field.yml
591
- - test/fixtures/string_field.yml
585
+ - test/dummy/app/assets/stylesheets/application.css
586
+ - test/dummy/app/assets/config/manifest.js
587
+ - test/routing/route_test.rb
588
+ - test/services/forest_liana/schema_adapter_test.rb
589
+ - test/services/forest_liana/operator_date_interval_parser_test.rb
590
+ - test/fixtures/belongs_to_field.yml
591
+ - test/fixtures/tree.yml
592
592
  - test/fixtures/owner.yml
593
+ - test/fixtures/reference.yml
594
+ - test/fixtures/has_many_through_field.yml
593
595
  - test/fixtures/has_one_field.yml
594
- - test/fixtures/tree.yml
595
596
  - test/fixtures/serialize_field.yml
596
- - test/fixtures/belongs_to_field.yml
597
- - test/fixtures/reference.yml
598
- - test/test_helper.rb
599
- - spec/services/forest_liana/has_many_getter_spec.rb
600
- - spec/services/forest_liana/permissions_formatter_spec.rb
601
- - spec/services/forest_liana/filters_parser_spec.rb
602
- - spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
603
- - spec/services/forest_liana/value_stat_getter_spec.rb
604
- - spec/services/forest_liana/pie_stat_getter_spec.rb
605
- - spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
606
- - spec/services/forest_liana/smart_action_field_validator_spec.rb
607
- - spec/services/forest_liana/schema_adapter_spec.rb
608
- - spec/services/forest_liana/permissions_getter_spec.rb
609
- - spec/services/forest_liana/resources_getter_spec.rb
610
- - spec/services/forest_liana/line_stat_getter_spec.rb
611
- - spec/services/forest_liana/apimap_sorter_spec.rb
612
- - spec/services/forest_liana/ip_whitelist_checker_spec.rb
613
- - spec/services/forest_liana/resource_updater_spec.rb
614
- - spec/services/forest_liana/permissions_checker_live_queries_spec.rb
615
- - spec/services/forest_liana/scope_manager_spec.rb
616
- - spec/config/initializers/logger_spec.rb
617
- - spec/requests/resources_spec.rb
597
+ - test/fixtures/string_field.yml
598
+ - test/fixtures/has_many_field.yml
599
+ - test/forest_liana_test.rb
600
+ - spec/helpers/forest_liana/query_helper_spec.rb
601
+ - spec/helpers/forest_liana/schema_helper_spec.rb
618
602
  - spec/requests/stats_spec.rb
619
- - spec/requests/actions_controller_spec.rb
603
+ - spec/requests/resources_spec.rb
620
604
  - spec/requests/authentications_spec.rb
621
- - spec/spec_helper.rb
622
- - spec/lib/forest_liana/schema_file_updater_spec.rb
623
- - spec/lib/forest_liana/bootstrapper_spec.rb
624
- - spec/rails_helper.rb
625
- - spec/dummy/bin/rake
626
- - spec/dummy/bin/bundle
605
+ - spec/requests/actions_controller_spec.rb
606
+ - spec/dummy/config.ru
627
607
  - spec/dummy/bin/setup
608
+ - spec/dummy/bin/bundle
609
+ - spec/dummy/bin/rake
628
610
  - spec/dummy/bin/rails
629
- - spec/dummy/config/boot.rb
611
+ - spec/dummy/lib/forest_liana/collections/user.rb
612
+ - spec/dummy/lib/forest_liana/collections/island.rb
613
+ - spec/dummy/lib/forest_liana/collections/location.rb
614
+ - spec/dummy/Rakefile
615
+ - spec/dummy/db/schema.rb
616
+ - spec/dummy/db/migrate/20190716130830_add_age_to_tree.rb
617
+ - spec/dummy/db/migrate/20190226174951_create_tree.rb
618
+ - spec/dummy/db/migrate/20210526084712_create_products.rb
619
+ - spec/dummy/db/migrate/20190226172951_create_user.rb
620
+ - spec/dummy/db/migrate/20210326110524_create_references.rb
621
+ - spec/dummy/db/migrate/20190226173051_create_isle.rb
622
+ - spec/dummy/db/migrate/20210326140855_create_locations.rb
623
+ - spec/dummy/db/migrate/20190716135241_add_type_to_user.rb
624
+ - spec/dummy/db/migrate/20210511141752_create_owners.rb
625
+ - spec/dummy/README.rdoc
630
626
  - spec/dummy/config/secrets.yml
631
- - spec/dummy/config/routes.rb
632
627
  - spec/dummy/config/environments/test.rb
633
- - spec/dummy/config/environments/development.rb
634
628
  - spec/dummy/config/environments/production.rb
635
- - spec/dummy/config/initializers/inflections.rb
636
- - spec/dummy/config/initializers/forest_liana.rb
629
+ - spec/dummy/config/environments/development.rb
630
+ - spec/dummy/config/boot.rb
631
+ - spec/dummy/config/routes.rb
632
+ - spec/dummy/config/application.rb
633
+ - spec/dummy/config/database.yml
634
+ - spec/dummy/config/environment.rb
637
635
  - spec/dummy/config/initializers/cookies_serializer.rb
638
636
  - spec/dummy/config/initializers/wrap_parameters.rb
639
- - spec/dummy/config/initializers/mime_types.rb
640
- - spec/dummy/config/initializers/assets.rb
637
+ - spec/dummy/config/initializers/inflections.rb
641
638
  - spec/dummy/config/initializers/session_store.rb
642
- - spec/dummy/config/initializers/filter_parameter_logging.rb
639
+ - spec/dummy/config/initializers/forest_liana.rb
640
+ - spec/dummy/config/initializers/assets.rb
643
641
  - spec/dummy/config/initializers/backtrace_silencers.rb
644
- - spec/dummy/config/application.rb
645
- - spec/dummy/config/database.yml
646
- - spec/dummy/config/environment.rb
647
- - spec/dummy/Rakefile
648
- - spec/dummy/db/schema.rb
649
- - spec/dummy/db/migrate/20190716135241_add_type_to_user.rb
650
- - spec/dummy/db/migrate/20210511141752_create_owners.rb
651
- - spec/dummy/db/migrate/20190226172951_create_user.rb
652
- - spec/dummy/db/migrate/20190716130830_add_age_to_tree.rb
653
- - spec/dummy/db/migrate/20210326140855_create_locations.rb
654
- - spec/dummy/db/migrate/20210326110524_create_references.rb
655
- - spec/dummy/db/migrate/20210526084712_create_products.rb
656
- - spec/dummy/db/migrate/20190226173051_create_isle.rb
657
- - spec/dummy/db/migrate/20190226174951_create_tree.rb
658
- - spec/dummy/config.ru
659
- - spec/dummy/lib/forest_liana/collections/location.rb
660
- - spec/dummy/lib/forest_liana/collections/user.rb
661
- - spec/dummy/lib/forest_liana/collections/island.rb
662
- - spec/dummy/app/config/routes.rb
663
- - spec/dummy/app/models/reference.rb
642
+ - spec/dummy/config/initializers/mime_types.rb
643
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
644
+ - spec/dummy/app/helpers/application_helper.rb
645
+ - spec/dummy/app/views/layouts/application.html.erb
646
+ - spec/dummy/app/controllers/forest/islands_controller.rb
647
+ - spec/dummy/app/controllers/application_controller.rb
664
648
  - spec/dummy/app/models/product.rb
665
- - spec/dummy/app/models/location.rb
666
649
  - spec/dummy/app/models/user.rb
667
- - spec/dummy/app/models/island.rb
668
650
  - spec/dummy/app/models/owner.rb
669
651
  - spec/dummy/app/models/tree.rb
670
- - spec/dummy/app/assets/config/manifest.js
671
- - spec/dummy/app/assets/stylesheets/application.css
652
+ - spec/dummy/app/models/island.rb
653
+ - spec/dummy/app/models/location.rb
654
+ - spec/dummy/app/models/reference.rb
672
655
  - spec/dummy/app/assets/javascripts/application.js
673
- - spec/dummy/app/controllers/forest/islands_controller.rb
674
- - spec/dummy/app/controllers/application_controller.rb
675
- - spec/dummy/app/views/layouts/application.html.erb
676
- - spec/dummy/app/helpers/application_helper.rb
677
- - spec/dummy/README.rdoc
678
- - spec/helpers/forest_liana/schema_helper_spec.rb
679
- - spec/helpers/forest_liana/query_helper_spec.rb
656
+ - spec/dummy/app/assets/stylesheets/application.css
657
+ - spec/dummy/app/assets/config/manifest.js
658
+ - spec/dummy/app/config/routes.rb
659
+ - spec/rails_helper.rb
660
+ - spec/services/forest_liana/permissions_getter_spec.rb
661
+ - spec/services/forest_liana/filters_parser_spec.rb
662
+ - spec/services/forest_liana/schema_adapter_spec.rb
663
+ - spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
664
+ - spec/services/forest_liana/smart_action_field_validator_spec.rb
665
+ - spec/services/forest_liana/apimap_sorter_spec.rb
666
+ - spec/services/forest_liana/permissions_formatter_spec.rb
667
+ - spec/services/forest_liana/line_stat_getter_spec.rb
668
+ - spec/services/forest_liana/pie_stat_getter_spec.rb
669
+ - spec/services/forest_liana/has_many_getter_spec.rb
670
+ - spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
671
+ - spec/services/forest_liana/ip_whitelist_checker_spec.rb
672
+ - spec/services/forest_liana/resources_getter_spec.rb
673
+ - spec/services/forest_liana/value_stat_getter_spec.rb
674
+ - spec/services/forest_liana/scope_manager_spec.rb
675
+ - spec/services/forest_liana/permissions_checker_live_queries_spec.rb
676
+ - spec/services/forest_liana/resource_updater_spec.rb
677
+ - spec/lib/forest_liana/bootstrapper_spec.rb
678
+ - spec/lib/forest_liana/schema_file_updater_spec.rb
679
+ - spec/spec_helper.rb
680
+ - spec/config/initializers/logger_spec.rb