Ver código fonte

Merge branch 'feature/mrf-user-filter' into 'develop'

mrf: add support for filtering users

See merge request pleroma/pleroma!1188
tags/v1.1.4
kaniini 5 anos atrás
pai
commit
75e78d4e23
7 arquivos alterados com 133 adições e 9 exclusões
  1. +2
    -0
      CHANGELOG.md
  2. +3
    -1
      config/config.exs
  3. +3
    -0
      docs/config.md
  4. +13
    -3
      lib/pleroma/web/activity_pub/activity_pub.ex
  5. +36
    -2
      lib/pleroma/web/activity_pub/mrf/simple_policy.ex
  6. +4
    -2
      lib/pleroma/web/activity_pub/mrf/user_allowlist.ex
  7. +72
    -1
      test/web/activity_pub/mrf/simple_policy_test.exs

+ 2
- 0
CHANGELOG.md Ver arquivo

@@ -43,6 +43,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Emoji packs and emoji pack manager
- Object pruning (`mix pleroma.database prune_objects`)
- OAuth: added job to clean expired access tokens
- MRF: Support for rejecting reports from specific instances (`mrf_simple`)
- MRF: Support for stripping avatars and banner images from specific instances (`mrf_simple`)

### Changed
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer


+ 3
- 1
config/config.exs Ver arquivo

@@ -314,7 +314,9 @@ config :pleroma, :mrf_simple,
federated_timeline_removal: [],
report_removal: [],
reject: [],
accept: []
accept: [],
avatar_removal: [],
banner_removal: []

config :pleroma, :mrf_keyword,
reject: [],


+ 3
- 0
docs/config.md Ver arquivo

@@ -220,6 +220,9 @@ relates to mascots on the mastodon frontend
* `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline
* `reject`: List of instances to reject any activities from
* `accept`: List of instances to accept any activities from
* `report_removal`: List of instances to reject reports from
* `avatar_removal`: List of instances to strip avatars from
* `banner_removal`: List of instances to strip banners from

## :mrf_rejectnonpublic
* `allow_followersonly`: whether to allow followers-only posts


+ 13
- 3
lib/pleroma/web/activity_pub/activity_pub.ex Ver arquivo

@@ -909,7 +909,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end

def user_data_from_user_object(data) do
defp object_to_user_data(data) do
avatar =
data["icon"]["url"] &&
%{
@@ -956,9 +956,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, user_data}
end

def user_data_from_user_object(data) do
with {:ok, data} <- MRF.filter(data),
{:ok, data} <- object_to_user_data(data) do
{:ok, data}
else
e -> {:error, e}
end
end

def fetch_and_prepare_user_from_ap_id(ap_id) do
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id) do
user_data_from_user_object(data)
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
{:ok, data} <- user_data_from_user_object(data) do
{:ok, data}
else
e -> Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
end


+ 36
- 2
lib/pleroma/web/activity_pub/mrf/simple_policy.ex Ver arquivo

@@ -104,9 +104,29 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do

defp check_report_removal(_actor_info, object), do: {:ok, object}

defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do
if actor_host in Pleroma.Config.get([:mrf_simple, :avatar_removal]) do
{:ok, Map.delete(object, "icon")}
else
{:ok, object}
end
end

defp check_avatar_removal(_actor_info, object), do: {:ok, object}

defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do
if actor_host in Pleroma.Config.get([:mrf_simple, :banner_removal]) do
{:ok, Map.delete(object, "image")}
else
{:ok, object}
end
end

defp check_banner_removal(_actor_info, object), do: {:ok, object}

@impl true
def filter(object) do
actor_info = URI.parse(object["actor"])
def filter(%{"actor" => actor} = object) do
actor_info = URI.parse(actor)

with {:ok, object} <- check_accept(actor_info, object),
{:ok, object} <- check_reject(actor_info, object),
@@ -119,4 +139,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
_e -> {:reject, nil}
end
end

def filter(%{"id" => actor, "type" => obj_type} = object)
when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
actor_info = URI.parse(actor)

with {:ok, object} <- check_avatar_removal(actor_info, object),
{:ok, object} <- check_banner_removal(actor_info, object) do
{:ok, object}
else
_e -> {:reject, nil}
end
end

def filter(object), do: {:ok, object}
end

+ 4
- 2
lib/pleroma/web/activity_pub/mrf/user_allowlist.ex Ver arquivo

@@ -19,10 +19,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
end

@impl true
def filter(object) do
actor_info = URI.parse(object["actor"])
def filter(%{"actor" => actor} = object) do
actor_info = URI.parse(actor)
allow_list = Config.get([:mrf_user_allowlist, String.to_atom(actor_info.host)], [])

filter_by_list(object, allow_list)
end

def filter(object), do: {:ok, object}
end

+ 72
- 1
test/web/activity_pub/mrf/simple_policy_test.exs Ver arquivo

@@ -17,7 +17,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
federated_timeline_removal: [],
report_removal: [],
reject: [],
accept: []
accept: [],
avatar_removal: [],
banner_removal: []
)

on_exit(fn ->
@@ -206,6 +208,60 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
end
end

describe "when :avatar_removal" do
test "is empty" do
Config.put([:mrf_simple, :avatar_removal], [])

remote_user = build_remote_user()

assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
end

test "is not empty but it doesn't have a matching host" do
Config.put([:mrf_simple, :avatar_removal], ["non.matching.remote"])

remote_user = build_remote_user()

assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
end

test "has a matching host" do
Config.put([:mrf_simple, :avatar_removal], ["remote.instance"])

remote_user = build_remote_user()
{:ok, filtered} = SimplePolicy.filter(remote_user)

refute filtered["icon"]
end
end

describe "when :banner_removal" do
test "is empty" do
Config.put([:mrf_simple, :banner_removal], [])

remote_user = build_remote_user()

assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
end

test "is not empty but it doesn't have a matching host" do
Config.put([:mrf_simple, :banner_removal], ["non.matching.remote"])

remote_user = build_remote_user()

assert SimplePolicy.filter(remote_user) == {:ok, remote_user}
end

test "has a matching host" do
Config.put([:mrf_simple, :banner_removal], ["remote.instance"])

remote_user = build_remote_user()
{:ok, filtered} = SimplePolicy.filter(remote_user)

refute filtered["image"]
end
end

defp build_local_message do
%{
"actor" => "#{Pleroma.Web.base_url()}/users/alice",
@@ -217,4 +273,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
defp build_remote_message do
%{"actor" => "https://remote.instance/users/bob"}
end

defp build_remote_user do
%{
"id" => "https://remote.instance/users/bob",
"icon" => %{
"url" => "http://example.com/image.jpg",
"type" => "Image"
},
"image" => %{
"url" => "http://example.com/image.jpg",
"type" => "Image"
},
"type" => "Person"
}
end
end

Carregando…
Cancelar
Salvar