forest_liana 6.0.5 → 6.2.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.
@@ -109,7 +109,7 @@ module ForestLiana
109
109
 
110
110
  describe 'handling cache' do
111
111
  let(:collection_name) { 'all_rights_collection' }
112
- let(:fake_ressource) { nil }
112
+ let(:fake_ressource) { collection_name }
113
113
  let(:default_rendering_id) { 1 }
114
114
 
115
115
  context 'when calling twice the same permissions' do
@@ -191,7 +191,7 @@ module ForestLiana
191
191
 
192
192
 
193
193
  context 'scopes cache' do
194
- let(:fake_ressource) { nil }
194
+ let(:fake_ressource) { collection_name }
195
195
  let(:rendering_id) { 1 }
196
196
  let(:collection_name) { 'custom' }
197
197
  let(:scope_permissions) { { rendering_id => { 'custom' => nil } } }
@@ -349,7 +349,7 @@ module ForestLiana
349
349
  describe '#is_authorized?' do
350
350
  # Resource is only used to retrieve the collection name as it's stubbed it does not
351
351
  # need to be defined
352
- let(:fake_ressource) { nil }
352
+ let(:fake_ressource) { collection_name }
353
353
  let(:default_rendering_id) { nil }
354
354
  let(:api_permissions) { default_api_permissions }
355
355
  let(:collection_name) { 'all_rights_collection' }
@@ -132,7 +132,7 @@ module ForestLiana
132
132
 
133
133
  describe 'handling cache' do
134
134
  let(:collection_name) { 'all_rights_collection_boolean' }
135
- let(:fake_ressource) { nil }
135
+ let(:fake_ressource) { collection_name }
136
136
  let(:default_rendering_id) { 1 }
137
137
 
138
138
  context 'collections cache' do
@@ -396,7 +396,7 @@ module ForestLiana
396
396
  describe '#is_authorized?' do
397
397
  # Resource is only used to retrieve the collection name as it's stub it does not
398
398
  # need to be defined
399
- let(:fake_ressource) { nil }
399
+ let(:fake_ressource) { collection_name }
400
400
  let(:default_rendering_id) { nil }
401
401
  let(:api_permissions) { default_api_permissions }
402
402
 
