forest_liana 7.8.0 → 8.0.0.beta.2
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.
- 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
|