forest_liana 7.8.0 → 8.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +5 -3
  3. data/app/controllers/forest_liana/application_controller.rb +15 -0
  4. data/app/controllers/forest_liana/resources_controller.rb +31 -57
  5. data/app/controllers/forest_liana/smart_actions_controller.rb +44 -58
  6. data/app/controllers/forest_liana/stats_controller.rb +14 -58
  7. data/app/services/forest_liana/ability/exceptions/access_denied.rb +16 -0
  8. data/app/services/forest_liana/ability/exceptions/action_condition_error.rb +16 -0
  9. data/app/services/forest_liana/ability/exceptions/require_approval.rb +18 -0
  10. data/app/services/forest_liana/ability/exceptions/trigger_forbidden.rb +16 -0
  11. data/app/services/forest_liana/ability/fetch.rb +23 -0
  12. data/app/services/forest_liana/ability/permission/request_permission.rb +19 -0
  13. data/app/services/forest_liana/ability/permission/smart_action_checker.rb +71 -0
  14. data/app/services/forest_liana/ability/permission.rb +148 -0
  15. data/app/services/forest_liana/ability.rb +24 -0
  16. data/app/services/forest_liana/filters_parser.rb +7 -7
  17. data/app/services/forest_liana/leaderboard_stat_getter.rb +7 -7
  18. data/app/services/forest_liana/line_stat_getter.rb +8 -8
  19. data/app/services/forest_liana/pie_stat_getter.rb +17 -17
  20. data/app/services/forest_liana/stat_getter.rb +1 -2
  21. data/app/services/forest_liana/value_stat_getter.rb +7 -7
  22. data/lib/forest_liana/bootstrapper.rb +1 -1
  23. data/lib/forest_liana/version.rb +1 -1
  24. data/spec/dummy/lib/forest_liana/collections/island.rb +1 -1
  25. data/spec/requests/actions_controller_spec.rb +3 -4
  26. data/spec/requests/count_spec.rb +5 -9
  27. data/spec/requests/resources_spec.rb +55 -11
  28. data/spec/requests/stats_spec.rb +103 -42
  29. data/spec/services/forest_liana/ability/ability_spec.rb +48 -0
  30. data/spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb +357 -0
  31. data/spec/services/forest_liana/ability/permission_spec.rb +332 -0
  32. data/spec/services/forest_liana/filters_parser_spec.rb +0 -12
  33. data/spec/services/forest_liana/line_stat_getter_spec.rb +9 -9
  34. data/spec/services/forest_liana/pie_stat_getter_spec.rb +7 -7
  35. data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +33 -17
  38. data/app/services/forest_liana/permissions_checker.rb +0 -223
  39. data/app/services/forest_liana/permissions_formatter.rb +0 -52
  40. data/app/services/forest_liana/permissions_getter.rb +0 -59
  41. data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +0 -713
  42. data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +0 -845
  43. data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +0 -175
  44. data/spec/services/forest_liana/permissions_formatter_spec.rb +0 -222
  45. data/spec/services/forest_liana/permissions_getter_spec.rb +0 -83
@@ -4,12 +4,12 @@ require 'json'
4
4
  describe "Stats", type: :request do
5
5
 
6
6
  token = JWT.encode({
7
- id: 38,
7
+ id: 1,
8
8
  email: 'michael.kelso@that70.show',
9
9
  first_name: 'Michael',
10
10
  last_name: 'Kelso',
11
11
  team: 'Operations',
12
- rendering_id: 16,
12
+ rendering_id: '1',
13
13
  exp: Time.now.to_i + 2.weeks.to_i,
14
14
  permission_level: 'admin'
15
15
  }, ForestLiana.auth_secret, 'HS256')
