forest_liana 9.22.6 → 9.22.7
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/services/forest_liana/ability/permission.rb +2 -2
- data/app/services/forest_liana/field_path.rb +5 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/requests/unresolved_polymorphic_relation_spec.rb +64 -0
- data/spec/services/forest_liana/ability/redact_fields_spec.rb +8 -7
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1899aa8f55f2188189973046573741eb4492ad3e47c8bac900125d7468cc1845
|
|
4
|
+
data.tar.gz: 8fe15b7c2eaca28fa7c74ad66af35eecc7299dcea6f0671b8e07fa36f07529cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5c3b883ebdc5412f0a982b5cd12d23e361163471e5cbe39bc6e7ca956672f8a34ef06eb41300279ce0ac9ca79aab26f28377539e9ada69cf39f8716b17323d3
|
|
7
|
+
data.tar.gz: 320775ad84781e8b15a27b5cffa365975afa2da9e4d59317bf6bdf2cd9978951eac6b0671e989b6201203df37bc1450e349cd171a4eaf799d6f5a94a28ed56bc
|
|
@@ -205,7 +205,7 @@ module ForestLiana
|
|
|
205
205
|
if readable.call(entry[:owners][collection_key])
|
|
206
206
|
acc[collection_key] = entry[:field_names].join(',')
|
|
207
207
|
else
|
|
208
|
-
denied << denial_entry(collection_key, entry[:owners][collection_key], readable_collection_names) if named
|
|
208
|
+
denied << denial_entry(collection_key, entry[:owners][collection_key], readable_collection_names) if named && !FieldPath.unresolved?(entry[:owners][collection_key])
|
|
209
209
|
end
|
|
210
210
|
else
|
|
211
211
|
kept = entry[:field_names].select do |field_name|
|
|
@@ -216,7 +216,7 @@ module ForestLiana
|
|
|
216
216
|
# differs from root_name — prefix the message so it doesn't read as if 'field_name'
|
|
217
217
|
# were a bare field of the root.
|
|
218
218
|
display_path = collection_key == root_name ? field_name : "#{collection_key}:#{field_name}"
|
|
219
|
-
denied << denial_entry(field_name, entry[:owners][field_name], readable_collection_names, display_path) if named
|
|
219
|
+
denied << denial_entry(field_name, entry[:owners][field_name], readable_collection_names, display_path) if named && !FieldPath.unresolved?(entry[:owners][field_name])
|
|
220
220
|
false
|
|
221
221
|
end
|
|
222
222
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ForestLiana
|
|
2
2
|
class FieldPath
|
|
3
3
|
# An empty list (a polymorphic relation with no declared target) is read as denied by
|
|
4
|
-
# readable_leaves?, not as nothing to check.
|
|
4
|
+
# readable_leaves?, not as nothing to check: a query refuses it, a projection drops it.
|
|
5
5
|
#
|
|
6
6
|
# A prefix naming no relation raises rather than falling back to the root collection, which
|
|
7
7
|
# is pinned readable upstream — a fallback would turn "does not resolve" into "allowed".
|
|
@@ -30,6 +30,10 @@ module ForestLiana
|
|
|
30
30
|
collection_names.any? && collection_names.all? { |name| readable_collection_names.include?(name) }
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def self.unresolved?(collection_names)
|
|
34
|
+
collection_names.empty?
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
def self.leaf_label(collection_names)
|
|
34
38
|
return 'an unresolved polymorphic relation' if collection_names.empty?
|
|
35
39
|
|
data/lib/forest_liana/version.rb
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
# devise_invitable declares `belongs_to :invited_by, polymorphic: true` with no `as: :invited_by`
|
|
4
|
+
# inverse anywhere, so no target can be resolved for it (#824).
|
|
5
|
+
describe 'A polymorphic relation with no declared target', type: :request do
|
|
6
|
+
token = JWT.encode({ id: 1, email: 'michael.kelso@that70.show', first_name: 'Michael',
|
|
7
|
+
last_name: 'Kelso', team: 'Operations', rendering_id: 16,
|
|
8
|
+
exp: Time.now.to_i + 2.weeks.to_i, permission_level: 'admin' },
|
|
9
|
+
ForestLiana.auth_secret, 'HS256')
|
|
10
|
+
headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json',
|
|
11
|
+
'Authorization' => "Bearer #{token}" }
|
|
12
|
+
|
|
13
|
+
let!(:user) { User.create!(name: 'Michel') }
|
|
14
|
+
let!(:address) { Address.create!(line1: '1 Palm Street', city: 'Papeete', zipcode: '98713', addressable: user) }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
Rails.cache.clear
|
|
18
|
+
Rails.cache.write('forest.users', { '1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' } })
|
|
19
|
+
Rails.cache.write('forest.has_permission', true)
|
|
20
|
+
enabled = { 'roles' => [1] }
|
|
21
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch).to receive(:get_permissions)
|
|
22
|
+
.with('/liana/v4/permissions/environment').and_return(
|
|
23
|
+
'collections' => %w[Address User].to_h do |name|
|
|
24
|
+
[name, { 'collection' => %w[browseEnabled readEnabled editEnabled addEnabled deleteEnabled exportEnabled]
|
|
25
|
+
.to_h { |key| [key, enabled] }, 'actions' => {} }]
|
|
26
|
+
end
|
|
27
|
+
)
|
|
28
|
+
allow(ForestLiana::SchemaUtils).to receive(:polymorphic_models).and_call_original
|
|
29
|
+
allow(ForestLiana::SchemaUtils).to receive(:polymorphic_models)
|
|
30
|
+
.with(Address.reflect_on_association(:addressable)).and_return([])
|
|
31
|
+
|
|
32
|
+
allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
|
|
33
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
|
|
34
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
|
|
35
|
+
allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
|
|
36
|
+
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes)
|
|
37
|
+
.and_return('scopes' => {}, 'team' => { 'id' => '1', 'name' => 'Operations' })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
after do
|
|
41
|
+
Address.destroy_all
|
|
42
|
+
User.destroy_all
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'serves the get-one without the relation instead of refusing it' do
|
|
46
|
+
get "/forest/Address/#{address.id}",
|
|
47
|
+
params: { fields: { 'Address' => 'id,line1,addressable', 'addressable' => 'id' }, timezone: 'Europe/Paris' },
|
|
48
|
+
headers: headers
|
|
49
|
+
|
|
50
|
+
expect(response.status).to eq(200)
|
|
51
|
+
body = JSON.parse(response.body)
|
|
52
|
+
expect(body['data']['attributes']['line1']).to eq('1 Palm Street')
|
|
53
|
+
expect(body['data'].fetch('relationships', {})).not_to have_key('addressable')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'still refuses a sort on the relation' do
|
|
57
|
+
get '/forest/Address',
|
|
58
|
+
params: { fields: { 'Address' => 'id,line1' }, sort: 'addressable.id', page: { 'number' => '1', 'size' => '10' },
|
|
59
|
+
timezone: 'Europe/Paris' },
|
|
60
|
+
headers: headers
|
|
61
|
+
|
|
62
|
+
expect(response.status).to eq(403)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -510,16 +510,17 @@ module ForestLiana
|
|
|
510
510
|
%w[addresses addresses= address_ids address_ids=].each { |m| Island.undef_method(m) rescue nil }
|
|
511
511
|
end
|
|
512
512
|
|
|
513
|
-
it '
|
|
513
|
+
it 'drops a relation with no declared target even when the caller named it' do
|
|
514
514
|
write_permissions('Tree' => true)
|
|
515
515
|
Tree.class_eval { belongs_to :subject, polymorphic: true, optional: true }
|
|
516
516
|
|
|
517
|
-
expect
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
517
|
+
expect(dummy_class.redact_fields(user, Tree, { 'subject' => 'id' }, named_collections: ['subject']))
|
|
518
|
+
.to eq({})
|
|
519
|
+
expect(
|
|
520
|
+
dummy_class.redact_fields(
|
|
521
|
+
user, Tree, { 'Tree' => 'id,subject', 'subject' => 'id' }, named_collections: %w[Tree subject]
|
|
522
|
+
)
|
|
523
|
+
).to eq('Tree' => 'id')
|
|
523
524
|
ensure
|
|
524
525
|
Tree._reflections.delete('subject')
|
|
525
526
|
Tree._reflections.delete(:subject)
|
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: 9.22.
|
|
4
|
+
version: 9.22.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sandro Munda
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -490,6 +490,7 @@ files:
|
|
|
490
490
|
- spec/requests/stats_spec.rb
|
|
491
491
|
- spec/requests/sti_record_conversion_spec.rb
|
|
492
492
|
- spec/requests/test.ru
|
|
493
|
+
- spec/requests/unresolved_polymorphic_relation_spec.rb
|
|
493
494
|
- spec/requests/workflow_executions_spec.rb
|
|
494
495
|
- spec/routing/routes_spec.rb
|
|
495
496
|
- spec/serializers/forest_liana/missing_attribute_valve_spec.rb
|
|
@@ -847,6 +848,7 @@ test_files:
|
|
|
847
848
|
- spec/requests/stats_spec.rb
|
|
848
849
|
- spec/requests/sti_record_conversion_spec.rb
|
|
849
850
|
- spec/requests/test.ru
|
|
851
|
+
- spec/requests/unresolved_polymorphic_relation_spec.rb
|
|
850
852
|
- spec/requests/workflow_executions_spec.rb
|
|
851
853
|
- spec/routing/routes_spec.rb
|
|
852
854
|
- spec/serializers/forest_liana/missing_attribute_valve_spec.rb
|