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
@@ -0,0 +1,332 @@
|
|
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, 'rendering_id' => '1' } }
|
6
|
+
let(:permission) {
|
7
|
+
{
|
8
|
+
'Island' => {
|
9
|
+
'browse' => [1],
|
10
|
+
'read' => [1],
|
11
|
+
'edit' => [1],
|
12
|
+
'add' => [1],
|
13
|
+
'delete' => [1],
|
14
|
+
'export' => [1],
|
15
|
+
:actions => {
|
16
|
+
'my_action' => {
|
17
|
+
'triggerEnabled' => [1],
|
18
|
+
'triggerConditions' => [],
|
19
|
+
'approvalRequired' => [],
|
20
|
+
'approvalRequiredConditions' => [
|
21
|
+
{ 'filter' =>
|
22
|
+
{ 'aggregator' => 'and',
|
23
|
+
'conditions' =>
|
24
|
+
[
|
25
|
+
{ 'field' => 'price',
|
26
|
+
'value' => '1',
|
27
|
+
'source' => 'data',
|
28
|
+
'operator' => 'greater_than' }
|
29
|
+
]
|
30
|
+
},
|
31
|
+
'roleId' => 10
|
32
|
+
}
|
33
|
+
],
|
34
|
+
'userApprovalEnabled' => [1],
|
35
|
+
'userApprovalConditions' =>
|
36
|
+
[
|
37
|
+
{ 'filter' =>
|
38
|
+
{ 'aggregator' => 'and',
|
39
|
+
'conditions' =>
|
40
|
+
[
|
41
|
+
{ 'field' => 'price',
|
42
|
+
'value' => '1',
|
43
|
+
'source' => 'data',
|
44
|
+
'operator' => 'greater_than'
|
45
|
+
}
|
46
|
+
]
|
47
|
+
},
|
48
|
+
'roleId' => 11 }
|
49
|
+
],
|
50
|
+
'selfApprovalEnabled' => [1]
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
before do
|
58
|
+
Rails.cache.clear
|
59
|
+
Rails.cache.write('forest.users', {'1' => user})
|
60
|
+
Rails.cache.write('forest.has_permission', true)
|
61
|
+
Rails.cache.write('forest.collections',permission)
|
62
|
+
Rails.cache.write('forest.stats', ['Leaderboard:b47e6fea7f7b9e2c7496d0c9399591f289552de6', 'Objective:fb40159a0cf0025de5fddf9a565e7ba2fef2c2b5', 'Value:b9a64a2ce88cb59ab5e2d5f5b25c6cfe35bf9350'])
|
63
|
+
Island.create!(name: "L'île de la muerta")
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'is_crud_authorized' do
|
67
|
+
it 'should return true when has_permission is false' do
|
68
|
+
Rails.cache.clear
|
69
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
70
|
+
.to receive(:get_permissions)
|
71
|
+
.and_return(true)
|
72
|
+
|
73
|
+
expect(dummy_class.is_crud_authorized?('browse', user, Island.first)).to equal true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return true when the action is in [browse read edit add delete export] list' do
|
77
|
+
%w[browse read edit add delete export].each do |action|
|
78
|
+
expect(dummy_class.is_crud_authorized?(action, user, Island)).to equal true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should throw an exception when the collection doesn\'t exist' do
|
83
|
+
expect {dummy_class.is_crud_authorized?('browse', user, String)}.to raise_error(ForestLiana::Errors::ExpectedError, 'The collection String doesn\'t exist')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should re-fetch the permission once when user permission is not allowed' do
|
87
|
+
Rails.cache.write(
|
88
|
+
'forest.collections',
|
89
|
+
{
|
90
|
+
'Island' => {
|
91
|
+
'browse' => [2],
|
92
|
+
'read' => [1],
|
93
|
+
'edit' => [1],
|
94
|
+
'add' => [1],
|
95
|
+
'delete' => [1],
|
96
|
+
'export' => [1],
|
97
|
+
'actions' =>
|
98
|
+
{
|
99
|
+
'Mark as Live' => { 'triggerEnabled' => [10, 8, 9],
|
100
|
+
'triggerConditions' => [],
|
101
|
+
'approvalRequired' => [10, 8],
|
102
|
+
'approvalRequiredConditions' =>
|
103
|
+
[
|
104
|
+
{ 'filter' =>
|
105
|
+
{ 'aggregator' => 'and',
|
106
|
+
'conditions' =>
|
107
|
+
[
|
108
|
+
{ 'field' => 'price',
|
109
|
+
'value' => 1,
|
110
|
+
'source' => 'data',
|
111
|
+
'operator' => 'greater_than'
|
112
|
+
}
|
113
|
+
]
|
114
|
+
},
|
115
|
+
'roleId' => 10
|
116
|
+
}
|
117
|
+
],
|
118
|
+
'userApprovalEnabled' => [10, 8, 11],
|
119
|
+
'userApprovalConditions' =>
|
120
|
+
[
|
121
|
+
{ 'filter' =>
|
122
|
+
{ 'aggregator' => 'and',
|
123
|
+
'conditions' =>
|
124
|
+
[
|
125
|
+
{ 'field' => 'price',
|
126
|
+
'value' => 1,
|
127
|
+
'source' => 'data',
|
128
|
+
'operator' => 'greater_than'
|
129
|
+
}
|
130
|
+
]
|
131
|
+
},
|
132
|
+
'roleId' => 11 }
|
133
|
+
],
|
134
|
+
'selfApprovalEnabled' => [8]
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
)
|
140
|
+
|
141
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
142
|
+
.to receive(:get_permissions)
|
143
|
+
.and_return(
|
144
|
+
{
|
145
|
+
"collections" => {
|
146
|
+
"Island" => {
|
147
|
+
"collection" => {
|
148
|
+
"browseEnabled" => { "roles" => [1] },
|
149
|
+
"readEnabled" => { "roles" => [1] },
|
150
|
+
"editEnabled" => { "roles" => [1] },
|
151
|
+
"addEnabled" => { "roles" => [1] },
|
152
|
+
"deleteEnabled" => { "roles" => [1] },
|
153
|
+
"exportEnabled" => { "roles" => [1] }
|
154
|
+
},
|
155
|
+
"actions" => {
|
156
|
+
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
)
|
162
|
+
|
163
|
+
expect(dummy_class.is_crud_authorized?('browse', user, Island)).to equal true
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should return false when user permission is not allowed' do
|
167
|
+
Rails.cache.delete('forest.users')
|
168
|
+
|
169
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
170
|
+
.to receive(:get_permissions)
|
171
|
+
.with('/liana/v4/permissions/users')
|
172
|
+
.and_return(
|
173
|
+
[
|
174
|
+
{"id"=>1, "firstName"=>"John", "lastName"=>"Doe", "email"=>"jd@forestadmin.com", "tags"=>{}, "roleId"=>'2', "permissionLevel"=>"admin"}
|
175
|
+
]
|
176
|
+
)
|
177
|
+
|
178
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
179
|
+
.to receive(:get_permissions)
|
180
|
+
.with('/liana/v4/permissions/environment')
|
181
|
+
.and_return(
|
182
|
+
{
|
183
|
+
"collections" => {
|
184
|
+
"Island" => {
|
185
|
+
"collection" => {
|
186
|
+
"browseEnabled" => { "roles" => [1] },
|
187
|
+
"readEnabled" => { "roles" => [1] },
|
188
|
+
"editEnabled" => { "roles" => [1] },
|
189
|
+
"addEnabled" => { "roles" => [1] },
|
190
|
+
"deleteEnabled" => { "roles" => [1] },
|
191
|
+
"exportEnabled" => { "roles" => [1] }
|
192
|
+
},
|
193
|
+
"actions"=>
|
194
|
+
{
|
195
|
+
"Mark as Live"=>
|
196
|
+
{
|
197
|
+
"triggerEnabled" => {"roles"=>[1]},
|
198
|
+
"triggerConditions" => [],
|
199
|
+
"approvalRequired" => {"roles" => [1]},
|
200
|
+
"approvalRequiredConditions" => [],
|
201
|
+
"userApprovalEnabled" => {"roles" => [1]},
|
202
|
+
"userApprovalConditions" => [],
|
203
|
+
"selfApprovalEnabled" => {"roles" => [1]}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}
|
208
|
+
}
|
209
|
+
)
|
210
|
+
|
211
|
+
expect(dummy_class.is_crud_authorized?('browse', user, Island)).to be false
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'is_chart_authorized?' do
|
216
|
+
it 'should return true when sha1 of parameters exist in the list of sha1 of forest.stats cache' do
|
217
|
+
parameters = ActionController::Parameters.new(
|
218
|
+
type: 'Objective',
|
219
|
+
sourceCollectionName: 'Customer',
|
220
|
+
aggregateFieldName: 'id',
|
221
|
+
aggregator: 'Sum',
|
222
|
+
objective: 20,
|
223
|
+
filter: nil,
|
224
|
+
contextVariables: ActionController::Parameters.new,
|
225
|
+
timezone: 'Europe/Paris',
|
226
|
+
controller: 'forest_liana/stats',
|
227
|
+
action: 'get',
|
228
|
+
collection: 'Customer'
|
229
|
+
).permit!
|
230
|
+
|
231
|
+
expect(dummy_class.is_chart_authorized?(user, parameters)).to equal true
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should return false when sha1 of parameters doesn\'t exist in the list of sha1 of forest.stats cache' do
|
235
|
+
parameters = ActionController::Parameters.new(
|
236
|
+
type: 'Objective',
|
237
|
+
sourceCollectionName: 'Product',
|
238
|
+
aggregateFieldName: 'id',
|
239
|
+
aggregator: 'Sum',
|
240
|
+
objective: 20,
|
241
|
+
filter: nil,
|
242
|
+
contextVariables: ActionController::Parameters.new,
|
243
|
+
timezone: 'Europe/Berlin',
|
244
|
+
controller: 'forest_liana/stats',
|
245
|
+
action: 'get',
|
246
|
+
collection: 'Customer'
|
247
|
+
).permit!
|
248
|
+
|
249
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
250
|
+
.to receive(:get_permissions)
|
251
|
+
.and_return(
|
252
|
+
{
|
253
|
+
"stats" => [{
|
254
|
+
"type" => "Leaderboard",
|
255
|
+
"limit" => '1',
|
256
|
+
"aggregator" => "Count",
|
257
|
+
"labelFieldName" => "label",
|
258
|
+
"aggregateFieldName" => nil,
|
259
|
+
"relationshipFieldName" => "orders",
|
260
|
+
"sourceCollectionName" => "Product"
|
261
|
+
}, {
|
262
|
+
"type" => "Objective",
|
263
|
+
"filter" => nil,
|
264
|
+
"objective" => '20',
|
265
|
+
"aggregator" => "Sum",
|
266
|
+
"aggregateFieldName" => "id",
|
267
|
+
"sourceCollectionName" => "Customer"
|
268
|
+
}, {
|
269
|
+
"type" => "Value",
|
270
|
+
"filter" => {
|
271
|
+
"aggregator" => "and",
|
272
|
+
"conditions" => [{
|
273
|
+
"field" => "price",
|
274
|
+
"operator" => "greater_than",
|
275
|
+
"value" => "{{dropdown1.selectedValue}}"
|
276
|
+
}]
|
277
|
+
},
|
278
|
+
"aggregator" => "Count",
|
279
|
+
"aggregateFieldName" => nil,
|
280
|
+
"sourceCollectionName" => "Product"
|
281
|
+
}],
|
282
|
+
}
|
283
|
+
)
|
284
|
+
|
285
|
+
expect(dummy_class.is_chart_authorized?(user, parameters)).to equal false
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'is_smart_action_authorized?' do
|
290
|
+
let(:parameters) {
|
291
|
+
ActionController::Parameters.new(
|
292
|
+
{
|
293
|
+
"data": {
|
294
|
+
"attributes": {
|
295
|
+
"values": {},
|
296
|
+
"ids": [
|
297
|
+
"1"
|
298
|
+
],
|
299
|
+
"collection_name": "Island",
|
300
|
+
"parent_collection_name": nil,
|
301
|
+
"parent_collection_id": nil,
|
302
|
+
"parent_association_name": nil,
|
303
|
+
"all_records": false,
|
304
|
+
"all_records_subset_query": {
|
305
|
+
"fields[Island]": "id,name",
|
306
|
+
"fields[file_attachment]": "name",
|
307
|
+
"fields[file_blob]": "id",
|
308
|
+
"page[number]": 1,
|
309
|
+
"page[size]": 15,
|
310
|
+
"sort": "-id",
|
311
|
+
"timezone": "Europe/Paris"
|
312
|
+
},
|
313
|
+
"all_records_ids_excluded": ["3", "2"],
|
314
|
+
"smart_action_id": "my_action",
|
315
|
+
"signed_approval_request": nil
|
316
|
+
}
|
317
|
+
}
|
318
|
+
}
|
319
|
+
).permit!
|
320
|
+
}
|
321
|
+
|
322
|
+
it 'should return true' do
|
323
|
+
expect(dummy_class.is_smart_action_authorized?(user, Island, parameters, '/forest/actions/my_action', 'POST')).to equal true
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'should throw an exception when the collection doesn\'t exist' do
|
327
|
+
expect {dummy_class.is_smart_action_authorized?(user, String, parameters, '/forest/actions/my_action', 'POST')}.to raise_error(ForestLiana::Errors::ExpectedError, 'The collection String doesn\'t exist')
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
@@ -28,18 +28,6 @@ module ForestLiana
|
|
28
28
|
Island.destroy_all
|
29
29
|
}
|
30
30
|
|
31
|
-
describe 'initialization' do
|
32
|
-
context 'badly formated filters' do
|
33
|
-
let(:filter_parser) { described_class.new('{ toto: 1', resource, timezone) }
|
34
|
-
|
35
|
-
it {
|
36
|
-
expect {
|
37
|
-
described_class.new('{ toto: 1', resource, timezone)
|
38
|
-
}.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid filters JSON format')
|
39
|
-
}
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
31
|
describe 'apply_filters' do
|
44
32
|
let(:parsed_filters) { filter_parser.apply_filters }
|
45
33
|
|
@@ -7,7 +7,6 @@ module ForestLiana
|
|
7
7
|
before(:each) do
|
8
8
|
ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
|
9
9
|
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
|
10
|
-
Owner.delete_all
|
11
10
|
end
|
12
11
|
|
13
12
|
describe 'Check client_timezone function' do
|
@@ -15,7 +14,7 @@ module ForestLiana
|
|
15
14
|
it 'should return false' do
|
16
15
|
expect(LineStatGetter.new(Owner, {
|
17
16
|
timezone: "Europe/Paris",
|
18
|
-
|
17
|
+
aggregator: "Count",
|
19
18
|
}, user).client_timezone).to eq(false)
|
20
19
|
end
|
21
20
|
end
|
@@ -28,7 +27,7 @@ module ForestLiana
|
|
28
27
|
it 'should return the timezone' do
|
29
28
|
expect(LineStatGetter.new(Owner, {
|
30
29
|
timezone: "Europe/Paris",
|
31
|
-
|
30
|
+
aggregator: "Count",
|
32
31
|
}, user).client_timezone).to eq('Europe/Paris')
|
33
32
|
end
|
34
33
|
end
|
@@ -40,6 +39,7 @@ module ForestLiana
|
|
40
39
|
it 'should return consistent data based on monday as week_start ' do
|
41
40
|
# Week should start on monday
|
42
41
|
# 08-05-2021 was a Saturday
|
42
|
+
Owner.delete_all
|
43
43
|
Owner.create(name: 'Michel', hired_at: Date.parse('08-05-2021'));
|
44
44
|
Owner.create(name: 'Robert', hired_at: Date.parse('09-05-2021'));
|
45
45
|
Owner.create(name: 'José', hired_at: Date.parse('10-05-2021'));
|
@@ -47,9 +47,9 @@ module ForestLiana
|
|
47
47
|
|
48
48
|
stat = LineStatGetter.new(Owner, {
|
49
49
|
timezone: "Europe/Paris",
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
aggregator: "Count",
|
51
|
+
timeRange: "Week",
|
52
|
+
groupByFieldName: "hired_at",
|
53
53
|
}, user).perform
|
54
54
|
|
55
55
|
expect(stat.value.find { |item| item[:label] == "W18-2021" }[:values][:value]).to eq(2)
|
@@ -65,9 +65,9 @@ module ForestLiana
|
|
65
65
|
Owner.create(name: 'Shuri', hired_at: Date.parse('09-11-2022'));
|
66
66
|
stat = LineStatGetter.new(Owner, {
|
67
67
|
timezone: "Europe/Paris",
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
aggregator: "Count",
|
69
|
+
timeRange: "Day",
|
70
|
+
groupByFieldName: "hired_at",
|
71
71
|
}, user)
|
72
72
|
|
73
73
|
expect(stat.get_resource.where(name: "Shuri").to_sql.downcase.exclude? "order by").to be true
|
@@ -28,10 +28,10 @@ module ForestLiana
|
|
28
28
|
let(:params) {
|
29
29
|
{
|
30
30
|
type: 'Pie',
|
31
|
-
|
31
|
+
sourceCollectionName: collection,
|
32
32
|
timezone: 'Europe/Paris',
|
33
|
-
|
34
|
-
|
33
|
+
aggregator: 'Count',
|
34
|
+
groupByFieldName: groupByFieldName
|
35
35
|
}
|
36
36
|
}
|
37
37
|
|
@@ -41,7 +41,7 @@ module ForestLiana
|
|
41
41
|
let(:scopes) { { } }
|
42
42
|
|
43
43
|
describe 'with an aggregate on the name field' do
|
44
|
-
let(:
|
44
|
+
let(:groupByFieldName) { 'name' }
|
45
45
|
|
46
46
|
it 'should be as many categories as records count' do
|
47
47
|
subject.perform
|
@@ -60,7 +60,7 @@ module ForestLiana
|
|
60
60
|
end
|
61
61
|
|
62
62
|
describe 'with an aggregate on the age field' do
|
63
|
-
let(:
|
63
|
+
let(:groupByFieldName) { 'age' }
|
64
64
|
|
65
65
|
it 'should be as many categories as different ages among records' do
|
66
66
|
subject.perform
|
@@ -87,7 +87,7 @@ module ForestLiana
|
|
87
87
|
}
|
88
88
|
|
89
89
|
describe 'with an aggregate on the name field' do
|
90
|
-
let(:
|
90
|
+
let(:groupByFieldName) { 'name' }
|
91
91
|
|
92
92
|
it 'should be as many categories as records inside the scope' do
|
93
93
|
subject.perform
|
@@ -102,7 +102,7 @@ module ForestLiana
|
|
102
102
|
end
|
103
103
|
|
104
104
|
describe 'with an aggregate on the age field' do
|
105
|
-
let(:
|
105
|
+
let(:groupByFieldName) { 'age' }
|
106
106
|
|
107
107
|
it 'should be only one category' do
|
108
108
|
subject.perform
|
@@ -18,10 +18,10 @@ module ForestLiana
|
|
18
18
|
let(:params) {
|
19
19
|
{
|
20
20
|
type: "Value",
|
21
|
-
|
21
|
+
sourceCollectionName: sourceCollectionName,
|
22
22
|
timezone: "Europe/Paris",
|
23
|
-
|
24
|
-
|
23
|
+
aggregator: "Count",
|
24
|
+
filter: filter
|
25
25
|
}
|
26
26
|
}
|
27
27
|
|
@@ -32,8 +32,8 @@ module ForestLiana
|
|
32
32
|
|
33
33
|
describe 'with a simple filter matching no entries' do
|
34
34
|
let(:model) { User }
|
35
|
-
let(:
|
36
|
-
let(:
|
35
|
+
let(:sourceCollectionName) { 'users' }
|
36
|
+
let(:filter) { { field: 'name', operator: 'in', value: ['Merry', 'Pippin'] }.to_json }
|
37
37
|
|
38
38
|
it 'should have a countCurrent of 0' do
|
39
39
|
subject.perform
|
@@ -43,8 +43,8 @@ module ForestLiana
|
|
43
43
|
|
44
44
|
describe 'with a filter on a belongs_to string field' do
|
45
45
|
let(:model) { Tree }
|
46
|
-
let(:
|
47
|
-
let(:
|
46
|
+
let(:sourceCollectionName) { 'trees' }
|
47
|
+
let(:filter) { { field: 'owner:name', operator: 'equal', value: 'Aragorn' }.to_json }
|
48
48
|
|
49
49
|
it 'should have a countCurrent of 2' do
|
50
50
|
subject.perform
|
@@ -54,8 +54,8 @@ module ForestLiana
|
|
54
54
|
|
55
55
|
describe 'with a filter on a belongs_to enum field' do
|
56
56
|
let(:model) { Tree }
|
57
|
-
let(:
|
58
|
-
let(:
|
57
|
+
let(:sourceCollectionName) { 'trees' }
|
58
|
+
let(:filter) { { field: 'owner:title', operator: 'equal', value: 'villager' }.to_json }
|
59
59
|
|
60
60
|
it 'should have a countCurrent of 1' do
|
61
61
|
subject.perform
|
@@ -83,8 +83,8 @@ module ForestLiana
|
|
83
83
|
|
84
84
|
describe 'with a filter on a belongs_to enum field' do
|
85
85
|
let(:model) { User }
|
86
|
-
let(:
|
87
|
-
let(:
|
86
|
+
let(:sourceCollectionName) { 'users' }
|
87
|
+
let(:filter) { { field: 'title', operator: 'equal', value: 'villager' }.to_json }
|
88
88
|
|
89
89
|
it 'should have a countCurrent of 0' do
|
90
90
|
subject.perform
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'simplecov'
|
2
2
|
SimpleCov.start 'rails'
|
3
|
+
SimpleCov.add_filter ['app/services/forest_liana/ability/fetch.rb', 'lib/forest_liana/version.rb']
|
3
4
|
|
4
5
|
# This file was generated by the `rails generate rspec:install` command. Conventionally, all
|
5
6
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_liana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 8.0.0.beta.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Munda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -192,6 +192,20 @@ dependencies:
|
|
192
192
|
- - '='
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: 1.4.2
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: deepsort
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
195
209
|
description: Forest is a modern admin interface that works on all major web frameworks.
|
196
210
|
forest_liana is the gem that makes Forest admin work on any Rails application (Rails
|
197
211
|
>= 4.0).
|
@@ -244,6 +258,15 @@ files:
|
|
244
258
|
- app/serializers/forest_liana/stripe_invoice_serializer.rb
|
245
259
|
- app/serializers/forest_liana/stripe_payment_serializer.rb
|
246
260
|
- app/serializers/forest_liana/stripe_subscription_serializer.rb
|
261
|
+
- app/services/forest_liana/ability.rb
|
262
|
+
- app/services/forest_liana/ability/exceptions/access_denied.rb
|
263
|
+
- app/services/forest_liana/ability/exceptions/action_condition_error.rb
|
264
|
+
- app/services/forest_liana/ability/exceptions/require_approval.rb
|
265
|
+
- app/services/forest_liana/ability/exceptions/trigger_forbidden.rb
|
266
|
+
- app/services/forest_liana/ability/fetch.rb
|
267
|
+
- app/services/forest_liana/ability/permission.rb
|
268
|
+
- app/services/forest_liana/ability/permission/request_permission.rb
|
269
|
+
- app/services/forest_liana/ability/permission/smart_action_checker.rb
|
247
270
|
- app/services/forest_liana/apimap_sorter.rb
|
248
271
|
- app/services/forest_liana/authentication.rb
|
249
272
|
- app/services/forest_liana/authorization_getter.rb
|
@@ -270,9 +293,6 @@ files:
|
|
270
293
|
- app/services/forest_liana/oidc_configuration_retriever.rb
|
271
294
|
- app/services/forest_liana/oidc_dynamic_client_registrator.rb
|
272
295
|
- app/services/forest_liana/operator_date_interval_parser.rb
|
273
|
-
- app/services/forest_liana/permissions_checker.rb
|
274
|
-
- app/services/forest_liana/permissions_formatter.rb
|
275
|
-
- app/services/forest_liana/permissions_getter.rb
|
276
296
|
- app/services/forest_liana/pie_stat_getter.rb
|
277
297
|
- app/services/forest_liana/query_stat_getter.rb
|
278
298
|
- app/services/forest_liana/resource_creator.rb
|
@@ -401,16 +421,14 @@ files:
|
|
401
421
|
- spec/requests/stats_spec.rb
|
402
422
|
- spec/requests/test.ru
|
403
423
|
- spec/routing/routes_spec.rb
|
424
|
+
- spec/services/forest_liana/ability/ability_spec.rb
|
425
|
+
- spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb
|
426
|
+
- spec/services/forest_liana/ability/permission_spec.rb
|
404
427
|
- spec/services/forest_liana/apimap_sorter_spec.rb
|
405
428
|
- spec/services/forest_liana/filters_parser_spec.rb
|
406
429
|
- spec/services/forest_liana/has_many_getter_spec.rb
|
407
430
|
- spec/services/forest_liana/ip_whitelist_checker_spec.rb
|
408
431
|
- spec/services/forest_liana/line_stat_getter_spec.rb
|
409
|
-
- spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
|
410
|
-
- spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
|
411
|
-
- spec/services/forest_liana/permissions_checker_live_queries_spec.rb
|
412
|
-
- spec/services/forest_liana/permissions_formatter_spec.rb
|
413
|
-
- spec/services/forest_liana/permissions_getter_spec.rb
|
414
432
|
- spec/services/forest_liana/pie_stat_getter_spec.rb
|
415
433
|
- spec/services/forest_liana/resource_updater_spec.rb
|
416
434
|
- spec/services/forest_liana/resources_getter_spec.rb
|
@@ -521,9 +539,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
521
539
|
version: '0'
|
522
540
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
523
541
|
requirements:
|
524
|
-
- - "
|
542
|
+
- - ">"
|
525
543
|
- !ruby/object:Gem::Version
|
526
|
-
version:
|
544
|
+
version: 1.3.1
|
527
545
|
requirements: []
|
528
546
|
rubygems_version: 3.3.5
|
529
547
|
signing_key:
|
@@ -699,16 +717,14 @@ test_files:
|
|
699
717
|
- spec/requests/stats_spec.rb
|
700
718
|
- spec/requests/test.ru
|
701
719
|
- spec/routing/routes_spec.rb
|
720
|
+
- spec/services/forest_liana/ability/ability_spec.rb
|
721
|
+
- spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb
|
722
|
+
- spec/services/forest_liana/ability/permission_spec.rb
|
702
723
|
- spec/services/forest_liana/apimap_sorter_spec.rb
|
703
724
|
- spec/services/forest_liana/filters_parser_spec.rb
|
704
725
|
- spec/services/forest_liana/has_many_getter_spec.rb
|
705
726
|
- spec/services/forest_liana/ip_whitelist_checker_spec.rb
|
706
727
|
- spec/services/forest_liana/line_stat_getter_spec.rb
|
707
|
-
- spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
|
708
|
-
- spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
|
709
|
-
- spec/services/forest_liana/permissions_checker_live_queries_spec.rb
|
710
|
-
- spec/services/forest_liana/permissions_formatter_spec.rb
|
711
|
-
- spec/services/forest_liana/permissions_getter_spec.rb
|
712
728
|
- spec/services/forest_liana/pie_stat_getter_spec.rb
|
713
729
|
- spec/services/forest_liana/resource_updater_spec.rb
|
714
730
|
- spec/services/forest_liana/resources_getter_spec.rb
|