@@ -4,10 +4,13 @@ All notable changes to this project will be documented in this file. | |||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |||
## [unreleased] | |||
### Changed | |||
- MFR policy to set global expiration for all local Create activities | |||
- OGP rich media parser merged with TwitterCard | |||
- Configuration: `rewrite_policy` renamed to `policies` and moved from `instance` to `mrf` group. Old config namespace is deprecated. | |||
- Configuration: `mrf_transparency` renamed to `transparency` and moved from `instance` to `mrf` group. Old config namespace is deprecated. | |||
- Configuration: `mrf_transparency_exclusions` renamed to `transparency_exclusions` and moved from `instance` to `mrf` group. Old config namespace is deprecated. | |||
<details> | |||
<summary>API Changes</summary> | |||
- **Breaking:** Emoji API: changed methods and renamed routes. | |||
@@ -209,7 +209,6 @@ config :pleroma, :instance, | |||
Pleroma.Web.ActivityPub.Publisher | |||
], | |||
allow_relay: true, | |||
rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy, | |||
public: true, | |||
quarantined_instances: [], | |||
managed_config: true, | |||
@@ -220,8 +219,6 @@ config :pleroma, :instance, | |||
"text/markdown", | |||
"text/bbcode" | |||
], | |||
mrf_transparency: true, | |||
mrf_transparency_exclusions: [], | |||
autofollowed_nicknames: [], | |||
max_pinned_statuses: 1, | |||
attachment_links: false, | |||
@@ -685,6 +682,11 @@ config :pleroma, :restrict_unauthenticated, | |||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false | |||
config :pleroma, :mrf, | |||
policies: Pleroma.Web.ActivityPub.MRF.NoOpPolicy, | |||
transparency: true, | |||
transparency_exclusions: [] | |||
# Import environment specific config. This must remain at the bottom | |||
# of this file so it overrides the configuration defined above. | |||
import_config "#{Mix.env()}.exs" |
@@ -690,17 +690,6 @@ config :pleroma, :config_description, [ | |||
description: "Enable Pleroma's Relay, which makes it possible to follow a whole instance" | |||
}, | |||
%{ | |||
key: :rewrite_policy, | |||
type: [:module, {:list, :module}], | |||
description: | |||
"A list of enabled MRF policies. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.", | |||
suggestions: | |||
Generator.list_modules_in_dir( | |||
"lib/pleroma/web/activity_pub/mrf", | |||
"Elixir.Pleroma.Web.ActivityPub.MRF." | |||
) | |||
}, | |||
%{ | |||
key: :public, | |||
type: :boolean, | |||
description: | |||
@@ -743,23 +732,6 @@ config :pleroma, :config_description, [ | |||
] | |||
}, | |||
%{ | |||
key: :mrf_transparency, | |||
label: "MRF transparency", | |||
type: :boolean, | |||
description: | |||
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)" | |||
}, | |||
%{ | |||
key: :mrf_transparency_exclusions, | |||
label: "MRF transparency exclusions", | |||
type: {:list, :string}, | |||
description: | |||
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.", | |||
suggestions: [ | |||
"exclusion.com" | |||
] | |||
}, | |||
%{ | |||
key: :extended_nickname_format, | |||
type: :boolean, | |||
description: | |||
@@ -3325,5 +3297,41 @@ config :pleroma, :config_description, [ | |||
suggestions: [false] | |||
} | |||
] | |||
}, | |||
%{ | |||
group: :pleroma, | |||
key: :mrf, | |||
type: :group, | |||
description: "General MRF settings", | |||
children: [ | |||
%{ | |||
key: :policies, | |||
type: [:module, {:list, :module}], | |||
description: | |||
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.", | |||
suggestions: | |||
Generator.list_modules_in_dir( | |||
"lib/pleroma/web/activity_pub/mrf", | |||
"Elixir.Pleroma.Web.ActivityPub.MRF." | |||
) | |||
}, | |||
%{ | |||
key: :transparency, | |||
label: "MRF transparency", | |||
type: :boolean, | |||
description: | |||
"Make the content of your Message Rewrite Facility settings public (via nodeinfo)" | |||
}, | |||
%{ | |||
key: :transparency_exclusions, | |||
label: "MRF transparency exclusions", | |||
type: {:list, :string}, | |||
description: | |||
"Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.", | |||
suggestions: [ | |||
"exclusion.com" | |||
] | |||
} | |||
] | |||
} | |||
] |
@@ -36,26 +36,10 @@ To add configuration to your config file, you can copy it from the base config. | |||
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes. | |||
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it. | |||
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance. | |||
* `rewrite_policy`: Message Rewrite Policy, either one or a list. Here are the ones available by default: | |||
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default). | |||
* `Pleroma.Web.ActivityPub.MRF.DropPolicy`: Drops all activities. It generally doesn’t makes sense to use in production. | |||
* `Pleroma.Web.ActivityPub.MRF.SimplePolicy`: Restrict the visibility of activities from certain instances (See [`:mrf_simple`](#mrf_simple)). | |||
* `Pleroma.Web.ActivityPub.MRF.TagPolicy`: Applies policies to individual users based on tags, which can be set using pleroma-fe/admin-fe/any other app that supports Pleroma Admin API. For example it allows marking posts from individual users nsfw (sensitive). | |||
* `Pleroma.Web.ActivityPub.MRF.SubchainPolicy`: Selectively runs other MRF policies when messages match (See [`:mrf_subchain`](#mrf_subchain)). | |||
* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic`: Drops posts with non-public visibility settings (See [`:mrf_rejectnonpublic`](#mrf_rejectnonpublic)). | |||
* `Pleroma.Web.ActivityPub.MRF.EnsureRePrepended`: Rewrites posts to ensure that replies to posts with subjects do not have an identical subject and instead begin with re:. | |||
* `Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy`: Rejects posts from likely spambots by rejecting posts from new users that contain links. | |||
* `Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`: Crawls attachments using their MediaProxy URLs so that the MediaProxy cache is primed. | |||
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)). | |||
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)). | |||
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)). | |||
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Adds expiration to all local Create activities (see [`:mrf_activity_expiration`](#mrf_activity_expiration)). | |||
* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. | |||
* `quarantined_instances`: List of ActivityPub instances where private(DMs, followers-only) activities will not be send. | |||
* `managed_config`: Whenether the config for pleroma-fe is configured in [:frontend_configurations](#frontend_configurations) or in ``static/config.json``. | |||
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML). | |||
* `mrf_transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo). | |||
* `mrf_transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value. | |||
* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with | |||
older software for theses nicknames. | |||
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature. | |||
@@ -78,11 +62,30 @@ To add configuration to your config file, you can copy it from the base config. | |||
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users. | |||
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances. | |||
## Message rewrite facility | |||
### :mrf | |||
* `policies`: Message Rewrite Policy, either one or a list. Here are the ones available by default: | |||
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default). | |||
* `Pleroma.Web.ActivityPub.MRF.DropPolicy`: Drops all activities. It generally doesn’t makes sense to use in production. | |||
* `Pleroma.Web.ActivityPub.MRF.SimplePolicy`: Restrict the visibility of activities from certains instances (See [`:mrf_simple`](#mrf_simple)). | |||
* `Pleroma.Web.ActivityPub.MRF.TagPolicy`: Applies policies to individual users based on tags, which can be set using pleroma-fe/admin-fe/any other app that supports Pleroma Admin API. For example it allows marking posts from individual users nsfw (sensitive). | |||
* `Pleroma.Web.ActivityPub.MRF.SubchainPolicy`: Selectively runs other MRF policies when messages match (See [`:mrf_subchain`](#mrf_subchain)). | |||
* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic`: Drops posts with non-public visibility settings (See [`:mrf_rejectnonpublic`](#mrf_rejectnonpublic)). | |||
* `Pleroma.Web.ActivityPub.MRF.EnsureRePrepended`: Rewrites posts to ensure that replies to posts with subjects do not have an identical subject and instead begin with re:. | |||
* `Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy`: Rejects posts from likely spambots by rejecting posts from new users that contain links. | |||
* `Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`: Crawls attachments using their MediaProxy URLs so that the MediaProxy cache is primed. | |||
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)). | |||
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)). | |||
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)). | |||
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo). | |||
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value. | |||
## Federation | |||
### MRF policies | |||
!!! note | |||
Configuring MRF policies is not enough for them to take effect. You have to enable them by specifying their module in `rewrite_policy` under [:instance](#instance) section. | |||
Configuring MRF policies is not enough for them to take effect. You have to enable them by specifying their module in `policies` under [:mrf](#mrf) section. | |||
#### :mrf_simple | |||
* `media_removal`: List of instances to remove media from. | |||
@@ -969,13 +972,13 @@ config :pleroma, :database_config_whitelist, [ | |||
Restrict access for unauthenticated users to timelines (public and federate), user profiles and statuses. | |||
* `timelines` - public and federated timelines | |||
* `local` - public timeline | |||
* `timelines`: public and federated timelines | |||
* `local`: public timeline | |||
* `federated` | |||
* `profiles` - user profiles | |||
* `profiles`: user profiles | |||
* `local` | |||
* `remote` | |||
* `activities` - statuses | |||
* `activities`: statuses | |||
* `local` | |||
* `remote` | |||
@@ -34,9 +34,9 @@ config :pleroma, :instance, | |||
To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this: | |||
```elixir | |||
config :pleroma, :instance, | |||
config :pleroma, :mrf, | |||
[...] | |||
rewrite_policy: Pleroma.Web.ActivityPub.MRF.SimplePolicy | |||
policies: Pleroma.Web.ActivityPub.MRF.SimplePolicy | |||
``` | |||
Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are: | |||
@@ -58,8 +58,8 @@ Servers should be configured as lists. | |||
This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`: | |||
```elixir | |||
config :pleroma, :instance, | |||
rewrite_policy: [Pleroma.Web.ActivityPub.MRF.SimplePolicy] | |||
config :pleroma, :mrf, | |||
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy] | |||
config :pleroma, :mrf_simple, | |||
media_removal: ["illegalporn.biz"], | |||
@@ -75,7 +75,7 @@ The effects of MRF policies can be very drastic. It is important to use this fun | |||
## Writing your own MRF Policy | |||
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `rewrite_policy` config setting. | |||
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `policies` config setting. | |||
For example, here is a sample policy module which rewrites all messages to "new message content": | |||
@@ -125,8 +125,8 @@ end | |||
If you save this file as `lib/pleroma/web/activity_pub/mrf/rewrite_policy.ex`, it will be included when you next rebuild Pleroma. You can enable it in the configuration like so: | |||
```elixir | |||
config :pleroma, :instance, | |||
rewrite_policy: [ | |||
config :pleroma, :mrf, | |||
policies: [ | |||
Pleroma.Web.ActivityPub.MRF.SimplePolicy, | |||
Pleroma.Web.ActivityPub.MRF.RewritePolicy | |||
] | |||
@@ -54,13 +54,13 @@ defmodule Pleroma.ConfigDB do | |||
defp create(params) do | |||
%ConfigDB{} | |||
|> changeset(params) | |||
|> changeset(params, transform?) | |||
|> Repo.insert() | |||
end | |||
defp update(%ConfigDB{} = config, %{value: value}) do | |||
config | |||
|> changeset(%{value: value}) | |||
|> changeset(%{value: value}, transform?) | |||
|> Repo.update() | |||
end | |||
@@ -167,7 +167,9 @@ defmodule Pleroma.ConfigDB do | |||
end) | |||
end | |||
@spec delete(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()} | |||
@spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()} | |||
def delete(%ConfigDB{} = config), do: Repo.delete(config) | |||
def delete(params) do | |||
search_opts = Map.delete(params, :subkeys) | |||
@@ -3,9 +3,23 @@ | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Config.DeprecationWarnings do | |||
alias Pleroma.Config | |||
require Logger | |||
alias Pleroma.Config | |||
@type config_namespace() :: [atom()] | |||
@type config_map() :: {config_namespace(), config_namespace(), String.t()} | |||
@mrf_config_map [ | |||
{[:instance, :rewrite_policy], [:mrf, :policies], | |||
"\n* `config :pleroma, :instance, rewrite_policy` is now `config :pleroma, :mrf, policies`"}, | |||
{[:instance, :mrf_transparency], [:mrf, :transparency], | |||
"\n* `config :pleroma, :instance, mrf_transparency` is now `config :pleroma, :mrf, transparency`"}, | |||
{[:instance, :mrf_transparency_exclusions], [:mrf, :transparency_exclusions], | |||
"\n* `config :pleroma, :instance, mrf_transparency_exclusions` is now `config :pleroma, :mrf, transparency_exclusions`"} | |||
] | |||
def check_hellthread_threshold do | |||
if Config.get([:mrf_hellthread, :threshold]) do | |||
Logger.warn(""" | |||
@@ -39,5 +53,35 @@ defmodule Pleroma.Config.DeprecationWarnings do | |||
def warn do | |||
check_hellthread_threshold() | |||
mrf_user_allowlist() | |||
check_old_mrf_config() | |||
end | |||
def check_old_mrf_config do | |||
warning_preface = """ | |||
!!!DEPRECATION WARNING!!! | |||
Your config is using old namespaces for MRF configuration. They should work for now, but you are advised to change to new namespaces to prevent possible issues later: | |||
""" | |||
move_namespace_and_warn(@mrf_config_map, warning_preface) | |||
end | |||
@spec move_namespace_and_warn([config_map()], String.t()) :: :ok | |||
def move_namespace_and_warn(config_map, warning_preface) do | |||
warning = | |||
Enum.reduce(config_map, "", fn | |||
{old, new, err_msg}, acc -> | |||
old_config = Config.get(old) | |||
if old_config do | |||
Config.put(new, old_config) | |||
acc <> err_msg | |||
else | |||
acc | |||
end | |||
end) | |||
if warning != "" do | |||
Logger.warn(warning_preface <> warning) | |||
end | |||
end | |||
end |
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do | |||
def filter(%{} = object), do: get_policies() |> filter(object) | |||
def get_policies do | |||
Pleroma.Config.get([:instance, :rewrite_policy], []) |> get_policies() | |||
Pleroma.Config.get([:mrf, :policies], []) |> get_policies() | |||
end | |||
defp get_policies(policy) when is_atom(policy), do: [policy] | |||
@@ -51,7 +51,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do | |||
get_policies() | |||
|> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end) | |||
exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions]) | |||
exclusions = Pleroma.Config.get([:mrf, :transparency_exclusions]) | |||
base = | |||
%{ | |||
@@ -3,21 +3,23 @@ | |||
# SPDX-License-Identifier: AGPL-3.0-only | |||
defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.MRF | |||
@moduledoc "Filter activities depending on their origin instance" | |||
@behaviour Pleroma.Web.ActivityPub.MRF | |||
alias Pleroma.Config | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.MRF | |||
require Pleroma.Constants | |||
defp check_accept(%{host: actor_host} = _actor_info, object) do | |||
accepts = | |||
Pleroma.Config.get([:mrf_simple, :accept]) | |||
Config.get([:mrf_simple, :accept]) | |||
|> MRF.subdomains_regex() | |||
cond do | |||
accepts == [] -> {:ok, object} | |||
actor_host == Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object} | |||
actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object} | |||
MRF.subdomain_match?(accepts, actor_host) -> {:ok, object} | |||
true -> {:reject, nil} | |||
end | |||
@@ -25,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
defp check_reject(%{host: actor_host} = _actor_info, object) do | |||
rejects = | |||
Pleroma.Config.get([:mrf_simple, :reject]) | |||
Config.get([:mrf_simple, :reject]) | |||
|> MRF.subdomains_regex() | |||
if MRF.subdomain_match?(rejects, actor_host) do | |||
@@ -41,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
) | |||
when length(child_attachment) > 0 do | |||
media_removal = | |||
Pleroma.Config.get([:mrf_simple, :media_removal]) | |||
Config.get([:mrf_simple, :media_removal]) | |||
|> MRF.subdomains_regex() | |||
object = | |||
@@ -65,7 +67,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
} = object | |||
) do | |||
media_nsfw = | |||
Pleroma.Config.get([:mrf_simple, :media_nsfw]) | |||
Config.get([:mrf_simple, :media_nsfw]) | |||
|> MRF.subdomains_regex() | |||
object = | |||
@@ -85,7 +87,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do | |||
timeline_removal = | |||
Pleroma.Config.get([:mrf_simple, :federated_timeline_removal]) | |||
Config.get([:mrf_simple, :federated_timeline_removal]) | |||
|> MRF.subdomains_regex() | |||
object = | |||
@@ -108,7 +110,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do | |||
report_removal = | |||
Pleroma.Config.get([:mrf_simple, :report_removal]) | |||
Config.get([:mrf_simple, :report_removal]) | |||
|> MRF.subdomains_regex() | |||
if MRF.subdomain_match?(report_removal, actor_host) do | |||
@@ -122,7 +124,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do | |||
avatar_removal = | |||
Pleroma.Config.get([:mrf_simple, :avatar_removal]) | |||
Config.get([:mrf_simple, :avatar_removal]) | |||
|> MRF.subdomains_regex() | |||
if MRF.subdomain_match?(avatar_removal, actor_host) do | |||
@@ -136,7 +138,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do | |||
banner_removal = | |||
Pleroma.Config.get([:mrf_simple, :banner_removal]) | |||
Config.get([:mrf_simple, :banner_removal]) | |||
|> MRF.subdomains_regex() | |||
if MRF.subdomain_match?(banner_removal, actor_host) do | |||
@@ -197,10 +199,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do | |||
@impl true | |||
def describe do | |||
exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions]) | |||
exclusions = Config.get([:mrf, :transparency_exclusions]) | |||
mrf_simple = | |||
Pleroma.Config.get(:mrf_simple) | |||
Config.get(:mrf_simple) | |||
|> Enum.map(fn {k, v} -> {k, Enum.reject(v, fn v -> v in exclusions end)} end) | |||
|> Enum.into(%{}) | |||
@@ -78,7 +78,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do | |||
def federation do | |||
quarantined = Config.get([:instance, :quarantined_instances], []) | |||
if Config.get([:instance, :mrf_transparency]) do | |||
if Config.get([:mrf, :transparency]) do | |||
{:ok, data} = MRF.describe() | |||
data | |||
@@ -0,0 +1,39 @@ | |||
defmodule Pleroma.Repo.Migrations.MrfConfigMoveFromInstanceNamespace do | |||
use Ecto.Migration | |||
alias Pleroma.ConfigDB | |||
@old_keys [:rewrite_policy, :mrf_transparency, :mrf_transparency_exclusions] | |||
def change do | |||
config = ConfigDB.get_by_params(%{group: ":pleroma", key: ":instance"}) | |||
if config do | |||
old_instance = ConfigDB.from_binary(config.value) | |||
mrf = | |||
old_instance | |||
|> Keyword.take(@old_keys) | |||
|> Keyword.new(fn | |||
{:rewrite_policy, policies} -> {:policies, policies} | |||
{:mrf_transparency, transparency} -> {:transparency, transparency} | |||
{:mrf_transparency_exclusions, exclusions} -> {:transparency_exclusions, exclusions} | |||
end) | |||
if mrf != [] do | |||
{:ok, _} = | |||
ConfigDB.create( | |||
%{group: ":pleroma", key: ":mrf", value: ConfigDB.to_binary(mrf)}, | |||
false | |||
) | |||
new_instance = Keyword.drop(old_instance, @old_keys) | |||
if new_instance != [] do | |||
{:ok, _} = ConfigDB.update(config, %{value: ConfigDB.to_binary(new_instance)}, false) | |||
else | |||
{:ok, _} = ConfigDB.delete(config) | |||
end | |||
end | |||
end | |||
end | |||
end |
@@ -0,0 +1,57 @@ | |||
defmodule Pleroma.Config.DeprecationWarningsTest do | |||
use ExUnit.Case, async: true | |||
use Pleroma.Tests.Helpers | |||
import ExUnit.CaptureLog | |||
test "check_old_mrf_config/0" do | |||
clear_config([:instance, :rewrite_policy], Pleroma.Web.ActivityPub.MRF.NoOpPolicy) | |||
clear_config([:instance, :mrf_transparency], true) | |||
clear_config([:instance, :mrf_transparency_exclusions], []) | |||
assert capture_log(fn -> Pleroma.Config.DeprecationWarnings.check_old_mrf_config() end) =~ | |||
""" | |||
!!!DEPRECATION WARNING!!! | |||
Your config is using old namespaces for MRF configuration. They should work for now, but you are advised to change to new namespaces to prevent possible issues later: | |||
* `config :pleroma, :instance, rewrite_policy` is now `config :pleroma, :mrf, policies` | |||
* `config :pleroma, :instance, mrf_transparency` is now `config :pleroma, :mrf, transparency` | |||
* `config :pleroma, :instance, mrf_transparency_exclusions` is now `config :pleroma, :mrf, transparency_exclusions` | |||
""" | |||
end | |||
test "move_namespace_and_warn/2" do | |||
old_group1 = [:group, :key] | |||
old_group2 = [:group, :key2] | |||
old_group3 = [:group, :key3] | |||
new_group1 = [:another_group, :key4] | |||
new_group2 = [:another_group, :key5] | |||
new_group3 = [:another_group, :key6] | |||
clear_config(old_group1, 1) | |||
clear_config(old_group2, 2) | |||
clear_config(old_group3, 3) | |||
clear_config(new_group1) | |||
clear_config(new_group2) | |||
clear_config(new_group3) | |||
config_map = [ | |||
{old_group1, new_group1, "\n error :key"}, | |||
{old_group2, new_group2, "\n error :key2"}, | |||
{old_group3, new_group3, "\n error :key3"} | |||
] | |||
assert capture_log(fn -> | |||
Pleroma.Config.DeprecationWarnings.move_namespace_and_warn( | |||
config_map, | |||
"Warning preface" | |||
) | |||
end) =~ "Warning preface\n error :key\n error :key2\n error :key3" | |||
assert Pleroma.Config.get(new_group1) == 1 | |||
assert Pleroma.Config.get(new_group2) == 2 | |||
assert Pleroma.Config.get(new_group3) == 3 | |||
end | |||
end |
@@ -120,14 +120,11 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do | |||
federation_reachability_timeout_days: 7, | |||
federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher], | |||
allow_relay: true, | |||
rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy, | |||
public: true, | |||
quarantined_instances: [], | |||
managed_config: true, | |||
static_dir: "instance/static/", | |||
allowed_post_formats: ["text/plain", "text/html", "text/markdown", "text/bbcode"], | |||
mrf_transparency: true, | |||
mrf_transparency_exclusions: [], | |||
autofollowed_nicknames: [], | |||
max_pinned_statuses: 1, | |||
attachment_links: false, | |||
@@ -174,7 +171,7 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do | |||
end | |||
assert file == | |||
"#{header}\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n mrf_transparency: true,\n mrf_transparency_exclusions: [],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n welcome_user_nickname: nil,\n welcome_message: nil,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" | |||
"#{header}\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n welcome_user_nickname: nil,\n welcome_message: nil,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" | |||
end | |||
end | |||
end |
@@ -60,8 +60,6 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do | |||
end | |||
describe "describe/0" do | |||
setup do: clear_config([:instance, :rewrite_policy]) | |||
test "it works as expected with noop policy" do | |||
expected = %{ | |||
mrf_policies: ["NoOpPolicy"], | |||
@@ -72,7 +70,7 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do | |||
end | |||
test "it works as expected with mock policy" do | |||
Pleroma.Config.put([:instance, :rewrite_policy], [MRFModuleMock]) | |||
clear_config([:mrf, :policies], [MRFModuleMock]) | |||
expected = %{ | |||
mrf_policies: ["MRFModuleMock"], | |||
@@ -23,7 +23,7 @@ defmodule Pleroma.Web.FederatorTest do | |||
setup_all do: clear_config([:instance, :federating], true) | |||
setup do: clear_config([:instance, :allow_relay]) | |||
setup do: clear_config([:instance, :rewrite_policy]) | |||
setup do: clear_config([:mrf, :policies]) | |||
setup do: clear_config([:mrf_keyword]) | |||
describe "Publish an activity" do | |||
@@ -158,7 +158,7 @@ defmodule Pleroma.Web.FederatorTest do | |||
Pleroma.Config.put([:mrf_keyword, :reject], ["lain"]) | |||
Pleroma.Config.put( | |||
[:instance, :rewrite_policy], | |||
[:mrf, :policies], | |||
Pleroma.Web.ActivityPub.MRF.KeywordPolicy | |||
) | |||
@@ -67,10 +67,10 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
end | |||
test "returns fieldsLimits field", %{conn: conn} do | |||
Config.put([:instance, :max_account_fields], 10) | |||
Config.put([:instance, :max_remote_account_fields], 15) | |||
Config.put([:instance, :account_field_name_length], 255) | |||
Config.put([:instance, :account_field_value_length], 2048) | |||
clear_config([:instance, :max_account_fields], 10) | |||
clear_config([:instance, :max_remote_account_fields], 15) | |||
clear_config([:instance, :account_field_name_length], 255) | |||
clear_config([:instance, :account_field_value_length], 2048) | |||
response = | |||
conn | |||
@@ -84,8 +84,7 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
end | |||
test "it returns the safe_dm_mentions feature if enabled", %{conn: conn} do | |||
option = Config.get([:instance, :safe_dm_mentions]) | |||
Config.put([:instance, :safe_dm_mentions], true) | |||
clear_config([:instance, :safe_dm_mentions], true) | |||
response = | |||
conn | |||
@@ -102,8 +101,6 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
|> json_response(:ok) | |||
refute "safe_dm_mentions" in response["metadata"]["features"] | |||
Config.put([:instance, :safe_dm_mentions], option) | |||
end | |||
describe "`metadata/federation/enabled`" do | |||
@@ -156,14 +153,11 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
end | |||
test "it shows MRF transparency data if enabled", %{conn: conn} do | |||
config = Config.get([:instance, :rewrite_policy]) | |||
Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) | |||
option = Config.get([:instance, :mrf_transparency]) | |||
Config.put([:instance, :mrf_transparency], true) | |||
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) | |||
clear_config([:mrf, :transparency], true) | |||
simple_config = %{"reject" => ["example.com"]} | |||
Config.put(:mrf_simple, simple_config) | |||
clear_config(:mrf_simple, simple_config) | |||
response = | |||
conn | |||
@@ -171,26 +165,17 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
|> json_response(:ok) | |||
assert response["metadata"]["federation"]["mrf_simple"] == simple_config | |||
Config.put([:instance, :rewrite_policy], config) | |||
Config.put([:instance, :mrf_transparency], option) | |||
Config.put(:mrf_simple, %{}) | |||
end | |||
test "it performs exclusions from MRF transparency data if configured", %{conn: conn} do | |||
config = Config.get([:instance, :rewrite_policy]) | |||
Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) | |||
option = Config.get([:instance, :mrf_transparency]) | |||
Config.put([:instance, :mrf_transparency], true) | |||
exclusions = Config.get([:instance, :mrf_transparency_exclusions]) | |||
Config.put([:instance, :mrf_transparency_exclusions], ["other.site"]) | |||
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.SimplePolicy]) | |||
clear_config([:mrf, :transparency], true) | |||
clear_config([:mrf, :transparency_exclusions], ["other.site"]) | |||
simple_config = %{"reject" => ["example.com", "other.site"]} | |||
expected_config = %{"reject" => ["example.com"]} | |||
clear_config(:mrf_simple, simple_config) | |||
Config.put(:mrf_simple, simple_config) | |||
expected_config = %{"reject" => ["example.com"]} | |||
response = | |||
conn | |||
@@ -199,10 +184,5 @@ defmodule Pleroma.Web.NodeInfoTest do | |||
assert response["metadata"]["federation"]["mrf_simple"] == expected_config | |||
assert response["metadata"]["federation"]["exclusions"] == true | |||
Config.put([:instance, :rewrite_policy], config) | |||
Config.put([:instance, :mrf_transparency], option) | |||
Config.put([:instance, :mrf_transparency_exclusions], exclusions) | |||
Config.put(:mrf_simple, %{}) | |||
end | |||
end |