forest_liana 9.1.10 → 9.2.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 (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/forest_liana/ability/permission/smart_action_checker.rb +1 -1
  3. data/app/services/forest_liana/filters_parser.rb +1 -5
  4. data/app/services/forest_liana/leaderboard_stat_getter.rb +1 -1
  5. data/app/services/forest_liana/line_stat_getter.rb +1 -1
  6. data/app/services/forest_liana/pie_stat_getter.rb +1 -1
  7. data/app/services/forest_liana/scope_manager.rb +34 -58
  8. data/app/services/forest_liana/utils/context_variables.rb +41 -0
  9. data/app/services/forest_liana/utils/context_variables_injector.rb +53 -0
  10. data/app/services/forest_liana/value_stat_getter.rb +1 -1
  11. data/lib/forest_liana/version.rb +1 -1
  12. data/spec/requests/actions_controller_spec.rb +32 -4
  13. data/spec/requests/count_spec.rb +1 -1
  14. data/spec/requests/resources_spec.rb +6 -7
  15. data/spec/requests/stats_spec.rb +29 -28
  16. data/spec/services/forest_liana/filters_parser_spec.rb +35 -35
  17. data/spec/services/forest_liana/has_many_getter_spec.rb +13 -11
  18. data/spec/services/forest_liana/line_stat_getter_spec.rb +1 -1
  19. data/spec/services/forest_liana/pie_stat_getter_spec.rb +11 -11
  20. data/spec/services/forest_liana/resource_updater_spec.rb +25 -21
  21. data/spec/services/forest_liana/resources_getter_spec.rb +10 -10
  22. data/spec/services/forest_liana/scope_manager_spec.rb +243 -152
  23. data/spec/services/forest_liana/utils/context_variables_injector_spec.rb +107 -0
  24. data/spec/services/forest_liana/utils/context_variables_spec.rb +43 -0
  25. data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
  26. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a0e913808b061b713f2f30f49f2a06c43fa7b47089e1d917a9eedd0090d5750
4
- data.tar.gz: 51b70d6fbc9333e273587c63f5f1b48a6b0a6d679c8265bcd8374a8e2416c1af
3
+ metadata.gz: b721a5f9e7e41711b05b4e34c607d8e23e7030646eb8896629b1170e55466869
4
+ data.tar.gz: 999494458850509c7698b2d00a77f2e8d41d767419b0e5b652ac8114b4fcbb9a
5
5
  SHA512:
6
- metadata.gz: 0ec7cd50fb18a1ddb46e069e78729005c1676294550971c80a4452010d776e6ca095f756cfc29a57f36bb14a7ac5aa81d2fdf55b212f63772b5c7f5fe686d646
7
- data.tar.gz: 22e270257029f42d3669aa5b55c786aa3865534db5be8d28de9f12c172f6f6b3515a72f8d1933ed82f4bef137db9c506cd5beeb598a84bdb08ff95ba98d86a5c
6
+ metadata.gz: 4fdc7007c031c6377f6d1281dad2ca82e1966d4692995ab592d149d6afe5c8b1a78bbc202ff5b558b3ee770f864a4caacb84c67ffc4aa79f1416ccaeb38c214d
7
+ data.tar.gz: e3dd0966176770f7b301a888480b72499025c2e0e1f727677a315f880397fa9903786eb2cb547cbdb6612b545c7a382d17c1ec5eeb95ab5496680bcde0bd8977
@@ -49,7 +49,7 @@ module ForestLiana
49
49
  begin
50
50
  attributes = @parameters[:data][:attributes]
51
51
  records = FiltersParser.new(
52
- @smart_action[condition_name][0]['filter'].to_json,
52
+ @smart_action[condition_name][0]['filter'],
53
53
  @collection,
54
54
  @parameters[:timezone],
55
55
  @parameters
@@ -3,7 +3,7 @@ module ForestLiana
3
3
  AGGREGATOR_OPERATOR = %w(and or)
4
4
 
5
5
  def initialize(filters, resource, timezone, params = nil)
6
- @filters = filters.instance_of?(ActionController::Parameters) ? filters.to_h : JSON.parse(filters)
6
+ @filters = filters
7
7
  @params = params
8
8
  @resource = resource
9
9
  @operator_date_parser = OperatorDateIntervalParser.new(timezone)
@@ -87,10 +87,6 @@ module ForestLiana
87
87
  value = condition['value']
88
88
  field_name = condition['field']
89
89
 
90
- if value.is_a?(String) && value.start_with?('{{')
91
- value = @params[:contextVariables][value.gsub(/[{}]/, '')]
92
- end
93
-
94
90
  if @operator_date_parser.is_date_operator?(operator)
95
91
  condition = @operator_date_parser.get_date_filter(operator, value)
96
92
  return "#{parse_field_name(field_name)} #{condition}"
@@ -27,7 +27,7 @@ module ForestLiana
27
27
  end
28
28
 
29
29
  def get_scoped_model(model, forest_user, timezone)
30
- scope_filters = ForestLiana::ScopeManager.get_scope_for_user(forest_user, model.name, as_string: true)
30
+ scope_filters = ForestLiana::ScopeManager.get_scope(model.name, forest_user)
31
31
 
32
32
  return model.unscoped if scope_filters.blank?
33
33
 
@@ -25,7 +25,7 @@ module ForestLiana
25
25
  def perform
26
26
  value = get_resource()
27
27
 
28
- filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
28
+ filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name, @params['contextVariables'])
29
29
 
30
30
  unless filters.blank?
31
31
  value = FiltersParser.new(filters, @resource, @params[:timezone], @params).apply_filters
@@ -7,7 +7,7 @@ module ForestLiana
7
7
  timezone_offset = @params[:timezone].to_i
8
8
  resource = optimize_record_loading(@resource, get_resource)
9
9
 
10
- filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
10
+ filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name, @params['contextVariables'])
11
11
 
