Refactor checking permissions when managing events and tests

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-07-26 17:23:42 +02:00
parent 52fe274c5a
commit acd921432f
3 changed files with 539 additions and 343 deletions

View File

@@ -255,11 +255,19 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
# See https://github.com/absinthe-graphql/absinthe/issues/490
with {:is_owned, %Actor{} = organizer_actor} <- User.owns_actor(user, organizer_actor_id),
args <- Map.put(args, :options, args[:options] || %{}),
{:group_check, true} <- {:group_check, is_organizer_group_member?(args)},
args_with_organizer <- Map.put(args, :organizer_actor, organizer_actor),
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
API.Events.create_event(args_with_organizer) do
{:ok, event}
else
{:group_check, false} ->
{:error,
dgettext(
"errors",
"Organizer profile doesn't have permission to create an event on behalf of this group"
)}
{:is_owned, nil} ->
{:error, dgettext("errors", "Organizer profile is not owned by the user")}
@@ -286,16 +294,21 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
# See https://github.com/absinthe-graphql/absinthe/issues/490
with args <- Map.put(args, :options, args[:options] || %{}),
{:ok, %Event{} = event} <- Events.get_event_with_preload(event_id),
{:old_actor, {:is_owned, %Actor{}}} <-
{:old_actor, User.owns_actor(user, event.organizer_actor_id)},
new_organizer_actor_id <- args |> Map.get(:organizer_actor_id, event.organizer_actor_id),
{:new_actor, {:is_owned, %Actor{} = organizer_actor}} <-
{:new_actor, User.owns_actor(user, new_organizer_actor_id)},
args <- Map.put(args, :organizer_actor, organizer_actor),
%Actor{} = actor <- Users.get_actor_for_user(user),
{:ok, args} <- verify_profile_change(args, event, user, actor),
{:event_can_be_managed, true} <-
{:event_can_be_managed, can_event_be_updated_by?(event, actor)},
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
API.Events.update_event(args, event) do
{:ok, event}
else
{:event_can_be_managed, false} ->
{:error,
dgettext(
"errors",
"This profile doesn't have permission to update an event on behalf of this group"
)}
{:error, :event_not_found} ->
{:error, dgettext("errors", "Event not found")}
@@ -325,7 +338,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
with {:ok, %Event{local: is_local} = event} <- Events.get_event_with_preload(event_id),
%Actor{id: actor_id} = actor <- Users.get_actor_for_user(user) do
cond do
{:event_can_be_managed, true} == Event.can_be_managed_by(event, actor_id) ->
{:event_can_be_managed, true} ==
{:event_can_be_managed, can_event_be_deleted_by?(event, actor)} ->
do_delete_event(event, actor)
role in [:moderator, :administrator] ->
@@ -355,4 +369,67 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
{:ok, %{id: event.id}}
end
end
defp is_organizer_group_member?(%{
attributed_to_id: attributed_to_id,
organizer_actor_id: organizer_actor_id
})
when not is_nil(attributed_to_id) do
Actors.is_member?(organizer_actor_id, attributed_to_id) &&
Permission.can_create_group_object?(organizer_actor_id, attributed_to_id, %Event{})
end
defp is_organizer_group_member?(_), do: true
defp verify_profile_change(
args,
%Event{attributed_to: %Actor{}},
%User{} = _user,
%Actor{} = current_profile
) do
# The organizer_actor has to be the current profile, because otherwise we're left with a possible remote organizer
args = Map.put(args, :organizer_actor, current_profile)
{:ok, args}
end
defp verify_profile_change(
args,
%Event{organizer_actor: %Actor{id: organizer_actor_id}},
%User{} = user,
%Actor{} = _actor
) do
with {:old_actor, {:is_owned, %Actor{}}} <-
{:old_actor, User.owns_actor(user, organizer_actor_id)},
new_organizer_actor_id <- args |> Map.get(:organizer_actor_id, organizer_actor_id),
{:new_actor, {:is_owned, %Actor{} = organizer_actor}} <-
{:new_actor, User.owns_actor(user, new_organizer_actor_id)},
args <- Map.put(args, :organizer_actor, organizer_actor) do
{:ok, args}
end
end
defp can_event_be_updated_by?(
%Event{attributed_to: %Actor{type: :Group}} = event,
%Actor{} = actor_member
) do
Permission.can_update_group_object?(actor_member, event)
end
defp can_event_be_updated_by?(
%Event{} = event,
%Actor{id: actor_member_id}
) do
Event.can_be_managed_by?(event, actor_member_id)
end
defp can_event_be_deleted_by?(
%Event{attributed_to: %Actor{type: :Group}} = event,
%Actor{} = actor_member
) do
Permission.can_delete_group_object?(actor_member, event)
end
defp can_event_be_deleted_by?(%Event{} = event, %Actor{id: actor_member_id}) do
Event.can_be_managed_by?(event, actor_member_id)
end
end

View File

@@ -153,6 +153,7 @@ defmodule Mobilizon.Events do
def get_event_by_url!(url) do
url
|> event_by_url_query()
|> preload_for_event()
|> Repo.one!()
end