Federate participations

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2019-08-14 17:45:11 +02:00
parent b8daf87dd9
commit 641129dc74
18 changed files with 752 additions and 123 deletions

View File

@@ -58,6 +58,10 @@ defmodule Mobilizon.Actors do
Repo.get!(Actor, id)
end
def get_actor(id) do
Repo.get(Actor, id)
end
# Get actor by ID and preload organized events, followers and followings
@spec get_actor_with_everything(integer()) :: Ecto.Query.t()
defp do_get_actor_with_everything(id) do

View File

@@ -214,6 +214,27 @@ defmodule Mobilizon.Events do
])
end
@doc """
Gets a single event, with all associations loaded.
"""
def get_event_full(id) do
case Repo.get(Event, id) do
%Event{} = event ->
{:ok,
Repo.preload(event, [
:organizer_actor,
:sessions,
:tracks,
:tags,
:participants,
:physical_address
])}
err ->
{:error, err}
end
end
@doc """
Gets an event by it's URL
"""
@@ -700,17 +721,28 @@ defmodule Mobilizon.Events do
[%Participant{}, ...]
"""
def list_participants_for_event(uuid, page \\ nil, limit \\ nil) do
Repo.all(
from(
p in Participant,
join: e in Event,
on: p.event_id == e.id,
where: e.uuid == ^uuid and p.role != ^:not_approved,
preload: [:actor]
)
|> paginate(page, limit)
def list_participants_for_event(uuid, page \\ nil, limit \\ nil, include_not_improved \\ false)
def list_participants_for_event(uuid, page, limit, false) do
query = do_list_participants_for_event(uuid, page, limit)
query = from(p in query, where: p.role != ^:not_approved)
Repo.all(query)
end
def list_participants_for_event(uuid, page, limit, true) do
query = do_list_participants_for_event(uuid, page, limit)
Repo.all(query)
end
defp do_list_participants_for_event(uuid, page, limit) do
from(
p in Participant,
join: e in Event,
on: p.event_id == e.id,
where: e.uuid == ^uuid,
preload: [:actor]
)
|> paginate(page, limit)
end
@doc """
@@ -787,6 +819,15 @@ defmodule Mobilizon.Events do
end
end
def get_participant_by_url(url) do
Repo.one(
from(p in Participant,
where: p.url == ^url,
preload: [:actor, :event]
)
)
end
@doc """
Creates a participant.
@@ -800,9 +841,10 @@ defmodule Mobilizon.Events do
"""
def create_participant(attrs \\ %{}) do
%Participant{}
|> Participant.changeset(attrs)
|> Repo.insert()
with {:ok, %Participant{} = participant} <-
%Participant{} |> Participant.changeset(attrs) |> Repo.insert() do
{:ok, Repo.preload(participant, [:event, :actor])}
end
end
@doc """

View File

@@ -17,9 +17,10 @@ defmodule Mobilizon.Events.Participant do
alias Mobilizon.Events.{Participant, Event}
alias Mobilizon.Actors.Actor
@primary_key false
@primary_key {:id, :binary_id, autogenerate: true}
schema "participants" do
field(:role, Mobilizon.Events.ParticipantRoleEnum, default: :participant)
field(:url, :string)
belongs_to(:event, Event, primary_key: true)
belongs_to(:actor, Actor, primary_key: true)
@@ -29,7 +30,49 @@ defmodule Mobilizon.Events.Participant do
@doc false
def changeset(%Participant{} = participant, attrs) do
participant
|> Ecto.Changeset.cast(attrs, [:role, :event_id, :actor_id])
|> validate_required([:role, :event_id, :actor_id])
|> Ecto.Changeset.cast(attrs, [:url, :role, :event_id, :actor_id])
|> generate_url()
|> validate_required([:url, :role, :event_id, :actor_id])
end
# If there's a blank URL that's because we're doing the first insert
defp generate_url(%Ecto.Changeset{data: %Participant{url: nil}} = changeset) do
case fetch_change(changeset, :url) do
{:ok, _url} -> changeset
:error -> do_generate_url(changeset)
end
end
# Most time just go with the given URL
defp generate_url(%Ecto.Changeset{} = changeset), do: changeset
defp do_generate_url(%Ecto.Changeset{} = changeset) do
uuid = Ecto.UUID.generate()
changeset
|> put_change(
:url,
"#{MobilizonWeb.Endpoint.url()}/join/event/#{uuid}"
)
|> put_change(
:id,
uuid
)
end
@doc """
We check that the actor asking to leave the event is not it's only organizer
We start by fetching the list of organizers and if there's only one of them
and that it's the actor requesting leaving the event we return true
"""
@spec check_that_participant_is_not_only_organizer(integer(), integer()) :: boolean()
def check_that_participant_is_not_only_organizer(event_id, actor_id) do
case Mobilizon.Events.list_organizers_participants_for_event(event_id) do
[%Participant{actor: %Actor{id: participant_actor_id}}] ->
participant_actor_id == actor_id
_ ->
false
end
end
end