@@ -0,0 +1,131 @@
1
+ module ForestLiana
2
+ describe PermissionsChecker do
3
+ before(:each) do
4
+ described_class.empty_cache
5
+ end
6
+
7
+ let(:user_id) { 1 }
8
+ let(:schema) {
9
+ [
10
+ ForestLiana::Model::Collection.new({
11
+ name: 'all_rights_collection_boolean',
12
+ fields: [],
13
+ actions: [
14
+ ForestLiana::Model::Action.new({
15
+ name: 'Test',
16
+ endpoint: 'forest/actions/Test',
17
+ http_method: 'POST'
18
+ })
19
+ ]
20
+ })
21
+ ]
22
+ }
23
+ let(:scope_permissions) { nil }
24
+ let(:default_api_permissions) {
25
+ {
26
+ "data" => {
27
+ 'collections' => {
28
+ "all_rights_collection_boolean" => {
29
+ "collection" => {
30
+ "browseEnabled" => true,
31
+ "readEnabled" => true,
32
+ "editEnabled" => true,
33
+ "addEnabled" => true,
34
+ "deleteEnabled" => true,
35
+ "exportEnabled" => true
36
+ },
37
+ "actions" => {
38
+ "Test" => {
39
+ "triggerEnabled" => true
40
+ },
41
+ }
42
+ },
43
+ },
44
+ 'renderings' => scope_permissions
45
+ },
46
+ "meta" => {
47
+ "rolesACLActivated" => true
48
+ },
49
+ "stats" => {
50
+ "queries" => [
51
+ 'SELECT COUNT(*) AS value FROM products;',
52
+ 'SELECT COUNT(*) AS value FROM sometings;'
53
+ ],
54
+ "values" => [
55
+ {
56
+ "type" => "Value",
57
+ "collection" => "Product",
58
+ "aggregate" => "Count"
59
+ }
60
+ ],
61
+ },
62
+ }
63
+ }
64
+ let(:default_rendering_id) { 1 }
65
+
66
+ before do
67
+ allow(ForestLiana).to receive(:apimap).and_return(schema)
68
+ end
69
+
70
+ describe '#is_authorized?' do
71
+ # Resource is only used to retrieve the collection name as it's stub it does not
72
+ # need to be defined
73
+ let(:fake_ressource) { nil }
74
+ let(:default_rendering_id) { nil }
75
+ let(:api_permissions) { default_api_permissions }
76
+
77
+ before do
78
+ allow(ForestLiana::PermissionsGetter).to receive(:get_permissions_for_rendering).and_return(api_permissions)
79
+ end
80
+
81
+ context 'when permissions liveQueries' do
82
+ context 'contains the query' do
83
+ request_info = {
84
+ "type" => "Value",
85
+ "collection" => "Product",
86
+ "aggregate" => "Count"
87
+ };
88
+ subject { described_class.new(fake_ressource, 'liveQueries', default_rendering_id, user_id: user_id, query_request_info: 'SELECT COUNT(*) AS value FROM sometings;') }
89
+
90
+ it 'should be authorized' do
91
+ expect(subject.is_authorized?).to be true
92
+ end
93
+ end
94
+
95
+ context 'does not contains the query' do
96
+ subject { described_class.new(fake_ressource, 'liveQueries', default_rendering_id, user_id: user_id, query_request_info: 'SELECT * FROM products WHERE category = Gifts OR 1=1-- AND released = 1') }
97
+ it 'should NOT be authorized' do
98
+ expect(subject.is_authorized?).to be false
99
+ end
100
+ end
101
+ end
102
+
103
+ context 'when permissions statWithParameters' do
104
+ context 'contains the stat with the same parameters' do
105
+ request_info = {
106
+ "type" => "Value",
107
+ "collection" => "Product",
108
+ "aggregate" => "Count"
109
+ };
110
+ subject { described_class.new(fake_ressource, 'statWithParameters', default_rendering_id, user_id: user_id, query_request_info: request_info) }
111
+
112
+ it 'should be authorized' do
113
+ expect(subject.is_authorized?).to be true
114
+ end
115
+ end
116
+
117
+ context 'does not contains the stat with the same parameters' do
118
+ other_request_info = {
119
+ "type" => "Leaderboard",
120
+ "collection" => "Product",
121
+ "aggregate" => "Sum"
122
+ };
123
+ subject { described_class.new(fake_ressource, 'statWithParameters', default_rendering_id, user_id: user_id, query_request_info: other_request_info) }
124
+ it 'should NOT be authorized' do
125
+ expect(subject.is_authorized?).to be false
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,359 @@
1
+ module ForestLiana
2
+ describe ResourcesGetter do
3
+ let(:resource) { User }
4
+ let(:pageSize) { 10 }
5
+ let(:pageNumber) { 1 }
6
+ let(:sort) { 'id' }
7
+ let(:fields) { }
8
+ let(:filters) { }
9
+
10
+ let(:getter) { described_class.new(resource, {
11
+ page: { size: pageSize, number: pageNumber },
12
+ sort: sort,
13
+ fields: fields,
14
+ filters: filters,
15
+ })}
16
+
17
+ before(:each) do
18
+ users = ['Michel', 'Robert', 'Vince', 'Sandro', 'Olesya', 'Romain', 'Valentin', 'Jason', 'Arnaud', 'Jeff', 'Steve', 'Marc', 'Xavier', 'Paul', 'Mickael', 'Mike', 'Maxime', 'Gertrude', 'Monique', 'Mia', 'Rachid', 'Edouard', 'Sacha', 'Caro', 'Amand', 'Nathan', 'Noémie', 'Robin', 'Gaelle', 'Isabelle']
19
+ .map { |name| User.create(name: name) }
20
+
21
+ islands = [
22
+ { :name => 'Skull', :updated_at => Time.now - 1.years },
23
+ { :name => 'Muerta', :updated_at => Time.now - 5.years },
24
+ { :name => 'Treasure', :updated_at => Time.now },
25
+ { :name => 'Birds', :updated_at => Time.now - 7.years },
26
+ { :name => 'Lille', :updated_at => Time.now - 1.years }
27
+ ].map { |island| Island.create(name: island[:name], updated_at: island[:updated_at]) }
28
+
29
+ trees = [
30
+ { :name => 'Lemon Tree', :created_at => Time.now - 7.years, :island => islands[0], :owner => users[0], :cutter => users[0] },
31
+ { :name => 'Ginger Tree', :created_at => Time.now - 7.years, :island => islands[0], :owner => users[1], :cutter => users[0] },
32
+ { :name => 'Apple Tree', :created_at => Time.now - 5.years, :island => islands[1], :owner => users[2], :cutter => users[0] },
33
+ { :name => 'Pear Tree', :created_at => Time.now + 4.hours, :island => islands[3], :owner => users[3], :cutter => users[1] },
34
+ { :name => 'Choco Tree', :created_at => Time.now, :island => islands[3], :owner => users[4], :cutter => users[1] }
35
+ ].map { |tree| Tree.create(name: tree[:name], created_at: tree[:created_at], island: tree[:island], owner: tree[:owner], cutter: tree[:cutter]) }
36
+
37
+ locations = [
38
+ { :coordinates => '12345', :island => islands[0] },
39
+ { :coordinates => '54321', :island => islands[1] },
40
+ { :coordinates => '43215', :island => islands[2] },
41
+ { :coordinates => '21543', :island => islands[3] },
42
+ { :coordinates => '32154', :island => islands[4] }
43
+ ].map { |location| Location.create(coordinates: location[:coordinates], island: location[:island]) }
44
+
45
+ reference = Reference.create()
46
+ end
47
+
48
+ after(:each) do
49
+ User.destroy_all
50
+ Island.destroy_all
51
+ Location.destroy_all
52
+ Tree.destroy_all
53
+ end
54
+
55
+ describe 'when there are more records than the page size' do
56
+ describe 'when asking for the 1st page and 15 records' do
57
+ let(:pageSize) { 15 }
58
+ let(:sort) { '-id' }
59
+
60
+ it 'should get only the expected records' do
61
+ getter.perform
62
+ records = getter.records
63
+ count = getter.count
64
+
65
+ expect(records.count).to eq 15
66
+ expect(count).to eq 30
67
+ expect(records.first.id).to eq 30
68
+ expect(records.last.id).to eq 16
69
+ end
70
+ end
71
+
72
+ describe 'when asking for the 2nd page and 10 records' do
73
+ let(:pageNumber) { 2 }
74
+ let(:sort) { '-id' }
75
+
76
+ it 'should get only the expected records' do
77
+ getter.perform
78
+ records = getter.records
79
+ count = getter.count
80
+
81
+ expect(records.count).to eq 10
82
+ expect(count).to eq 30
83
+ expect(records.first.id).to eq 20
84
+ expect(records.last.id).to eq 11
85
+ end
86
+ end
87
+ end
88
+
89
+ describe 'when on a model having a reserved SQL word as name' do
90
+ let(:resource) { Reference }
91
+
92
+ it 'should get the ressource properly' do
93
+ getter.perform
94
+ records = getter.records
95
+ count = getter.count
96
+
97
+ expect(records.count).to eq 1
98
+ expect(count).to eq 1
99
+ expect(records.first.id).to eq 1
100
+ end
101
+ end
102
+
103
+ describe 'when sorting by a specific field' do
104
+ let(:pageSize) { 5 }
105
+ let(:sort) { '-name' }
106
+
107
+ it 'should get only the expected records' do
108
+ getter.perform
109
+ records = getter.records
110
+ count = getter.count
111
+
112
+ expect(records.count).to eq 5
113
+ expect(count).to eq 30
114
+ expect(records.map(&:name)).to eq ['Xavier', 'Vince', 'Valentin', 'Steve', 'Sandro']
115
+ end
116
+ end
117
+
118
+ describe 'when sorting by a belongs_to association' do
119
+ let(:resource) { Tree }
120
+ let(:sort) { 'owner.name' }
121
+
122
+ it 'should get only the expected records' do
123
+ getter.perform
124
+ records = getter.records
125
+ count = getter.count
126
+
127
+ expect(records.count).to eq 5
128
+ expect(count).to eq 5
129
+ expect(records.map(&:id)).to eq [1, 5, 2, 4, 3]
130
+ end
131
+ end
132
+
133
+ describe 'when sorting by a has_one association' do
134
+ let(:resource) { Island }
135
+ let(:sort) { 'location.coordinates' }
136
+ let(:pageSize) { 5 }
137
+
138
+ it 'should get only the expected records' do
139
+ getter.perform
140
+ records = getter.records
141
+ count = getter.count
142
+
143
+ expect(records.count).to eq 5
144
+ expect(count).to eq 5
145
+ expect(records.map(&:id)).to eq [1, 4, 5, 3, 2]
146
+ end
147
+ end
148
+
149
+ describe 'when filtering on an ambiguous field' do
150
+ let(:resource) { Tree }
151
+ let(:pageSize) { 5 }
152
+ let(:fields) { { 'Tree' => 'id' } }
153
+ let(:filters) { {
154
+ aggregator: 'and',
155
+ conditions: [{
156
+ field: 'created_at',
157
+ operator: 'after',
158
+ value: "#{Time.now - 6.year}",
159
+ }, {
160
+ field: 'cutter:name',
161
+ operator: 'equal',
162
+ value: 'Michel'
163
+ }]
164
+ }.to_json }
165
+
166
+ it 'should get only the expected records' do
167
+ getter.perform
168
+ records = getter.records
169
+ count = getter.count
170
+
171
+ expect(records.count).to eq 1
172
+ expect(count).to eq 1
173
+ expect(records.first.id).to eq 3
174
+ expect(records.first.name).to eq 'Apple Tree'
175
+ expect(records.first.cutter.name).to eq 'Michel'
176
+ end
177
+ end
178
+
179
+ describe 'when filtering on before x hours ago' do
180
+ let(:resource) { Tree }
181
+ let(:fields) { { 'Tree' => 'id' } }
182
+ let(:filters) { {
183
+ field: 'created_at',
184
+ operator: 'before_x_hours_ago',
185
+ value: 3
186
+ }.to_json }
187
+
188
+ it 'should filter as expected' do
189
+ getter.perform
190
+ records = getter.records
191
+ count = getter.count
192
+
193
+ expect(records.count).to eq 3
194
+ expect(count).to eq 3
195
+ expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree', 'Apple Tree']
196
+ end
197
+ end
198
+
199
+ describe 'when filtering on after x hours ago' do
200
+ let(:resource) { Tree }
201
+ let(:fields) { { 'Tree' => 'id' } }
202
+ let(:filters) { {
203
+ field: 'created_at',
204
+ operator: 'after_x_hours_ago',
205
+ value: 3
206
+ }.to_json }
207
+
208
+ it 'should filter as expected' do
209
+ getter.perform
210
+ records = getter.records
211
+ count = getter.count
212
+
213
+ expect(records.count).to eq 2
214
+ expect(count).to eq 2
215
+ expect(records.map(&:name)).to eq ['Pear Tree', 'Choco Tree']
216
+ end
217
+ end
218
+
219
+ describe 'when sorting on an ambiguous field name with a filter' do
220
+ let(:resource) { Tree }
221
+ let(:sort) { '-name' }
222
+ let(:fields) { { 'Tree' => 'id' } }
223
+ let(:filters) { {
224
+ field: 'cutter:name',
225
+ operator: 'equal',
226
+ value: 'Michel'
227
+ }.to_json }
228
+
229
+ it 'should get only the sorted expected records' do
230
+ getter.perform
231
+ records = getter.records
232
+ count = getter.count
233
+
234
+ expect(records.count).to eq 3
235
+ expect(count).to eq 3
236
+ expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree', 'Apple Tree']
237
+ end
238
+ end
239
+
240
+ describe 'when filtering on an updated_at field of the main collection' do
241
+ let(:resource) { Island }
242
+ let(:filters) { {
243
+ field: 'updated_at',
244
+ operator: 'previous_year'
245
+ }.to_json }
246
+
247
+ it 'should get only the expected records' do
248
+ getter.perform
249
+ records = getter.records
250
+ count = getter.count
251
+
252
+ expect(records.count).to eq 2
253
+ expect(count).to eq 2
254
+ expect(records.map(&:name)).to eq ['Skull', 'Lille']
255
+ end
256
+ end
257
+
258
+ describe 'when filtering on an updated_at field of an associated collection' do
259
+ let(:resource) { Tree }
260
+ let(:fields) { { 'Tree' => 'id' } }
261
+ let(:filters) { {
262
+ field: 'island:updated_at',
263
+ operator: 'previous_year'
264
+ }.to_json }
265
+
266
+ it 'should get only the expected records' do
267
+ getter.perform
268
+ records = getter.records
269
+ count = getter.count
270
+
271
+ expect(records.count).to eq 2
272
+ expect(count).to eq 2
273
+ expect(records.map(&:name)).to eq ['Lemon Tree', 'Ginger Tree']
274
+ end
275
+ end
276
+
277
+ describe 'when filtering on an exact updated_at field of an associated collection' do
278
+ let(:resource) { Tree }
279
+ let(:fields) { { 'Tree' => 'id' } }
280
+ let(:filters) { {
281
+ field: 'island:updated_at',
282
+ operator: 'equal',
283
+ value: 'Sat Jul 02 2016 11:52:00 GMT-0400 (EDT)',
284
+ }.to_json }
285
+
286
+ it 'should get only the expected records' do
287
+ getter.perform
288
+ records = getter.records
289
+ count = getter.count
290
+
291
+ expect(records.count).to eq 0
292
+ expect(count).to eq 0
293
+ end
294
+ end
295
+
296
+ describe 'when filtering on a field of an associated collection that does not exist' do
297
+ let(:resource) { Tree }
298
+ let(:fields) { { 'Tree' => 'id' } }
299
+ let(:filters) { {
300
+ field: 'leaf:id',
301
+ operator: 'equal',
302
+ value: 1
303
+ }.to_json }
304
+
305
+ it 'should raise the right error' do
306
+ expect { getter }.to raise_error(ForestLiana::Errors::HTTP422Error, "Association 'leaf' not found")
307
+ end
308
+ end
309
+
310
+ describe 'when filtering on a field that does not exists' do
311
+ let(:resource) { Tree }
312
+ let(:fields) { { 'Tree' => 'id' } }
313
+ let(:filters) { {
314
+ field: 'content',
315
+ operator: 'contains',
316
+ value: 'c'
317
+ }.to_json }
318
+
319
+ it 'should raise the right error' do
320
+ expect { getter }.to raise_error(ForestLiana::Errors::HTTP422Error, "Field 'content' not found")
321
+ end
322
+ end
323
+
324
+ describe 'when filtering on a smart field' do
325
+ let(:filters) { {
326
+ field: 'cap_name',
327
+ operator: 'equal',
328
+ value: 'MICHEL',
329
+ }.to_json }
330
+
331
+ it 'should filter as expected' do
332
+ getter.perform
333
+ records = getter.records
334
+ count = getter.count
335
+
336
+ expect(records.count).to eq 1
337
+ expect(count).to eq 1
338
+ expect(records.first.id).to eq 1
339
+ expect(records.first.name).to eq 'Michel'
340
+ end
341
+ end
342
+
343
+ describe 'when filtering on a smart field with no filter method' do
344
+ let(:resource) { Location }
345
+ let(:filters) { {
346
+ field: 'alter_coordinates',
347
+ operator: 'equal',
348
+ value: '12345XYZ',
349
+ }.to_json }
350
+
351
+ it 'should raise the right error' do
352
+ expect { getter }.to raise_error(
353
+ ForestLiana::Errors::NotImplementedMethodError,
354
+ "method filter on smart field 'alter_coordinates' not found"
355
+ )
356
+ end
357
+ end
358
+ end
359
+ end