@@ -23,7 +23,7 @@ describe "Stats", type: :request do
23
23
  let(:schema) {
24
24
  [
25
25
  ForestLiana::Model::Collection.new({
26
- name: 'Products',
26
+ name: 'Product',
27
27
  fields: [],
28
28
  actions: []
29
29
  })
@@ -31,62 +31,113 @@ describe "Stats", type: :request do
31
31
  }
32
32
 
33
33
  before do
34
- allow(ForestLiana).to receive(:apimap).and_return(schema)
35
- end
34
+ Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
35
+ Rails.cache.write('forest.has_permission', true)
36
+ allow_any_instance_of(ForestLiana::Ability::Fetch)
37
+ .to receive(:get_permissions)
38
+ .and_return(
39
+ {
40
+ "stats" => [
41
+ {
42
+ "type" => "Value",
43
+ "filter" => nil,
44
+ "aggregator" => "Count",
45
+ "aggregateFieldName" => nil,
46
+ "sourceCollectionName" => "Owner"
47
+ },
48
+ {
49
+ "type" => "Value",
50
+ "query" => "SELECT COUNT(*) AS value FROM products;"
51
+ }
52
+ ],
53
+ }
54
+ )
55
+
56
+ ForestLiana::ScopeManager.class_variable_set(:@@scopes_cache, {
57
+ '1' => {
58
+ :fetched_at => Time.now,
59
+ :scopes => {}
60
+ }
61
+ })
36
62
 
37
- before(:each) do
63
+ allow(ForestLiana).to receive(:apimap).and_return(schema)
38
64
  allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
39
65
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
40
66
  allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
41
-
42
- allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { true }
43
-
44
- allow_any_instance_of(ForestLiana::ValueStatGetter).to receive(:perform) { true }
45
- allow_any_instance_of(ForestLiana::QueryStatGetter).to receive(:perform) { true }
46
67
  end
47
68
 
48
-
49
-
50
69
  describe 'POST /stats/:collection' do
51
- params = { type: 'Value', collection: 'User', aggregate: 'Count' }
52
-
70
+ params = { type: 'Value', collection: 'Owner', aggregator: 'Count', sourceCollectionName: 'Owner', aggregateFieldName: nil, filter: nil}
53
71
  it 'should respond 200' do
54
- data = ForestLiana::Model::Stat.new(value: { countCurrent: 0, countPrevious: 0 })
55
- allow_any_instance_of(ForestLiana::ValueStatGetter).to receive(:record) { data }
56
- # NOTICE: bypass : find_resource error
57
- allow_any_instance_of(ForestLiana::StatsController).to receive(:find_resource) { true }
58
- allow(ForestLiana::QueryHelper).to receive(:get_one_association_names_symbol) { true }
72
+ Rails.cache.delete('forest.stats')
73
+ post '/forest/stats/Owner', params: JSON.dump(params), headers: headers
59
74
 
60
- post '/forest/stats/Products', params: JSON.dump(params), headers: headers
61
75
  expect(response.status).to eq(200)
62
76
  end
63
77
 
64
- it 'should respond 401 with no headers' do
65
- post '/forest/stats/Products', params: JSON.dump(params)
66
- expect(response.status).to eq(401)
78
+ it 'should respond 200 with Objective chart' do
79
+ Rails.cache.delete('forest.stats')
80
+ params = {type: "Objective", sourceCollectionName: "Owner", aggregateFieldName: nil, aggregator: "Count", objective: 200, filter: nil, contextVariables: {}}
81
+ post '/forest/stats/Owner', params: JSON.dump(params), headers: headers
82
+
83
+ expect(response.status).to eq(200)
67
84
  end
68
85
 
69
- it 'should respond 404 with non existing collection' do
70
- allow_any_instance_of(ForestLiana::ValueStatGetter).to receive(:record) { nil }
86
+ it 'should respond 200 with Pie chart' do
87
+ Rails.cache.delete('forest.stats')
88
+ params = { type: "Pie", sourceCollectionName: "Owner", aggregateFieldName: nil, groupByFieldName: "id", aggregator: "Count", filter: nil, contextVariables:nil }
89
+ post '/forest/stats/Owner', params: JSON.dump(params), headers: headers
71
90
 
72
- post '/forest/stats/NoCollection', params: {}, headers: headers
73
- expect(response.status).to eq(404)
91
+ expect(response.status).to eq(200)
92
+ end
93
+
94
+ it 'should respond 200 with Line chart' do
95
+ Rails.cache.delete('forest.stats')
96
+ params = { type: "Line", sourceCollectionName: "Owner", aggregateFieldName: nil, groupByFieldName: "hired_at", aggregator: "Count", timeRange: "Week", filter: nil, contextVariables:nil }
97
+ post '/forest/stats/Owner', params: JSON.dump(params), headers: headers
98
+
99
+ expect(response.status).to eq(200)
74
100
  end
75
101
 
76
102
  it 'should respond 403 Forbidden' do
77
- allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { false }
103
+ no_admin_token = JWT.encode({
104
+ id: 1,
105
+ email: 'michael.kelso@that70.show',
106
+ first_name: 'Michael',
107
+ last_name: 'Kelso',
108
+ team: 'Operations',
109
+ rendering_id: '1',
110
+ exp: Time.now.to_i + 2.weeks.to_i,
111
+ permission_level: 'user'
112
+ }, ForestLiana.auth_secret, 'HS256')
113
+
114
+ no_admin_headers = {
115
+ 'Accept' => 'application/json',
116
+ 'Content-Type' => 'application/json',
117
+ 'Authorization' => "Bearer #{no_admin_token}"
118
+ }
119
+
120
+ params[:aggregateFieldName] = 'foo'
121
+ Rails.cache.delete('forest.stats')
122
+ allow_any_instance_of(ForestLiana::StatsController).to receive(:find_resource).and_return(Product)
123
+ data = ForestLiana::Model::Stat.new(value: { countCurrent: 0, countPrevious: 0 })
124
+ allow_any_instance_of(ForestLiana::ValueStatGetter).to receive(:record) { data }
78
125
  # NOTICE: bypass : find_resource error
79
126
  allow_any_instance_of(ForestLiana::StatsController).to receive(:find_resource) { true }
127
+ allow(ForestLiana::QueryHelper).to receive(:get_one_association_names_symbol) { true }
128
+
129
+
130
+ post '/forest/stats/Products', params: JSON.dump(params), headers: no_admin_headers
80
131
 
81
- post '/forest/stats/Products', params: JSON.dump(params), headers: headers
82
132
  expect(response.status).to eq(403)
83
133
  end
84
134
  end
85
135
 
86
136
  describe 'POST /stats' do
87
- params = { query: 'SELECT COUNT(*) AS value FROM products;' }
137
+ params = { type: 'Value', query: 'SELECT COUNT(*) AS value FROM products;' }
88
138
 
89
139
  it 'should respond 200' do
140
+ allow_any_instance_of(ForestLiana::StatsController).to receive(:find_resource).and_return(Product)
90
141
  data = ForestLiana::Model::Stat.new(value: { value: 0, objective: 0 })
91
142
  allow_any_instance_of(ForestLiana::QueryStatGetter).to receive(:record) { data }
92
143
 
@@ -100,18 +151,28 @@ describe "Stats", type: :request do
100
151
  end
101
152
 
102
153
  it 'should respond 403 Forbidden' do
103
- allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { false }
104
-
105
- post '/forest/stats', params: JSON.dump(params), headers: headers
154
+ no_admin_token = JWT.encode({
155
+ id: 1,
156
+ email: 'michael.kelso@that70.show',
157
+ first_name: 'Michael',
158
+ last_name: 'Kelso',
159
+ team: 'Operations',
160
+ rendering_id: '16',
161
+ exp: Time.now.to_i + 2.weeks.to_i,
162
+ permission_level: 'user'
163
+ }, ForestLiana.auth_secret, 'HS256')
164
+
165
+ no_admin_headers = {
166
+ 'Accept' => 'application/json',
167
+ 'Content-Type' => 'application/json',
168
+ 'Authorization' => "Bearer #{no_admin_token}"
169
+ }
170
+ params[:query] = 'SELECT COUNT(*) AS value FROM trees;'
171
+ Rails.cache.delete('forest.stats')
172
+ allow_any_instance_of(ForestLiana::StatsController).to receive(:find_resource).and_return(Product)
173
+
174
+ post '/forest/stats', params: JSON.dump(params), headers: no_admin_headers
106
175
  expect(response.status).to eq(403)
107
176
  end
108
-
109
- it 'should respond 422 with unprocessable query' do
110
- allow_any_instance_of(ForestLiana::QueryStatGetter).to receive(:perform) { raise ForestLiana::Errors::LiveQueryError.new }
111
-
112
- post '/forest/stats', params: JSON.dump(params), headers: headers
113
- expect(response.status).to eq(422)
114
- end
115
177
  end
116
-
117
178
  end
@@ -0,0 +1,48 @@
1
+ module ForestLiana
2
+ module Ability
3
+ describe Ability do
4
+ let(:dummy_class) { Class.new { extend ForestLiana::Ability } }
5
+ let(:user) { { 'id' => '1', 'roleId' => '1' } }
6
+
7
+ before do
8
+ Island.create!(name: "L'île de la muerta")
9
+ end
10
+
11
+ describe 'forest authorize' do
12
+ it 'should call is_crud_authorized? when the action is in [browse read edit add delete export] list' do
13
+ allow_any_instance_of(ForestLiana::Ability::Permission).to receive(:is_crud_authorized?).and_return(true)
14
+ %w[browse read edit add delete export].each do |action|
15
+ expect(dummy_class.forest_authorize!(action, :user, Island.first)).to equal nil
16
+ end
17
+ end
18
+
19
+ it 'should call is_chart_authorized? when the action equal chart' do
20
+ allow_any_instance_of(ForestLiana::Ability::Permission).to receive(:is_chart_authorized?).and_return(true)
21
+ expect(dummy_class.forest_authorize!('chart', :user, Island.first, {parameters: []})).to equal nil
22
+ end
23
+
24
+ it 'should raise error 422 on a chart action when the argument parameter is nil' do
25
+ expect { dummy_class.forest_authorize!('chart', :user, Island.first) }.to raise_error(ForestLiana::Errors::HTTP422Error, "The argument parameters is missing")
26
+ end
27
+
28
+ it 'should call is_smart_action_authorized? when the action equal action' do
29
+ allow_any_instance_of(ForestLiana::Ability::Permission).to receive(:is_smart_action_authorized?).and_return(true)
30
+ expect(dummy_class.forest_authorize!('action', :user, Island.first, {parameters: [], endpoint: '...', http_method: 'POST'})).to equal true
31
+ end
32
+
33
+ it 'should raise error 422 on a chart smart-action when one or many arguments are missing' do
34
+ expect { dummy_class.forest_authorize!('action', :user, Island.first) }.to raise_error(ForestLiana::Errors::HTTP422Error, "You must implement the arguments : parameters, endpoint & http_method")
35
+ end
36
+
37
+ it 'should raise access denied when the action is unknown' do
38
+ expect { dummy_class.forest_authorize!('unknown', :user, Island.first) }.to raise_error(ForestLiana::Ability::Exceptions::AccessDenied, "You don't have permission to access this resource")
39
+ end
40
+
41
+ it 'should authorized user with correct permission_level to access charts' do
42
+ user['permission_level'] = 'admin'
43
+ expect(dummy_class.forest_authorize!('chart', user, Island.first, {parameters: []})).to equal nil
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,357 @@
1
+ module ForestLiana
2
+ module Ability
3
+ # include ForestLiana::Ability::Permission
4
+ describe Ability do
5
+ let(:user) { { 'id' => 1, 'roleId' => 1, 'rendering_id' => 1 } }
6
+ let(:action) {
7
+ {
8
+ 'triggerEnabled' => [],
9
+ 'triggerConditions' => [],
10
+ 'approvalRequired' => [],
11
+ 'approvalRequiredConditions' => [],
12
+ 'userApprovalEnabled' => [],
13
+ 'userApprovalConditions' => [],
14
+ 'selfApprovalEnabled' => []
15
+ }
16
+ }
17
+
18
+ let(:params) {
19
+ {
20
+ 'data' => {
21
+ 'attributes' => {
22
+ 'values': {},
23
+ 'ids': [
24
+ '1'
25
+ ],
26
+ 'collection_name': 'Island',
27
+ 'parent_collection_name': nil,
28
+ 'parent_collection_id': nil,
29
+ 'parent_association_name': nil,
30
+ 'all_records': false,
31
+ 'all_records_subset_query': {
32
+ 'fields[Island]': 'is,name',
33
+ 'fields[file_attachment]': 'name',
34
+ 'fields[file_blob]': 'id',
35
+ 'page[number]': 1,
36
+ 'page[size]': 15,
37
+ 'sort': '-id',
38
+ 'timezone': 'Europe/Paris'
39
+ },
40
+ 'all_records_ids_excluded': [],
41
+ 'smart_action_id': 'Island-my_action',
42
+ 'signed_approval_request': nil
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ before do
49
+ Island.create!(name: "foo")
50
+ end
51
+
52
+ describe 'can_execute with triggerEnabled' do
53
+ it 'should return true if triggerConditions is empty and user can trigger' do
54
+ parameters = ActionController::Parameters.new(params).permit!
55
+ action['triggerEnabled'] = [1]
56
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
57
+
58
+ expect(smart_action_checker.can_execute?).to equal true
59
+ end
60
+
61
+ it 'should return true if match triggerConditions and user can trigger' do
62
+ parameters = ActionController::Parameters.new(params).permit!
63
+ action['triggerEnabled'] = [1]
64
+ action['triggerConditions'] = [
65
+ { 'filter' =>
66
+ { 'aggregator' => 'and',
67
+ 'conditions' =>
68
+ [
69
+ {
70
+ 'field' => 'name',
71
+ 'value' => 'foo',
72
+ 'source' => 'data',
73
+ 'operator' => 'equal'
74
+ }
75
+ ]
76
+ },
77
+ 'roleId' => 1
78
+ }
79
+ ]
80
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
81
+
82
+ expect(smart_action_checker.can_execute?).to equal true
83
+ end
84
+
85
+ it 'should return true if match triggerConditions on allRecords and user can trigger' do
86
+ params['data']['attributes']['all_records'] = true
87
+ parameters = ActionController::Parameters.new(params).permit!
88
+ action['triggerEnabled'] = [1]
89
+ action['triggerConditions'] = [
90
+ { 'filter' =>
91
+ { 'aggregator' => 'and',
92
+ 'conditions' =>
93
+ [
94
+ {
95
+ 'field' => 'name',
96
+ 'value' => 'foo',
97
+ 'source' => 'data',
98
+ 'operator' => 'equal'
99
+ }
100
+ ]
101
+ },
102
+ 'roleId' => 1
103
+ }
104
+ ]
105
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
106
+
107
+ expect(smart_action_checker.can_execute?).to equal true
108
+ end
109
+
110
+ it 'should raise error when user can not trigger' do
111
+ parameters = ActionController::Parameters.new(params).permit!
112
+ action['triggerEnabled'] = [2]
113
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
114
+
115
+ expect{smart_action_checker.can_execute?}.to raise_error(ForestLiana::Ability::Exceptions::TriggerForbidden)
116
+ end
117
+
118
+ it 'should raise error when triggerConditions not match' do
119
+ parameters = ActionController::Parameters.new(params).permit!
120
+ action['triggerEnabled'] = [1]
121
+ action['triggerConditions'] = [
122
+ { 'filter' =>
123
+ { 'aggregator' => 'and',
124
+ 'conditions' =>
125
+ [
126
+ {
127
+ 'field' => 'name',
128
+ 'value' => 'fake island',
129
+ 'source' => 'data',
130
+ 'operator' => 'equal'
131
+ }
132
+ ]
133
+ },
134
+ 'roleId' => 1
135
+ }
136
+ ]
137
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
138
+
139
+ expect{smart_action_checker.can_execute?}.to raise_error ForestLiana::Ability::Exceptions::TriggerForbidden
140
+ end
141
+
142
+ it 'should raise error when conditions is on an unknown field' do
143
+ parameters = ActionController::Parameters.new(params).permit!
144
+ action['triggerEnabled'] = [1]
145
+ action['triggerConditions'] = [
146
+ { 'filter' =>
147
+ { 'aggregator' => 'and',
148
+ 'conditions' =>
149
+ [
150
+ {
151
+ 'field' => 'unknown-field',
152
+ 'value' => 'fake island',
153
+ 'source' => 'data',
154
+ 'operator' => 'equal'
155
+ }
156
+ ]
157
+ },
158
+ 'roleId' => 1
159
+ }
160
+ ]
161
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
162
+
163
+ expect{smart_action_checker.can_execute?}.to raise_error ForestLiana::Ability::Exceptions::ActionConditionError
164
+ end
165
+ end
166
+
167
+ describe 'can_execute with approvalRequired' do
168
+ it 'should raise RequireApproval error if approvalRequiredConditions is empty' do
169
+ parameters = ActionController::Parameters.new(params).permit!
170
+ action['approvalRequired'] = [1]
171
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
172
+
173
+ expect{smart_action_checker.can_execute?}.to raise_error ForestLiana::Ability::Exceptions::RequireApproval
174
+ end
175
+
176
+ it 'should raise RequireApproval error if match approvalRequiredConditions' do
177
+ parameters = ActionController::Parameters.new(params).permit!
178
+ action['approvalRequired'] = [1]
179
+ action['approvalRequiredConditions'] = [
180
+ { 'filter' =>
181
+ { 'aggregator' => 'and',
182
+ 'conditions' =>
183
+ [
184
+ {
185
+ 'field' => 'name',
186
+ 'value' => 'foo',
187
+ 'source' => 'data',
188
+ 'operator' => 'equal'
189
+ }
190
+ ]
191
+ },
192
+ 'roleId' => 1
193
+ }
194
+ ]
195
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
196
+
197
+ expect{smart_action_checker.can_execute?}.to raise_error ForestLiana::Ability::Exceptions::RequireApproval
198
+ end
199
+
200
+ it 'should raise error when user can not trigger' do
201
+ parameters = ActionController::Parameters.new(params).permit!
202
+ action['approvalRequired'] = [2]
203
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
204
+
205
+ expect{smart_action_checker.can_execute?}.to raise_error(ForestLiana::Ability::Exceptions::TriggerForbidden)
206
+ end
207
+
208
+ it 'should raise error when triggerConditions not match' do
209
+ parameters = ActionController::Parameters.new(params).permit!
210
+ action['approvalRequired'] = [1]
211
+ action['approvalRequiredConditions'] = [
212
+ { 'filter' =>
213
+ { 'aggregator' => 'and',
214
+ 'conditions' =>
215
+ [
216
+ {
217
+ 'field' => 'name',
218
+ 'value' => 'fake island',
219
+ 'source' => 'data',
220
+ 'operator' => 'equal'
221
+ }
222
+ ]
223
+ },
224
+ 'roleId' => 1
225
+ }
226
+ ]
227
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
228
+
229
+ expect{smart_action_checker.can_execute?}.to raise_error ForestLiana::Ability::Exceptions::TriggerForbidden
230
+ end
231
+ end
232
+
233
+ describe 'can_execute with userApproval' do
234
+ before do
235
+ params['data']['attributes']['requester_id'] = 2
236
+ request = params
237
+ params['data']['attributes']['signed_approval_request'] = JWT::encode(request, ForestLiana.env_secret)
238
+ action['userApprovalEnabled'] = [1]
239
+ end
240
+
241
+ it 'should return true if userApprovalConditions is empty and user has userApprovalEnabled permission' do
242
+ parameters = ActionController::Parameters.new(params).permit!
243
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
244
+
245
+ expect(smart_action_checker.can_execute?).to equal true
246
+ end
247
+
248
+ it 'should return true when record match userApprovalConditions and requester_id different of current user id' do
249
+ action['userApprovalConditions'] = [
250
+ { 'filter' =>
251
+ { 'aggregator' => 'and',
252
+ 'conditions' =>
253
+ [
254
+ {
255
+ 'field' => 'name',
256
+ 'value' => 'foo',
257
+ 'source' => 'data',
258
+ 'operator' => 'equal'
259
+ }
260
+ ]
261
+ },
262
+ 'roleId' => 1
263
+ }
264
+ ]
265
+ parameters = ActionController::Parameters.new(params).permit!
266
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
267
+
268
+ expect(smart_action_checker.can_execute?).to equal true
269
+ end
270
+
271
+ it 'should return true when record match userApprovalConditions and user can self approve' do
272
+ action['userApprovalConditions'] = [
273
+ { 'filter' =>
274
+ { 'aggregator' => 'and',
275
+ 'conditions' =>
276
+ [
277
+ {
278
+ 'field' => 'name',
279
+ 'value' => 'foo',
280
+ 'source' => 'data',
281
+ 'operator' => 'equal'
282
+ }
283
+ ]
284
+ },
285
+ 'roleId' => 1
286
+ }
287
+ ]
288
+ action['selfApprovalEnabled'] = [1]
289
+ params['data']['attributes']['requester_id'] = 2
290
+ request = params
291
+ params['data']['attributes']['signed_approval_request'] = JWT::encode(request, ForestLiana.env_secret)
292
+ parameters = ActionController::Parameters.new(params).permit!
293
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
294
+
295
+ expect(smart_action_checker.can_execute?).to equal true
296
+ end
297
+
298
+ it 'should raise error when user has userApprovalEnabled permission' do
299
+ parameters = ActionController::Parameters.new(params).permit!
300
+ action['userApprovalEnabled'] = [2]
301
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
302
+
303
+ expect{smart_action_checker.can_execute?}.to raise_error(ForestLiana::Ability::Exceptions::TriggerForbidden)
304
+ end
305
+
306
+ it 'should raise error when triggerConditions not match' do
307
+ parameters = ActionController::Parameters.new(params).permit!
308
+ action['userApprovalConditions'] = [
309
+ { 'filter' =>
310
+ { 'aggregator' => 'and',
311
+ 'conditions' =>
312
+ [
313
+ {
314
+ 'field' => 'name',
315
+ 'value' => 'fake island',
316
+ 'source' => 'data',
317
+ 'operator' => 'equal'
318
+ }
319
+ ]
320
+ },
321
+ 'roleId' => 1
322
+ }
323
+ ]
324
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
325
+
326
+ expect{smart_action_checker.can_execute?}.to raise_error(ForestLiana::Ability::Exceptions::TriggerForbidden)
327
+ end
328
+
329
+ it 'should raise error when requester_id equal to current user id without selfApprove permission' do
330
+ action['userApprovalConditions'] = [
331
+ { 'filter' =>
332
+ { 'aggregator' => 'and',
333
+ 'conditions' =>
334
+ [
335
+ {
336
+ 'field' => 'name',
337
+ 'value' => 'foo',
338
+ 'source' => 'data',
339
+ 'operator' => 'equal'
340
+ }
341
+ ]
342
+ },
343
+ 'roleId' => 1
344
+ }
345
+ ]
346
+ params['data']['attributes']['requester_id'] = 1
347
+ request = params
348
+ params['data']['attributes']['signed_approval_request'] = JWT::encode(request, ForestLiana.env_secret)
349
+ parameters = ActionController::Parameters.new(params).permit!
350
+ smart_action_checker = ForestLiana::Ability::Permission::SmartActionChecker.new(parameters, Island, action, user)
351
+
352
+ expect{smart_action_checker.can_execute?}.to raise_error(ForestLiana::Ability::Exceptions::TriggerForbidden)
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end