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.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +5 -3
- data/app/controllers/forest_liana/application_controller.rb +15 -0
- data/app/controllers/forest_liana/resources_controller.rb +31 -57
- data/app/controllers/forest_liana/smart_actions_controller.rb +44 -58
- data/app/controllers/forest_liana/stats_controller.rb +14 -58
- data/app/services/forest_liana/ability/exceptions/access_denied.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/action_condition_error.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/require_approval.rb +18 -0
- data/app/services/forest_liana/ability/exceptions/trigger_forbidden.rb +16 -0
- data/app/services/forest_liana/ability/fetch.rb +23 -0
- data/app/services/forest_liana/ability/permission/request_permission.rb +19 -0
- data/app/services/forest_liana/ability/permission/smart_action_checker.rb +71 -0
- data/app/services/forest_liana/ability/permission.rb +148 -0
- data/app/services/forest_liana/ability.rb +24 -0
- data/app/services/forest_liana/filters_parser.rb +7 -7
- data/app/services/forest_liana/leaderboard_stat_getter.rb +7 -7
- data/app/services/forest_liana/line_stat_getter.rb +8 -8
- data/app/services/forest_liana/pie_stat_getter.rb +17 -17
- data/app/services/forest_liana/stat_getter.rb +1 -2
- data/app/services/forest_liana/value_stat_getter.rb +7 -7
- data/lib/forest_liana/bootstrapper.rb +1 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/lib/forest_liana/collections/island.rb +1 -1
- data/spec/requests/actions_controller_spec.rb +3 -4
- data/spec/requests/count_spec.rb +5 -9
- data/spec/requests/resources_spec.rb +55 -11
- data/spec/requests/stats_spec.rb +103 -42
- data/spec/services/forest_liana/ability/ability_spec.rb +48 -0
- data/spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb +357 -0
- data/spec/services/forest_liana/ability/permission_spec.rb +332 -0
- data/spec/services/forest_liana/filters_parser_spec.rb +0 -12
- data/spec/services/forest_liana/line_stat_getter_spec.rb +9 -9
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +7 -7
- data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
- data/spec/spec_helper.rb +1 -0
- metadata +33 -17
- data/app/services/forest_liana/permissions_checker.rb +0 -223
- data/app/services/forest_liana/permissions_formatter.rb +0 -52
- data/app/services/forest_liana/permissions_getter.rb +0 -59
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +0 -713
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +0 -845
- data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +0 -175
- data/spec/services/forest_liana/permissions_formatter_spec.rb +0 -222
- data/spec/services/forest_liana/permissions_getter_spec.rb +0 -83
data/spec/requests/stats_spec.rb
CHANGED
@@ -4,12 +4,12 @@ require 'json'
|
|
4
4
|
describe "Stats", type: :request do
|
5
5
|
|
6
6
|
token = JWT.encode({
|
7
|
-
id:
|
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:
|
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: '
|
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
|
-
|
35
|
-
|
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
|
-
|
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: '
|
52
|
-
|
70
|
+
params = { type: 'Value', collection: 'Owner', aggregator: 'Count', sourceCollectionName: 'Owner', aggregateFieldName: nil, filter: nil}
|
53
71
|
it 'should respond 200' do
|
54
|
-
|
55
|
-
|
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
|
65
|
-
|
66
|
-
|
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
|
70
|
-
|
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
|
-
|
73
|
-
|
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
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
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
|