446c5f00ab
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
137 lines
4.5 KiB
Elixir
137 lines
4.5 KiB
Elixir
defmodule Mobilizon.Federation.ActivityPub.Types.Todos do
|
|
@moduledoc """
|
|
ActivityPub type handler for Todos
|
|
"""
|
|
alias Mobilizon.{Actors, Todos}
|
|
alias Mobilizon.Actors.Actor
|
|
alias Mobilizon.Federation.ActivityPub.Permission
|
|
alias Mobilizon.Federation.ActivityPub.Types.Entity
|
|
alias Mobilizon.Federation.ActivityStream
|
|
alias Mobilizon.Federation.ActivityStream.Convertible
|
|
alias Mobilizon.Todos.{Todo, TodoList}
|
|
import Mobilizon.Federation.ActivityPub.Utils, only: [make_create_data: 2, make_update_data: 2]
|
|
require Logger
|
|
|
|
@behaviour Entity
|
|
|
|
@impl Entity
|
|
@spec create(map(), map()) ::
|
|
{:ok, Todo.t(), ActivityStream.t()} | {:error, Ecto.Changeset.t() | atom()}
|
|
def create(args, additional) do
|
|
with {:ok, %Todo{todo_list_id: todo_list_id, creator_id: creator_id} = todo} <-
|
|
Todos.create_todo(args),
|
|
{:ok, %Actor{} = creator, %TodoList{} = todo_list, %Actor{} = group} <-
|
|
creator_todo_list_and_group(creator_id, todo_list_id) do
|
|
todo = %{todo | todo_list: %{todo_list | actor: group}, creator: creator}
|
|
todo_as_data = Convertible.model_to_as(todo)
|
|
audience = %{"to" => [group.members_url], "cc" => []}
|
|
create_data = make_create_data(todo_as_data, Map.merge(audience, additional))
|
|
{:ok, todo, create_data}
|
|
end
|
|
end
|
|
|
|
@impl Entity
|
|
@spec update(Todo.t(), map, map) ::
|
|
{:ok, Todo.t(), ActivityStream.t()}
|
|
| {:error, atom() | Ecto.Changeset.t()}
|
|
def update(%Todo{} = old_todo, args, additional) do
|
|
with {:ok, %Todo{todo_list_id: todo_list_id} = todo} <- Todos.update_todo(old_todo, args),
|
|
{:ok, %TodoList{} = todo_list, %Actor{} = group} <- todo_list_and_group(todo_list_id) do
|
|
todo_as_data = Convertible.model_to_as(%{todo | todo_list: %{todo_list | actor: group}})
|
|
audience = %{"to" => [group.members_url], "cc" => []}
|
|
update_data = make_update_data(todo_as_data, Map.merge(audience, additional))
|
|
{:ok, todo, update_data}
|
|
end
|
|
end
|
|
|
|
@spec creator_todo_list_and_group(integer(), String.t()) ::
|
|
{:ok, Actor.t(), TodoList.t(), Actor.t()}
|
|
| {:error, :creator_not_found | :group_not_found | :todo_list_not_found}
|
|
defp creator_todo_list_and_group(creator_id, todo_list_id) do
|
|
case Actors.get_actor(creator_id) do
|
|
%Actor{} = creator ->
|
|
case todo_list_and_group(todo_list_id) do
|
|
{:ok, %TodoList{} = todo_list, %Actor{} = group} ->
|
|
{:ok, creator, todo_list, group}
|
|
|
|
{:error, err} ->
|
|
{:error, err}
|
|
end
|
|
|
|
nil ->
|
|
{:error, :creator_not_found}
|
|
end
|
|
end
|
|
|
|
@spec todo_list_and_group(String.t()) ::
|
|
{:ok, TodoList.t(), Actor.t()} | {:error, :group_not_found | :todo_list_not_found}
|
|
defp todo_list_and_group(todo_list_id) do
|
|
case Todos.get_todo_list(todo_list_id) do
|
|
%TodoList{actor_id: group_id} = todo_list ->
|
|
case Actors.get_group_by_actor_id(group_id) do
|
|
{:ok, %Actor{} = group} ->
|
|
{:ok, todo_list, group}
|
|
|
|
{:error, :group_not_found} ->
|
|
{:error, :group_not_found}
|
|
end
|
|
|
|
nil ->
|
|
{:error, :todo_list_not_found}
|
|
end
|
|
end
|
|
|
|
@impl Entity
|
|
@spec delete(Todo.t(), Actor.t(), any(), any()) ::
|
|
{:ok, ActivityStream.t(), Actor.t(), Todo.t()} | {:error, Ecto.Changeset.t()}
|
|
def delete(
|
|
%Todo{url: url, creator: %Actor{url: group_url}} = todo,
|
|
%Actor{url: actor_url} = actor,
|
|
_local,
|
|
_additionnal
|
|
) do
|
|
Logger.debug("Building Delete Todo activity")
|
|
|
|
activity_data = %{
|
|
"actor" => actor_url,
|
|
"type" => "Delete",
|
|
"object" => %{
|
|
"type" => "Tombstone",
|
|
"formerType" => "Todo",
|
|
"deleted" => DateTime.utc_now(),
|
|
"id" => url
|
|
},
|
|
"id" => "#{url}/delete",
|
|
"to" => [group_url]
|
|
}
|
|
|
|
case Todos.delete_todo(todo) do
|
|
{:ok, _todo} ->
|
|
Cachex.del(:activity_pub, "todo_#{todo.id}")
|
|
{:ok, activity_data, actor, todo}
|
|
|
|
{:error, %Ecto.Changeset{} = err} ->
|
|
{:error, err}
|
|
end
|
|
end
|
|
|
|
@spec actor(Todo.t()) :: Actor.t() | nil
|
|
def actor(%Todo{creator_id: creator_id}), do: Actors.get_actor(creator_id)
|
|
|
|
@spec group_actor(Todo.t()) :: Actor.t() | nil
|
|
def group_actor(%Todo{todo_list_id: todo_list_id}) do
|
|
case Todos.get_todo_list(todo_list_id) do
|
|
%TodoList{actor_id: group_id} ->
|
|
Actors.get_actor(group_id)
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
end
|
|
|
|
@spec permissions(Todo.t()) :: Permission.t()
|
|
def permissions(%Todo{}) do
|
|
%Permission{access: :member, create: :member, update: :member, delete: :member}
|
|
end
|
|
end
|