12
12
  unless filters.blank?
13
13
  resource = FiltersParser.new(filters, resource, @params[:timezone], @params).apply_filters
@@ -1,20 +1,19 @@
1
1
  module ForestLiana
2
2
  class ScopeManager
3
- @@scopes_cache = Hash.new
4
- # 5 minutes exipration cache
3
+ # 5 minutes expiration cache
5
4
  @@scope_cache_expiration_delta = 300
6
5
 
7
- def self.apply_scopes_on_records(records, forest_user, collection_name, timezone)
8
- scope_filters = get_scope_for_user(forest_user, collection_name, as_string: true)
6
+ def self.apply_scopes_on_records(records, user, collection_name, timezone)
7
+ scope_filters = get_scope(collection_name, user)
9
8
 
10
9
  return records if scope_filters.blank?
11
10
 
12
11
  FiltersParser.new(scope_filters, records, timezone).apply_filters
13
12
  end
14
13
 
15
- def self.append_scope_for_user(existing_filter, user, collection_name)
16
- existing_filter = existing_filter.to_json if existing_filter.is_a?(ActionController::Parameters)
17
- scope_filter = get_scope_for_user(user, collection_name, as_string: true)
14
+ def self.append_scope_for_user(existing_filter, user, collection_name, request_context_variables = nil)
15
+ existing_filter = inject_context_variables(existing_filter, user, request_context_variables) if existing_filter
16
+ scope_filter = get_scope(collection_name, user, request_context_variables)
18
17
  filters = [existing_filter, scope_filter].compact
19
18
 
20
19
  case filters.length
@@ -23,80 +22,57 @@ module ForestLiana
23
22
  when 1
24
23
  filters[0]
25
24
  else
26
- "{\"aggregator\":\"and\",\"conditions\":[#{existing_filter},#{scope_filter}]}"
25
+ { 'aggregator' => 'and', 'conditions' => [existing_filter, scope_filter] }
27
26
  end
28
27
  end
29
28
 
30
- def self.get_scope_for_user(user, collection_name, as_string: false)
31
- raise 'Missing required rendering_id' unless user['rendering_id']
32
- raise 'Missing required collection_name' unless collection_name
29
+ def self.get_scope(collection_name, user, request_context_variables = nil)
30
+ retrieve = fetch_scopes(user['rendering_id'])
31
+ scope = retrieve['scopes'][collection_name]
33
32
 
34
- collection_scope = get_collection_scope(user['rendering_id'], collection_name)
33
+ return nil if scope.nil?
35
34
 
36
- return nil unless collection_scope
37
-
38
- filters = format_dynamic_values(user['id'], collection_scope)
39
-
40
- as_string && filters ? JSON.generate(filters) : filters
35
+ inject_context_variables(scope, user, request_context_variables)
41
36
  end
42
37
 
43
- def self.get_collection_scope(rendering_id, collection_name)
44
- if !@@scopes_cache[rendering_id]
45
- # when scope cache is unset wait for the refresh
46
- refresh_scopes_cache(rendering_id)
47
- elsif has_cache_expired?(rendering_id)
48
- # when cache expired refresh the scopes without waiting for it
49
- Thread.new { refresh_scopes_cache(rendering_id) }
50
- end
38
+ def self.inject_context_variables(filter, user, request_context_variables = nil)
39
+ filter = JSON.parse(filter) if filter.is_a? String
51
40
 
