From c7f1da3a88769b553b28b4f9bdbba32f9815537b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Pr=C3=A1?= Date: Fri, 9 Aug 2019 10:20:14 -0300 Subject: [PATCH] Fix object scope authorization when query returns a list or nil --- lib/middlewares/object_scope_authorization.ex | 21 +++--- .../object_scope_authorization_test.exs | 68 ++++++++++++++++++- 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/lib/middlewares/object_scope_authorization.ex b/lib/middlewares/object_scope_authorization.ex index 620cddd..2604c78 100644 --- a/lib/middlewares/object_scope_authorization.ex +++ b/lib/middlewares/object_scope_authorization.ex @@ -118,18 +118,19 @@ defmodule Rajska.ObjectScopeAuthorization do apply_authorization!(resolution, scoped_struct, Map.get(resolution, :value), nested_keys ++ [:id]) end - defp apply_authorization!(resolution, scoped_struct, value, [first_key | remaining_keys]) when length(remaining_keys) > 0 do - case Map.get(value, first_key) do - nested_value when is_map(nested_value) -> - apply_authorization!(resolution, scoped_struct, nested_value, remaining_keys) + defp apply_authorization!(resolution, scoped_struct, values, keys) when is_list(values) do + Enum.all?(values, fn value -> + apply_authorization!(resolution, scoped_struct, value, keys) + end) + end - values when is_list(values) -> - Enum.all?(values, fn value -> - apply_authorization!(resolution, scoped_struct, value, remaining_keys) - end) + defp apply_authorization!(resolution, scoped_struct, nil, _keys) do + Rajska.apply_auth_mod(resolution, :has_resolution_access?, [resolution, scoped_struct, nil]) + end - nil -> Rajska.apply_auth_mod(resolution, :has_resolution_access?, [resolution, scoped_struct, nil]) - end + defp apply_authorization!(resolution, scoped_struct, value, [first_key | remaining_keys]) when length(remaining_keys) > 0 do + nested_value = Map.get(value, first_key) + apply_authorization!(resolution, scoped_struct, nested_value, remaining_keys) end defp apply_authorization!(resolution, scoped_struct, value, [first_key]) do diff --git a/test/middlewares/object_scope_authorization_test.exs b/test/middlewares/object_scope_authorization_test.exs index c4aee7e..2b1ff89 100644 --- a/test/middlewares/object_scope_authorization_test.exs +++ b/test/middlewares/object_scope_authorization_test.exs @@ -88,6 +88,23 @@ defmodule Rajska.ObjectScopeAuthorizationTest do }} end end + + field :users_query, list_of(:user) do + middleware Rajska.QueryAuthorization, permit: :all + resolve fn _args, _ -> + {:ok, [ + %{id: 1, name: "bob"}, + %{id: 2, name: "bob"}, + ]} + end + end + + field :nil_user_query, :user do + middleware Rajska.QueryAuthorization, permit: :all + resolve fn _args, _ -> + {:ok, nil} + end + end end object :user do @@ -179,7 +196,7 @@ defmodule Rajska.ObjectScopeAuthorizationTest do ] == errors end - test "Works when returned object is nil" do + test "Works when returned nested object is nil" do assert {:ok, result} = Absinthe.run(all_query_no_company(2), __MODULE__.Schema, context: %{current_user: %{role: :user, id: 2}}) assert %{data: %{"allQueryNoCompany" => %{}}} = result refute Map.has_key?(result, :errors) @@ -198,7 +215,17 @@ defmodule Rajska.ObjectScopeAuthorizationTest do ] == errors end - test "Works when returned object is a list" do + test "Works when query returns nil" do + assert {:ok, result} = Absinthe.run(nil_user_query(), __MODULE__.Schema, context: %{current_user: %{role: :user, id: 1}}) + assert %{data: %{"nilUserQuery" => nil}} = result + refute Map.has_key?(result, :errors) + + {:ok, result} = Absinthe.run(nil_user_query(), __MODULE__.Schema, context: %{current_user: %{role: :admin, id: 2}}) + assert %{data: %{"nilUserQuery" => nil}} = result + refute Map.has_key?(result, :errors) + end + + test "Works when returned nested object is a list" do assert {:ok, %{errors: errors}} = Absinthe.run(all_query_companies_list(2), __MODULE__.Schema, context: %{current_user: %{role: :user, id: 2}}) assert [ %{ @@ -222,6 +249,21 @@ defmodule Rajska.ObjectScopeAuthorizationTest do ] == errors end + test "Works when query returns a list" do + assert {:ok, %{errors: errors}} = Absinthe.run(users_query(), __MODULE__.Schema, context: %{current_user: %{role: :user, id: 2}}) + assert [ + %{ + locations: [%{column: 0, line: 2}], + message: "Not authorized to access object user", + path: ["usersQuery"] + } + ] == errors + + {:ok, result} = Absinthe.run(users_query(), __MODULE__.Schema, context: %{current_user: %{role: :admin, id: 2}}) + assert %{data: %{"usersQuery" => [_ | _]}} = result + refute Map.has_key?(result, :errors) + end + defp all_query(id) do """ { @@ -301,4 +343,26 @@ defmodule Rajska.ObjectScopeAuthorizationTest do } """ end + + defp users_query do + """ + { + usersQuery { + name + email + } + } + """ + end + + defp nil_user_query do + """ + { + nilUserQuery { + name + email + } + } + """ + end end