Add anonymous and remote participations

This commit is contained in:
Thomas Citharel
2019-12-20 13:04:34 +01:00
parent 17e0b3968f
commit 2ed9050a90
135 changed files with 10141 additions and 2271 deletions

View File

@@ -17,6 +17,7 @@ defmodule Mobilizon.Events.EventOptions do
maximum_attendee_capacity: integer,
remaining_attendee_capacity: integer,
show_remaining_attendee_capacity: boolean,
anonymous_participation: boolean,
attendees: [String.t()],
program: String.t(),
comment_moderation: CommentModeration.t(),
@@ -31,6 +32,7 @@ defmodule Mobilizon.Events.EventOptions do
:maximum_attendee_capacity,
:remaining_attendee_capacity,
:show_remaining_attendee_capacity,
:anonymous_participation,
:attendees,
:program,
:comment_moderation,
@@ -45,6 +47,7 @@ defmodule Mobilizon.Events.EventOptions do
field(:maximum_attendee_capacity, :integer)
field(:remaining_attendee_capacity, :integer)
field(:show_remaining_attendee_capacity, :boolean)
field(:anonymous_participation, :boolean)
field(:attendees, {:array, :string})
field(:program, :string)
field(:comment_moderation, CommentModeration)

View File

@@ -8,6 +8,7 @@ defmodule Mobilizon.Events.EventParticipantStats do
@type t :: %__MODULE__{
not_approved: integer(),
not_confirmed: integer(),
rejected: integer(),
participant: integer(),
moderator: integer(),
@@ -17,6 +18,7 @@ defmodule Mobilizon.Events.EventParticipantStats do
@attrs [
:not_approved,
:not_confirmed,
:rejected,
:participant,
:moderator,
@@ -29,6 +31,7 @@ defmodule Mobilizon.Events.EventParticipantStats do
@derive Jason.Encoder
embedded_schema do
field(:not_approved, :integer, default: 0)
field(:not_confirmed, :integer, default: 0)
field(:rejected, :integer, default: 0)
field(:participant, :integer, default: 0)
field(:moderator, :integer, default: 0)
@@ -47,6 +50,7 @@ defmodule Mobilizon.Events.EventParticipantStats do
defp validate_stats(%Ecto.Changeset{} = changeset) do
changeset
|> validate_number(:not_approved, greater_than_or_equal_to: 0)
|> validate_number(:not_confirmed, greater_than_or_equal_to: 0)
|> validate_number(:rejected, greater_than_or_equal_to: 0)
|> validate_number(:participant, greater_than_or_equal_to: 0)
|> validate_number(:moderator, greater_than_or_equal_to: 0)

View File

@@ -76,6 +76,7 @@ defmodule Mobilizon.Events do
defenum(ParticipantRole, :participant_role, [
:not_approved,
:not_confirmed,
:rejected,
:participant,
:moderator,
@@ -661,9 +662,39 @@ defmodule Mobilizon.Events do
@doc """
Gets a single participation for an event and actor.
"""
@spec get_participant(integer | String.t(), integer | String.t()) ::
@spec get_participant(integer | String.t(), integer | String.t(), map()) ::
{:ok, Participant.t()} | {:error, :participant_not_found}
def get_participant(event_id, actor_id) do
def get_participant(event_id, actor_id, params \\ %{})
# This one if to check someone doesn't go to the same event twice
def get_participant(event_id, actor_id, %{email: email}) do
case Participant
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|> where([p], fragment("? ->>'email' = ?", p.metadata, ^email))
|> Repo.one() do
%Participant{} = participant ->
{:ok, participant}
nil ->
{:error, :participant_not_found}
end
end
# This one if for finding participants by their cancellation token when wanting to cancel a participation
def get_participant(event_id, actor_id, %{cancellation_token: cancellation_token}) do
case Participant
|> where([p], event_id: ^event_id, actor_id: ^actor_id)
|> where([p], fragment("? ->>'cancellation_token' = ?", p.metadata, ^cancellation_token))
|> Repo.one() do
%Participant{} = participant ->
{:ok, participant}
nil ->
{:error, :participant_not_found}
end
end
def get_participant(event_id, actor_id, %{}) do
case Repo.get_by(Participant, event_id: event_id, actor_id: actor_id) do
%Participant{} = participant ->
{:ok, participant}
@@ -673,6 +704,14 @@ defmodule Mobilizon.Events do
end
end
@spec get_participant_by_confirmation_token(String.t()) :: Participant.t()
def get_participant_by_confirmation_token(confirmation_token) do
Participant
|> where([p], fragment("? ->>'confirmation_token' = ?", p.metadata, ^confirmation_token))
|> preload([p], [:actor, :event])
|> Repo.one()
end
@doc """
Gets a single participation for an event and actor.
@@ -706,7 +745,7 @@ defmodule Mobilizon.Events do
@doc """
Returns the list of participants for an event.
Default behaviour is to not return :not_approved participants
Default behaviour is to not return :not_approved or :not_confirmed participants
"""
@spec list_participants_for_event(String.t(), list(atom()), integer | nil, integer | nil) ::
[Participant.t()]

View File

@@ -10,6 +10,7 @@ defmodule Mobilizon.Events.Participant do
alias Mobilizon.Actors.Actor
alias Mobilizon.Events
alias Mobilizon.Events.{Event, ParticipantRole}
alias Mobilizon.Web.Email.Checker
alias Mobilizon.Web.Endpoint
@@ -28,6 +29,12 @@ defmodule Mobilizon.Events.Participant do
field(:role, ParticipantRole, default: :participant)
field(:url, :string)
embeds_one :metadata, Metadata, on_replace: :delete do
field(:email, :string)
field(:confirmation_token, :string)
field(:cancellation_token, :string)
end
belongs_to(:event, Event, primary_key: true)
belongs_to(:actor, Actor, primary_key: true)
@@ -55,11 +62,18 @@ defmodule Mobilizon.Events.Participant do
def changeset(%__MODULE__{} = participant, attrs) do
participant
|> cast(attrs, @attrs)
|> cast_embed(:metadata, with: &metadata_changeset/2)
|> ensure_url()
|> validate_required(@required_attrs)
|> unique_constraint(:actor_id, name: :participants_event_id_actor_id_index)
end
defp metadata_changeset(schema, params) do
schema
|> cast(params, [:email, :confirmation_token, :cancellation_token])
|> Checker.validate_changeset()
end
# If there's a blank URL that's because we're doing the first insert
@spec ensure_url(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp ensure_url(%Ecto.Changeset{data: %__MODULE__{url: nil}} = changeset) do