52
- @@scopes_cache[rendering_id][:scopes][collection_name].deep_dup
53
- end
41
+ retrieve = fetch_scopes(user['rendering_id'])
42
+ context_variables = Utils::ContextVariables.new(retrieve['team'], user, request_context_variables)
54
43
 
55
- def self.has_cache_expired?(rendering_id)
56
- rendering_scopes = @@scopes_cache[rendering_id]
57
- return true unless rendering_scopes
58
-
59
- second_since_last_fetch = Time.now - rendering_scopes[:fetched_at]
60
- second_since_last_fetch >= @@scope_cache_expiration_delta
44
+ Utils::ContextVariablesInjector.inject_context_in_filter(filter, context_variables)
61
45
  end
62
46
 
63
- def self.refresh_scopes_cache(rendering_id)
64
- scopes = fetch_scopes(rendering_id)
65
- @@scopes_cache[rendering_id] = {
66
- :fetched_at => Time.now,
67
- :scopes => scopes
68
- }
47
+ def self.invalidate_scope_cache(rendering_id)
48
+ Rails.cache.delete('forest.scopes.' + rendering_id.to_s)
69
49
  end
70
50
 
71
51
  def self.fetch_scopes(rendering_id)
72
- query_parameters = { 'renderingId' => rendering_id }
73
- response = ForestLiana::ForestApiRequester.get('/liana/scopes', query: query_parameters)
52
+ response = ForestLiana::ForestApiRequester.get("/liana/v4/permissions/renderings/#{rendering_id}")
74
53
 
75
54
  if response.is_a?(Net::HTTPOK)
76
- JSON.parse(response.body)
55
+ Rails.cache.fetch('forest.scopes.' + rendering_id.to_s, expires_in: @@scope_cache_expiration_delta) do
56
+ data = {}
57
+ parse_response = JSON.parse(response.body)
58
+
59
+ data['scopes'] = decode_scope(parse_response['collections'])
60
+ data['team'] = parse_response['team']
61
+
62
+ data
63
+ end
77
64
  else
78
65
  raise 'Unable to fetch scopes'
79
66
  end
80
67
  end
81
68
 
82
- def self.format_dynamic_values(user_id, collection_scope)
83
- filter = collection_scope.dig('scope', 'filter')
84
- return nil unless filter
85
-
86
- dynamic_scopes_values = collection_scope.dig('scope', 'dynamicScopesValues')
87
-
88
- # Only goes one level deep as required for now
89
- filter['conditions'].map do |condition|
90
- value = condition['value']
91
- if value.is_a?(String) && value.start_with?('$currentUser')
92
- condition['value'] = dynamic_scopes_values.dig('users', user_id, value)
93
- end
69
+ def self.decode_scope(raw_scopes)
70
+ scopes = {}
71
+ raw_scopes.each do |collection_name, value|
72
+ scopes[collection_name] = value['scope'] unless value['scope'].nil?
94
73
  end
95
- filter
96
- end
97
74
 
98
- def self.invalidate_scope_cache(rendering_id)
99
- @@scopes_cache.delete(rendering_id)
75
+ scopes
100
76
  end
101
77
  end
102
78
  end
