From dfa25e0d21f2e17131a96287d9afb385a2cec4ca Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 7 Feb 2019 17:57:49 +0100 Subject: [PATCH] Events with only one event creator participant can't be left Signed-off-by: Thomas Citharel --- lib/mobilizon/events/events.ex | 22 +++++ lib/mobilizon_web/resolvers/event.ex | 9 +- .../resolvers/participant_resolver_test.exs | 95 +++++++++++++++++-- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 91632615c..e0c9bc137 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -582,6 +582,28 @@ defmodule Mobilizon.Events do ) end + @doc """ + Returns the list of organizers participants for an event. + + ## Examples + + iex> list_organizers_participants_for_event(id) + [%Participant{role: :creator}, ...] + + """ + def list_organizers_participants_for_event(id, page \\ nil, limit \\ nil) do + Repo.all( + from( + p in Participant, + join: e in Event, + on: p.event_id == e.id, + where: e.id == ^id and p.role == ^:creator, + preload: [:actor] + ) + |> paginate(page, limit) + ) + end + @doc """ Gets a single participant. diff --git a/lib/mobilizon_web/resolvers/event.ex b/lib/mobilizon_web/resolvers/event.ex index 8ae77232d..74938c19d 100644 --- a/lib/mobilizon_web/resolvers/event.ex +++ b/lib/mobilizon_web/resolvers/event.ex @@ -100,12 +100,19 @@ defmodule MobilizonWeb.Resolvers.Event do with {:is_owned, true, _} <- User.owns_actor(user, actor_id), {:ok, %Participant{} = participant} <- Mobilizon.Events.get_participant(event_id, actor_id), - {:ok, _} <- Mobilizon.Events.delete_participant(participant) do + {:only_organizer, false} <- + {:only_organizer, + Mobilizon.Events.list_organizers_participants_for_event(event_id) |> length == 1}, + {:ok, _} <- + Mobilizon.Events.delete_participant(participant) do {:ok, %{event: %{id: event_id}, actor: %{id: actor_id}}} else {:is_owned, false} -> {:error, "Actor id is not owned by authenticated user"} + {:only_organizer, true} -> + {:error, "You can't leave event because you're the only event creator participant"} + {:error, :participant_not_found} -> {:error, "Participant not found"} end diff --git a/test/mobilizon_web/resolvers/participant_resolver_test.exs b/test/mobilizon_web/resolvers/participant_resolver_test.exs index e54fe34ad..ca5d0ddab 100644 --- a/test/mobilizon_web/resolvers/participant_resolver_test.exs +++ b/test/mobilizon_web/resolvers/participant_resolver_test.exs @@ -46,7 +46,7 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) assert json_response(res, 200)["errors"] == nil - assert json_response(res, 200)["data"]["joinEvent"]["role"] == 1 + assert json_response(res, 200)["data"]["joinEvent"]["role"] == "participant" assert json_response(res, 200)["data"]["joinEvent"]["event"]["id"] == event.id assert json_response(res, 200)["data"]["joinEvent"]["actor"]["id"] == actor.id @@ -122,6 +122,63 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do conn: conn, user: user, actor: actor + } do + event = insert(:event, %{organizer_actor: actor}) + participant = insert(:participant, %{actor: actor, event: event}) + participant2 = insert(:participant, %{event: event}) + + mutation = """ + mutation { + leaveEvent( + actor_id: #{participant.actor.id}, + event_id: #{event.id} + ) { + actor { + id + }, + event { + id + } + } + } + """ + + res = + conn + |> auth_conn(user) + |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) + + assert json_response(res, 200)["errors"] == nil + assert json_response(res, 200)["data"]["leaveEvent"]["event"]["id"] == event.id + assert json_response(res, 200)["data"]["leaveEvent"]["actor"]["id"] == participant.actor.id + + query = """ + { + participants(uuid: "#{event.uuid}") { + role, + actor { + preferredUsername + } + } + } + """ + + res = + conn + |> get("/api", AbsintheHelpers.query_skeleton(query, "participants")) + + assert json_response(res, 200)["data"]["participants"] == [ + %{ + "actor" => %{"preferredUsername" => participant2.actor.preferred_username}, + "role" => "creator" + } + ] + end + + test "actor_leave_event/3 should check if the participant is the only creator", %{ + conn: conn, + actor: actor, + user: user } do participant = insert(:participant, %{actor: actor}) @@ -146,9 +203,35 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do |> auth_conn(user) |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) - assert json_response(res, 200)["errors"] == nil - assert json_response(res, 200)["data"]["leaveEvent"]["event"]["id"] == participant.event.id - assert json_response(res, 200)["data"]["leaveEvent"]["actor"]["id"] == participant.actor.id + assert hd(json_response(res, 200)["errors"])["message"] == + "You can't leave event because you're the only event creator participant" + + # If we have a second participant but not an event creator + insert(:participant, %{event: participant.event, role: :participant}) + + mutation = """ + mutation { + leaveEvent( + actor_id: #{participant.actor.id}, + event_id: #{participant.event.id} + ) { + actor { + id + }, + event { + id + } + } + } + """ + + res = + conn + |> auth_conn(user) + |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) + + assert hd(json_response(res, 200)["errors"])["message"] == + "You can't leave event because you're the only event creator participant" end test "actor_leave_event/3 should check the user is logged in", %{conn: conn, actor: actor} do @@ -258,7 +341,7 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do assert json_response(res, 200)["data"]["participants"] == [ %{ "actor" => %{"preferredUsername" => context.actor.preferred_username}, - "role" => 4 + "role" => "creator" } ] @@ -266,7 +349,7 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do actor2 = insert(:actor) actor3 = insert(:actor) # This one won't get listed (as not approved) - participant = insert(:participant, event: event, actor: actor2, role: :not_approved) + insert(:participant, event: event, actor: actor2, role: :not_approved) # This one will (as a participant) participant2 = insert(:participant, event: event, actor: actor3, role: :participant)