diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/activity.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/emails/admin_email.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 7 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 78 | ||||
-rw-r--r-- | lib/pleroma/web/admin_api/admin_api_controller.ex | 81 | ||||
-rw-r--r-- | lib/pleroma/web/admin_api/views/report_view.ex | 41 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 57 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 10 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 8 |
9 files changed, 277 insertions, 9 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 3fd4003f8..4e54b15ba 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -111,7 +111,7 @@ defmodule Pleroma.Activity do def change(struct, params \\ %{}) do struct - |> cast(params, [:data]) + |> cast(params, [:data, :recipients]) |> validate_required([:data]) |> unique_constraint(:ap_id, name: :activities_unique_apid_index) end diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex index df0f72f96..d0e254362 100644 --- a/lib/pleroma/emails/admin_email.ex +++ b/lib/pleroma/emails/admin_email.ex @@ -29,7 +29,7 @@ defmodule Pleroma.Emails.AdminEmail do end statuses_html = - if length(statuses) > 0 do + if is_list(statuses) && length(statuses) > 0 do statuses_list_html = statuses |> Enum.map(fn diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 6a186efbf..5c3156978 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -703,6 +703,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_type(query, _), do: query + defp restrict_state(query, %{"state" => state}) do + from(activity in query, where: fragment("?->>'state' = ?", activity.data, ^state)) + end + + defp restrict_state(query, _), do: query + defp restrict_favorited_by(query, %{"favorited_by" => ap_id}) do from( activity in query, @@ -855,6 +861,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> restrict_local(opts) |> restrict_actor(opts) |> restrict_type(opts) + |> restrict_state(opts) |> restrict_favorited_by(opts) |> restrict_blocked(opts) |> restrict_muted(opts) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 236d1b4ac..ca8a0844b 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -20,6 +20,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do require Logger @supported_object_types ["Article", "Note", "Video", "Page"] + @supported_report_states ~w(open closed resolved) + @valid_visibilities ~w(public unlisted private direct) # Some implementations send the actor URI as the actor field, others send the entire actor object, # so figure out what the actor's URI is based on what we have. @@ -670,7 +672,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do "actor" => params.actor.ap_id, "content" => params.content, "object" => object, - "context" => params.context + "context" => params.context, + "state" => "open" } |> Map.merge(additional) end @@ -713,4 +716,77 @@ defmodule Pleroma.Web.ActivityPub.Utils do end end end + + #### Report-related helpers + + def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do + with new_data <- Map.put(activity.data, "state", state), + changeset <- Changeset.change(activity, data: new_data), + {:ok, activity} <- Repo.update(changeset) do + {:ok, activity} + end + end + + def update_report_state(_, _), do: {:error, "Unsupported state"} + + def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do + [to, cc, recipients] = + activity + |> get_updated_targets(visibility) + |> Enum.map(&Enum.uniq/1) + + object_data = + activity.object.data + |> Map.put("to", to) + |> Map.put("cc", cc) + + {:ok, object} = + activity.object + |> Object.change(%{data: object_data}) + |> Object.update_and_set_cache() + + activity_data = + activity.data + |> Map.put("to", to) + |> Map.put("cc", cc) + + activity + |> Map.put(:object, object) + |> Activity.change(%{data: activity_data, recipients: recipients}) + |> Repo.update() + end + + def update_activity_visibility(_, _), do: {:error, "Unsupported visibility"} + + defp get_updated_targets( + %Activity{data: %{"to" => to} = data, recipients: recipients}, + visibility + ) do + cc = Map.get(data, "cc", []) + follower_address = User.get_cached_by_ap_id(data["actor"]).follower_address + public = "https://www.w3.org/ns/activitystreams#Public" + + case visibility do + "public" -> + to = [public | List.delete(to, follower_address)] + cc = [follower_address | List.delete(cc, public)] + recipients = [public | recipients] + [to, cc, recipients] + + "private" -> + to = [follower_address | List.delete(to, public)] + cc = List.delete(cc, public) + recipients = List.delete(recipients, public) + [to, cc, recipients] + + "unlisted" -> + to = [follower_address | List.delete(to, public)] + cc = [public | List.delete(cc, follower_address)] + recipients = recipients ++ [follower_address, public] + [to, cc, recipients] + + _ -> + [to, cc, recipients] + end + end end diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index e00b33aba..de2a13c01 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -4,11 +4,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do use Pleroma.Web, :controller + alias Pleroma.Activity alias Pleroma.User alias Pleroma.UserInviteToken + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.AdminAPI.AccountView + alias Pleroma.Web.AdminAPI.ReportView alias Pleroma.Web.AdminAPI.Search + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.MastodonAPI.StatusView import Pleroma.Web.ControllerHelper, only: [json_response: 3] @@ -287,12 +292,88 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do |> json(token.token) end + def list_reports(conn, params) do + params = + params + |> Map.put("type", "Flag") + |> Map.put("skip_preload", true) + + reports = + [] + |> ActivityPub.fetch_activities(params) + |> Enum.reverse() + + conn + |> put_view(ReportView) + |> render("index.json", %{reports: reports}) + end + + def report_show(conn, %{"id" => id}) do + with %Activity{} = report <- Activity.get_by_id(id) do + conn + |> put_view(ReportView) + |> render("show.json", %{report: report}) + else + _ -> {:error, :not_found} + end + end + + def report_update_state(conn, %{"id" => id, "state" => state}) do + with {:ok, report} <- CommonAPI.update_report_state(id, state) do + conn + |> put_view(ReportView) + |> render("show.json", %{report: report}) + end + end + + def report_respond(%{assigns: %{user: user}} = conn, %{"id" => id} = params) do + with false <- is_nil(params["status"]), + %Activity{} <- Activity.get_by_id(id) do + params = + params + |> Map.put("in_reply_to_status_id", id) + |> Map.put("visibility", "direct") + + {:ok, activity} = CommonAPI.post(user, params) + + conn + |> put_view(StatusView) + |> render("status.json", %{activity: activity}) + else + true -> + {:param_cast, nil} + + nil -> + {:error, :not_found} + end + end + + def status_update(conn, %{"id" => id} = params) do + with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do + conn + |> put_view(StatusView) + |> render("status.json", %{activity: activity}) + end + end + + def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do + json(conn, %{}) + end + end + def errors(conn, {:error, :not_found}) do conn |> put_status(404) |> json("Not found") end + def errors(conn, {:error, reason}) do + conn + |> put_status(400) + |> json(reason) + end + def errors(conn, {:param_cast, _}) do conn |> put_status(400) diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex new file mode 100644 index 000000000..47a73dc7e --- /dev/null +++ b/lib/pleroma/web/admin_api/views/report_view.ex @@ -0,0 +1,41 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.ReportView do + use Pleroma.Web, :view + alias Pleroma.Activity + alias Pleroma.User + alias Pleroma.Web.CommonAPI.Utils + alias Pleroma.Web.MastodonAPI.AccountView + alias Pleroma.Web.MastodonAPI.StatusView + + def render("index.json", %{reports: reports}) do + %{ + reports: render_many(reports, __MODULE__, "show.json", as: :report) + } + end + + def render("show.json", %{report: report}) do + user = User.get_cached_by_ap_id(report.data["actor"]) + created_at = Utils.to_masto_date(report.data["published"]) + + [account_ap_id | status_ap_ids] = report.data["object"] + account = User.get_cached_by_ap_id(account_ap_id) + + statuses = + Enum.map(status_ap_ids, fn ap_id -> + Activity.get_by_ap_id_with_object(ap_id) + end) + + %{ + id: report.id, + account: AccountView.render("account.json", %{user: account}), + actor: AccountView.render("account.json", %{user: user}), + content: report.data["content"], + created_at: created_at, + statuses: StatusView.render("index.json", %{activities: statuses, as: :activity}), + state: report.data["state"] + } + end +end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 29c4c1014..208c12c7b 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -71,6 +71,9 @@ defmodule Pleroma.Web.CommonAPI do {:ok, _} <- unpin(activity_id, user), {:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} + else + _ -> + {:error, "Could not delete"} end end @@ -315,6 +318,60 @@ defmodule Pleroma.Web.CommonAPI do end end + def update_report_state(activity_id, state) do + with %Activity{} = activity <- Activity.get_by_id(activity_id), + {:ok, activity} <- Utils.update_report_state(activity, state) do + {:ok, activity} + else + nil -> + {:error, :not_found} + + {:error, reason} -> + {:error, reason} + + _ -> + {:error, "Could not update state"} + end + end + + def update_activity_scope(activity_id, opts \\ %{}) do + with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id), + {:ok, activity} <- toggle_sensitive(activity, opts), + {:ok, activity} <- set_visibility(activity, opts) do + {:ok, activity} + else + nil -> + {:error, :not_found} + + {:error, reason} -> + {:error, reason} + end + end + + defp toggle_sensitive(activity, %{"sensitive" => sensitive}) when sensitive in ~w(true false) do + toggle_sensitive(activity, %{"sensitive" => String.to_existing_atom(sensitive)}) + end + + defp toggle_sensitive(%Activity{object: object} = activity, %{"sensitive" => sensitive}) + when is_boolean(sensitive) do + new_data = Map.put(object.data, "sensitive", sensitive) + + {:ok, object} = + object + |> Object.change(%{data: new_data}) + |> Object.update_and_set_cache() + + {:ok, Map.put(activity, :object, object)} + end + + defp toggle_sensitive(activity, _), do: {:ok, activity} + + defp set_visibility(activity, %{"visibility" => visibility}) do + Utils.update_activity_visibility(activity, visibility) + end + + defp set_visibility(activity, _), do: {:ok, activity} + def hide_reblogs(user, muted) do ap_id = muted.ap_id diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 1dfe50b40..bee2fd159 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -237,13 +237,11 @@ defmodule Pleroma.Web.CommonAPI.Utils do "tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq() } - if in_reply_to do - in_reply_to_object = Object.normalize(in_reply_to) - - object - |> Map.put("inReplyTo", in_reply_to_object.data["id"]) + with false <- is_nil(in_reply_to), + %Object{} = in_reply_to_object <- Object.normalize(in_reply_to) do + Map.put(object, "inReplyTo", in_reply_to_object.data["id"]) else - object + _ -> object end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 7fef82f82..6a4e4a1d4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -194,6 +194,14 @@ defmodule Pleroma.Web.Router do get("/users", AdminAPIController, :list_users) get("/users/:nickname", AdminAPIController, :user_show) + + get("/reports", AdminAPIController, :list_reports) + get("/reports/:id", AdminAPIController, :report_show) + put("/reports/:id", AdminAPIController, :report_update_state) + post("/reports/:id/respond", AdminAPIController, :report_respond) + + put("/statuses/:id", AdminAPIController, :status_update) + delete("/statuses/:id", AdminAPIController, :status_delete) end scope "/", Pleroma.Web.TwitterAPI do |