@@ -0,0 +1,41 @@
1
+ module ForestLiana
2
+ module Utils
3
+ class ContextVariables
4
+ attr_reader :team, :user, :request_context_variables
5
+
6
+ USER_VALUE_PREFIX = 'currentUser.'.freeze
7
+
8
+ USER_VALUE_TAG_PREFIX = 'currentUser.tags.'.freeze
9
+
10
+ USER_VALUE_TEAM_PREFIX = 'currentUser.team.'.freeze
11
+
12
+ def initialize(team, user, request_context_variables = nil)
13
+ @team = team
14
+ @user = user
15
+ @request_context_variables = request_context_variables
16
+ end
17
+
18
+ def get_value(context_variable_key)
19
+ return get_current_user_data(context_variable_key) if context_variable_key.start_with?(USER_VALUE_PREFIX)
20
+
21
+ request_context_variables[context_variable_key] if request_context_variables
22
+ end
23
+
24
+ private
25
+
26
+ def get_current_user_data(context_variable_key)
27
+ if context_variable_key.start_with?(USER_VALUE_TEAM_PREFIX)
28
+ return team[context_variable_key[USER_VALUE_TEAM_PREFIX.length..]]
29
+ end
30
+
31
+ if context_variable_key.start_with?(USER_VALUE_TAG_PREFIX)
32
+ user['tags'].each do |tag|
33
+ return tag[context_variable_key[USER_VALUE_TAG_PREFIX.length..]] if tag.key?(context_variable_key[USER_VALUE_TAG_PREFIX.length..])
34
+ end
35
+ end
36
+
37
+ user[context_variable_key[USER_VALUE_PREFIX.length..]]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ module ForestLiana
2
+ module Utils
3
+ class ContextVariablesInjector
4
+
5
+ def self.inject_context_in_value(value, context_variables)
6
+ inject_context_in_value_custom(value) do |context_variable_key|
7
+ context_variables.get_value(context_variable_key).to_s
8
+ end
9
+ end
10
+
11
+ def self.inject_context_in_value_custom(value)
12
+ return value unless value.is_a?(String)
13
+
14
+ value_with_context_variables_injected = value
15
+ regex = /{{([^}]+)}}/
16
+ encountered_variables = []
17
+
18
+ while (match = regex.match(value_with_context_variables_injected))
19
+ context_variable_key = match[1]
20
+
21
+ unless encountered_variables.include?(context_variable_key)
22
+ value_with_context_variables_injected.gsub!(
23
+ /{{#{context_variable_key}}}/,
24
+ yield(context_variable_key)
25
+ )
26
+ end
27
+
28
+ encountered_variables.push(context_variable_key)
29
+ end
30
+
31
+ value_with_context_variables_injected
32
+ end
33
+
34
+ def self.inject_context_in_filter(filter, context_variables)
35
+ return nil unless filter
36
+
37
+ if filter.key? 'aggregator'
38
+ return {
39
+ 'aggregator' => filter['aggregator'],
40
+ 'conditions' => filter['conditions'].map { |condition| inject_context_in_filter(condition, context_variables) }
41
+ }
42
+ end
43
+
44
+ {
45
+ 'field' => filter['field'],
46
+ 'operator' => filter['operator'],
47
+ 'value' => inject_context_in_value(filter['value'], context_variables)
48
+ }
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -6,7 +6,7 @@ module ForestLiana
6
6
  return if @params[:aggregator].blank?
7
7
  resource = optimize_record_loading(@resource, get_resource)
8
8
 
9
- filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
9
+ filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name, @params['contextVariables'])
10
10
 
11
11
  unless filters.blank?
12
12
  filter_parser = FiltersParser.new(filters, resource, @params[:timezone], @params)
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "9.1.10"
2
+ VERSION = "9.2.0"
3
3
  end
@@ -2,7 +2,7 @@ require 'rails_helper'
2
2
 
3
3
  describe 'Requesting Actions routes', :type => :request do
4
4
  let(:rendering_id) { 13 }
5
- let(:scope_filters) { nil }
5
+ let(:scope_filters) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
6
6
 
7
7
  before(:each) do
8
8
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
@@ -10,7 +10,7 @@ describe 'Requesting Actions routes', :type => :request do
10
10
  Island.create(id: 1, name: 'Corsica')
11
11
 
12
12
  ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
13
- allow(ForestLiana::ScopeManager).to receive(:get_scope_for_user).and_return(scope_filters)
13
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scope_filters)
14
14
  end
15
15
 
16
16
  after(:each) do
@@ -291,7 +291,21 @@ describe 'Requesting Actions routes', :type => :request do
291
291
 
292
292
  describe 'with scopes' do
293
293
  describe 'when record is in scope' do
294
- let(:scope_filters) { JSON.generate({ field: 'name', operator: 'equal', value: 'Corsica' }) }
294
+ let(:scope_filters) {
295
+ {
296
+ 'scopes' =>
297
+ {
298
+ 'Island' => {
299
+ 'aggregator' => 'and',
300
+ 'conditions' => [{'field' => 'name', 'operator' => 'equal', 'value' => 'Corsica'}]
301
+ }
302
+ },
303
+ 'team' => {
304
+ 'id' => 43,
305
+ 'name' => 'Operations'
306
+ }
307
+ }
308
+ }
295
309
 
296
310
  it 'should respond 200 and perform the action' do
297
311
  post '/forest/actions/test', params: JSON.dump(params), headers: headers
@@ -301,7 +315,21 @@ describe 'Requesting Actions routes', :type => :request do
301
315
  end
302
316
 
303
317
  describe 'when record is out of scope' do
304
- let(:scope_filters) { JSON.generate({ field: 'name', operator: 'equal', value: 'Ré' }) }
318
+ let(:scope_filters) {
319
+ {
320
+ 'scopes' =>
321
+ {
322
+ 'Island' => {
323
+ 'aggregator' => 'and',
324
+ 'conditions' => [{'field' => 'name', 'operator' => 'equal', 'value' => 'Ré'}]
325
+ }
326
+ },
327
+ 'team' => {
328
+ 'id' => 43,
329
+ 'name' => 'Operations'
330
+ }
331
+ }
332
+ }
305
333
 
