131 lines
4.5 KiB
Elixir
131 lines
4.5 KiB
Elixir
defmodule MobilizonWeb.API.Reports do
|
|
@moduledoc """
|
|
API for Reports.
|
|
"""
|
|
|
|
import Mobilizon.Service.Admin.ActionLogService
|
|
|
|
import MobilizonWeb.API.Utils
|
|
|
|
alias Mobilizon.Actors
|
|
alias Mobilizon.Actors.Actor
|
|
alias Mobilizon.Events
|
|
alias Mobilizon.Reports, as: ReportsAction
|
|
alias Mobilizon.Reports.{Note, Report, ReportStatus}
|
|
alias Mobilizon.Service.ActivityPub
|
|
alias Mobilizon.Service.ActivityPub.Activity
|
|
alias Mobilizon.Users
|
|
alias Mobilizon.Users.User
|
|
|
|
@doc """
|
|
Create a report/flag on an actor, and optionally on an event or on comments.
|
|
"""
|
|
def report(
|
|
%{
|
|
reporter_actor_id: reporter_actor_id,
|
|
reported_actor_id: reported_actor_id
|
|
} = args
|
|
) do
|
|
with {:reporter, %Actor{url: reporter_url} = _reporter_actor} <-
|
|
{:reporter, Actors.get_actor!(reporter_actor_id)},
|
|
{:reported, %Actor{url: reported_actor_url} = reported_actor} <-
|
|
{:reported, Actors.get_actor!(reported_actor_id)},
|
|
{:ok, content} <- args |> Map.get(:content, nil) |> make_report_content_text(),
|
|
{:ok, event} <- args |> Map.get(:event_id, nil) |> get_event(),
|
|
{:get_report_comments, comments_urls} <-
|
|
get_report_comments(reported_actor, Map.get(args, :comments_ids, [])),
|
|
{:make_activity, {:ok, %Activity{} = activity, %Report{} = report}} <-
|
|
{:make_activity,
|
|
ActivityPub.flag(%{
|
|
reporter_url: reporter_url,
|
|
reported_actor_url: reported_actor_url,
|
|
event_url: (!is_nil(event) && event.url) || nil,
|
|
comments_url: comments_urls,
|
|
content: content,
|
|
forward: args[:forward] || false,
|
|
local: args[:local] || args[:forward] || false
|
|
})} do
|
|
{:ok, activity, report}
|
|
else
|
|
{:make_activity, err} -> {:error, err}
|
|
{:error, err} -> {:error, err}
|
|
{:actor_id, %{}} -> {:error, "Valid `actor_id` required"}
|
|
{:reporter, nil} -> {:error, "Reporter Actor not found"}
|
|
{:reported, nil} -> {:error, "Reported Actor not found"}
|
|
end
|
|
end
|
|
|
|
defp get_event(nil), do: {:ok, nil}
|
|
defp get_event(event_id), do: Events.get_event(event_id)
|
|
|
|
@doc """
|
|
Update the state of a report
|
|
"""
|
|
def update_report_status(%Actor{} = actor, %Report{} = report, state) do
|
|
with {:valid_state, true} <-
|
|
{:valid_state, ReportStatus.valid_value?(state)},
|
|
{:ok, report} <- ReportsAction.update_report(report, %{"status" => state}),
|
|
{:ok, _} <- log_action(actor, "update", report) do
|
|
{:ok, report}
|
|
else
|
|
{:valid_state, false} -> {:error, "Unsupported state"}
|
|
end
|
|
end
|
|
|
|
defp get_report_comments(%Actor{id: actor_id}, comment_ids) do
|
|
{:get_report_comments,
|
|
actor_id |> Events.list_comments_by_actor_and_ids(comment_ids) |> Enum.map(& &1.url)}
|
|
end
|
|
|
|
defp get_report_comments(_, _), do: {:get_report_comments, nil}
|
|
|
|
@doc """
|
|
Create a note on a report
|
|
"""
|
|
@spec create_report_note(Report.t(), Actor.t(), String.t()) :: {:ok, Note.t()}
|
|
def create_report_note(
|
|
%Report{id: report_id},
|
|
%Actor{id: moderator_id, user_id: user_id} = moderator,
|
|
content
|
|
) do
|
|
with %User{role: role} <- Users.get_user!(user_id),
|
|
{:role, true} <- {:role, role in [:administrator, :moderator]},
|
|
{:ok, %Note{} = note} <-
|
|
Mobilizon.Reports.create_note(%{
|
|
"report_id" => report_id,
|
|
"moderator_id" => moderator_id,
|
|
"content" => content
|
|
}),
|
|
{:ok, _} <- log_action(moderator, "create", note) do
|
|
{:ok, note}
|
|
else
|
|
{:role, false} ->
|
|
{:error, "You need to be a moderator or an administrator to create a note on a report"}
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Delete a report note
|
|
"""
|
|
@spec delete_report_note(Note.t(), Actor.t()) :: {:ok, Note.t()}
|
|
def delete_report_note(
|
|
%Note{moderator_id: note_moderator_id} = note,
|
|
%Actor{id: moderator_id, user_id: user_id} = moderator
|
|
) do
|
|
with {:same_actor, true} <- {:same_actor, note_moderator_id == moderator_id},
|
|
%User{role: role} <- Users.get_user!(user_id),
|
|
{:role, true} <- {:role, role in [:administrator, :moderator]},
|
|
{:ok, %Note{} = note} <-
|
|
Mobilizon.Reports.delete_note(note),
|
|
{:ok, _} <- log_action(moderator, "delete", note) do
|
|
{:ok, note}
|
|
else
|
|
{:role, false} ->
|
|
{:error, "You need to be a moderator or an administrator to create a note on a report"}
|
|
|
|
{:same_actor, false} ->
|
|
{:error, "You can only remove your own notes"}
|
|
end
|
|
end
|
|
end
|