Make sure people can't join an event with limited participants
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
db5b02e397
commit
bf25d22786
|
@ -762,6 +762,17 @@ defmodule Mobilizon.Events do
|
|||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Counts participant participants.
|
||||
"""
|
||||
@spec count_participant_participants(integer | String.t()) :: integer
|
||||
def count_participant_participants(event_id) do
|
||||
event_id
|
||||
|> count_participants_query()
|
||||
|> filter_participant_role()
|
||||
|> Repo.aggregate(:count, :id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Counts unapproved participants.
|
||||
"""
|
||||
|
@ -1457,6 +1468,11 @@ defmodule Mobilizon.Events do
|
|||
from(p in query, where: p.role not in ^[:not_approved, :rejected])
|
||||
end
|
||||
|
||||
@spec filter_participant_role(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
defp filter_participant_role(query) do
|
||||
from(p in query, where: p.role == ^:participant)
|
||||
end
|
||||
|
||||
@spec filter_unapproved_role(Ecto.Query.t()) :: Ecto.Query.t()
|
||||
defp filter_unapproved_role(query) do
|
||||
from(p in query, where: p.role == ^:not_approved)
|
||||
|
|
|
@ -170,6 +170,9 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||
|> Map.put(:actor, Person.proxify_pictures(actor)) do
|
||||
{:ok, participant}
|
||||
else
|
||||
{:maximum_attendee_capacity, _} ->
|
||||
{:error, "The event has already reached it's maximum capacity"}
|
||||
|
||||
{:has_event, _} ->
|
||||
{:error, "Event with this ID #{inspect(event_id)} doesn't exist"}
|
||||
|
||||
|
|
|
@ -411,8 +411,16 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||
|
||||
def join(object, actor, local \\ true)
|
||||
|
||||
def join(%Event{} = event, %Actor{} = actor, local) do
|
||||
with role <- Mobilizon.Events.get_default_participant_role(event),
|
||||
def join(%Event{options: options} = event, %Actor{} = actor, local) do
|
||||
# TODO Refactor me for federation
|
||||
with maximum_attendee_capacity <-
|
||||
Map.get(options, :maximum_attendee_capacity, 2_000_000) || false,
|
||||
{:maximum_attendee_capacity, true} <-
|
||||
{:maximum_attendee_capacity,
|
||||
!maximum_attendee_capacity ||
|
||||
Mobilizon.Events.count_participant_participants(event.id) <
|
||||
maximum_attendee_capacity},
|
||||
role <- Mobilizon.Events.get_default_participant_role(event),
|
||||
{:ok, %Participant{} = participant} <-
|
||||
Mobilizon.Events.create_participant(%{
|
||||
role: role,
|
||||
|
|
|
@ -74,6 +74,76 @@ defmodule MobilizonWeb.Resolvers.ParticipantResolverTest do
|
|||
assert hd(json_response(res, 200)["errors"])["message"] =~ "already a participant"
|
||||
end
|
||||
|
||||
test "actor_join_event/3 doesn't work if the event already has too much participants", %{
|
||||
conn: conn,
|
||||
actor: actor
|
||||
} do
|
||||
event = insert(:event, options: %{maximum_attendee_capacity: 2})
|
||||
insert(:participant, event: event, actor: actor, role: :creator)
|
||||
insert(:participant, event: event, role: :participant)
|
||||
insert(:participant, event: event, role: :not_approved)
|
||||
insert(:participant, event: event, role: :rejected)
|
||||
user_participant = insert(:user)
|
||||
actor_participant = insert(:actor, user: user_participant)
|
||||
|
||||
mutation = """
|
||||
mutation {
|
||||
joinEvent(
|
||||
actor_id: #{actor_participant.id},
|
||||
event_id: #{event.id}
|
||||
) {
|
||||
role,
|
||||
actor {
|
||||
id
|
||||
},
|
||||
event {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user_participant)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert json_response(res, 200)["errors"] == nil
|
||||
assert json_response(res, 200)["data"]["joinEvent"]["role"] == "PARTICIPANT"
|
||||
assert json_response(res, 200)["data"]["joinEvent"]["event"]["id"] == to_string(event.id)
|
||||
|
||||
assert json_response(res, 200)["data"]["joinEvent"]["actor"]["id"] ==
|
||||
to_string(actor_participant.id)
|
||||
|
||||
user_participant_2 = insert(:user)
|
||||
actor_participant_2 = insert(:actor, user: user_participant_2)
|
||||
|
||||
mutation = """
|
||||
mutation {
|
||||
joinEvent(
|
||||
actor_id: #{actor_participant_2.id},
|
||||
event_id: #{event.id}
|
||||
) {
|
||||
role,
|
||||
actor {
|
||||
id
|
||||
},
|
||||
event {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user_participant_2)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"The event has already reached it's maximum capacity"
|
||||
end
|
||||
|
||||
test "actor_join_event/3 should check the actor is owned by the user", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
|
|
|
@ -124,7 +124,8 @@ defmodule Mobilizon.Factory do
|
|||
url: Routes.page_url(Endpoint, :event, uuid),
|
||||
picture: insert(:picture),
|
||||
uuid: uuid,
|
||||
join_options: :free
|
||||
join_options: :free,
|
||||
options: %{}
|
||||
}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue