diff --git a/.woodpecker/docker-armv7.yaml b/.woodpecker/docker-armv7.yaml
deleted file mode 100644
index c921a56f9..000000000
--- a/.woodpecker/docker-armv7.yaml
+++ /dev/null
@@ -1,85 +0,0 @@
-when:
- # Temporary PR validation while arm/v7 Docker builds are being brought up.
- - event: pull_request
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**", "Dockerfile" ]
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**", "Dockerfile" ]
- - event: tag
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: stable
-
-# Target the CAX21 arm64 host with native arm32 userspace support, not generic arm64 runners.
-labels:
- platform: linux/arm
- armv7: native
-
-variables:
- docker_variables: &docker_variables
- repo: pleroma/pleroma
- registry: git.pleroma.social
- armv7_build_settings: &armv7_build_settings
- <<: *docker_variables
- build_args:
- - ELIXIR_IMG=arm32v7/elixir
- - ELIXIR_TAG=1.17.3-otp-26-alpine
- - ALPINE_IMG=arm32v7/alpine
- - ALPINE_VER=3.20
- extra_opts: --custom-platform=linux/arm/v7
- armv7_push_settings: &armv7_push_settings
- <<: *armv7_build_settings
- username:
- from_secret: pleroma-ci-user
- password:
- from_secret: pleroma-ci-password
-
-steps:
- docker-armv7-pr:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - event: pull_request
- settings:
- <<: *armv7_build_settings
- dry_run: true
- tags:
- - armv7-pr-check
-
- docker-develop-armv7:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- settings:
- <<: *armv7_push_settings
- tags:
- - latest-armv7
- - develop-armv7
- - ${CI_COMMIT_SHA:0:8}-armv7
-
- docker-stable-armv7:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - evaluate: 'CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG == ""'
- settings:
- <<: *armv7_push_settings
- tags:
- - latest-armv7
- - stable-armv7
- - ${CI_COMMIT_SHA:0:8}-armv7
-
- docker-stable-tag-armv7:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - event: tag
- - evaluate: 'CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG != ""'
- settings:
- <<: *armv7_push_settings
- tags:
- - latest-armv7
- - stable-armv7
- - ${CI_COMMIT_SHA:0:8}-armv7
- - ${CI_COMMIT_TAG}-armv7
diff --git a/.woodpecker/docker-combine.yaml b/.woodpecker/docker-combine.yaml
index 6c91d26e9..9b9f89fdb 100644
--- a/.woodpecker/docker-combine.yaml
+++ b/.woodpecker/docker-combine.yaml
@@ -27,7 +27,7 @@ steps:
settings: &docker_settings
registry: "git.pleroma.social"
image: "pleroma/pleroma"
- architectures: [amd64, arm64]
+ architectures: [amd64, arm64, armv7]
tags:
- latest
- develop
diff --git a/.woodpecker/docker.yaml b/.woodpecker/docker.yaml
index 9a5be78e2..1bcf1d2ed 100644
--- a/.woodpecker/docker.yaml
+++ b/.woodpecker/docker.yaml
@@ -12,6 +12,7 @@ matrix:
platform:
- linux/amd64
- linux/arm64
+ - linux/arm
# This is needed for the when clauses below.
labels:
@@ -26,11 +27,19 @@ variables:
from_secret: pleroma-ci-user
password:
from_secret: pleroma-ci-password
- kaniko_image: &kaniko_image woodpeckerci/plugin-kaniko:2.3.1
+ armv7_docker_variables: &armv7_docker_variables
+ <<: *docker_variables
+ build_args:
+ - ELIXIR_IMG=docker.io/arm32v7/elixir
+ - ELIXIR_TAG=1.17.3-otp-26-alpine
+ - ALPINE_IMG=docker.io/arm32v7/alpine
+ - ALPINE_VER=3.20
+ extra_opts: --custom-platform=linux/arm/v7
+ kaniko_image: &kaniko_image docker.io/woodpeckerci/plugin-kaniko:2.3.2
steps:
docker-develop-amd64:
- image: woodpeckerci/plugin-kaniko:2.3.1
+ image: *kaniko_image
when:
- evaluate: 'platform == "linux/amd64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
settings:
@@ -41,7 +50,7 @@ steps:
- ${CI_COMMIT_SHA:0:8}-amd64
docker-develop-arm64:
- image: woodpeckerci/plugin-kaniko:2.3.1
+ image: *kaniko_image
when:
- evaluate: 'platform == "linux/arm64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
settings:
@@ -51,6 +60,17 @@ steps:
- develop-arm64
- ${CI_COMMIT_SHA:0:8}-arm64
+ docker-develop-armv7:
+ image: *kaniko_image
+ when:
+ - evaluate: 'platform == "linux/arm" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
+ settings:
+ <<: *armv7_docker_variables
+ tags:
+ - latest-armv7
+ - develop-armv7
+ - ${CI_COMMIT_SHA:0:8}-armv7
+
docker-stable-amd64:
image: *kaniko_image
when:
@@ -106,3 +126,25 @@ steps:
tags:
- <<: *arm64_tags
- ${CI_COMMIT_TAG}-arm64
+
+ docker-stable-armv7:
+ image: *kaniko_image
+ when:
+ - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG == ""'
+ settings:
+ <<: *armv7_docker_variables
+ tags: &armv7_tags
+ - latest-armv7
+ - stable-armv7
+ - ${CI_COMMIT_SHA:0:8}-armv7
+
+ docker-stable-tag-armv7:
+ image: *kaniko_image
+ when:
+ - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
+ - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG != ""'
+ settings:
+ <<: *armv7_docker_variables
+ tags:
+ - <<: *armv7_tags
+ - ${CI_COMMIT_TAG}-armv7
diff --git a/.woodpecker/unit-testing-elixir-1.15.yaml b/.woodpecker/unit-testing-elixir-1.15.yaml
index a5bcc0ef3..0f8eac566 100644
--- a/.woodpecker/unit-testing-elixir-1.15.yaml
+++ b/.woodpecker/unit-testing-elixir-1.15.yaml
@@ -24,10 +24,11 @@ steps:
entrypoint: *script_file_entrypoint
environment:
MIX_ENV: test
+ VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
DB_HOST: postgres
DB_PORT: 5432
commands:
- - apk add --no-cache build-base cmake exiftool ffmpeg file-dev git openssl
+ - apk add --no-cache build-base cmake exiftool ffmpeg vips-dev file-dev git openssl
- adduser -D -h /home/testuser testuser
- mkdir -p /home/testuser/.mix /home/testuser/.hex
- chown -R testuser:testuser . /home/testuser
diff --git a/.woodpecker/unit-testing-elixir-1.18.yaml b/.woodpecker/unit-testing-elixir-1.19.yaml
similarity index 85%
rename from .woodpecker/unit-testing-elixir-1.18.yaml
rename to .woodpecker/unit-testing-elixir-1.19.yaml
index 6e576fad9..60b0826a7 100644
--- a/.woodpecker/unit-testing-elixir-1.18.yaml
+++ b/.woodpecker/unit-testing-elixir-1.19.yaml
@@ -19,15 +19,16 @@ variables:
- 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
steps:
- unit-testing-elixir-1.18:
- image: elixir:1.18-otp-27-alpine
+ unit-testing-elixir-1.19:
+ image: elixir:1.19-otp-28-alpine
entrypoint: *script_file_entrypoint
environment:
MIX_ENV: test
+ VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
DB_HOST: postgres
DB_PORT: 5432
commands:
- - apk add --no-cache build-base cmake exiftool ffmpeg file-dev git openssl
+ - apk add --no-cache build-base cmake exiftool ffmpeg vips-dev file-dev git openssl
- adduser -D -h /home/testuser testuser
- mkdir -p /home/testuser/.mix /home/testuser/.hex
- chown -R testuser:testuser . /home/testuser
diff --git a/Dockerfile b/Dockerfile
index 5fd1cc0a1..87c698f93 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,8 @@
# https://hub.docker.com/r/hexpm/elixir/tags
ARG ELIXIR_IMG=hexpm/elixir
ARG ELIXIR_VER=1.17.3
-ARG ERLANG_VER=26.2.5.6
-ARG ALPINE_VER=3.17.9
+ARG ERLANG_VER=27.3.4.14
+ARG ALPINE_VER=3.23.5
ARG ELIXIR_TAG=${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER}
ARG ALPINE_IMG=alpine
diff --git a/changelog.d/disabling-chats.change b/changelog.d/disabling-chats.change
new file mode 100644
index 000000000..579679a03
--- /dev/null
+++ b/changelog.d/disabling-chats.change
@@ -0,0 +1 @@
+Allow disabling Chats feature
diff --git a/changelog.d/docker-arm32v7-pr-forbid-build.skip b/changelog.d/docker-arm32v7-pr-forbid-build.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/docker-baseimage-ssl.fix b/changelog.d/docker-baseimage-ssl.fix
new file mode 100644
index 000000000..441423f49
--- /dev/null
+++ b/changelog.d/docker-baseimage-ssl.fix
@@ -0,0 +1 @@
+Dockerfile: update base images to fix problems with SSL handshakes
\ No newline at end of file
diff --git a/changelog.d/elixir-1-19.add b/changelog.d/elixir-1-19.add
new file mode 100644
index 000000000..b010b2dfa
--- /dev/null
+++ b/changelog.d/elixir-1-19.add
@@ -0,0 +1 @@
+Implemented ConfigDB configuration blacklist and accompanying Mix task
diff --git a/changelog.d/elixir-1-19.fix b/changelog.d/elixir-1-19.fix
new file mode 100644
index 000000000..53079b0f7
--- /dev/null
+++ b/changelog.d/elixir-1-19.fix
@@ -0,0 +1 @@
+Fixed Elixir 1.19 warnings
diff --git a/changelog.d/fix-preferred-frontend.fix b/changelog.d/fix-preferred-frontend.fix
new file mode 100644
index 000000000..07bf4d0c6
--- /dev/null
+++ b/changelog.d/fix-preferred-frontend.fix
@@ -0,0 +1 @@
+Fix preferred frontend not working due to InstanceStatic plug prematurely returning HTTP 404
diff --git a/changelog.d/hashtag-timeline.fix b/changelog.d/hashtag-timeline.fix
new file mode 100644
index 000000000..c5814d9c9
--- /dev/null
+++ b/changelog.d/hashtag-timeline.fix
@@ -0,0 +1 @@
+Fix hashtag timeline query for additional tag handling
diff --git a/changelog.d/logger-backends.change b/changelog.d/logger-backends.change
new file mode 100644
index 000000000..5f044c2c7
--- /dev/null
+++ b/changelog.d/logger-backends.change
@@ -0,0 +1 @@
+Changed how Logger is configured due to changes in Elixir and added deprecation warnings for the old configuration format
diff --git a/changelog.d/oauth-user-preload.change b/changelog.d/oauth-user-preload.change
new file mode 100644
index 000000000..43f5ea06b
--- /dev/null
+++ b/changelog.d/oauth-user-preload.change
@@ -0,0 +1 @@
+Avoid a duplicate user query during OAuth authentication.
diff --git a/changelog.d/publisher-worker-atoms.fix b/changelog.d/publisher-worker-atoms.fix
new file mode 100644
index 000000000..2df6608ba
--- /dev/null
+++ b/changelog.d/publisher-worker-atoms.fix
@@ -0,0 +1 @@
+Avoid creating atoms from serialized PublisherWorker parameters.
diff --git a/changelog.d/rss.fix b/changelog.d/rss.fix
new file mode 100644
index 000000000..a3455698a
--- /dev/null
+++ b/changelog.d/rss.fix
@@ -0,0 +1 @@
+Fix RSS feeds to be W3C compliant and render better in RSS readers
diff --git a/changelog.d/stream-domain-block-following.fix b/changelog.d/stream-domain-block-following.fix
new file mode 100644
index 000000000..84890c680
--- /dev/null
+++ b/changelog.d/stream-domain-block-following.fix
@@ -0,0 +1 @@
+Keep followed users visible in streams when their domain is blocked.
diff --git a/changelog.d/unit-testing-build-vix.skip b/changelog.d/unit-testing-build-vix.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/user-cache-keys.fix b/changelog.d/user-cache-keys.fix
new file mode 100644
index 000000000..4af21dd1f
--- /dev/null
+++ b/changelog.d/user-cache-keys.fix
@@ -0,0 +1 @@
+Fix inconsistent User cache keys and invalidate numeric ID aliases.
diff --git a/changelog.d/woodpecker-armv7-fixups.fix b/changelog.d/woodpecker-armv7-fixups.fix
new file mode 100644
index 000000000..7bbe7ab3e
--- /dev/null
+++ b/changelog.d/woodpecker-armv7-fixups.fix
@@ -0,0 +1 @@
+Include arm32v7 in multi-arch Docker images
diff --git a/config/config.exs b/config/config.exs
index 3f880af53..f13c12fb9 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -133,13 +133,17 @@ config :pleroma, Pleroma.Web.Endpoint,
]
# Configures Elixir's Logger
-config :logger, backends: [:console]
+# Primary config
+config :logger, level: :debug
-config :logger, :console,
- level: :debug,
+# Console config
+config :logger, :default_handler, level: :debug
+
+config :logger, :default_formatter,
format: "\n$time $metadata[$level] $message\n",
metadata: [:actor, :path, :type, :user]
+# Syslog config
config :logger, :ex_syslogger,
level: :debug,
ident: "pleroma",
@@ -962,6 +966,10 @@ config :pleroma, Pleroma.Search.QdrantSearch,
vectors: %{size: 384, distance: "Cosine"}
}
+config :pleroma, :database_config_blacklist, [
+ {:pleroma, :logger}
+]
+
config :pleroma, :database_config_whitelist, [
{:pleroma},
{:cors_plug},
@@ -971,6 +979,8 @@ config :pleroma, :database_config_whitelist, [
{:web_push_encryption, :vapid_details}
]
+config :pleroma, Pleroma.Chat, enabled: true
+
# 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 7c377588c..1293179b9 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -2726,6 +2726,19 @@ config :pleroma, :config_description, [
}
]
},
+ %{
+ group: :pleroma,
+ key: Pleroma.Chat,
+ type: :group,
+ description: "Pleroma Chat settings",
+ children: [
+ %{
+ key: :enabled,
+ type: :boolean,
+ description: "Enables the chats API."
+ }
+ ]
+ },
%{
group: :pleroma,
key: :http,
diff --git a/config/dev.exs b/config/dev.exs
index 14cf4a6dc..e86bdb7fd 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -36,7 +36,7 @@ config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Local
# different ports.
# Do not include timestamps in development logs
-config :logger, Logger.Backends.Console, format: "$metadata[$level] $message\n"
+config :logger, :default_formatter, format: "$metadata[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
diff --git a/config/prod.exs b/config/prod.exs
index 2d252bf02..1dfbbe937 100644
--- a/config/prod.exs
+++ b/config/prod.exs
@@ -20,8 +20,7 @@ config :pleroma, Pleroma.Web.Endpoint,
config :phoenix, serve_endpoints: true
# Do not print debug messages in production
-config :logger, Logger.Backends.Console, level: :info
-config :logger, :console, level: :info
+config :logger, :default_handler, level: :info
config :logger, :ex_syslogger, level: :info
# ## SSL Support
diff --git a/config/test.exs b/config/test.exs
index 9652b7d4b..ed5283a26 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -15,9 +15,11 @@ config :pleroma, Pleroma.Captcha,
method: Pleroma.Captcha.Mock
# Print only warnings and errors during test
-config :logger, :console,
- level: :warning,
- format: "\n[$level] $message\n"
+config :logger, :default_handler, level: :warning
+
+config :logger, :default_formatter,
+ format: "\n[$level] $message\n",
+ colors: [enabled: false]
config :pleroma, :auth, oauth_consumer_strategies: []
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index 9efa1c8b3..b0a7087a7 100644
--- a/docs/configuration/cheatsheet.md
+++ b/docs/configuration/cheatsheet.md
@@ -858,21 +858,23 @@ Web Push Notifications configuration. You can use the mix task `mix web_push.gen
* ``private_key``: VAPID private key
## :logger
-* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
+* Logging to console/stdout is done by default, use `{ExSyslogger, :ex_syslogger}` to log to syslog
An example to enable ONLY ExSyslogger (f/ex in ``prod.secret.exs``) with info and debug suppressed:
```elixir
-config :logger,
+config :pleroma, :logger,
backends: [{ExSyslogger, :ex_syslogger}]
+config :logger, default_handler: false
+
config :logger, :ex_syslogger,
level: :warning
```
Another example, keeping console output and adding the pid to syslog output:
```elixir
-config :logger,
- backends: [:console, {ExSyslogger, :ex_syslogger}]
+config :pleroma, :logger,
+ backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger,
level: :warning,
@@ -883,23 +885,22 @@ See: [logger’s documentation](https://hexdocs.pm/logger/Logger.html) and [ex_s
An example of logging info to local syslog, but debug to console:
```elixir
-config :logger,
- backends: [ {ExSyslogger, :ex_syslogger}, :console ],
- level: :info
+config :pleroma, :logger,
+ backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger,
level: :info,
ident: "pleroma",
format: "$metadata[$level] $message"
-config :logger, :console,
- level: :debug,
+config :logger, :default_handler,
+ level: :debug
+
+config :logger, :default_formatter,
format: "\n$time $metadata[$level] $message\n",
metadata: [:request_id]
```
-
-
## Database options
### RUM indexing for full text search
diff --git a/docs/installation/generic_dependencies.include b/docs/installation/generic_dependencies.include
index 588a6c019..382f07a6c 100644
--- a/docs/installation/generic_dependencies.include
+++ b/docs/installation/generic_dependencies.include
@@ -1,8 +1,8 @@
## Required dependencies
* PostgreSQL >=11.0
-* Elixir >=1.15.0 <1.19
-* Erlang OTP >=23.0.0 (supported: <28)
+* Elixir >=1.15.0, <1.20
+* Erlang OTP >=24.0.0 (supported: <29)
* git
* file / libmagic
* gcc or clang
diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex
index c5f2e9b0a..a10506236 100644
--- a/lib/mix/tasks/pleroma/config.ex
+++ b/lib/mix/tasks/pleroma/config.ex
@@ -252,40 +252,43 @@ defmodule Mix.Tasks.Pleroma.Config do
if whitelisted_configs in [nil, false] do
shell_error("No unwanted settings in ConfigDB. No changes made.")
else
- whitelisted_groups =
- whitelisted_configs
- |> Enum.filter(fn
- {_group} -> true
- _ -> false
- end)
- |> Enum.map(fn {group} -> group end)
-
- whitelisted_keys =
- whitelisted_configs
- |> Enum.filter(fn
- {_group, _key} -> true
- _ -> false
- end)
+ {whitelisted_groups, whitelisted_keys} = get_filters(whitelisted_configs)
filtered =
from(c in ConfigDB)
|> Repo.all()
|> Enum.filter(¬_whitelisted?(&1, whitelisted_groups, whitelisted_keys))
- if not Enum.empty?(filtered) do
- shell_info("The following settings will be removed from ConfigDB:\n")
- Enum.each(filtered, &dump(&1))
+ do_config_filter(filtered, force)
+ end
+ end
- if force or shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
- filtered_ids = Enum.map(filtered, fn %{id: id} -> id end)
+ # Removes blacklisted configuration sections
+ def run(["filter_blacklisted" | rest]) do
+ {options, [], []} =
+ OptionParser.parse(
+ rest,
+ strict: [force: :boolean],
+ aliases: [f: :force]
+ )
- Repo.delete_all(from(c in ConfigDB, where: c.id in ^filtered_ids))
- else
- shell_error("No changes made.")
- end
- else
- shell_error("No unwanted settings in ConfigDB. No changes made.")
- end
+ force = Keyword.get(options, :force, false)
+
+ start_pleroma()
+
+ blacklisted_configs = Pleroma.Config.get(:database_config_blacklist)
+
+ if blacklisted_configs in [nil, false] do
+ shell_error("No unwanted settings in ConfigDB. No changes made.")
+ else
+ {blacklisted_groups, blacklisted_keys} = get_filters(blacklisted_configs)
+
+ filtered =
+ from(c in ConfigDB)
+ |> Repo.all()
+ |> Enum.filter(&blacklisted?(&1, blacklisted_groups, blacklisted_keys))
+
+ do_config_filter(filtered, force)
end
end
@@ -490,8 +493,49 @@ defmodule Mix.Tasks.Pleroma.Config do
Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
end
+ defp get_filters(config) do
+ groups =
+ config
+ |> Enum.filter(fn
+ {_group} -> true
+ _ -> false
+ end)
+ |> Enum.map(fn {group} -> group end)
+
+ keys =
+ config
+ |> Enum.filter(fn
+ {_group, _key} -> true
+ _ -> false
+ end)
+
+ {groups, keys}
+ end
+
defp not_whitelisted?(%{group: group, key: key}, whitelisted_groups, whitelisted_keys) do
not Enum.member?(whitelisted_groups, group) and
not Enum.member?(whitelisted_keys, {group, key})
end
+
+ defp blacklisted?(%{group: group, key: key}, blacklisted_groups, blacklisted_keys) do
+ Enum.member?(blacklisted_groups, group) or
+ Enum.member?(blacklisted_keys, {group, key})
+ end
+
+ defp do_config_filter(filtered, _) when length(filtered) == 0 do
+ shell_error("No unwanted settings in ConfigDB. No changes made.")
+ end
+
+ defp do_config_filter(filtered, force) do
+ shell_info("The following settings will be removed from ConfigDB:\n")
+ Enum.each(filtered, &dump(&1))
+
+ if force or shell_prompt("Are you sure you want to continue?", "n") in ~w(Yn Y y) do
+ filtered_ids = Enum.map(filtered, fn %{id: id} -> id end)
+
+ Repo.delete_all(from(c in ConfigDB, where: c.id in ^filtered_ids))
+ else
+ shell_error("No changes made.")
+ end
+ end
end
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 8e1c5de0d..78073b430 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -43,6 +43,7 @@ defmodule Pleroma.Application do
# every time the application is restarted, so we disable module
# conflicts at runtime
Code.compiler_options(ignore_module_conflict: true)
+ configure_logger()
Pleroma.Telemetry.Logger.attach()
Config.Holder.save_default()
Pleroma.HTML.compile_scrubbers()
@@ -113,6 +114,44 @@ defmodule Pleroma.Application do
Supervisor.start_link(children, opts)
end
+ def configure_logger do
+ Config.get([:logger, :backends], [])
+ |> Enum.each(fn backend ->
+ case backend_to_logger(backend) do
+ {:ok, logger} ->
+ add_logger(logger)
+
+ {:error, :console_backend} ->
+ Logger.warning(":console is no longer considered a backend and is enabled by default")
+ end
+ end)
+ end
+
+ defp add_logger(backend) do
+ case LoggerBackends.add(backend) do
+ {:ok, _} ->
+ Logger.debug("Successfully added logger backend: #{inspect(backend)}")
+
+ {:error, :already_present} ->
+ :ok
+
+ {:error, reason} ->
+ Logger.error("Failed to add logger backend #{inspect(backend)}: #{inspect(reason)}")
+ end
+ end
+
+ defp backend_to_logger(:console), do: {:error, :console_backend}
+
+ defp backend_to_logger({:ex_syslogger = backend, name}) do
+ Logger.warning(
+ "Configuration {:#{backend}, :#{name}} is incorrect. Use {ExSyslogger, :#{name}} instead!"
+ )
+
+ {:ok, {ExSyslogger, name}}
+ end
+
+ defp backend_to_logger(backend), do: {:ok, backend}
+
def load_custom_modules do
dir = Config.get([:modules, :runtime_dir])
diff --git a/lib/pleroma/chat.ex b/lib/pleroma/chat.ex
index 926176bfa..6ac1b24b8 100644
--- a/lib/pleroma/chat.ex
+++ b/lib/pleroma/chat.ex
@@ -108,4 +108,6 @@ defmodule Pleroma.Chat do
|> cast(%{pinned: false}, [:pinned])
|> Repo.update()
end
+
+ def enabled?, do: Pleroma.Config.get([__MODULE__, :enabled], true)
end
diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex
index 58d164dc7..934a4a02e 100644
--- a/lib/pleroma/config/deprecation_warnings.ex
+++ b/lib/pleroma/config/deprecation_warnings.ex
@@ -20,6 +20,8 @@ defmodule Pleroma.Config.DeprecationWarnings do
"\n* `config :pleroma, :instance, mrf_transparency_exclusions` is now `config :pleroma, :mrf, transparency_exclusions`"}
]
+ @logger_formatter_config_knobs [:colors, :format, :metadata, :truncate, :utc_log]
+
def check_exiftool_filter do
filters = Config.get([Pleroma.Upload]) |> Keyword.get(:filters, [])
@@ -218,7 +220,8 @@ defmodule Pleroma.Config.DeprecationWarnings do
check_quarantined_instances_tuples(),
check_transparency_exclusions_tuples(),
check_simple_policy_tuples(),
- check_exiftool_filter()
+ check_exiftool_filter(),
+ check_deprecated_logger_config()
]
|> Enum.reduce(:ok, fn
:ok, :ok -> :ok
@@ -415,4 +418,72 @@ defmodule Pleroma.Config.DeprecationWarnings do
:ok
end
end
+
+ defp merge_deprecated_logger_config(config) do
+ formatter_config = Enum.filter(config, fn {k, _} -> k in @logger_formatter_config_knobs end)
+ formatter = Logger.default_formatter(formatter_config)
+ log_level = Keyword.get(config, :level, nil)
+
+ Logger.debug("""
+ Reconfiguring console Logger with deprecated configuration syntax.
+ Handler configuration:
+ log_level: #{inspect(log_level)}
+
+ Formatter:
+ #{inspect(formatter)}
+ """)
+
+ if Config.get(:env) != :test do
+ if log_level, do: :logger.update_handler_config(:default, :level, log_level)
+ :logger.set_handler_config(:default, :formatter, formatter)
+ end
+ end
+
+ @spec check_deprecated_logger_config() :: :ok | :error
+ def check_deprecated_logger_config do
+ backends_config = Application.get_env(:logger, :backends)
+ console_config = Application.get_env(:logger, :console)
+
+ # NOTE: No need to merge the old backends config since it still works.
+ # And new configuration will just add new Logger backends.
+ backend =
+ if backends_config do
+ Logger.warning("""
+ !!!DEPRECATION WARNING!!!
+ Your configuration is using deprecated syntax for configuring backends of Elixir's logger.
+ `config :logger, backends: [...]` is deprecated syntax due to changes in Elixir.
+ Please update your configuration at your earliest convenience to use:
+ `config :pleroma, :logger, backends: [...]`
+
+ Note: `:console` is no longer considered a backend and is used by default, you can disable it using:
+ `config :logger, :default_handler: false`
+ """)
+
+ true
+ else
+ false
+ end
+
+ console =
+ if console_config do
+ Logger.warning("""
+ !!!DEPRECATION WARNING!!!
+ Your configuration is using deprecated syntax for configuring logging to console.
+ `config :logger, :console` is deprecated syntax due to changes in Elixir.
+ Please update your configuration at your earliest convenience to use
+ `config :logger, default_handler` and `config :logger, :default_formatter`.
+
+ Note: `:default_handler` is used only for the `level` setting. All other configurations go under
+ `:default_formatter`. For more info visit: https://hexdocs.pm/logger/Logger.html#module-backends-and-backwards-compatibility
+ """)
+
+ merge_deprecated_logger_config(console_config)
+
+ true
+ else
+ false
+ end
+
+ if backend or console, do: :error, else: :ok
+ end
end
diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex
index 140dd7711..3e59dc4e0 100644
--- a/lib/pleroma/config/transfer_task.ex
+++ b/lib/pleroma/config/transfer_task.ex
@@ -51,7 +51,7 @@ defmodule Pleroma.Config.TransferTask do
started_applications = Application.started_applications()
- reject = [nil, :postgrex]
+ reject = [nil, :postgrex, :logger]
reject =
if restart_pleroma? do
diff --git a/lib/pleroma/docs/generator.ex b/lib/pleroma/docs/generator.ex
index 93b19484f..70413837a 100644
--- a/lib/pleroma/docs/generator.ex
+++ b/lib/pleroma/docs/generator.ex
@@ -12,13 +12,27 @@ defmodule Pleroma.Docs.Generator do
@spec list_behaviour_implementations(behaviour :: module()) :: [module()]
def list_behaviour_implementations(behaviour) do
- :code.all_loaded()
- |> Enum.filter(fn {module, _} ->
+ # :code.all_loaded() no longer works on Elixir 1.19 and newer since modules are lazily loaded.
+ # We can get a complete list of modules by interating over Application.loaded_applications/0,
+ # but that includes every module which would get loaded below, which is very slow.
+ # Hardcode the Pleroma application instead, which is good enough for now.
+ application_modules =
+ case :application.get_key(:pleroma, :modules) do
+ {:ok, modules} -> modules
+ :undefined -> []
+ end
+
+ # At compile time or in tests some modules will be outside of the Pleroma application.
+ loaded_modules = Enum.map(:code.all_loaded(), fn {module, _} -> module end)
+
+ (application_modules ++ loaded_modules)
+ |> Enum.uniq()
+ |> Enum.filter(fn module ->
+ Code.ensure_loaded(module)
+
# This shouldn't be needed as all modules are expected to have module_info/1,
# but in test environments some transient modules `:elixir_compiler_XX`
# are loaded for some reason (where XX is a random integer).
- Code.ensure_loaded(module)
-
if function_exported?(module, :module_info, 1) do
module.module_info(:attributes)
|> Keyword.get_values(:behaviour)
@@ -26,7 +40,6 @@ defmodule Pleroma.Docs.Generator do
|> Enum.member?(behaviour)
end
end)
- |> Enum.map(fn {module, _} -> module end)
end
@doc """
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 75da41da9..768a6f3c2 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -272,13 +272,13 @@ defmodule Pleroma.User do
end
def cached_blocked_users_ap_ids(user) do
- @cachex.fetch!(:user_cache, "blocked_users_ap_ids:#{user.ap_id}", fn _ ->
+ @cachex.fetch!(:user_cache, cache_key(:blocked_users_ap_ids, user), fn _ ->
blocked_users_ap_ids(user)
end)
end
def cached_muted_users_ap_ids(user) do
- @cachex.fetch!(:user_cache, "muted_users_ap_ids:#{user.ap_id}", fn _ ->
+ @cachex.fetch!(:user_cache, cache_key(:muted_users_ap_ids, user), fn _ ->
muted_users_ap_ids(user)
end)
end
@@ -1253,13 +1253,18 @@ defmodule Pleroma.User do
get_cached_by_nickname(nickname)
end
+ defp cache_key(:id, %User{id: id}), do: cache_key(:id, id)
+ defp cache_key(:nickname, %User{nickname: nickname}), do: cache_key(:nickname, nickname)
+ defp cache_key(namespace, %User{ap_id: ap_id}), do: cache_key(namespace, ap_id)
+ defp cache_key(namespace, value), do: "#{namespace}:#{value}"
+
def set_cache({:ok, user}), do: set_cache(user)
def set_cache({:error, err}), do: {:error, err}
def set_cache(%User{} = user) do
- @cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
- @cachex.put(:user_cache, "nickname:#{user.nickname}", user)
- @cachex.put(:user_cache, "friends_ap_ids:#{user.nickname}", get_user_friends_ap_ids(user))
+ @cachex.put(:user_cache, cache_key(:ap_id, user), user)
+ @cachex.put(:user_cache, cache_key(:nickname, user), user)
+ @cachex.put(:user_cache, cache_key(:friends_ap_ids, user), get_user_friends_ap_ids(user))
{:ok, user}
end
@@ -1287,22 +1292,23 @@ defmodule Pleroma.User do
@spec get_cached_user_friends_ap_ids(User.t()) :: [String.t()]
def get_cached_user_friends_ap_ids(user) do
- @cachex.fetch!(:user_cache, "friends_ap_ids:#{user.ap_id}", fn _ ->
+ @cachex.fetch!(:user_cache, cache_key(:friends_ap_ids, user), fn _ ->
get_user_friends_ap_ids(user)
end)
end
def invalidate_cache(user) do
- @cachex.del(:user_cache, "ap_id:#{user.ap_id}")
- @cachex.del(:user_cache, "nickname:#{user.nickname}")
- @cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}")
- @cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
- @cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}")
+ @cachex.del(:user_cache, cache_key(:ap_id, user))
+ @cachex.del(:user_cache, cache_key(:nickname, user))
+ @cachex.del(:user_cache, cache_key(:id, user))
+ @cachex.del(:user_cache, cache_key(:friends_ap_ids, user))
+ @cachex.del(:user_cache, cache_key(:blocked_users_ap_ids, user))
+ @cachex.del(:user_cache, cache_key(:muted_users_ap_ids, user))
end
@spec get_cached_by_ap_id(String.t()) :: User.t() | nil
def get_cached_by_ap_id(ap_id) do
- key = "ap_id:#{ap_id}"
+ key = cache_key(:ap_id, ap_id)
with {:ok, nil} <- @cachex.get(:user_cache, key),
user when not is_nil(user) <- get_by_ap_id(ap_id),
@@ -1315,14 +1321,14 @@ defmodule Pleroma.User do
end
def get_cached_by_id(id) do
- key = "id:#{id}"
+ key = cache_key(:id, id)
ap_id =
@cachex.fetch!(:user_cache, key, fn _ ->
user = get_by_id(id)
if user do
- @cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
+ @cachex.put(:user_cache, cache_key(:ap_id, user), user)
{:commit, user.ap_id}
else
{:ignore, ""}
@@ -1333,7 +1339,7 @@ defmodule Pleroma.User do
end
def get_cached_by_nickname(nickname) do
- key = "nickname:#{nickname}"
+ key = cache_key(:nickname, nickname)
@cachex.fetch!(:user_cache, key, fn _ ->
case get_or_fetch_by_nickname(nickname) do
@@ -1651,7 +1657,7 @@ defmodule Pleroma.User do
|> Oban.insert()
end
- @cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
+ @cachex.del(:user_cache, cache_key(:muted_users_ap_ids, muter))
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
end
@@ -1661,7 +1667,7 @@ defmodule Pleroma.User do
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
{:ok, user_notification_mute} <-
UserRelationship.delete_notification_mute(muter, mutee) do
- @cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
+ @cachex.del(:user_cache, cache_key(:muted_users_ap_ids, muter))
{:ok, [user_mute, user_notification_mute]}
end
end
@@ -2815,7 +2821,7 @@ defmodule Pleroma.User do
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
defp add_to_block(%User{} = user, %User{} = blocked, expires_at) do
with {:ok, relationship} <- UserRelationship.create_block(user, blocked, expires_at) do
- @cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
+ @cachex.del(:user_cache, cache_key(:blocked_users_ap_ids, user))
{:ok, relationship}
end
end
@@ -2824,7 +2830,7 @@ defmodule Pleroma.User do
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
defp remove_from_block(%User{} = user, %User{} = blocked) do
with {:ok, relationship} <- UserRelationship.delete_block(user, blocked) do
- @cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
+ @cachex.del(:user_cache, cache_key(:blocked_users_ap_ids, user))
{:ok, relationship}
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 1e8bfe3dd..4efd18d39 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -893,14 +893,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Repo.all()
# Note: NO extra ordering should be done on "activities.id desc nulls last" for optimal plan
- from(
- [_activity, object] in query,
- join: hto in "hashtags_objects",
- on: hto.object_id == object.id,
- where: hto.hashtag_id in ^hashtag_ids,
- distinct: [desc: object.id],
- order_by: [desc: object.id]
- )
+ query =
+ from(
+ [_activity, object] in query,
+ join: hto in "hashtags_objects",
+ on: hto.object_id == object.id,
+ where: hto.hashtag_id in ^hashtag_ids
+ )
+
+ if is_nil(query.distinct) do
+ from([_activity, object] in query,
+ distinct: [desc: object.id],
+ order_by: [desc: object.id]
+ )
+ else
+ query
+ end
end
defp restrict_hashtag_any(query, %{tag: tag}) when is_binary(tag) do
diff --git a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
index 88f6ca028..41abe17c0 100644
--- a/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy do
@moduledoc "Adds expiration to all local Create activities"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(activity) do
activity =
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index 8ea61aec2..990ff31c9 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
+ @moduledoc "Prevent followbots from following with a bit of heuristic"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
alias Pleroma.User
- @moduledoc "Prevent followbots from following with a bit of heuristic"
-
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
# XXX: this should become User.normalize_by_ap_id() or similar, really.
defp normalize_by_ap_id(%{"id" => id}), do: User.get_cached_by_ap_id(id)
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
index 2be6d8df4..5c3b66e37 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
@@ -3,9 +3,11 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
require Logger
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
index 1d76a307b..c6f5781b3 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_mention_spam_policy.ex
@@ -3,11 +3,13 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.User
require Pleroma.Constants
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp user_has_posted?(%User{} = u), do: u.note_count > 0
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index cf07db7f3..4aa1968f7 100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -3,10 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
- require Logger
@moduledoc "Drop and log everything received"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ require Logger
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(activity) do
Logger.debug("REJECTING #{inspect(activity)}")
diff --git a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
index 1de5280d9..cc5fd49bf 100644
--- a/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/emoji_policy.ex
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Pleroma.Constants
alias Pleroma.Object.Updater
@@ -10,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
@moduledoc "Reject or force-unlisted emojis with certain URLs or names"
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp config_remove_url do
Pleroma.Config.get([:mrf_emoji, :remove_url], [])
diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
index f5983c8a7..6e43e746c 100644
--- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
+++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
@@ -3,11 +3,13 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
- alias Pleroma.Object
-
@moduledoc "Ensure a re: is prepended on replies to a post with a Subject"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ alias Pleroma.Object
+
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@reply_prefix Regex.compile!("^re:[[:space:]]*", [:caseless])
def history_awareness, do: :auto
diff --git a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
index 480a03ef6..4612b2cc5 100644
--- a/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/follow_bot_policy.ex
@@ -4,12 +4,15 @@
defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.User
alias Pleroma.Web.CommonAPI
require Logger
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(activity) do
with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]),
diff --git a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
index 3b3251dc3..58d02f433 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_bot_unlisted_policy.ex
@@ -3,9 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
- alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
@moduledoc "Remove bot posts from federated timeline"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ alias Pleroma.User
+
+ use Pleroma.Web.ActivityPub.MRF.Policy
require Pleroma.Constants
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mention.ex b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
index 4ea23540d..62aff36bc 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mention.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mention.ex
@@ -3,13 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
require Pleroma.Constants
alias Pleroma.Config
alias Pleroma.Object
alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp get_author(url) do
with %Object{data: %{"actor" => actor}} <- Object.normalize(url, fetch: false),
diff --git a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
index caae365e5..e7c3f2d88 100644
--- a/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
+++ b/lib/pleroma/web/activity_pub/mrf/force_mentions_in_content.ex
@@ -3,13 +3,15 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Pleroma.Constants
alias Pleroma.Formatter
alias Pleroma.Object
alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
@impl true
def history_awareness, do: :auto
diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
index 72f2274ed..a3fae3bae 100644
--- a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Pleroma.Constants
alias Pleroma.Config
@@ -14,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.
"""
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
@impl true
def history_awareness, do: :manual
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 3a80d0a69..a84a7b0c8 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -3,13 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
+ @moduledoc "Block activities with too much mentions (configurable)"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.User
require Pleroma.Constants
- @moduledoc "Block activities with too much mentions (configurable)"
-
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp delist_activity(activity, threshold) when threshold > 0 do
follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
diff --git a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
index 51dcd3918..17879b4bd 100644
--- a/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/inline_quote_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
@moduledoc "Force a quote line into the message content."
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
defp build_inline_quote(template, url) do
quote_line = String.replace(template, "{url}", "#{url}")
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index 6ba6fd509..33f32e781 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -3,13 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
+ @moduledoc "Reject or Word-Replace activities with a keyword or regex"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Pleroma.Constants
alias Pleroma.Web.ActivityPub.MRF.Utils
- @moduledoc "Reject or Word-Replace activities with a keyword or regex"
-
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp string_matches?(string, pattern) when is_binary(pattern) do
String.contains?(string, pattern)
diff --git a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
index 43c2c0449..07046a666 100644
--- a/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/media_proxy_warming_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
@moduledoc "Preloads any attachments in the MediaProxy cache by prefetching them"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.HTTP
alias Pleroma.Web.MediaProxy
diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
index f7bff121f..8e108a0ae 100644
--- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
@@ -4,9 +4,10 @@
defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
@moduledoc "Block activities which mention a user"
-
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(%{"type" => "Create"} = activity) do
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
diff --git a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
index 08dd39878..8283fd504 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_empty_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
@moduledoc "Filter local activities which have no content"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Web.Endpoint
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
index 64a5872bc..3adbb598a 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_op_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
@moduledoc "Does nothing (lets the messages go through unmodified)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(activity) do
{:ok, activity}
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
index c6f239a5e..2a10c7e97 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
@moduledoc "Ensure no content placeholder is present (such as the dot from mastodon)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def history_awareness, do: :auto
diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
index 91855ef84..de0f5b619 100644
--- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
+++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
@@ -4,9 +4,11 @@
defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
@moduledoc "Scrub configured hypertext markup"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.HTML
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
@impl true
def history_awareness, do: :auto
diff --git a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
index 52aaf05aa..7e3ec3de5 100644
--- a/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/nsfw_api_policy.ex
@@ -38,6 +38,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
- `unlist`: Unlist all detected NSFW content? Default: `false`
- `reject`: Reject all detected NSFW content (takes precedence)? Default: `false`
"""
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.Constants
alias Pleroma.HTTP
@@ -46,7 +48,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
require Logger
require Pleroma.Constants
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@policy :mrf_nsfw_api
def build_request_url(url) do
diff --git a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
index 34905fc21..00f4cf84b 100644
--- a/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/object_age_policy.ex
@@ -3,13 +3,15 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
+ @moduledoc "Filter activities depending on their age"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.User
require Pleroma.Constants
- @moduledoc "Filter activities depending on their age"
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp check_date(%{"object" => %{"published" => published}} = activity) do
with %DateTime{} = now <- DateTime.utc_now(),
diff --git a/lib/pleroma/web/activity_pub/mrf/policy.ex b/lib/pleroma/web/activity_pub/mrf/policy.ex
index 08bcac08a..b9a693c9e 100644
--- a/lib/pleroma/web/activity_pub/mrf/policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/policy.ex
@@ -15,4 +15,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.Policy do
}
@callback history_awareness() :: :auto | :manual
@optional_callbacks config_description: 0, history_awareness: 0, id_filter: 1
+
+ defmacro __using__(_) do
+ quote do
+ # Otherwise Pleroma.Docs.Generator.list_behaviour_implementations fails
+ # since the Elixir compiler doesn't automatically load the module since v1.19.
+ @compile {:autoload, true}
+ end
+ end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
index b3eb0b390..b47e9edb9 100644
--- a/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
+++ b/lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
@@ -6,11 +6,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuietReply do
@moduledoc """
QuietReply alters the scope of activities from local users when replying by enforcing them to be "Unlisted" or "Quiet Public". This delivers the activity to all the expected recipients and instances, but it will not be published in the Federated / The Whole Known Network timelines. It will still be published to the Home timelines of the user's followers and visible to anyone who opens the thread.
"""
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Pleroma.Constants
alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
@impl true
def history_awareness, do: :auto
diff --git a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
index 2a17b6761..e1ad17585 100644
--- a/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/quote_to_link_tag_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
@moduledoc "Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
require Pleroma.Constants
diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
index 9d4a7a405..7d113dbf6 100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
@@ -4,11 +4,12 @@
defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
@moduledoc "Rejects non-public (followers-only, direct) activities"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
alias Pleroma.Config
alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
require Pleroma.Constants
diff --git a/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex b/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
index 8422832dd..f9f8d2298 100644
--- a/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
@@ -2,6 +2,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy do
@moduledoc "Drop remote reports if they don't contain enough information."
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
@impl true
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index a97e8db7b..7045fe90f 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
@moduledoc "Filter activities depending on their origin instance"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.FollowingRelationship
alias Pleroma.User
diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
index 54f0e6bc1..f1e99aead 100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -3,12 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
+ @moduledoc "Detect new emojis by their shortcode and steals them"
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
require Logger
alias Pleroma.Config
- @moduledoc "Detect new emojis by their shortcode and steals them"
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp accept_host?(host), do: host in Config.get([:mrf_steal_emoji, :hosts], [])
diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
index 97acca7e8..1fe7b00e9 100644
--- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
@@ -3,12 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
alias Pleroma.Config
alias Pleroma.Web.ActivityPub.MRF
require Logger
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
defp lookup_subchain(actor) do
with matches <- Config.get([:mrf_subchain, :match_actor]),
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index c236a5a99..df5594808 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -3,8 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
- alias Pleroma.User
- @behaviour Pleroma.Web.ActivityPub.MRF.Policy
@moduledoc """
Apply policies based on user tags
@@ -18,6 +16,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
- `mrf_tag:disable-remote-subscription`: Reject non-local follow requests
- `mrf_tag:disable-any-subscription`: Reject any follow requests
"""
+ @behaviour Pleroma.Web.ActivityPub.MRF.Policy
+
+ alias Pleroma.User
+
+ use Pleroma.Web.ActivityPub.MRF.Policy
require Pleroma.Constants
diff --git a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
index 10cc0e09d..a04ca90bd 100644
--- a/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/user_allow_list_policy.ex
@@ -3,11 +3,13 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
- alias Pleroma.Config
-
@moduledoc "Accept-list of users from specified instances"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ alias Pleroma.Config
+
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
defp filter_by_list(activity, []), do: {:ok, activity}
defp filter_by_list(%{"actor" => actor} = activity, allow_list) do
diff --git a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
index 5671e4cf3..ecba3a2c6 100644
--- a/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
@@ -4,9 +4,10 @@
defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
@moduledoc "Filter activities which belong to certain activity vocabularies"
-
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
+ use Pleroma.Web.ActivityPub.MRF.Policy
+
@impl true
def filter(%{"type" => "Undo", "object" => object} = activity) do
with {:ok, _} <- filter(object) do
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 8847692c8..c273043e1 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
capabilities =
if is_boolean(user.accepts_chat_messages) do
%{
- "acceptsChatMessages" => user.accepts_chat_messages
+ "acceptsChatMessages" => Pleroma.Chat.enabled?() and user.accepts_chat_messages
}
else
%{}
diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex
index 3eba03525..753690d45 100644
--- a/lib/pleroma/web/admin_api/controllers/config_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex
@@ -71,7 +71,10 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
end
def descriptions(conn, _params) do
- descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1)
+ descriptions =
+ Pleroma.Docs.JSON.compiled_descriptions()
+ |> Enum.filter(&allowed_config?(&1, :whitelist))
+ |> Enum.reject(&allowed_config?(&1, :blacklist))
json(conn, translate_descriptions(descriptions))
end
@@ -132,7 +135,8 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
with :ok <- configurable_from_database() do
results =
configs
- |> Enum.filter(&whitelisted_config?/1)
+ |> Enum.filter(&allowed_config?(&1, :whitelist))
+ |> Enum.reject(&allowed_config?(&1, :blacklist))
|> Enum.map(fn
%{group: group, key: key, delete: true} = params ->
ConfigDB.delete(%{group: group, key: key, subkeys: params[:subkeys]})
@@ -174,27 +178,34 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
end
end
- defp whitelisted_config?(":pleroma", ":database_config_whitelist"), do: false
+ defp allowed_config?(":pleroma", ":database_config_whitelist", _), do: true
+ defp allowed_config?(":pleroma", ":database_config_blacklist", _), do: true
- defp whitelisted_config?(group, key) do
- if whitelisted_configs = Config.get(:database_config_whitelist) do
- Enum.any?(whitelisted_configs, fn
- {whitelisted_group} ->
- group == inspect(whitelisted_group)
+ defp allowed_config?(group, key, mode) do
+ configs =
+ case mode do
+ :whitelist -> Config.get(:database_config_whitelist)
+ :blacklist -> Config.get(:database_config_blacklist)
+ end
- {whitelisted_group, whitelisted_key} ->
- group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
+ if configs do
+ Enum.any?(configs, fn
+ {allowed_group} ->
+ group == inspect(allowed_group)
+
+ {allowed_group, allowed_key} ->
+ group == inspect(allowed_group) && key == inspect(allowed_key)
end)
else
true
end
end
- defp whitelisted_config?(%{group: group, key: key}) do
- whitelisted_config?(group, key)
+ defp allowed_config?(%{group: group, key: key}, mode) do
+ allowed_config?(group, key, mode)
end
- defp whitelisted_config?(%{group: group} = config) do
- whitelisted_config?(group, config[:key])
+ defp allowed_config?(%{group: group} = config, mode) do
+ allowed_config?(group, config[:key], mode)
end
end
diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex
index 76c2db57e..7bc39acc6 100644
--- a/lib/pleroma/web/api_spec/operations/chat_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex
@@ -31,7 +31,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"The updated chat",
"application/json",
Chat
- )
+ ),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -56,7 +57,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"The read ChatMessage",
"application/json",
ChatMessage
- )
+ ),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -87,7 +89,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"The existing chat",
"application/json",
Chat
- )
+ ),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -118,7 +121,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"The created or existing chat",
"application/json",
Chat
- )
+ ),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -146,7 +150,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats")
],
responses: %{
- 200 => Operation.response("The chats of the user", "application/json", chats_response())
+ 200 => Operation.response("The chats of the user", "application/json", chats_response()),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -172,7 +177,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
| pagination_params()
],
responses: %{
- 200 => Operation.response("The chats of the user", "application/json", chats_response())
+ 200 => Operation.response("The chats of the user", "application/json", chats_response()),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -224,6 +230,7 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
ChatMessage
),
400 => Operation.response("Bad Request", "application/json", ApiError),
+ 404 => Operation.response("Not Found", "application/json", ApiError),
422 => Operation.response("MRF Rejection", "application/json", ApiError)
},
security: [
@@ -249,7 +256,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
"The deleted ChatMessage",
"application/json",
ChatMessage
- )
+ ),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -268,7 +276,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
],
responses: %{
- 200 => Operation.response("The existing chat", "application/json", Chat)
+ 200 => Operation.response("The existing chat", "application/json", Chat),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
@@ -287,7 +296,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
],
responses: %{
- 200 => Operation.response("The existing chat", "application/json", Chat)
+ 200 => Operation.response("The existing chat", "application/json", Chat),
+ 404 => Operation.response("Not Found", "application/json", ApiError)
},
security: [
%{
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index 07b33f866..8552f5d0a 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -139,6 +139,8 @@ defmodule Pleroma.Web.Endpoint do
from: {:pleroma, "priv/static/adminfe/"}
)
+ plug(Pleroma.Web.Plugs.StaticNotFoundPlug)
+
# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
if code_reloading? do
diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex
index 90cd2e54a..88b267331 100644
--- a/lib/pleroma/web/federator.ex
+++ b/lib/pleroma/web/federator.ex
@@ -89,7 +89,8 @@ defmodule Pleroma.Web.Federator do
# Job Worker Callbacks
- @spec perform(atom(), any()) :: {:ok, any()} | {:error, any()}
+ @impl true
+ @spec perform(atom(), any()) :: :ok | {:ok, any()} | {:error, any()}
def perform(:publish_one, params) do
Publisher.prepare_one(params)
|> Publisher.publish_one()
diff --git a/lib/pleroma/web/federator/publishing.ex b/lib/pleroma/web/federator/publishing.ex
index 3a242b8dc..889b6b83e 100644
--- a/lib/pleroma/web/federator/publishing.ex
+++ b/lib/pleroma/web/federator/publishing.ex
@@ -3,5 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Federator.Publishing do
+ @callback perform(atom(), any()) :: :ok | {:ok, any()} | {:error, any()}
@callback publish(map()) :: any()
end
diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex
index e1ee33d62..b409b1923 100644
--- a/lib/pleroma/web/feed/feed_view.ex
+++ b/lib/pleroma/web/feed/feed_view.ex
@@ -38,6 +38,20 @@ defmodule Pleroma.Web.Feed.FeedView do
end
end
+ def most_recent_update([], :rss), do: nil
+
+ def most_recent_update(activities, :rss) do
+ activities
+ |> Enum.map(fn activity ->
+ case activity.object do
+ %Object{updated_at: updated_at} -> updated_at
+ _ -> activity.updated_at
+ end
+ end)
+ |> Enum.max_by(&NaiveDateTime.to_erl/1)
+ |> to_rfc2822()
+ end
+
def most_recent_update(activities, user, :atom) do
(List.first(activities) || user).updated_at
|> to_rfc3339()
@@ -97,6 +111,67 @@ defmodule Pleroma.Web.Feed.FeedView do
end
end
+ def rss_content_encoded(data) do
+ data
+ |> feed_content_encoded()
+ |> String.replace("]]>", "]]>")
+ end
+
+ def atom_content_encoded(data), do: feed_content_encoded(data)
+
+ defp feed_content_encoded(data) do
+ base_content =
+ case activity_content(data) do
+ "" ->
+ (data["summary"] || data["type"] || "")
+ |> escape()
+
+ content ->
+ content
+ end
+
+ attachments_html =
+ if sensitive?(data) do
+ ""
+ else
+ (data["attachment"] || [])
+ |> Enum.map(&rss_attachment_preview/1)
+ |> Enum.reject(&(&1 == ""))
+ |> Enum.join("
")
+ end
+
+ [base_content, attachments_html]
+ |> Enum.reject(&(&1 == ""))
+ |> Enum.join("
")
+ end
+
+ defp rss_attachment_preview(attachment) do
+ href = attachment_href(attachment)
+
+ if is_binary(href) and href != "" do
+ media_type = attachment_type(attachment) || "application/octet-stream"
+ escaped_href = escape(href)
+ name = attachment["name"] || "Attachment"
+ escaped_name = escape(name)
+
+ cond do
+ String.starts_with?(media_type, "image/") ->
+ ~s(