306
334
  it 'should respond 400 and NOT perform the action' do
307
335
  post '/forest/actions/test', params: JSON.dump(params), headers: headers
@@ -15,7 +15,7 @@ describe 'Requesting Owner', :type => :request do
15
15
 
16
16
  allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
17
17
 
18
- allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
18
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}})
19
19
  end
20
20
 
21
21
  token = JWT.encode({
@@ -1,10 +1,10 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  describe 'Requesting Tree resources', :type => :request do
4
-
4
+ let(:scope_filters) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
5
5
  before do
6
6
  user = User.create(name: 'Michel')
7
- tree = Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
7
+ Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
8
8
 
9
9
  Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
10
10
  Rails.cache.write('forest.has_permission', true)
@@ -26,8 +26,7 @@ describe 'Requesting Tree resources', :type => :request do
26
26
  allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
27
27
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
28
28
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
29
- # allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
30
- allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
29
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scope_filters)
31
30
  end
32
31
 
33
32
  after do
@@ -156,10 +155,10 @@ describe 'Requesting Tree resources', :type => :request do
156
155
  end
157
156
 
158
157
  describe 'Requesting Address resources', :type => :request do
159
-
158
+ let(:scope_filters) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
160
159
  before do
161
160
  user = User.create(name: 'Michel')
162
- address = Address.create(line1: '10 Downing Street', city: 'London', zipcode: '2AB', addressable: user)
161
+ Address.create(line1: '10 Downing Street', city: 'London', zipcode: '2AB', addressable: user)
163
162
 
164
163
  Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
165
164
  Rails.cache.write('forest.has_permission', true)
@@ -181,7 +180,7 @@ describe 'Requesting Address resources', :type => :request do
181
180
  allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
182
181
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
183
182
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
184
- allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
183
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scope_filters)
185
184
  end
186
185
 
187
186
  after do
@@ -2,34 +2,39 @@ require 'rails_helper'
2
2
  require 'json'
3
3
 
4
4
  describe "Stats", type: :request do
5
-
6
- token = JWT.encode({
7
- id: 1,
8
- email: 'michael.kelso@that70.show',
9
- first_name: 'Michael',
10
- last_name: 'Kelso',
11
- team: 'Operations',
12
- rendering_id: '1',
13
- exp: Time.now.to_i + 2.weeks.to_i,
14
- permission_level: 'admin'
15
- }, ForestLiana.auth_secret, 'HS256')
16
-
17
- headers = {
18
- 'Accept' => 'application/json',
19
- 'Content-Type' => 'application/json',
20
- 'Authorization' => "Bearer #{token}"
21
- }
22
-
5
+ let(:rendering_id) { 13 }
6
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
23
7
  let(:schema) {
24
8
  [
25
9
  ForestLiana::Model::Collection.new({
26
- name: 'Product',
27
- fields: [],
28
- actions: []
29
- })
10
+ name: 'Product',
11
+ fields: [],
12
+ actions: []
13
+ })
30
14
  ]
31
15
  }
32
16
 
17
+ let(:token) {
18
+ JWT.encode({
19
+ id: 1,
20
+ email: 'michael.kelso@that70.show',
21
+ first_name: 'Michael',
22
+ last_name: 'Kelso',
23
+ team: 'Operations',
24
+ rendering_id: rendering_id,
25
+ exp: Time.now.to_i + 2.weeks.to_i,
26
+ permission_level: 'admin'
27
+ }, ForestLiana.auth_secret, 'HS256')
28
+ }
29
+
30
+ let(:headers) {
31
+ {
32
+ 'Accept' => 'application/json',
33
+ 'Content-Type' => 'application/json',
34
+ 'Authorization' => "Bearer #{token}"
35
+ }
36
+ }
37
+
33
38
  before do
34
39
  Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
35
40
  Rails.cache.write('forest.has_permission', true)
@@ -53,12 +58,8 @@ describe "Stats", type: :request do
53
58
  }
54
59
  )
55
60
 
56
- ForestLiana::ScopeManager.class_variable_set(:@@scopes_cache, {
57
- '1' => {
58
- :fetched_at => Time.now,
59
- :scopes => {}
60
- }
61
- })
61
+ ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
62
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
62
63
 
63
64
  allow(ForestLiana).to receive(:apimap).and_return(schema)
64
65
  allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }