Skip to content

Commit 4ca3de1

Browse files
committed
Fix authorize_show_related_resource
1 parent 555e907 commit 4ca3de1

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

lib/jsonapi/authorization/authorizing_processor.rb

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,49 @@ def authorize_show_relationship
8585
end
8686

8787
def authorize_show_related_resource
88+
# 1. Load the related resource like jsonapi-resources loads them.
89+
# This code is copy-pasted from jsonapi-resources `Processor#related_resource`
90+
# so that we get to loading the resources the same way as JR does.
91+
include_directives = params[:include_directives]
8892
source_klass = params[:source_klass]
8993
source_id = params[:source_id]
90-
relationship_type = params[:relationship_type].to_sym
94+
relationship_type = params[:relationship_type]
95+
serializer = params[:serializer]
96+
fields = params[:fields]
97+
98+
find_options = {
99+
context: context,
100+
fields: fields,
101+
filters: {},
102+
include_directives: include_directives
103+
}
104+
105+
source_resource = source_klass.find_by_key(source_id, context: context, fields: fields)
106+
107+
resource_set = find_related_resource_set(source_resource,
108+
relationship_type,
109+
include_directives,
110+
find_options)
111+
112+
resource_set.populate!(serializer, context, find_options)
91113

92-
source_resource = source_klass.find_by_key(source_id, context: context)
114+
# 2. Authorize the showing of related resources. This code is specific to jsonapi-authorization.
93115

94-
related_resource = source_resource.public_send(relationship_type)
116+
# TODO: Figure out better names for the variables used when looping.
117+
# The reason they have bad names is that we don't know what they are.
118+
related_resources = resource_set.resource_klasses.flat_map do |_resource_klass, inner_thing|
119+
inner_thing.map { |_resource_id, lower_level_thing| lower_level_thing[:resource] }
120+
end
121+
122+
if related_resources.size > 1
123+
raise "Unexpectedly more than one related resource in a show_related_resource operation!"
124+
end
125+
126+
related_resource = related_resources.first
95127

96128
source_record = source_resource._model
97129
related_record = related_resource._model unless related_resource.nil?
130+
98131
authorizer.show_related_resource(
99132
source_record: source_record, related_record: related_record
100133
)

spec/requests/included_resources_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@
200200
end
201201

202202
describe 'a deep relationship with empty relations' do
203-
context 'first level has_one is nil' do
203+
context 'first level has_one is nil', pending: false do
204204
let(:include_query) { 'non-existing-article.comments' }
205205

206206
it { is_expected.to be_successful }
@@ -215,7 +215,7 @@
215215
it { is_expected.to be_forbidden }
216216
end
217217

218-
context 'authorized for first relationship' do
218+
context 'authorized for first relationship', pending: false do
219219
before { allow_operation('include_has_many_resource', source_record: an_instance_of(Article), record_class: Article, authorizer: chained_authorizer) }
220220

221221
it { is_expected.to be_successful }

spec/requests/related_resources_operations_spec.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,20 @@
5858
subject(:last_response) { get("/articles/#{article.external_id}/author") }
5959
let(:article) { articles(:article_with_author) }
6060
let(:policy_scope) { Article.all }
61+
let(:user_policy_scope) { User.all }
6162

62-
context 'unauthorized for show_related_resource', pending: 'Compatibility with JR 0.10' do
63+
before do
64+
allow_any_instance_of(UserPolicy::Scope).to receive(:resolve).and_return(user_policy_scope)
65+
end
66+
67+
context 'unauthorized for show_related_resource' do
6368
before { disallow_operation('show_related_resource', source_record: article, related_record: article.author) }
6469
it { is_expected.to be_forbidden }
6570
end
6671

6772
context 'authorized for show_related_resource' do
6873
before { allow_operation('show_related_resource', source_record: article, related_record: article.author) }
74+
it { is_expected.to be_ok }
6975

7076
# If this happens in real life, it's mostly a bug. We want to document the
7177
# behaviour in that case anyway, as it might be surprising.
@@ -74,5 +80,13 @@
7480
it { is_expected.to be_not_found }
7581
end
7682
end
83+
84+
context 'authorized for show_related_resource while related resource is limited by policy scope' do
85+
before { allow_operation('show_related_resource', source_record: article, related_record: nil) }
86+
87+
let(:user_policy_scope) { User.where.not(id: article.author.id) }
88+
89+
it { is_expected.to be_ok }
90+
end
7791
end
7892
end

0 commit comments

Comments
 (0)