From ed189568f3c2c6fc6ae9ba4d676e95902b3019d1 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Sat, 21 Mar 2020 09:47:05 +0300 Subject: [PATCH] moving mrf settings from instance to separate group --- CHANGELOG.md | 5 +- config/config.exs | 8 ++- config/description.exs | 64 +++++++++++-------- docs/configuration/cheatsheet.md | 45 +++++++------ docs/configuration/mrf.md | 14 ++-- lib/pleroma/config/config_db.ex | 8 ++- lib/pleroma/config/deprecation_warnings.ex | 44 +++++++++++++ lib/pleroma/web/activity_pub/mrf.ex | 4 +- .../web/activity_pub/mrf/simple_policy.ex | 28 ++++---- .../web/mastodon_api/views/instance_view.ex | 2 +- ...rf_config_move_from_instance_namespace.exs | 39 +++++++++++ test/config/deprecation_warnings_test.exs | 57 +++++++++++++++++ test/tasks/config_test.exs | 5 +- test/web/activity_pub/mrf/mrf_test.exs | 4 +- test/web/federator_test.exs | 4 +- test/web/node_info_test.exs | 46 ++++--------- 16 files changed, 256 insertions(+), 121 deletions(-) create mode 100644 priv/repo/migrations/20200323122421_mrf_config_move_from_instance_namespace.exs create mode 100644 test/config/deprecation_warnings_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index d2629bf84..12e8d58e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. +
API Changes - **Breaking:** Emoji API: changed methods and renamed routes. diff --git a/config/config.exs b/config/config.exs index 6a7bb9e06..3d6336a66 100644 --- a/config/config.exs +++ b/config/config.exs @@ -209,7 +209,6 @@ 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 @@ "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, 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" diff --git a/config/description.exs b/config/description.exs index b21d7840c..2ab95e5ab 100644 --- a/config/description.exs +++ b/config/description.exs @@ -689,17 +689,6 @@ type: :boolean, 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, @@ -742,23 +731,6 @@ "text/bbcode" ] }, - %{ - 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, @@ -3325,5 +3297,41 @@ 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" + ] + } + ] } ] diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index fad67fc4d..e9af604e2 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -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` diff --git a/docs/configuration/mrf.md b/docs/configuration/mrf.md index d48d0cc99..31c66e098 100644 --- a/docs/configuration/mrf.md +++ b/docs/configuration/mrf.md @@ -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 ] diff --git a/lib/pleroma/config/config_db.ex b/lib/pleroma/config/config_db.ex index 30bd51b05..c0f3fe888 100644 --- a/lib/pleroma/config/config_db.ex +++ b/lib/pleroma/config/config_db.ex @@ -54,13 +54,13 @@ def changeset(config, params \\ %{}) 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 @@ defp only_full_update?(%ConfigDB{group: group, key: key}) 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) diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex index b68ded01f..0a6c724fb 100644 --- a/lib/pleroma/config/deprecation_warnings.ex +++ b/lib/pleroma/config/deprecation_warnings.ex @@ -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 @@ def mrf_user_allowlist 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 diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex index 5a4a76085..206d6af52 100644 --- a/lib/pleroma/web/activity_pub/mrf.ex +++ b/lib/pleroma/web/activity_pub/mrf.ex @@ -16,7 +16,7 @@ def filter(policies, %{} = object) 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 @@ def describe(policies) 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 = %{ diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex index b7dcb1b86..9cea6bcf9 100644 --- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex @@ -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 @@ defp check_accept(%{host: actor_host} = _actor_info, object) 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 @@ defp check_media_removal( ) 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 @@ defp check_media_nsfw( } = 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 @@ defp check_media_nsfw(_actor_info, object), do: {:ok, object} 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 @@ defp check_ftl_removal(%{host: actor_host} = _actor_info, object) 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 @@ defp check_report_removal(_actor_info, object), do: {:ok, object} 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 @@ defp check_avatar_removal(_actor_info, object), do: {:ok, object} 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 @@ def filter(object), do: {:ok, object} @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(%{}) diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index c498fe632..4f0ae4e8f 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -78,7 +78,7 @@ def features 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 diff --git a/priv/repo/migrations/20200323122421_mrf_config_move_from_instance_namespace.exs b/priv/repo/migrations/20200323122421_mrf_config_move_from_instance_namespace.exs new file mode 100644 index 000000000..6f6094613 --- /dev/null +++ b/priv/repo/migrations/20200323122421_mrf_config_move_from_instance_namespace.exs @@ -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 diff --git a/test/config/deprecation_warnings_test.exs b/test/config/deprecation_warnings_test.exs new file mode 100644 index 000000000..548ee87b0 --- /dev/null +++ b/test/config/deprecation_warnings_test.exs @@ -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 diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs index e1bddfebf..bae171074 100644 --- a/test/tasks/config_test.exs +++ b/test/tasks/config_test.exs @@ -120,14 +120,11 @@ test "load a settings with large values and pass to file", %{temp_file: temp_fil 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 @@ test "load a settings with large values and pass to file", %{temp_file: temp_fil 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 diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs index c941066f2..a63b25423 100644 --- a/test/web/activity_pub/mrf/mrf_test.exs +++ b/test/web/activity_pub/mrf/mrf_test.exs @@ -60,8 +60,6 @@ test "matches are case-insensitive" 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 @@ test "it works as expected with noop policy" 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"], diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index de90aa6e0..592fdccd1 100644 --- a/test/web/federator_test.exs +++ b/test/web/federator_test.exs @@ -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 @@ test "it does not crash if MRF rejects the post" do Pleroma.Config.put([:mrf_keyword, :reject], ["lain"]) Pleroma.Config.put( - [:instance, :rewrite_policy], + [:mrf, :policies], Pleroma.Web.ActivityPub.MRF.KeywordPolicy ) diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index 00925caad..06b33607f 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -67,10 +67,10 @@ test "returns software.repository field in nodeinfo 2.1", %{conn: conn} 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 @@ test "returns fieldsLimits field", %{conn: conn} 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 @@ test "it returns the safe_dm_mentions feature if enabled", %{conn: conn} 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 @@ test "it shows default features flags", %{conn: conn} 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 @@ test "it shows MRF transparency data if enabled", %{conn: conn} 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 @@ test "it performs exclusions from MRF transparency data if configured", %{conn: 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