Refactor checking permissions when managing events and tests
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user