From 53a63e05e49d1266f8f90dd4428fb2889867dc07 Mon Sep 17 00:00:00 2001 From: NEETzsche Date: Tue, 16 Nov 2021 21:26:51 -0700 Subject: [PATCH 1/4] Block notification policy --- .../mrf/block_notification_policy.ex | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex diff --git a/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex new file mode 100644 index 0000000000..21854e8244 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex @@ -0,0 +1,104 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.BlockNotificationPolicy do + @moduledoc "Notify local users upon remote block and unblock." + @behaviour Pleroma.Web.ActivityPub.MRF.Policy + + alias Pleroma.User + alias Pleroma.Web.CommonAPI + alias Pleroma.Config + + require Logger + + defp is_block_or_unblock(%{"type" => "Block", "object" => object}), + do: {true, "blocked", object} + + defp is_block_or_unblock(%{ + "type" => "Undo", + "object" => %{"type" => "Block", "object" => object} + }), + do: {true, "unblocked", object} + + defp is_block_or_unblock(_), do: {false, nil, nil} + + defp is_local(actor, recipient) do + cond do + actor.local -> true + recipient.local -> true + true -> false + end + end + + @impl true + def filter(message) do + + with {true, action, object} <- is_block_or_unblock(message), + %User{} = actor <- User.get_cached_by_ap_id(message["actor"]), + %User{} = recipient <- User.get_cached_by_ap_id(object), + true <- is_local(actor, recipient), + false <- User.blocks_user?(recipient, actor) do + + bot_user = Pleroma.Config.get([:mrf_block_notification_policy, :user]) + + replacements = %{ + "actor" => actor.nickname, + "target" => recipient.nickname, + "action" => action + } + + msg = Regex.replace(~r/{([a-z]+)?}/, Pleroma.Config.get([:mrf_block_notification_policy, :message]), fn _, match -> + replacements[match] + end) + + _reply = + CommonAPI.post(User.get_by_nickname(bot_user), %{ + status: msg, + visibility: Pleroma.Config.get([:mrf_block_notification_policy, :visibility]) + }) + end + + {:ok, message} + end + + @impl true + def describe do + mrf_block_notification_policy = + Config.get(:mrf_block_notification_policy) + + {:ok, %{mrf_block_notification_policy: mrf_block_notification_policy}} + end + + @impl true + def config_description do + %{ + key: :mrf_block_notification_policy, + related_policy: "Pleroma.Web.ActivityPub.MRF.BlockNotificationPolicy", + description: "Notify local users upon remote block.", + children: [ + %{ + key: :message, + type: :string, + label: "Message", + description: "The message to send when someone is blocked or unblocked; use {actor}, {target}, and {action} variables", + suggestions: ["@{actor} {action} @{recipient}"] + }, + %{ + key: :user, + type: :string, + label: "Block User", + description: "The user account that announces a block" + }, + %{ + key: :visibility, + type: :string, + label: "Visibility", + description: "The visibility of block messages", + suggestions: ["public", "unlisted", "private", "direct"] + } + ] + } + end +end + -- GitLab From 37c8b44c725c58a1429f344ffde98bfc93a2c309 Mon Sep 17 00:00:00 2001 From: NEETzsche Date: Tue, 16 Nov 2021 22:01:57 -0700 Subject: [PATCH 2/4] Format BlockNotificationPolicy --- .../mrf/block_notification_policy.ex | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex index 21854e8244..31d72f5237 100644 --- a/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex @@ -25,36 +25,39 @@ defp is_block_or_unblock(_), do: {false, nil, nil} defp is_local(actor, recipient) do cond do - actor.local -> true + actor.local -> true recipient.local -> true - true -> false + true -> false end end @impl true def filter(message) do - with {true, action, object} <- is_block_or_unblock(message), %User{} = actor <- User.get_cached_by_ap_id(message["actor"]), %User{} = recipient <- User.get_cached_by_ap_id(object), true <- is_local(actor, recipient), false <- User.blocks_user?(recipient, actor) do - bot_user = Pleroma.Config.get([:mrf_block_notification_policy, :user]) replacements = %{ - "actor" => actor.nickname, - "target" => recipient.nickname, - "action" => action + "actor" => actor.nickname, + "target" => recipient.nickname, + "action" => action } - msg = Regex.replace(~r/{([a-z]+)?}/, Pleroma.Config.get([:mrf_block_notification_policy, :message]), fn _, match -> - replacements[match] - end) + msg = + Regex.replace( + ~r/{([a-z]+)?}/, + Pleroma.Config.get([:mrf_block_notification_policy, :message]), + fn _, match -> + replacements[match] + end + ) _reply = CommonAPI.post(User.get_by_nickname(bot_user), %{ - status: msg, + status: msg, visibility: Pleroma.Config.get([:mrf_block_notification_policy, :visibility]) }) end @@ -64,8 +67,7 @@ def filter(message) do @impl true def describe do - mrf_block_notification_policy = - Config.get(:mrf_block_notification_policy) + mrf_block_notification_policy = Config.get(:mrf_block_notification_policy) {:ok, %{mrf_block_notification_policy: mrf_block_notification_policy}} end @@ -81,8 +83,9 @@ def config_description do key: :message, type: :string, label: "Message", - description: "The message to send when someone is blocked or unblocked; use {actor}, {target}, and {action} variables", - suggestions: ["@{actor} {action} @{recipient}"] + description: + "The message to send when someone is blocked or unblocked; use {actor}, {target}, and {action} variables", + suggestions: ["@{actor} {action} @{recipient}"] }, %{ key: :user, @@ -95,10 +98,9 @@ def config_description do type: :string, label: "Visibility", description: "The visibility of block messages", - suggestions: ["public", "unlisted", "private", "direct"] + suggestions: ["public", "unlisted", "private", "direct"] } ] } end end - -- GitLab From ec59764b9b754c0a3cb70b13dec4e1b9be940c74 Mon Sep 17 00:00:00 2001 From: NEETzsche Date: Tue, 16 Nov 2021 22:13:26 -0700 Subject: [PATCH 3/4] Alphabetize BlockNotificationPolicy aliases --- lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex index 31d72f5237..99f8aa70ea 100644 --- a/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/block_notification_policy.ex @@ -6,9 +6,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.BlockNotificationPolicy do @moduledoc "Notify local users upon remote block and unblock." @behaviour Pleroma.Web.ActivityPub.MRF.Policy + alias Pleroma.Config alias Pleroma.User alias Pleroma.Web.CommonAPI - alias Pleroma.Config require Logger -- GitLab From e34249525c9c9eaff313b331db3edab308e06d46 Mon Sep 17 00:00:00 2001 From: NEETzsche Date: Mon, 14 Feb 2022 18:06:07 -0700 Subject: [PATCH 4/4] Add tests --- .../mrf/block_notification_policy_test.exs | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 test/pleroma/web/activity_pub/mrf/block_notification_policy_test.exs diff --git a/test/pleroma/web/activity_pub/mrf/block_notification_policy_test.exs b/test/pleroma/web/activity_pub/mrf/block_notification_policy_test.exs new file mode 100644 index 0000000000..c97fdba45f --- /dev/null +++ b/test/pleroma/web/activity_pub/mrf/block_notification_policy_test.exs @@ -0,0 +1,95 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.ActivityPub.MRF.BlockNotificationPolicyTest do + use Pleroma.DataCase, async: true + + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.MRF.BlockNotificationPolicy + + import Pleroma.Factory + + setup do: + clear_config(:mrf_block_notification_policy, + message: "@{actor} {action} @{target}", + user: "beholder", + visibility: "public" + ) + + setup do + %{ + beholder: insert(:user, nickname: "beholder"), + butthurt: insert(:user, nickname: "butthurt"), + sneed: insert(:user, nickname: "sneed") + } + end + + test "creates messages when user blocks other user", %{ + butthurt: butthurt, + sneed: sneed, + beholder: beholder + } do + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 0 + + message = %{ + "type" => "Block", + "object" => sneed.ap_id, + "actor" => butthurt.ap_id + } + + assert {:ok, _object} = BlockNotificationPolicy.filter(message) + + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 1 + + [head | _tail] = activities + + assert head.object.data["source"] == "@butthurt blocked @sneed" + end + + test "creates messages when user unblocks other user", %{ + butthurt: butthurt, + sneed: sneed, + beholder: beholder + } do + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 0 + + message = %{ + "type" => "Undo", + "object" => %{"type" => "Block", "object" => sneed.ap_id}, + "actor" => butthurt.ap_id + } + + assert {:ok, _object} = BlockNotificationPolicy.filter(message) + + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 1 + + [head | _tail] = activities + + assert head.object.data["source"] == "@butthurt unblocked @sneed" + end + + test "creates no message when the action type isn't block or unblock", %{ + butthurt: butthurt, + sneed: sneed, + beholder: beholder + } do + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 0 + + message = %{ + "type" => "Note", + "object" => sneed.ap_id, + "actor" => butthurt.ap_id + } + + assert {:ok, _object} = BlockNotificationPolicy.filter(message) + + activities = ActivityPub.fetch_user_activities(beholder, beholder, %{}) + assert length(activities) == 0 + end +end -- GitLab