diff --git a/config/config.exs b/config/config.exs
index 317299bf1..6119aaea1 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -164,7 +164,8 @@
max_pinned_statuses: 1,
no_attachment_links: false,
welcome_user_nickname: nil,
- welcome_message: nil
+ welcome_message: nil,
+ max_report_comment_size: 1000
config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because
@@ -340,7 +341,8 @@
config :pleroma, Pleroma.Jobs,
federator_incoming: [max_jobs: 50],
- federator_outgoing: [max_jobs: 50]
+ federator_outgoing: [max_jobs: 50],
+ mailer: [max_jobs: 10]
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
diff --git a/docs/config.md b/docs/config.md
index 6647549a2..14723b727 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -100,6 +100,7 @@ config :pleroma, Pleroma.Mailer,
* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
* `welcome_message`: A message that will be send to a newly registered users as a direct message.
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
+* `max_report_size`: The maximum size of the report comment (Default: `1000`)
## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index cdfe7ea9e..66854dc2d 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -113,4 +113,14 @@ def mastodon_notification_type(%Activity{data: %{"type" => unquote(ap_type)}}),
end
def mastodon_notification_type(%Activity{}), do: nil
+
+ def all_by_actor_and_id(actor, status_ids \\ [])
+ def all_by_actor_and_id(_actor, []), do: []
+
+ def all_by_actor_and_id(actor, status_ids) do
+ Activity
+ |> where([s], s.id in ^status_ids)
+ |> where([s], s.actor == ^actor)
+ |> Repo.all()
+ end
end
diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex
new file mode 100644
index 000000000..9b20c7e08
--- /dev/null
+++ b/lib/pleroma/emails/admin_email.ex
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors
Comment: #{comment}" + else + "" + end + + statuses_html = + if length(statuses) > 0 do + statuses_list_html = + statuses + |> Enum.map(fn %{id: id} -> + status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, id) + "
Statuses: +
Reported by: #{reporter.nickname}
+Reported Account: #{account.nickname}
+ #{comment_html} + #{statuses_html} + """ + + new() + |> to({to.name, to.email}) + |> from({instance_name(), instance_email()}) + |> reply_to({reporter.name, reporter.email}) + |> subject("#{instance_name()} Report") + |> html_body(html_body) + end +end diff --git a/lib/pleroma/emails/mailer.ex b/lib/pleroma/emails/mailer.ex index 8d12641f2..f7e3aa78b 100644 --- a/lib/pleroma/emails/mailer.ex +++ b/lib/pleroma/emails/mailer.ex @@ -4,4 +4,10 @@ defmodule Pleroma.Mailer do use Swoosh.Mailer, otp_app: :pleroma + + def deliver_async(email, config \\ []) do + Pleroma.Jobs.enqueue(:mailer, __MODULE__, [:deliver_async, email, config]) + end + + def perform(:deliver_async, email, config), do: deliver(email, config) end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 35ba4ad99..c98b942ff 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -273,7 +273,7 @@ def try_send_confirmation_email(%User{} = user) do Pleroma.Config.get([:instance, :account_activation_required]) do user |> Pleroma.UserEmail.account_confirmation_email() - |> Pleroma.Mailer.deliver() + |> Pleroma.Mailer.deliver_async() else {:ok, :noop} end @@ -1284,4 +1284,13 @@ def error_user(ap_id) do inserted_at: NaiveDateTime.utc_now() } end + + def all_superusers do + from( + u in User, + where: u.local == true, + where: fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info) + ) + |> Repo.all() + end end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index cb8a2139e..d1ac8172e 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -353,6 +353,31 @@ def unblock(blocker, blocked, activity_id \\ nil, local \\ true) do end end + def flag( + %{ + actor: actor, + context: context, + account: account, + statuses: statuses, + content: content + } = params + ) do + additional = params[:additional] || %{} + + # only accept false as false value + local = !(params[:local] == false) + + %{ + actor: actor, + context: context, + account: account, + statuses: statuses, + content: content + } + |> make_flag_data(additional) + |> insert(local) + end + def fetch_activities_for_context(context, opts \\ %{}) do public = ["https://www.w3.org/ns/activitystreams#Public"] diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6a89374d0..88f4779c8 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -598,4 +598,20 @@ def make_create_data(params, additional) do } |> Map.merge(additional) end + + #### Flag-related helpers + + def make_flag_data(params, additional) do + status_ap_ids = Enum.map(params.statuses || [], & &1.data["id"]) + object = [params.account.ap_id] ++ status_ap_ids + + %{ + "type" => "Flag", + "actor" => params.actor.ap_id, + "content" => params.content, + "object" => object, + "context" => params.context + } + |> Map.merge(additional) + end end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 90b208e54..e788337cc 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -243,4 +243,31 @@ def thread_muted?(user, activity) do _ -> true end end + + def report(user, data) do + with {:account_id, %{"account_id" => account_id}} <- {:account_id, data}, + {:account, %User{} = account} <- {:account, User.get_by_id(account_id)}, + {:ok, content_html} <- make_report_content_html(data["comment"]), + {:ok, statuses} <- get_report_statuses(account, data), + {:ok, activity} <- + ActivityPub.flag(%{ + context: Utils.generate_context_id(), + actor: user, + account: account, + statuses: statuses, + content: content_html + }) do + Enum.each(User.all_superusers(), fn superuser -> + superuser + |> Pleroma.AdminEmail.report(user, account, statuses, content_html) + |> Pleroma.Mailer.deliver_async() + end) + + {:ok, activity} + else + {:error, err} -> {:error, err} + {:account_id, %{}} -> {:error, "Valid `account_id` required"} + {:account, nil} -> {:error, "Account not found"} + end + end end diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index abdeee947..1d3a314ce 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -322,4 +322,22 @@ def maybe_extract_mentions(%{"tag" => tag}) do end def maybe_extract_mentions(_), do: [] + + def make_report_content_html(nil), do: {:ok, nil} + + def make_report_content_html(comment) do + max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000) + + if String.length(comment) <= max_size do + {:ok, format_input(comment, [], [], "text/plain")} + else + {:error, "Comment must be up to #{max_size} characters"} + end + end + + def get_report_statuses(%User{ap_id: actor}, %{"status_ids" => status_ids}) do + {:ok, Activity.all_by_actor_and_id(actor, status_ids)} + end + + def get_report_statuses(_, _), do: {:ok, nil} end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 17b95eb44..60738301b 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -24,6 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Web.MastodonAPI.MastodonView alias Pleroma.Web.MastodonAPI.PushSubscriptionView alias Pleroma.Web.MastodonAPI.StatusView + alias Pleroma.Web.MastodonAPI.ReportView alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.OAuth.App @@ -1533,6 +1534,20 @@ def status_card(conn, %{"id" => status_id}) do end end + def reports(%{assigns: %{user: user}} = conn, params) do + case CommonAPI.report(user, params) do + {:ok, activity} -> + conn + |> put_view(ReportView) + |> try_render("report.json", %{activity: activity}) + + {:error, err} -> + conn + |> put_status(:bad_request) + |> json(%{error: err}) + end + end + def try_render(conn, target, params) when is_binary(target) do res = render(conn, target, params) diff --git a/lib/pleroma/web/mastodon_api/views/report_view.ex b/lib/pleroma/web/mastodon_api/views/report_view.ex new file mode 100644 index 000000000..a16e7ff10 --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/report_view.ex @@ -0,0 +1,14 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors