From 70e4b86250da9ef97a836f497510c36bf22fa905 Mon Sep 17 00:00:00 2001 From: Ilja Date: Fri, 13 Nov 2020 13:35:46 +0000 Subject: [PATCH] Make notifs view work for reports * These are the first small steps for issue 2034 "Reports should send a notification to admins". * I added a new type of notification "pleroma:report" to the the database manually (a migration will need to be written later) * I added the new type to the notification_controller * I made the view return the notification. It doesn't include the report itself (yet) --- CHANGELOG.md | 1 + docs/API/differences_in_mastoapi_responses.md | 20 +++++++- lib/pleroma/notification.ex | 12 ++++- .../operations/notification_operation.ex | 3 ++ .../mastodon_api/views/notification_view.ex | 11 +++++ ...eroma_report_to_enum_for_notifications.exs | 48 +++++++++++++++++++ test/pleroma/notification_test.exs | 13 +++++ .../notification_controller_test.exs | 28 +++++++++++ .../views/notification_view_test.exs | 22 +++++++++ 9 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 priv/repo/migrations/20200831152600_add_pleroma_report_to_enum_for_notifications.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b90ff40..c963972c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Mix task for sending confirmation emails to all unconfirmed users (`mix pleroma.email send_confirmation_mails`) - Mix task option for force-unfollowing relays - Media preview proxy (requires `ffmpeg` and `ImageMagick` to be installed and media proxy to be enabled; see `:media_preview_proxy` config for more details). +- Reports now generate notifications for admins and mods. - Pleroma API: Importing the mutes users from CSV files. - Experimental websocket-based federation between Pleroma instances. - Support pagination of blocks and mutes diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md index 3075b6b86..ba48a2ca1 100644 --- a/docs/API/differences_in_mastoapi_responses.md +++ b/docs/API/differences_in_mastoapi_responses.md @@ -129,12 +129,30 @@ The `type` value is `pleroma:emoji_reaction`. Has these fields: - `account`: The account of the user who reacted - `status`: The status that was reacted on +### ChatMention Notification (not default) + +This notification has to be requested explicitly. + +The `type` value is `pleroma:chat_mention` + +- `account`: The account who sent the message +- `chat_message`: The chat message + +### Report Notification (not default) + +This notification has to be requested explicitly. + +The `type` value is `pleroma:report` + +- `account`: The account who reported +- `report`: The report + ## GET `/api/v1/notifications` Accepts additional parameters: - `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`. -- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`. +- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`, `pleroma:chat_mention`, `pleroma:report`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`. ## DELETE `/api/v1/notifications/destroy_multiple` diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 8868a910e..dd7a1c824 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -70,6 +70,7 @@ def unread_notifications_count(%User{id: user_id}) do move pleroma:chat_mention pleroma:emoji_reaction + pleroma:report reblog } @@ -367,7 +368,7 @@ def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = act end def create_notifications(%Activity{data: %{"type" => type}} = activity, options) - when type in ["Follow", "Like", "Announce", "Move", "EmojiReact"] do + when type in ["Follow", "Like", "Announce", "Move", "EmojiReact", "Flag"] do do_create_notifications(activity, options) end @@ -410,6 +411,9 @@ defp type_from_activity(%{data: %{"type" => type}} = activity) do "EmojiReact" -> "pleroma:emoji_reaction" + "Flag" -> + "pleroma:report" + # Compatibility with old reactions "EmojiReaction" -> "pleroma:emoji_reaction" @@ -467,7 +471,7 @@ def create_notification(%Activity{} = activity, %User{} = user, do_send \\ true) def get_notified_from_activity(activity, local_only \\ true) def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only) - when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do + when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact", "Flag"] do potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity) potential_receivers = @@ -503,6 +507,10 @@ def get_potential_receiver_ap_ids(%{data: %{"type" => "Follow", "object" => obje [object_id] end + def get_potential_receiver_ap_ids(%{data: %{"type" => "Flag"}}) do + User.all_superusers() |> Enum.map(fn user -> user.ap_id end) + end + def get_potential_receiver_ap_ids(activity) do [] |> Utils.maybe_notify_to_recipients(activity) diff --git a/lib/pleroma/web/api_spec/operations/notification_operation.ex b/lib/pleroma/web/api_spec/operations/notification_operation.ex index f09be64cb..264a530d2 100644 --- a/lib/pleroma/web/api_spec/operations/notification_operation.ex +++ b/lib/pleroma/web/api_spec/operations/notification_operation.ex @@ -193,6 +193,7 @@ defp notification_type do "mention", "pleroma:emoji_reaction", "pleroma:chat_mention", + "pleroma:report", "move", "follow_request" ], @@ -206,6 +207,8 @@ defp notification_type do - `poll` - A poll you have voted in or created has ended - `move` - Someone moved their account - `pleroma:emoji_reaction` - Someone reacted with emoji to your status + - `pleroma:chat_mention` - Someone mentioned you in a chat message + - `pleroma:report` - Someone was reported """ } end diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex index c97e6d32f..5b06a6b51 100644 --- a/lib/pleroma/web/mastodon_api/views/notification_view.ex +++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex @@ -11,6 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do alias Pleroma.Object alias Pleroma.User alias Pleroma.UserRelationship + alias Pleroma.Web.AdminAPI.Report + alias Pleroma.Web.AdminAPI.ReportView alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MastodonAPI.NotificationView @@ -118,11 +120,20 @@ def render( "pleroma:chat_mention" -> put_chat_message(response, activity, reading_user, status_render_opts) + "pleroma:report" -> + put_report(response, activity) + type when type in ["follow", "follow_request"] -> response end end + defp put_report(response, activity) do + report_render = ReportView.render("show.json", Report.extract_report_info(activity)) + + Map.put(response, :report, report_render) + end + defp put_emoji(response, activity) do Map.put(response, :emoji, activity.data["content"]) end diff --git a/priv/repo/migrations/20200831152600_add_pleroma_report_to_enum_for_notifications.exs b/priv/repo/migrations/20200831152600_add_pleroma_report_to_enum_for_notifications.exs new file mode 100644 index 000000000..01fb90459 --- /dev/null +++ b/priv/repo/migrations/20200831152600_add_pleroma_report_to_enum_for_notifications.exs @@ -0,0 +1,48 @@ +defmodule Pleroma.Repo.Migrations.AddPleromaReportTypeToEnumForNotifications do + use Ecto.Migration + + @disable_ddl_transaction true + + def up do + """ + alter type notification_type add value 'pleroma:report' + """ + |> execute() + end + + def down do + alter table(:notifications) do + modify(:type, :string) + end + + """ + delete from notifications where type = 'pleroma:report' + """ + |> execute() + + """ + drop type if exists notification_type + """ + |> execute() + + """ + create type notification_type as enum ( + 'follow', + 'follow_request', + 'mention', + 'move', + 'pleroma:emoji_reaction', + 'pleroma:chat_mention', + 'reblog', + 'favourite' + ) + """ + |> execute() + + """ + alter table notifications + alter column type type notification_type using (type::notification_type) + """ + |> execute() + end +end diff --git a/test/pleroma/notification_test.exs b/test/pleroma/notification_test.exs index 92c0bc8b6..ed2cd219d 100644 --- a/test/pleroma/notification_test.exs +++ b/test/pleroma/notification_test.exs @@ -32,6 +32,19 @@ test "never returns nil" do refute {:ok, [nil]} == Notification.create_notifications(activity) end + test "creates a notification for a report" do + reporting_user = insert(:user) + reported_user = insert(:user) + {:ok, moderator_user} = insert(:user) |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.report(reporting_user, %{account_id: reported_user.id}) + + {:ok, [notification]} = Notification.create_notifications(activity) + + assert notification.user_id == moderator_user.id + assert notification.type == "pleroma:report" + end + test "creates a notification for an emoji reaction" do user = insert(:user) other_user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs index 5fd518c60..9ac8488f6 100644 --- a/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs @@ -75,6 +75,34 @@ test "by default, does not contain pleroma:chat_mention" do assert [_] = result end + test "by default, does not contain pleroma:report" do + %{user: user, conn: conn} = oauth_access(["read:notifications"]) + other_user = insert(:user) + third_user = insert(:user) + + user + |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.post(other_user, %{status: "hey"}) + + {:ok, _report} = + CommonAPI.report(third_user, %{account_id: other_user.id, status_ids: [activity.id]}) + + result = + conn + |> get("/api/v1/notifications") + |> json_response_and_validate_schema(200) + + assert [] == result + + result = + conn + |> get("/api/v1/notifications?include_types[]=pleroma:report") + |> json_response_and_validate_schema(200) + + assert [_] = result + end + test "getting a single notification" do %{user: user, conn: conn} = oauth_access(["read:notifications"]) other_user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/views/notification_view_test.exs b/test/pleroma/web/mastodon_api/views/notification_view_test.exs index 2f6a808f1..9de11a87e 100644 --- a/test/pleroma/web/mastodon_api/views/notification_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/notification_view_test.exs @@ -12,6 +12,8 @@ defmodule Pleroma.Web.MastodonAPI.NotificationViewTest do alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.AdminAPI.Report + alias Pleroma.Web.AdminAPI.ReportView alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.AccountView @@ -207,6 +209,26 @@ test "EmojiReact notification" do test_notifications_rendering([notification], user, [expected]) end + test "Report notification" do + reporting_user = insert(:user) + reported_user = insert(:user) + {:ok, moderator_user} = insert(:user) |> User.admin_api_update(%{is_moderator: true}) + + {:ok, activity} = CommonAPI.report(reporting_user, %{account_id: reported_user.id}) + {:ok, [notification]} = Notification.create_notifications(activity) + + expected = %{ + id: to_string(notification.id), + pleroma: %{is_seen: false, is_muted: false}, + type: "pleroma:report", + account: AccountView.render("show.json", %{user: reporting_user, for: moderator_user}), + created_at: Utils.to_masto_date(notification.inserted_at), + report: ReportView.render("show.json", Report.extract_report_info(activity)) + } + + test_notifications_rendering([notification], moderator_user, [expected]) + end + test "muted notification" do user = insert(:user) another_user = insert(:user)