diff --git a/.woodpecker.yml b/.woodpecker.yml
deleted file mode 100644
index 49718d630..000000000
--- a/.woodpecker.yml
+++ /dev/null
@@ -1,197 +0,0 @@
-variables:
- - &scw-secrets
- - SCW_ACCESS_KEY
- - SCW_SECRET_KEY
- - SCW_DEFAULT_ORGANIZATION_ID
- - &setup-hex "mix local.hex --force && mix local.rebar --force"
- - &on-release
- when:
- event:
- - push
- - tag
- branch:
- - develop
- - stable
- - refs/tags/v*
- - refs/tags/stable-*
- - &on-stable
- when:
- event:
- - push
- - tag
- branch:
- - stable
- - refs/tags/stable-*
- - &on-point-release
- when:
- event:
- - push
- branch:
- - develop
- - stable
- - &on-pr-open
- when:
- event:
- - pull_request
-
- - &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
-
- - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- - &mix-clean "mix deps.clean --all && mix clean"
-
-services:
- postgres:
- image: postgres:15
- when:
- event:
- - pull_request
- environment:
- POSTGRES_DB: pleroma_test
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
-
-pipeline:
- lint:
- <<: *on-pr-open
- image: akkoma/ci-base:1.14
- commands:
- - mix local.hex --force
- - mix local.rebar --force
- - mix format --check-formatted
-
- build:
- image: akkoma/ci-base:1.14
- <<: *on-pr-open
- environment:
- MIX_ENV: test
- POSTGRES_DB: pleroma_test
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- DB_HOST: postgres
- commands:
- - mix local.hex --force
- - mix local.rebar --force
- - mix deps.get
- - mix compile
-
- test:
- image: akkoma/ci-base:1.14
- <<: *on-pr-open
- environment:
- MIX_ENV: test
- POSTGRES_DB: pleroma_test
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: postgres
- DB_HOST: postgres
- commands:
- - mix local.hex --force
- - mix local.rebar --force
- - mix deps.get
- - mix compile
- - mix ecto.drop -f -q
- - mix ecto.create
- - mix ecto.migrate
- - mix test --preload-modules --exclude erratic --exclude federated --max-cases 4
-
- # Canonical amd64
- ubuntu22:
- image: hexpm/elixir:1.14.3-erlang-25.2.2-ubuntu-jammy-20221130
- <<: *on-release
- environment:
- MIX_ENV: prod
- DEBIAN_FRONTEND: noninteractive
- commands:
- - apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
- - *clean
- - echo "import Config" > config/prod.secret.exs
- - *setup-hex
- - *tag-build
- - mix deps.get --only prod
- - mix release --path release
- - zip akkoma-ubuntu-jammy.zip -r release
-
- release-ubuntu22:
- image: akkoma/releaser
- <<: *on-release
- secrets: *scw-secrets
- commands:
- - export SOURCE=akkoma-ubuntu-jammy.zip
- - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-ubuntu-jammy.zip
- - /bin/sh /entrypoint.sh
- - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-ubuntu-jammy.zip
- - /bin/sh /entrypoint.sh
-
- debian-bullseye:
- image: hexpm/elixir:1.14.3-erlang-25.2.2-debian-bullseye-20230109
- <<: *on-release
- environment:
- MIX_ENV: prod
- DEBIAN_FRONTEND: noninteractive
- commands:
- - apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential gcc make g++ wget
- - *clean
- - echo "import Config" > config/prod.secret.exs
- - *setup-hex
- - *tag-build
- - *mix-clean
- - mix deps.get --only prod
- - mix release --path release
- - zip akkoma-amd64.zip -r release
-
- release-debian:
- image: akkoma/releaser
- <<: *on-release
- secrets: *scw-secrets
- commands:
- - export SOURCE=akkoma-amd64.zip
- - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
- - /bin/sh /entrypoint.sh
- - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-debian-stable.zip
- - /bin/sh /entrypoint.sh
-
- # Canonical amd64-musl
- musl:
- image: hexpm/elixir:1.14.3-erlang-25.2.2-alpine-3.15.6
- <<: *on-release
- environment:
- MIX_ENV: prod
- commands:
- - apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
- - *clean
- - *setup-hex
- - *mix-clean
- - *tag-build
- - mix deps.get --only prod
- - mix release --path release
- - zip akkoma-amd64-musl.zip -r release
-
- release-musl:
- image: akkoma/releaser
- <<: *on-release
- secrets: *scw-secrets
- commands:
- - export SOURCE=akkoma-amd64-musl.zip
- - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip
- - /bin/sh /entrypoint.sh
-
- docs:
- <<: *on-point-release
- secrets:
- - SCW_ACCESS_KEY
- - SCW_SECRET_KEY
- - SCW_DEFAULT_ORGANIZATION_ID
- environment:
- CI: "true"
- image: python:3.10-slim
- commands:
- - apt-get update && apt-get install -y rclone wget git zip
- - wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- - mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- - chmod +x scaleway-cli
- - ./scaleway-cli object config install type=rclone
- - cd docs
- - pip install -r requirements.txt
- - mkdocs build
- - zip -r docs.zip site/*
- - cd site
- - rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/
diff --git a/.woodpecker/build-amd64.yml b/.woodpecker/build-amd64.yml
new file mode 100644
index 000000000..61a37cd44
--- /dev/null
+++ b/.woodpecker/build-amd64.yml
@@ -0,0 +1,91 @@
+platform: linux/amd64
+
+depends_on:
+ - test
+
+variables:
+ - &scw-secrets
+ - SCW_ACCESS_KEY
+ - SCW_SECRET_KEY
+ - SCW_DEFAULT_ORGANIZATION_ID
+ - &setup-hex "mix local.hex --force && mix local.rebar --force"
+ - &on-release
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - develop
+ - stable
+ - &on-stable
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - stable
+ - &on-pr-open
+ when:
+ event:
+ - pull_request
+
+ - &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
+
+ - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
+ - &mix-clean "mix deps.clean --all && mix clean"
+
+pipeline:
+ # Canonical amd64
+ debian-bookworm:
+ image: hexpm/elixir:1.15.4-erlang-25.3.2.5-debian-bookworm-20230612
+ <<: *on-release
+ environment:
+ MIX_ENV: prod
+ DEBIAN_FRONTEND: noninteractive
+ commands:
+ - apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
+ - *clean
+ - echo "import Config" > config/prod.secret.exs
+ - *setup-hex
+ - *tag-build
+ - mix deps.get --only prod
+ - mix release --path release
+ - zip akkoma-amd64.zip -r release
+
+ release-debian-bookworm:
+ image: akkoma/releaser
+ <<: *on-release
+ secrets: *scw-secrets
+ commands:
+ - export SOURCE=akkoma-amd64.zip
+ # AMD64
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
+ - /bin/sh /entrypoint.sh
+ # Ubuntu jammy (currently compatible)
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-ubuntu-jammy.zip
+ - /bin/sh /entrypoint.sh
+
+ # Canonical amd64-musl
+ musl:
+ image: hexpm/elixir:1.14.3-erlang-25.2.2-alpine-3.18.0
+ <<: *on-stable
+ environment:
+ MIX_ENV: prod
+ commands:
+ - apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
+ - *clean
+ - *setup-hex
+ - *mix-clean
+ - *tag-build
+ - mix deps.get --only prod
+ - mix release --path release
+ - zip akkoma-amd64-musl.zip -r release
+
+ release-musl:
+ image: akkoma/releaser
+ <<: *on-stable
+ secrets: *scw-secrets
+ commands:
+ - export SOURCE=akkoma-amd64-musl.zip
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip
+ - /bin/sh /entrypoint.sh
diff --git a/.woodpecker/build-arm64.yml b/.woodpecker/build-arm64.yml
new file mode 100644
index 000000000..d923e5847
--- /dev/null
+++ b/.woodpecker/build-arm64.yml
@@ -0,0 +1,89 @@
+platform: linux/arm64
+
+depends_on:
+ - test
+
+variables:
+ - &scw-secrets
+ - SCW_ACCESS_KEY
+ - SCW_SECRET_KEY
+ - SCW_DEFAULT_ORGANIZATION_ID
+ - &setup-hex "mix local.hex --force && mix local.rebar --force"
+ - &on-release
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - stable
+ - develop
+ - &on-stable
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - stable
+ - &on-pr-open
+ when:
+ event:
+ - pull_request
+
+ - &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
+
+ - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
+ - &mix-clean "mix deps.clean --all && mix clean"
+
+pipeline:
+ # Canonical arm64
+ debian-bookworm:
+ image: hexpm/elixir:1.15.4-erlang-25.3.2.5-debian-bookworm-20230612
+ <<: *on-release
+ environment:
+ MIX_ENV: prod
+ DEBIAN_FRONTEND: noninteractive
+ commands:
+ - apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
+ - *clean
+ - echo "import Config" > config/prod.secret.exs
+ - *setup-hex
+ - *tag-build
+ - mix deps.get --only prod
+ - mix release --path release
+ - zip akkoma-arm64.zip -r release
+
+ release-debian-bookworm:
+ image: akkoma/releaser:arm64
+ <<: *on-release
+ secrets: *scw-secrets
+ commands:
+ - export SOURCE=akkoma-arm64.zip
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64-ubuntu-jammy.zip
+ - /bin/sh /entrypoint.sh
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64.zip
+ - /bin/sh /entrypoint.sh
+
+ # Canonical arm64-musl
+ musl:
+ image: hexpm/elixir:1.15.4-erlang-25.3.2.5-alpine-3.18.2
+ <<: *on-stable
+ environment:
+ MIX_ENV: prod
+ commands:
+ - apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
+ - *clean
+ - *setup-hex
+ - *mix-clean
+ - *tag-build
+ - mix deps.get --only prod
+ - mix release --path release
+ - zip akkoma-arm64-musl.zip -r release
+
+ release-musl:
+ image: akkoma/releaser:arm64
+ <<: *on-stable
+ secrets: *scw-secrets
+ commands:
+ - export SOURCE=akkoma-arm64-musl.zip
+ - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64-musl.zip
+ - /bin/sh /entrypoint.sh
diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml
new file mode 100644
index 000000000..cc4017659
--- /dev/null
+++ b/.woodpecker/docs.yml
@@ -0,0 +1,69 @@
+platform: linux/amd64
+
+depends_on:
+ - test
+ - build-amd64
+
+variables:
+ - &scw-secrets
+ - SCW_ACCESS_KEY
+ - SCW_SECRET_KEY
+ - SCW_DEFAULT_ORGANIZATION_ID
+ - &setup-hex "mix local.hex --force && mix local.rebar --force"
+ - &on-release
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - develop
+ - stable
+ - refs/tags/v*
+ - refs/tags/stable-*
+ - &on-stable
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - stable
+ - refs/tags/stable-*
+ - &on-point-release
+ when:
+ event:
+ - push
+ branch:
+ - develop
+ - stable
+ - &on-pr-open
+ when:
+ event:
+ - pull_request
+
+ - &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
+
+ - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
+ - &mix-clean "mix deps.clean --all && mix clean"
+
+pipeline:
+ docs:
+ <<: *on-point-release
+ secrets:
+ - SCW_ACCESS_KEY
+ - SCW_SECRET_KEY
+ - SCW_DEFAULT_ORGANIZATION_ID
+ environment:
+ CI: "true"
+ image: python:3.10-slim
+ commands:
+ - apt-get update && apt-get install -y rclone wget git zip
+ - wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
+ - mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
+ - chmod +x scaleway-cli
+ - ./scaleway-cli object config install type=rclone
+ - cd docs
+ - pip install -r requirements.txt
+ - mkdocs build
+ - zip -r docs.zip site/*
+ - cd site
+ - rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/
diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml
new file mode 100644
index 000000000..be8ea0dfa
--- /dev/null
+++ b/.woodpecker/test.yml
@@ -0,0 +1,114 @@
+platform: linux/amd64
+
+matrix:
+ ELIXIR_VERSION:
+ - 1.14
+ - 1.15
+ OTP_VERSION:
+ - 25
+ - 26
+ include:
+ - ELIXIR_VERSION: 1.14
+ OTP_VERSION: 25
+ - ELIXIR_VERSION: 1.15
+ OTP_VERSION: 25
+ # Soon
+ #- ELIXIR_VERSION: 1.15
+ # OTP_VERSION: 26
+
+variables:
+ - &scw-secrets
+ - SCW_ACCESS_KEY
+ - SCW_SECRET_KEY
+ - SCW_DEFAULT_ORGANIZATION_ID
+ - &setup-hex "mix local.hex --force && mix local.rebar --force"
+ - &on-release
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - develop
+ - stable
+ - refs/tags/v*
+ - refs/tags/stable-*
+ - &on-stable
+ when:
+ event:
+ - push
+ - tag
+ branch:
+ - stable
+ - refs/tags/stable-*
+ - &on-point-release
+ when:
+ event:
+ - push
+ branch:
+ - develop
+ - stable
+ - &on-pr-open
+ when:
+ event:
+ - pull_request
+
+ - &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
+
+ - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
+ - &mix-clean "mix deps.clean --all && mix clean"
+
+services:
+ postgres:
+ image: postgres:15
+ when:
+ event:
+ - pull_request
+ environment:
+ POSTGRES_DB: pleroma_test_${ELIXIR_VERSION}_${OTP_VERSION}
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+
+pipeline:
+ lint:
+ <<: *on-pr-open
+ image: akkoma/ci-base:1.15
+ commands:
+ - mix local.hex --force
+ - mix local.rebar --force
+ - mix format --check-formatted
+
+ build:
+ image: akkoma/ci-base:${ELIXIR_VERSION}-otp${OTP_VERSION}
+ <<: *on-pr-open
+ environment:
+ MIX_ENV: test
+ POSTGRES_DB: pleroma_test_${ELIXIR_VERSION}_${OTP_VERSION}
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ DB_HOST: postgres
+ commands:
+ - mix local.hex --force
+ - mix local.rebar --force
+ - mix deps.get
+ - mix compile
+
+ test:
+ image: akkoma/ci-base:${ELIXIR_VERSION}-otp${OTP_VERSION}
+ <<: *on-pr-open
+ environment:
+ MIX_ENV: test
+ POSTGRES_DB: pleroma_test_${ELIXIR_VERSION}_${OTP_VERSION}
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ DB_HOST: postgres
+ commands:
+ - mix local.hex --force
+ - mix local.rebar --force
+ - mix deps.get
+ - mix compile
+ - mix ecto.drop -f -q
+ - mix ecto.create
+ - mix ecto.migrate
+ - mkdir -p test/tmp
+ - mix test --preload-modules --exclude erratic --exclude federated --exclude mocked
+ - mix test --preload-modules --only mocked
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1ae94d0e..33bf9ce96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,50 @@ 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/).
+## 2023.08
+
+## Added
+
+- Added a new configuration option to the MediaProxy feature that allows the blocking of specific domains from using the media proxy or being explicitly allowed by the Content-Security-Policy.
+ - Please make sure instances you wanted to block media from are not in the MediaProxy `whitelist`, and instead use `blocklist`.
+- `OnlyMedia` Upload Filter to simplify restricting uploads to audio, image, and video types
+- ARM64 OTP builds
+ - Ubuntu22 builds are available for develop and stable
+ - other distributions are stable only
+- Support for Elixir 1.15
+ - 1.14 is still supported
+ - OTP26 is currently "unsupported". It will probably work, but due to the way
+ it handles map ordering, the test suite will not pass for it as yet.
+
+## Changed
+
+- Alpine OTP builds are now from alpine 3.18, which is OpenSSLv3 compatible.
+ If you use alpine OTP builds you will have to update your local system.
+- Debian OTP builds are now from a base of bookworm, which is OpenSSLv3 compatible.
+ If you use debian OTP builds you will have to update your local system to
+ bookworm (currently: stable).
+- Ubuntu and debian builds are compatible again! (for now...)
+- Blocks/Mutes now return from max ID to min ID, in line with mastodon.
+- The AnonymizeFilename filter is now enabled by default.
+
+## Fixed
+
+- Deactivated users can no longer show up in the emoji reaction list
+- Embedded posts can no longer bypass `:restrict\_unauthenticated`
+- GET/HEAD requests will now work when requesting AWS-based instances.
+
+## Security
+
+- Add `no_new_privs` hardening to OpenRC and systemd service files
+- Ensured that XML parsers cannot load external entities (thanks @Mae@is.badat.dev!)
+- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
+
+## Removed
+
+- Builds for debian oldstable (bullseye)
+ - If you are on oldstable you should NOT attempt to update OTP builds without
+ first updating your machine.
+
## 2023.05
## Added
@@ -86,7 +130,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Rich media will now hard-exit after 5 seconds, to prevent timeline hangs
- HTTP Content Security Policy is now far more strict to prevent any potential XSS/CSS leakages
- Follow requests are now paginated, matches mastodon API spec, so use the Link header to paginate.
-- `internal.fetch` and `relay` actors are now represented with the actor type `Application`
### Fixed
- /api/v1/accounts/lookup will now respect restrict\_unauthenticated
diff --git a/Dockerfile b/Dockerfile
index c6506c48c..f695322e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM hexpm/elixir:1.14.3-erlang-25.3-alpine-3.17.2
+FROM hexpm/elixir:1.15.4-erlang-25.3.2.5-alpine-3.18.2
ENV MIX_ENV=prod
ENV ERL_EPMD_ADDRESS=127.0.0.1
diff --git a/config/benchmark.exs b/config/benchmark.exs
index b6a0115c4..940c5f477 100644
--- a/config/benchmark.exs
+++ b/config/benchmark.exs
@@ -14,7 +14,7 @@ config :pleroma, Pleroma.Captcha,
method: Pleroma.Captcha.Mock
# Print only warnings and errors during test
-config :logger, level: :warn
+config :logger, level: :warning
config :pleroma, :auth, oauth_consumer_strategies: []
diff --git a/config/config.exs b/config/config.exs
index ca397a8fd..3430ee4d7 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -443,7 +443,8 @@ config :pleroma, :media_proxy,
# Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1
max_read_duration: 30_000
],
- whitelist: []
+ whitelist: [],
+ blocklist: []
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
method: :purge,
diff --git a/config/description.exs b/config/description.exs
index bd20cb239..e108aaae8 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -1081,7 +1081,7 @@ config :pleroma, :config_description, [
key: :level,
type: {:dropdown, :atom},
description: "Log level",
- suggestions: [:debug, :info, :warn, :error]
+ suggestions: [:debug, :info, :warning, :error]
},
%{
key: :ident,
@@ -1114,7 +1114,7 @@ config :pleroma, :config_description, [
key: :level,
type: {:dropdown, :atom},
description: "Log level",
- suggestions: [:debug, :info, :warn, :error]
+ suggestions: [:debug, :info, :warning, :error]
},
%{
key: :format,
@@ -1558,7 +1558,21 @@ config :pleroma, :config_description, [
%{
key: :whitelist,
type: {:list, :string},
- description: "List of hosts with scheme to bypass the MediaProxy",
+ description: """
+ List of hosts with scheme to bypass the MediaProxy.\n
+ The media will be fetched by the client, directly from the remote server.\n
+ To allow this, it will Content-Security-Policy exceptions for each instance listed.\n
+ This is to be used for instances you trust and do not want to cache media for.
+ """,
+ suggestions: ["http://example.com"]
+ },
+ %{
+ key: :blocklist,
+ type: {:list, :string},
+ description: """
+ List of hosts with scheme which will not go through the MediaProxy, and will not be explicitly allowed by the Content-Security-Policy.
+ This is to be used for instances where you do not want their media to go through your server or to be accessed by clients.
+ """,
suggestions: ["http://example.com"]
}
]
@@ -1844,7 +1858,7 @@ config :pleroma, :config_description, [
key: :log,
type: {:dropdown, :atom},
description: "Logs verbose mode",
- suggestions: [false, :error, :warn, :info, :debug]
+ suggestions: [false, :error, :warning, :info, :debug]
},
%{
key: :queues,
diff --git a/config/test.exs b/config/test.exs
index 4448eeb73..666a0fb87 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -16,7 +16,7 @@ config :pleroma, Pleroma.Captcha,
# Print only warnings and errors during test
config :logger, :console,
- level: :warn,
+ level: :warning,
format: "\n[$level] $message\n"
config :pleroma, :auth, oauth_consumer_strategies: []
@@ -81,10 +81,7 @@ config :web_push_encryption, :vapid_details,
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
-config :pleroma, Oban,
- queues: false,
- crontab: false,
- plugins: false
+config :pleroma, Oban, testing: :manual
config :pleroma, Pleroma.ScheduledActivity,
daily_user_limit: 2,
diff --git a/docker-resources/build.sh b/docker-resources/build.sh
index daa653da6..ce4f30f8d 100755
--- a/docker-resources/build.sh
+++ b/docker-resources/build.sh
@@ -1,4 +1,4 @@
#!/bin/sh
-docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
-docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db
+docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
+docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db
diff --git a/docker-resources/manage.sh b/docker-resources/manage.sh
index 944f5e2e2..acb6618c3 100755
--- a/docker-resources/manage.sh
+++ b/docker-resources/manage.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-docker-compose run --rm akkoma $@
+docker compose run --rm akkoma $@
diff --git a/docs/docs/administration/CLI_tasks/frontend.md b/docs/docs/administration/CLI_tasks/frontend.md
index 382ac268e..5d0c7147a 100644
--- a/docs/docs/administration/CLI_tasks/frontend.md
+++ b/docs/docs/administration/CLI_tasks/frontend.md
@@ -42,7 +42,7 @@ For a frontend configured under the `available` key, it's enough to install it b
This will download the latest build for the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
-You can override any of the details. To install a Pleroma-FE build from a different URL, you could do this:
+You can override any of the details. To install an Akkoma-FE build from a different URL, you could do this:
=== "OTP"
diff --git a/docs/docs/administration/updating.md b/docs/docs/administration/updating.md
index 6cea56e5c..94bddfb6c 100644
--- a/docs/docs/administration/updating.md
+++ b/docs/docs/administration/updating.md
@@ -62,6 +62,6 @@ mix ecto.migrate
# Start akkoma (replace with your system service manager's equivalent if different)
sudo systemctl start akkoma
-# Update Pleroma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
+# Update Akkoma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
mix pleroma.frontend install pleroma-fe --ref stable
```
diff --git a/docs/docs/clients.md b/docs/docs/clients.md
index 139796471..1452b9505 100644
--- a/docs/docs/clients.md
+++ b/docs/docs/clients.md
@@ -2,6 +2,14 @@
Note: Additional clients may work, but these are known to work with Akkoma.
Apps listed here might not support all of Akkoma's features.
+## Multiplatform
+### Kaiteki
+- Homepage:
+- Source Code:
+- Contact: [@kaiteki@fedi.software](https://fedi.software/@Kaiteki)
+- Platforms: Web, Windows, Linux, Android
+- Features: MastoAPI, Supports multiple backends
+
## Desktop
### Whalebird
- Homepage:
diff --git a/docs/docs/configuration/cheatsheet.md b/docs/docs/configuration/cheatsheet.md
index 1c4d9ec5d..73fdf9eea 100644
--- a/docs/docs/configuration/cheatsheet.md
+++ b/docs/docs/configuration/cheatsheet.md
@@ -246,11 +246,11 @@ Notes:
### :frontend_configurations
-This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Pleroma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
+This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Akkoma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
Frontends can access these settings at `/api/v1/pleroma/frontend_configurations`
-To add your own configuration for Pleroma-FE, use it like this:
+To add your own configuration for Akkoma-FE, use it like this:
```elixir
config :pleroma, :frontend_configurations,
@@ -615,6 +615,12 @@ This filter only strips the GPS and location metadata with Exiftool leaving colo
No specific configuration.
+#### Pleroma.Upload.Filter.OnlyMedia
+
+This filter rejects uploads that are not identified with Content-Type matching audio/\*, image/\*, or video/\*
+
+No specific configuration.
+
#### Pleroma.Upload.Filter.Mogrify
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
diff --git a/docs/docs/configuration/frontend_management.md b/docs/docs/configuration/frontend_management.md
index 5e4b9b051..bc5344826 100644
--- a/docs/docs/configuration/frontend_management.md
+++ b/docs/docs/configuration/frontend_management.md
@@ -26,7 +26,7 @@ config :pleroma, :frontends,
}
```
-This would serve the frontend from the the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit.
+This would serve the frontend from the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit.
Refer to [the frontend CLI task](../../administration/CLI_tasks/frontend) for how to install the frontend's files
diff --git a/docs/docs/configuration/howto_theming_your_instance.md b/docs/docs/configuration/howto_theming_your_instance.md
index c226d054b..093c12763 100644
--- a/docs/docs/configuration/howto_theming_your_instance.md
+++ b/docs/docs/configuration/howto_theming_your_instance.md
@@ -6,7 +6,7 @@ To add a custom theme to your instance, you'll first need to get a custom theme,
### Create your own theme
-* You can create your own theme using the Pleroma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
+* You can create your own theme using the Akkoma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
* To download your theme, you can do Save preset
* If you want to upload a theme to customise it further, you can upload it using Load preset
@@ -70,4 +70,4 @@ config :pleroma, :frontend_configurations,
}
```
-If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes.
\ No newline at end of file
+If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes.
diff --git a/docs/docs/development/API/differences_in_mastoapi_responses.md b/docs/docs/development/API/differences_in_mastoapi_responses.md
index b41561c45..053dc9663 100644
--- a/docs/docs/development/API/differences_in_mastoapi_responses.md
+++ b/docs/docs/development/API/differences_in_mastoapi_responses.md
@@ -25,6 +25,7 @@ Home, public, hashtag & list timelines accept these parameters:
## Statuses
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
+- `emoji_reactions`: additional field since Akkoma 3.2.0; identical to `pleroma/emoji_reactions`
Has these additional fields under the `pleroma` object:
@@ -36,7 +37,9 @@ Has these additional fields under the `pleroma` object:
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being its mimetype. Currently, the only alternate representation supported is `text/plain`
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
- `thread_muted`: true if the thread the post belongs to is muted
-- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
+- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 2, me: true, account_ids: ["UserID1", "UserID2"]}`.
+ The `account_ids` property was added in Akkoma 3.2.0.
+ Further info about all reacting users at once, can be found using the `/statuses/:id/reactions` endpoint.
- `parent_visible`: If the parent of this post is visible to the user or not.
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
@@ -214,6 +217,11 @@ Returns: array of Status.
The maximum number of statuses is limited to 100 per request.
+## PUT `/api/v1/statuses/:id/emoji_reactions/:emoji`
+
+This endpoint is an extension of the Fedibird Mastodon fork.
+It behaves identical to PUT `/api/v1/pleroma/statuses/:id/reactions/:emoji`.
+
## PATCH `/api/v1/accounts/update_credentials`
Additional parameters can be added to the JSON body/Form data:
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 241f790dc..8608f8196 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -3,7 +3,7 @@
# Introduction to Akkoma
## What is Akkoma?
Akkoma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
-It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named Pleroma-FE. It also includes the Mastodon frontend, if that's your thing.
+It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named Akkoma-FE. It also includes the Mastodon frontend, if that's your thing.
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
One account on an instance is enough to talk to the entire fediverse!
@@ -31,11 +31,11 @@ Installation instructions can be found in the installation section of these docs
## I got an account, now what?
Great! Now you can explore the fediverse! Open the login page for your Akkoma instance (e.g. ) and login with your username and password. (If you don't have an account yet, click on Register)
-### Pleroma-FE
-The default front-end used by Akkoma is Pleroma-FE. You can find more information on what it is and how to use it in the [Introduction to Pleroma-FE](https://docs-fe.akkoma.dev/stable/).
+### Akkoma-FE
+The default front-end used by Akkoma is Akkoma-FE. You can find more information on what it is and how to use it in the [Introduction to Akkoma-FE](https://docs-fe.akkoma.dev/stable/).
### Mastodon interface
-If the Pleroma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
+If the Akkoma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
Just add a "/web" after your instance url (e.g. ) and you'll end on the Mastodon web interface, but with a Akkoma backend! MAGIC!
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.
diff --git a/docs/docs/installation/debian_based_en.md b/docs/docs/installation/debian_based_en.md
index 265658fef..6a0f332ec 100644
--- a/docs/docs/installation/debian_based_en.md
+++ b/docs/docs/installation/debian_based_en.md
@@ -4,7 +4,7 @@
## Installation
-This guide will assume you are on Debian 11 (“bullseye”) or later. This guide should also work with Ubuntu 18.04 (“Bionic Beaver”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu akkoma`; in this case, use `su -s $SHELL -c 'command'` instead.
+This guide will assume you are on Debian 12 (“bookworm”) or later. This guide should also work with Ubuntu 22.04 (“Jammy Jellyfish”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu akkoma`; in this case, use `su -s $SHELL -c 'command'` instead.
{! installation/generic_dependencies.include !}
@@ -23,23 +23,7 @@ sudo apt full-upgrade
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev
```
-### Install Elixir and Erlang
-
-* Install Elixir and Erlang (you might need to use backports or [asdf](https://github.com/asdf-vm/asdf) on old systems):
-
-```shell
-sudo apt update
-sudo apt install elixir erlang-dev erlang-nox
-```
-
-
-### Optional packages: [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md)
-
-```shell
-sudo apt install imagemagick ffmpeg libimage-exiftool-perl
-```
-
-### Install AkkomaBE
+### Create the akkoma user
* Add a new system user for the Akkoma service:
@@ -49,7 +33,67 @@ sudo useradd -r -s /bin/false -m -d /var/lib/akkoma -U akkoma
**Note**: To execute a single command as the Akkoma system user, use `sudo -Hu akkoma command`. You can also switch to a shell by using `sudo -Hu akkoma $SHELL`. If you don’t have and want `sudo` on your system, you can use `su` as root user (UID 0) for a single command by using `su -l akkoma -s $SHELL -c 'command'` and `su -l akkoma -s $SHELL` for starting a shell.
-* Git clone the AkkomaBE repository from stable-branch and make the Akkoma user the owner of the directory:
+### Install Elixir and Erlang
+
+If your distribution packages a recent enough version of Elixir, you can install it directly from the distro repositories and skip to the next section of the guide:
+
+```shell
+sudo apt install elixir erlang-dev erlang-nox
+```
+
+Otherwise use [asdf](https://github.com/asdf-vm/asdf) to install the latest versions of Elixir and Erlang.
+
+First, install some dependencies needed to build Elixir and Erlang:
+```shell
+sudo apt install curl unzip build-essential autoconf m4 libncurses5-dev libssh-dev unixodbc-dev xsltproc libxml2-utils libncurses-dev
+```
+
+Then login to the `akkoma` user and install asdf:
+```shell
+git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3
+```
+
+Add the following lines to `~/.bashrc`:
+```shell
+. "$HOME/.asdf/asdf.sh"
+# asdf completions
+. "$HOME/.asdf/completions/asdf.bash"
+```
+
+Restart the shell:
+```shell
+exec $SHELL
+```
+
+Next install Erlang:
+```shell
+asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
+export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac"
+asdf install erlang 25.3.2.5
+asdf global erlang 25.3.2.5
+```
+
+Now install Elixir:
+```shell
+asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
+asdf install elixir 1.15.4-otp-25
+asdf global elixir 1.15.4-otp-25
+```
+
+Confirm that Elixir is installed correctly by checking the version:
+```shell
+elixir --version
+```
+
+### Optional packages: [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md)
+
+```shell
+sudo apt install imagemagick ffmpeg libimage-exiftool-perl
+```
+
+### Install AkkomaBE
+
+* Log into the `akkoma` user and clone the AkkomaBE repository from the stable branch and make the Akkoma user the owner of the directory:
```shell
sudo mkdir -p /opt/akkoma
diff --git a/docs/docs/installation/docker_en.md b/docs/docs/installation/docker_en.md
index 2a3b3d161..52c056173 100644
--- a/docs/docs/installation/docker_en.md
+++ b/docs/docs/installation/docker_en.md
@@ -10,7 +10,7 @@ If you want to migrate from or OTP to docker, check out [the migration guide](./
### Prepare the system
-* Install docker and docker-compose
+* Install docker and docker compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
@@ -26,7 +26,7 @@ echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
-variables for the docker-compose file.
+variables for the docker compose file.
### Building the container
@@ -65,9 +65,9 @@ cp config/generated_config.exs config/prod.secret.exs
We need to run a few commands on the database container, this isn't too bad
```bash
-docker-compose run --rm --user akkoma -d db
+docker compose run --rm --user akkoma -d db
# Note down the name it gives here, it will be something like akkoma_db_run
-docker-compose run --rm akkoma psql -h db -U akkoma -f config/setup_db.psql
+docker compose run --rm akkoma psql -h db -U akkoma -f config/setup_db.psql
docker stop akkoma_db_run # Replace with the name you noted down
```
@@ -84,17 +84,17 @@ We're going to run it in the foreground on the first run, just to make sure
everything start up.
```bash
-docker-compose up
+docker compose up
```
If everything went well, you should be able to access your instance at http://localhost:4000
-You can `ctrl-c` out of the docker-compose now to shutdown the server.
+You can `ctrl-c` out of the docker compose now to shutdown the server.
### Running in the background
```bash
-docker-compose up -d
+docker compose up -d
```
### Create your first user
@@ -125,8 +125,8 @@ cp docker-resources/Caddyfile.example docker-resources/Caddyfile
Then edit the TLD in your caddyfile to the domain you're serving on.
-Uncomment the `caddy` section in the docker-compose file,
-then run `docker-compose up -d` again.
+Uncomment the `caddy` section in the docker compose file,
+then run `docker compose up -d` again.
#### Running a reverse proxy on the host
@@ -152,7 +152,7 @@ git pull
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix ecto.migrate
-docker-compose restart akkoma db
+docker compose restart akkoma db
```
#### Further reading
diff --git a/docs/docs/installation/migrating_to_akkoma.md b/docs/docs/installation/migrating_to_akkoma.md
index 2df7bfad0..4a58e836e 100644
--- a/docs/docs/installation/migrating_to_akkoma.md
+++ b/docs/docs/installation/migrating_to_akkoma.md
@@ -117,4 +117,16 @@ To fix this, run:
mix pleroma.config delete pleroma frontends
```
-which will remove the config from the database. Things should work now.
\ No newline at end of file
+which will remove the config from the database. Things should work now.
+
+## Migrating back to Pleroma
+
+Akkoma is a hard fork of Pleroma. As such, migrating back is not guaranteed to always work. But if you want to migrate back to Pleroma, you can always try. Just note that you may run into unexpected issues and you're basically on your own. The following are some tips that may help, but note that these are barely tested, so proceed at your own risk.
+
+First you will need to roll back the database migrations. The latest migration both Akkoma and Pleroma still have in common should be 20210416051708, so roll back to that. If you run from source, that should be
+
+```sh
+MIX_ENV=prod mix ecto.rollback --to 20210416051708
+```
+
+Then switch back to Pleroma for updates (similar to how was done to migrate to Akkoma), and remove the front-ends. The front-ends are installed in the `frontends` folder in the [static directory](../configuration/static_dir.md). Once you are back to Pleroma, you will need to run the database migrations again. See the Pleroma documentation for this.
diff --git a/docs/docs/installation/migrating_to_docker_en.md b/docs/docs/installation/migrating_to_docker_en.md
index 945f43090..6a67f1eee 100644
--- a/docs/docs/installation/migrating_to_docker_en.md
+++ b/docs/docs/installation/migrating_to_docker_en.md
@@ -10,7 +10,7 @@ You probably should, in the first instance.
### Prepare the system
-* Install docker and docker-compose
+* Install docker and docker compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
@@ -46,7 +46,7 @@ For *most* from-source installs it'll already be there.
And the same with `uploads`, make sure your uploads (if you have them on disk) are
located at `uploads/` in the akkoma source directory.
-If you have them on a different disk, you will need to mount that disk into the docker-compose file,
+If you have them on a different disk, you will need to mount that disk into the docker compose file,
with an entry that looks like this:
```yaml
@@ -66,7 +66,7 @@ echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
-variables for the docker-compose file.
+variables for the docker compose file.
=== "From source"
@@ -126,21 +126,21 @@ mkdir pgdata
Now we can import our database to the container.
```bash
-docker-compose run --rm --user akkoma -d db
-docker-compose run --rm akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
+docker compose run --rm --user akkoma -d db
+docker compose run --rm akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
```
### Reverse proxies
If you're just reusing your old proxy, you may have to uncomment the line in
-the docker-compose file under `ports`. You'll find it.
+the docker compose file under `ports`. You'll find it.
Otherwise, you can use the same setup as the [docker installation guide](./docker_en.md#reverse-proxies).
### Let's go
```bash
-docker-compose up -d
+docker compose up -d
```
You should now be at the same point as you were before, but with a docker install.
diff --git a/docs/docs/installation/optional/media_graphics_packages.md b/docs/docs/installation/optional/media_graphics_packages.md
index cb3d71188..ab9f958f9 100644
--- a/docs/docs/installation/optional/media_graphics_packages.md
+++ b/docs/docs/installation/optional/media_graphics_packages.md
@@ -1,19 +1,19 @@
# Optional software packages needed for specific functionality
-For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
- * `ImageMagic`
+For specific Akkoma functionality (which is disabled by default) some or all of the below packages are required:
+ * `ImageMagick`
* `ffmpeg`
* `exiftool`
Please refer to documentation in `docs/installation` on how to install them on specific OS.
-Note: the packages are not required with the current default settings of Pleroma.
+Note: the packages are not required with the current default settings of Akkoma.
## `ImageMagick`
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
-It is required for the following Pleroma features:
+It is required for the following Akkoma features:
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
@@ -21,12 +21,12 @@ It is required for the following Pleroma features:
`ffmpeg` is software to record, convert and stream audio and video.
-It is required for the following Pleroma features:
+It is required for the following Akkoma features:
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `exiftool`
`exiftool` is media files metadata reader/writer.
-It is required for the following Pleroma features:
+It is required for the following Akkoma features:
* `Pleroma.Upload.Filters.Exiftool` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
diff --git a/docs/docs/installation/otp_en.md b/docs/docs/installation/otp_en.md
index 058040e19..b613e17b2 100644
--- a/docs/docs/installation/otp_en.md
+++ b/docs/docs/installation/otp_en.md
@@ -15,16 +15,16 @@ While in theory OTP releases are possbile to install on any compatible machine,
### Detecting flavour
-This is a little more complex than it used to be (thanks ubuntu)
-
Use the following mapping to figure out your flavour:
-| distribution | flavour | available branches |
-| ------------- | ------------------ | ------------------- |
-| debian stable | amd64 | develop, stable |
-| ubuntu focal | amd64 | develop, stable |
-| ubuntu jammy | amd64-ubuntu-jammy | develop, stable |
-| alpine | amd64-musl | stable |
+| distribution | architecture | flavour | available branches |
+| --------------- | ------------------ | ------------------- | ------------------- |
+| debian bookworm | amd64 | amd64 | develop, stable |
+| debian bookworm | arm64 | arm64 | stable |
+| ubuntu jammy | amd64 | amd64 | develop, stable |
+| ubuntu jammy | arm64 | arm64 | develop, stable |
+| alpine | amd64 | amd64-musl | stable |
+| alpine | arm64 | arm64-musl | stable |
Other similar distributions will _probably_ work, but if it is not listed above, there is no official
support.
@@ -118,8 +118,12 @@ Restart PostgreSQL to apply configuration changes:
adduser --system --shell /bin/false --home /opt/akkoma akkoma
# Set the flavour environment variable to the string you got in Detecting flavour section.
-# For example if the flavour is `amd64` the command will be
-export FLAVOUR="amd64"
+# For example if the flavour is `amd64-musl` the command will be
+# export FLAVOUR="amd64-musl"
+export FLAVOUR=""
+
+# Make sure the SHELL variable is set
+export SHELL="${SHELL:-/bin/sh}"
# Clone the release build into a temporary directory and unpack it
su akkoma -s $SHELL -lc "
diff --git a/docs/theme/partials/source.html b/docs/theme/partials/source.html
index 3ed0fff24..3b10223b1 100644
--- a/docs/theme/partials/source.html
+++ b/docs/theme/partials/source.html
@@ -38,11 +38,11 @@
{% endif %}
{% if page and page.url.startswith('backend') %}
- {% set repo_url = "https://git.pleroma.social/pleroma/pleroma" %}
- {% set repo_name = "pleroma/pleroma" %}
+ {% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma" %}
+ {% set repo_name = "AkkomaGang/akkoma" %}
{% elif page and page.url.startswith('frontend') %}
- {% set repo_url = "https://git.pleroma.social/pleroma/pleroma-fe" %}
- {% set repo_name = "pleroma/pleroma-fe" %}
+ {% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma-fe" %}
+ {% set repo_name = "AkkomaGang/akkoma-fe" %}
{% else %}
{% set repo_url = config.repo_url %}
{% set repo_name = config.repo_name %}
diff --git a/installation/akkoma.service b/installation/akkoma.service
index 012e9185e..717693495 100644
--- a/installation/akkoma.service
+++ b/installation/akkoma.service
@@ -8,6 +8,8 @@ Restart=on-failure
; Uncomment this if you're on Arch Linux
; Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl"
+; Uncomment if using asdf to manage Elixir and Erlang
+; Environment="PATH=/var/lib/akkoma/.asdf/shims:/var/lib/akkoma/.asdf/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
; Name of the user that runs the Akkoma service.
User=akkoma
@@ -24,6 +26,8 @@ Environment="HOME=/var/lib/akkoma"
WorkingDirectory=/opt/akkoma
; Path to the Mix binary.
ExecStart=/usr/bin/mix phx.server
+; If using asdf comment the above line and uncomment the one below instead
+; ExecStart=/var/lib/akkoma/.asdf/shims/mix phx.server
; Some security directives.
; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops.
@@ -34,6 +38,8 @@ ProtectHome=true
ProtectSystem=full
; Sets up a new /dev mount for the process and only adds API pseudo devices like /dev/null, /dev/zero or /dev/random but not physical devices. Disabled by default because it may not work on devices like the Raspberry Pi.
PrivateDevices=false
+; Ensures that the service process and all its children can never gain new privileges through execve().
+NoNewPrivileges=true
; Drops the sysadmin capability from the daemon.
CapabilityBoundingSet=~CAP_SYS_ADMIN
diff --git a/installation/caddy/Caddyfile b/installation/caddy/Caddyfile
index 5cc75a1fc..d50848207 100644
--- a/installation/caddy/Caddyfile
+++ b/installation/caddy/Caddyfile
@@ -4,6 +4,9 @@
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
# 2. Copy this section into your Caddyfile and restart Caddy.
+# If you are able to, it's highly recommended to have your media served via a separate subdomain for improved security.
+# Uncomment the relevant sectons here and modify the base_url setting for Pleroma.Upload and :media_proxy accordingly.
+
example.tld {
log {
output file /var/log/caddy/akkoma.log
@@ -14,4 +17,21 @@ example.tld {
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
# and `localhost.` resolves to [::0] on some systems: see issue #930
reverse_proxy 127.0.0.1:4000
+
+ # Uncomment if using a separate media subdomain
+ #@mediaproxy path /media/* /proxy/*
+ #handle @mediaproxy {
+ # redir https://media.example.tld{uri} permanent
+ #}
}
+
+# Uncomment if using a separate media subdomain
+#media.example.tld {
+# @mediaproxy path /media/* /proxy/*
+# reverse_proxy @mediaproxy 127.0.0.1:4000 {
+# transport http {
+# response_header_timeout 10s
+# read_timeout 15s
+# }
+# }
+#}
diff --git a/installation/init.d/akkoma b/installation/init.d/akkoma
index 6c1973db4..bd17516f2 100755
--- a/installation/init.d/akkoma
+++ b/installation/init.d/akkoma
@@ -8,6 +8,7 @@ pidfile="/var/run/akkoma.pid"
directory=/opt/akkoma
healthcheck_delay=60
healthcheck_timer=30
+no_new_privs="yes"
: ${akkoma_port:-4000}
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex
index 55d1c8ddc..09d2a4072 100644
--- a/lib/mix/tasks/pleroma/database.ex
+++ b/lib/mix/tasks/pleroma/database.ex
@@ -359,7 +359,7 @@ defmodule Mix.Tasks.Pleroma.Database do
)
end
- shell_info('Done.')
+ shell_info(~c"Done.")
end
end
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 52fd184b5..6a7d4f0d3 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -247,16 +247,22 @@ defmodule Mix.Tasks.Pleroma.Instance do
config_dir = Path.dirname(config_path)
psql_dir = Path.dirname(psql_path)
+ # Note: Distros requiring group read (0o750) on those directories should
+ # pre-create the directories.
to_create =
[config_dir, psql_dir, static_dir, uploads_dir]
|> Enum.reject(&File.exists?/1)
for dir <- to_create do
File.mkdir_p!(dir)
+ File.chmod!(dir, 0o700)
end
shell_info("Writing config to #{config_path}.")
+ # Sadly no fchmod(2) equivalent in Elixir…
+ File.touch!(config_path)
+ File.chmod!(config_path, 0o640)
File.write(config_path, result_config)
shell_info("Writing the postgres script to #{psql_path}.")
File.write(psql_path, result_psql)
@@ -275,8 +281,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
else
shell_error(
"The task would have overwritten the following files:\n" <>
- (Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>
- "Rerun with `--force` to overwrite them."
+ Enum.map_join(will_overwrite, &"- #{&1}\n") <> "Rerun with `--force` to overwrite them."
)
end
end
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index c94667fb9..bf851f808 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -390,7 +390,8 @@ defmodule Pleroma.Activity do
active in fragment(
"SELECT is_active from users WHERE ap_id = ? AND is_active = TRUE",
activity.actor
- )
+ ),
+ on: true
)
end
diff --git a/lib/pleroma/activity/ir/topics.ex b/lib/pleroma/activity/ir/topics.ex
index 7a603a615..bdbf4a285 100644
--- a/lib/pleroma/activity/ir/topics.ex
+++ b/lib/pleroma/activity/ir/topics.ex
@@ -21,7 +21,7 @@ defmodule Pleroma.Activity.Ir.Topics do
["user", "list"] ++ visibility_tags(object, activity)
end
- defp visibility_tags(object, activity) do
+ defp visibility_tags(object, %{data: %{"type" => type}} = activity) when type != "Announce" do
case Visibility.get_visibility(activity) do
"public" ->
if activity.local do
@@ -31,6 +31,10 @@ defmodule Pleroma.Activity.Ir.Topics do
end
|> item_creation_tags(object, activity)
+ "local" ->
+ ["public:local"]
+ |> item_creation_tags(object, activity)
+
"direct" ->
["direct"]
@@ -39,6 +43,10 @@ defmodule Pleroma.Activity.Ir.Topics do
end
end
+ defp visibility_tags(_object, _activity) do
+ []
+ end
+
defp item_creation_tags(tags, object, %{data: %{"type" => "Create"}} = activity) do
tags ++
remote_topics(activity) ++ hashtags_to_topics(object) ++ attachment_topics(object, activity)
@@ -63,7 +71,18 @@ defmodule Pleroma.Activity.Ir.Topics do
defp attachment_topics(%{data: %{"attachment" => []}}, _act), do: []
- defp attachment_topics(_object, %{local: true}), do: ["public:media", "public:local:media"]
+ defp attachment_topics(_object, %{local: true} = activity) do
+ case Visibility.get_visibility(activity) do
+ "public" ->
+ ["public:media", "public:local:media"]
+
+ "local" ->
+ ["public:local:media"]
+
+ _ ->
+ []
+ end
+ end
defp attachment_topics(_object, %{actor: actor}) when is_binary(actor),
do: ["public:media", "public:remote:media:" <> URI.parse(actor).host]
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 0273972be..db49ccfae 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -87,7 +87,7 @@ defmodule Pleroma.Application do
# Go for the default 3 unless we're in test
max_restarts =
if @mix_env == :test do
- 100
+ 1000
else
3
end
@@ -112,7 +112,7 @@ defmodule Pleroma.Application do
num
else
e ->
- Logger.warn(
+ Logger.warning(
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6"
)
@@ -262,6 +262,8 @@ defmodule Pleroma.Application do
proxy = Pleroma.HTTP.AdapterHelper.format_proxy(proxy_url)
pool_size = Config.get([:http, :pool_size])
+ :public_key.cacerts_load()
+
config =
[:http, :adapter]
|> Config.get([])
diff --git a/lib/pleroma/application_requirements.ex b/lib/pleroma/application_requirements.ex
index 19236aaa2..8dc269f0f 100644
--- a/lib/pleroma/application_requirements.ex
+++ b/lib/pleroma/application_requirements.ex
@@ -34,7 +34,7 @@ defmodule Pleroma.ApplicationRequirements do
defp check_welcome_message_config!(:ok) do
if Pleroma.Config.get([:welcome, :email, :enabled], false) and
not Pleroma.Emails.Mailer.enabled?() do
- Logger.warn("""
+ Logger.warning("""
To send welcome emails, you need to enable the mailer.
Welcome emails will NOT be sent with the current config.
@@ -53,7 +53,7 @@ defmodule Pleroma.ApplicationRequirements do
def check_confirmation_accounts!(:ok) do
if Pleroma.Config.get([:instance, :account_activation_required]) &&
not Pleroma.Emails.Mailer.enabled?() do
- Logger.warn("""
+ Logger.warning("""
Account activation is required, but the mailer is disabled.
Users will NOT be able to confirm their accounts with this config.
Either disable account activation or enable the mailer.
diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex
index 076b4cbf0..beb3f5e7f 100644
--- a/lib/pleroma/config/deprecation_warnings.ex
+++ b/lib/pleroma/config/deprecation_warnings.ex
@@ -28,7 +28,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|> Enum.any?(fn {_, v} -> is_list(v) and Enum.any?(v, &is_binary/1) end)
if has_strings do
- Logger.warn("""
+ Logger.warning("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the SimplePolicy configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@@ -87,7 +87,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
has_strings = Config.get([:instance, :quarantined_instances], []) |> Enum.any?(&is_binary/1)
if has_strings do
- Logger.warn("""
+ Logger.warning("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the quarantined_instances configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@@ -124,7 +124,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
has_strings = Config.get([:mrf, :transparency_exclusions]) |> Enum.any?(&is_binary/1)
if has_strings do
- Logger.warn("""
+ Logger.warning("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the transparency_exclusions configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@@ -159,7 +159,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
def check_hellthread_threshold do
if Config.get([:mrf_hellthread, :threshold]) do
- Logger.warn("""
+ Logger.warning("""
!!!DEPRECATION WARNING!!!
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
""")
@@ -264,7 +264,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
if warning == "" do
:ok
else
- Logger.warn(warning_preface <> warning)
+ Logger.warning(warning_preface <> warning)
:error
end
end
@@ -274,7 +274,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
whitelist = Config.get([:media_proxy, :whitelist])
if Enum.any?(whitelist, &(not String.starts_with?(&1, "http"))) do
- Logger.warn("""
+ Logger.warning("""
!!!DEPRECATION WARNING!!!
Your config is using old format (only domain) for MediaProxy whitelist option. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later.
""")
diff --git a/lib/pleroma/config/oban.ex b/lib/pleroma/config/oban.ex
index 53ea7d7be..ab1eee96f 100644
--- a/lib/pleroma/config/oban.ex
+++ b/lib/pleroma/config/oban.ex
@@ -23,7 +23,7 @@ defmodule Pleroma.Config.Oban do
You are using old workers in Oban crontab settings, which were removed.
Please, remove setting from crontab in your config file (prod.secret.exs): #{inspect(setting)}
"""
- |> Logger.warn()
+ |> Logger.warning()
List.delete(acc, setting)
else
diff --git a/lib/pleroma/config/release_runtime_provider.ex b/lib/pleroma/config/release_runtime_provider.ex
index e5f2d6339..a829a0206 100644
--- a/lib/pleroma/config/release_runtime_provider.ex
+++ b/lib/pleroma/config/release_runtime_provider.ex
@@ -22,6 +22,20 @@ defmodule Pleroma.Config.ReleaseRuntimeProvider do
with_runtime_config =
if File.exists?(config_path) do
+ #
+ %File.Stat{mode: mode} = File.lstat!(config_path)
+
+ if Bitwise.band(mode, 0o007) > 0 do
+ raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"
+ end
+
+ if Bitwise.band(mode, 0o020) > 0 do
+ raise "Configuration at #{config_path} has group-wise write permissions, execute the following: chmod g-w #{config_path}"
+ end
+
+ # Note: Elixir doesn't provides a getuid(2)
+ # so cannot forbid group-read only when config is owned by us
+
runtime_config = Config.Reader.read!(config_path)
with_defaults
diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex
index 52f6346a5..efbc84eb0 100644
--- a/lib/pleroma/config/transfer_task.ex
+++ b/lib/pleroma/config/transfer_task.ex
@@ -149,7 +149,7 @@ defmodule Pleroma.Config.TransferTask do
error_msg =
"updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}"
- Logger.warn(error_msg)
+ Logger.warning(error_msg)
nil
end
@@ -183,12 +183,12 @@ defmodule Pleroma.Config.TransferTask do
:ok = Application.start(app)
else
nil ->
- Logger.warn("#{app} is not started.")
+ Logger.warning("#{app} is not started.")
error ->
error
|> inspect()
- |> Logger.warn()
+ |> Logger.warning()
end
end
diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex
index 234dde1c9..94608a99b 100644
--- a/lib/pleroma/constants.ex
+++ b/lib/pleroma/constants.ex
@@ -25,7 +25,7 @@ defmodule Pleroma.Constants do
const(static_only_files,
do:
- ~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css)
+ ~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance embed sw.js sw-pleroma.js favicon.png schemas doc)
)
const(status_updatable_fields,
diff --git a/lib/pleroma/emoji/loader.ex b/lib/pleroma/emoji/loader.ex
index abc95d902..e09279dd0 100644
--- a/lib/pleroma/emoji/loader.ex
+++ b/lib/pleroma/emoji/loader.ex
@@ -59,7 +59,7 @@ defmodule Pleroma.Emoji.Loader do
Logger.info("Found emoji packs: #{Enum.join(packs, ", ")}")
if not Enum.empty?(files) do
- Logger.warn(
+ Logger.warning(
"Found files in the emoji folder. These will be ignored, please move them to a subdirectory\nFound files: #{Enum.join(files, ", ")}"
)
end
diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex
index f9b47a26b..9049d9097 100644
--- a/lib/pleroma/emoji/pack.ex
+++ b/lib/pleroma/emoji/pack.ex
@@ -287,6 +287,7 @@ defmodule Pleroma.Emoji.Pack do
@spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()}
def load_pack(name) do
+ name = Path.basename(name)
pack_file = Path.join([emoji_path(), name, "pack.json"])
with {:ok, _} <- File.stat(pack_file),
@@ -411,10 +412,10 @@ defmodule Pleroma.Emoji.Pack do
end
defp create_archive_and_cache(pack, hash) do
- files = ['pack.json' | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
+ files = [~c"pack.json" | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
{:ok, {_, result}} =
- :zip.zip('#{pack.name}.zip', files, [:memory, cwd: to_charlist(pack.path)])
+ :zip.zip(~c"#{pack.name}.zip", files, [:memory, cwd: to_charlist(pack.path)])
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
@@ -581,7 +582,7 @@ defmodule Pleroma.Emoji.Pack do
with :ok <- File.mkdir_p!(local_pack.path) do
files = Enum.map(remote_pack["files"], fn {_, path} -> to_charlist(path) end)
# Fallback cannot contain a pack.json file
- files = if pack_info[:fallback], do: files, else: ['pack.json' | files]
+ files = if pack_info[:fallback], do: files, else: [~c"pack.json" | files]
:zip.unzip(archive, cwd: to_charlist(local_pack.path), file_list: files)
end
diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex
index 6ae1cdebb..9346ffa16 100644
--- a/lib/pleroma/http.ex
+++ b/lib/pleroma/http.ex
@@ -27,10 +27,10 @@ defmodule Pleroma.HTTP do
nil | {:ok, Env.t()} | {:error, any()}
def get(url, headers \\ [], options \\ [])
def get(nil, _, _), do: nil
- def get(url, headers, options), do: request(:get, url, "", headers, options)
+ def get(url, headers, options), do: request(:get, url, nil, headers, options)
@spec head(Request.url(), Request.headers(), keyword()) :: {:ok, Env.t()} | {:error, any()}
- def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options)
+ def head(url, headers \\ [], options \\ []), do: request(:head, url, nil, headers, options)
@doc """
Performs POST request.
@@ -62,6 +62,13 @@ defmodule Pleroma.HTTP do
uri = URI.parse(url)
adapter_opts = AdapterHelper.options(uri, options || [])
+ adapter_opts =
+ if uri.scheme == :https do
+ AdapterHelper.maybe_add_cacerts(adapter_opts, :public_key.cacerts_get())
+ else
+ adapter_opts
+ end
+
options = put_in(options[:adapter], adapter_opts)
params = options[:params] || []
request = build_request(method, headers, options, url, body, params)
diff --git a/lib/pleroma/http/adapter_helper.ex b/lib/pleroma/http/adapter_helper.ex
index e5da3ffa8..303ccdf2a 100644
--- a/lib/pleroma/http/adapter_helper.ex
+++ b/lib/pleroma/http/adapter_helper.ex
@@ -47,6 +47,17 @@ defmodule Pleroma.HTTP.AdapterHelper do
|> put_in([:pools, :default, :conn_opts, :proxy], proxy)
end
+ def maybe_add_cacerts(opts, nil), do: opts
+
+ def maybe_add_cacerts(opts, cacerts) do
+ opts
+ |> maybe_add_pools()
+ |> maybe_add_default_pool()
+ |> maybe_add_conn_opts()
+ |> maybe_add_transport_opts()
+ |> put_in([:pools, :default, :conn_opts, :transport_opts, :cacerts], cacerts)
+ end
+
def add_pool_size(opts, pool_size) do
opts
|> maybe_add_pools()
@@ -82,6 +93,16 @@ defmodule Pleroma.HTTP.AdapterHelper do
end
end
+ defp maybe_add_transport_opts(opts) do
+ transport_opts = get_in(opts, [:pools, :default, :conn_opts, :transport_opts])
+
+ unless is_nil(transport_opts) do
+ opts
+ else
+ put_in(opts, [:pools, :default, :conn_opts, :transport_opts], [])
+ end
+ end
+
@doc """
Merge default connection & adapter options with received ones.
"""
@@ -110,7 +131,7 @@ defmodule Pleroma.HTTP.AdapterHelper do
{:ok, type, uri.host, uri.port}
else
e ->
- Logger.warn("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}")
+ Logger.warning("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}")
{:error, :invalid_proxy}
end
end
@@ -120,7 +141,7 @@ defmodule Pleroma.HTTP.AdapterHelper do
{:ok, type, host, port}
else
_ ->
- Logger.warn("Parsing proxy failed #{inspect(proxy)}")
+ Logger.warning("Parsing proxy failed #{inspect(proxy)}")
{:error, :invalid_proxy}
end
end
diff --git a/lib/pleroma/maintenance.ex b/lib/pleroma/maintenance.ex
index 41c799712..736fbf317 100644
--- a/lib/pleroma/maintenance.ex
+++ b/lib/pleroma/maintenance.ex
@@ -20,7 +20,7 @@ defmodule Pleroma.Maintenance do
"full" ->
Logger.info("Running VACUUM FULL.")
- Logger.warn(
+ Logger.warning(
"Re-packing your entire database may take a while and will consume extra disk space during the process."
)
diff --git a/lib/pleroma/migrators/support/base_migrator.ex b/lib/pleroma/migrators/support/base_migrator.ex
index 2ffb35081..02c6ed080 100644
--- a/lib/pleroma/migrators/support/base_migrator.ex
+++ b/lib/pleroma/migrators/support/base_migrator.ex
@@ -73,7 +73,7 @@ defmodule Pleroma.Migrators.Support.BaseMigrator do
data_migration.state == :manual or data_migration.name in manual_migrations ->
message = "Data migration is in manual execution or manual fix mode."
update_status(:manual, message)
- Logger.warn("#{__MODULE__}: #{message}")
+ Logger.warning("#{__MODULE__}: #{message}")
data_migration.state == :complete ->
on_complete(data_migration)
@@ -109,7 +109,7 @@ defmodule Pleroma.Migrators.Support.BaseMigrator do
Putting data migration to manual fix mode. Try running `#{__MODULE__}.retry_failed/0`.
"""
- Logger.warn("#{__MODULE__}: #{message}")
+ Logger.warning("#{__MODULE__}: #{message}")
update_status(:manual, message)
on_complete(data_migration())
@@ -125,7 +125,7 @@ defmodule Pleroma.Migrators.Support.BaseMigrator do
defp on_complete(data_migration) do
if data_migration.feature_lock || feature_state() == :disabled do
- Logger.warn(
+ Logger.warning(
"#{__MODULE__}: migration complete but feature is locked; consider enabling."
)
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 3995be01f..885d61233 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -195,6 +195,7 @@ defmodule Pleroma.Notification do
from([_n, a, o] in query,
where:
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
+ fragment("?->>'content' is null", o.data) or
fragment("?->>'actor' = ?", o.data, ^user.ap_id)
)
end
@@ -695,7 +696,7 @@ defmodule Pleroma.Notification do
cond do
opts[:type] == "poll" -> false
user.ap_id == actor -> false
- !User.following?(follower, user) -> true
+ !User.following?(user, follower) -> true
true -> false
end
end
diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex
index aeaf05986..9e62ca69f 100644
--- a/lib/pleroma/object/fetcher.ex
+++ b/lib/pleroma/object/fetcher.ex
@@ -117,6 +117,8 @@ defmodule Pleroma.Object.Fetcher do
# Note: will create a Create activity, which we need internally at the moment.
def fetch_object_from_id(id, options \\ []) do
with %URI{} = uri <- URI.parse(id),
+ # let's check the URI is even vaguely valid first
+ {:scheme, true} <- {:scheme, uri.scheme == "http" or uri.scheme == "https"},
# If we have instance restrictions, apply them here to prevent fetching from unwanted instances
{:ok, nil} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_reject(uri),
{:ok, _} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_accept(uri),
@@ -135,6 +137,9 @@ defmodule Pleroma.Object.Fetcher do
{:allowed_depth, false} ->
{:error, "Max thread distance exceeded."}
+ {:scheme, false} ->
+ {:error, "URI Scheme Invalid"}
+
{:containment, _} ->
{:error, "Object containment failed."}
diff --git a/lib/pleroma/object/updater.ex b/lib/pleroma/object/updater.ex
index ab38d3ed2..64faec074 100644
--- a/lib/pleroma/object/updater.ex
+++ b/lib/pleroma/object/updater.ex
@@ -129,7 +129,10 @@ defmodule Pleroma.Object.Updater do
else
%{updated_object: updated_data} =
updated_data
- |> maybe_update_history(original_data, updated: updated, use_history_in_new_object?: false)
+ |> maybe_update_history(original_data,
+ updated: updated,
+ use_history_in_new_object?: false
+ )
updated_data
|> Map.put("updated", date)
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 2f65540be..99b6b5215 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -63,6 +63,9 @@ defmodule Pleroma.Upload do
blurhash: String.t(),
path: String.t()
}
+
+ @always_enabled_filters [Pleroma.Upload.Filter.AnonymizeFilename]
+
defstruct [:id, :name, :tempfile, :content_type, :width, :height, :blurhash, :path]
@spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()}
@@ -132,7 +135,11 @@ defmodule Pleroma.Upload do
activity_type: Keyword.get(opts, :activity_type, activity_type),
size_limit: Keyword.get(opts, :size_limit, size_limit),
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
- filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
+ filters:
+ Enum.uniq(
+ Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])) ++
+ @always_enabled_filters
+ ),
description: Keyword.get(opts, :description),
base_url: base_url()
}
diff --git a/lib/pleroma/upload/filter.ex b/lib/pleroma/upload/filter.ex
index e5db2fb20..50e0f2c27 100644
--- a/lib/pleroma/upload/filter.ex
+++ b/lib/pleroma/upload/filter.ex
@@ -38,9 +38,9 @@ defmodule Pleroma.Upload.Filter do
{:ok, :noop} ->
filter(rest, upload)
- error ->
- Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(error)}")
- error
+ {:error, e} ->
+ Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(e)}")
+ {:error, e}
end
end
end
diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex
index 8990e97c0..e2dbacf6a 100644
--- a/lib/pleroma/upload/filter/analyze_metadata.ex
+++ b/lib/pleroma/upload/filter/analyze_metadata.ex
@@ -28,7 +28,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do
{:ok, :filtered, upload}
rescue
e in ErlangError ->
- Logger.warn("#{__MODULE__}: #{inspect(e)}")
+ Logger.warning("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end
@@ -45,7 +45,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do
{:ok, :filtered, upload}
rescue
e in ErlangError ->
- Logger.warn("#{__MODULE__}: #{inspect(e)}")
+ Logger.warning("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end
diff --git a/lib/pleroma/upload/filter/only_media.ex b/lib/pleroma/upload/filter/only_media.ex
new file mode 100644
index 000000000..a9caeba67
--- /dev/null
+++ b/lib/pleroma/upload/filter/only_media.ex
@@ -0,0 +1,20 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2023 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Upload.Filter.OnlyMedia do
+ @behaviour Pleroma.Upload.Filter
+ alias Pleroma.Upload
+
+ def filter(%Upload{content_type: content_type}) do
+ [type, _subtype] = String.split(content_type, "/")
+
+ if type in ["image", "video", "audio"] do
+ {:ok, :noop}
+ else
+ {:error, "Disallowed content-type: #{content_type}"}
+ end
+ end
+
+ def filter(_), do: {:ok, :noop}
+end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 273bdf337..83b45e3b4 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -876,7 +876,7 @@ defmodule Pleroma.User do
end
end
- defp send_user_approval_email(user) do
+ defp send_user_approval_email(%User{email: email} = user) when is_binary(email) do
user
|> Pleroma.Emails.UserEmail.approval_pending_email()
|> Pleroma.Emails.Mailer.deliver_async()
@@ -884,6 +884,10 @@ defmodule Pleroma.User do
{:ok, :enqueued}
end
+ defp send_user_approval_email(_user) do
+ {:ok, :skipped}
+ end
+
defp send_admin_approval_emails(user) do
all_superusers()
|> Enum.filter(fn user -> not is_nil(user.email) end)
@@ -1489,7 +1493,7 @@ defmodule Pleroma.User do
unmute(muter, mutee)
else
{who, result} = error ->
- Logger.warn(
+ Logger.warning(
"User.unmute/2 failed. #{who}: #{result}, muter_id: #{muter_id}, mutee_id: #{mutee_id}"
)
@@ -2006,7 +2010,6 @@ defmodule Pleroma.User do
%User{
invisible: true,
local: true,
- actor_type: "Application",
ap_id: uri,
nickname: nickname,
follower_address: uri <> "/followers"
diff --git a/lib/pleroma/user/backup.ex b/lib/pleroma/user/backup.ex
index 63709a484..de967abe3 100644
--- a/lib/pleroma/user/backup.ex
+++ b/lib/pleroma/user/backup.ex
@@ -119,7 +119,7 @@ defmodule Pleroma.User.Backup do
end
end
- @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json']
+ @files [~c"actor.json", ~c"outbox.json", ~c"likes.json", ~c"bookmarks.json"]
def export(%__MODULE__{} = backup) do
backup = Repo.preload(backup, :user)
name = String.trim_trailing(backup.file_name, ".zip")
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 4e6842d85..793b08f3d 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -454,7 +454,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(message)
e ->
- Logger.warn(fn -> "AP C2S: #{inspect(e)}" end)
+ Logger.warning(fn -> "AP C2S: #{inspect(e)}" end)
conn
|> put_status(:bad_request)
diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex
index 88a58421e..d03568444 100644
--- a/lib/pleroma/web/activity_pub/mrf.ex
+++ b/lib/pleroma/web/activity_pub/mrf.ex
@@ -70,6 +70,8 @@ defmodule Pleroma.Web.ActivityPub.MRF do
end
def filter_one(policy, message) do
+ Code.ensure_loaded!(policy)
+
should_plug_history? =
if function_exported?(policy, :history_awareness, 0) do
policy.history_awareness()
@@ -239,7 +241,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do
if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
[description | acc]
else
- Logger.warn(
+ Logger.warning(
"#{policy} config description doesn't have one or all required keys #{inspect(@required_description_keys)}"
)
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 61e95b49a..45b2d4ca7 100644
--- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex
@@ -41,7 +41,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
shortcode
e ->
- Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
+ Logger.warning("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
nil
end
else
@@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
end
else
e ->
- Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
+ Logger.warning("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
nil
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
index d4beed78d..4d1e80868 100644
--- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
import Ecto.Changeset
require Logger
+ require Pleroma.Web.ActivityPub.Transmogrifier
@primary_key false
@derive Jason.Encoder
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
index 6fa2bbb99..be7df3fb0 100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex
@@ -22,7 +22,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
end
def fix_object_defaults(data) do
- context = Utils.maybe_create_context(data["context"] || data["conversation"])
+ context =
+ Utils.maybe_create_context(
+ data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]
+ )
%User{follower_address: follower_collection} = User.get_cached_by_ap_id(data["attributedTo"])
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 5c96bf060..435343bf0 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -136,7 +136,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.drop(["conversation", "inReplyToAtomUri"])
else
e ->
- Logger.warn("Couldn't fetch reply@#{inspect(in_reply_to_id)}, error: #{inspect(e)}")
+ Logger.warning("Couldn't fetch reply@#{inspect(in_reply_to_id)}, error: #{inspect(e)}")
object
end
else
@@ -159,7 +159,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("quoteUri", quoted_object.data["id"])
else
e ->
- Logger.warn("Couldn't fetch quote@#{inspect(quote_url)}, error: #{inspect(e)}")
+ Logger.warning("Couldn't fetch quote@#{inspect(quote_url)}, error: #{inspect(e)}")
object
end
else
@@ -920,8 +920,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def prepare_attachments(object) do
attachments =
- object
- |> Map.get("attachment", [])
+ case Map.get(object, "attachment", []) do
+ [_ | _] = list -> list
+ _ -> []
+ end
+
+ attachments =
+ attachments
|> Enum.map(fn data ->
[%{"mediaType" => media_type, "href" => href} = url | _] = data["url"]
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 310f3ce3e..7333fb2c1 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -15,6 +15,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers
+ require Pleroma.Web.ActivityPub.Transmogrifier
+
import Ecto.Query
def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 8a6851d52..2d14316d1 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -410,7 +410,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
- parameters: pagination_params(),
+ parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
@@ -767,7 +767,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
"showing_reblogs" => true,
"followed_by" => true,
"blocking" => false,
- "blocked_by" => true,
+ "blocked_by" => false,
"muting" => false,
"muting_notifications" => false,
"note" => "",
@@ -783,7 +783,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
"showing_reblogs" => true,
"followed_by" => true,
"blocking" => false,
- "blocked_by" => true,
+ "blocked_by" => false,
"muting" => true,
"muting_notifications" => false,
"note" => "",
diff --git a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
index d25ab5247..9290ab09d 100644
--- a/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/admin/status_operation.ex
@@ -143,7 +143,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.StatusOperation do
}
},
tags: %Schema{type: :string},
- is_confirmed: %Schema{type: :string}
+ is_confirmed: %Schema{type: :boolean}
}
}
end
diff --git a/lib/pleroma/web/api_spec/schemas/account_relationship.ex b/lib/pleroma/web/api_spec/schemas/account_relationship.ex
index 5d9e3b56e..58751b261 100644
--- a/lib/pleroma/web/api_spec/schemas/account_relationship.ex
+++ b/lib/pleroma/web/api_spec/schemas/account_relationship.ex
@@ -13,7 +13,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.AccountRelationship do
description: "Relationship between current account and requested account",
type: :object,
properties: %{
- blocked_by: %Schema{type: :boolean},
+ blocked_by: %Schema{
+ type: :boolean,
+ description: "Represents being blocked by this user. Always false."
+ },
blocking: %Schema{type: :boolean},
domain_blocking: %Schema{type: :boolean},
endorsed: %Schema{type: :boolean},
diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex
index a6df9be94..28386b096 100644
--- a/lib/pleroma/web/api_spec/schemas/status.ex
+++ b/lib/pleroma/web/api_spec/schemas/status.ex
@@ -232,7 +232,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
source: %Schema{
nullable: true,
oneOf: [
- %Schema{type: :string, example: 'plaintext content'},
+ %Schema{type: :string, example: ~c"plaintext content"},
%Schema{
type: :object,
properties: %{
diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex
index ccf4b4104..44b50d126 100644
--- a/lib/pleroma/web/auth/ldap_authenticator.ex
+++ b/lib/pleroma/web/auth/ldap_authenticator.ex
@@ -110,7 +110,7 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
}
params =
- case List.keyfind(attributes, 'mail', 0) do
+ case List.keyfind(attributes, ~c"mail", 0) do
{_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
_ -> params
end
diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex
index f1f51acf5..6b62ef2d1 100644
--- a/lib/pleroma/web/common_api.ex
+++ b/lib/pleroma/web/common_api.ex
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.CommonAPI do
def delete(activity_id, user) do
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
- {:find_activity, Activity.get_by_id(activity_id)},
+ {:find_activity, Activity.get_by_id(activity_id, filter: [])},
{_, %Object{} = object, _} <-
{:find_object, Object.normalize(activity, fetch: false), activity},
true <- User.superuser?(user) || user.ap_id == object.data["actor"],
@@ -467,7 +467,7 @@ defmodule Pleroma.Web.CommonAPI do
remove_mute(user, activity)
else
{what, result} = error ->
- Logger.warn(
+ Logger.warning(
"CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{activity_id}"
)
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 54918d13c..e79b12fc9 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -144,6 +144,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
when is_list(options) do
limits = Config.get([:instance, :poll_limits])
+ options = options |> Enum.uniq()
+
with :ok <- validate_poll_expiration(expires_in, limits),
:ok <- validate_poll_options_amount(options, limits),
:ok <- validate_poll_options_length(options, limits) do
@@ -179,10 +181,15 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
defp validate_poll_options_amount(options, %{max_options: max_options}) do
- if Enum.count(options) > max_options do
- {:error, "Poll can't contain more than #{max_options} options"}
- else
- :ok
+ cond do
+ Enum.count(options) < 2 ->
+ {:error, "Poll must contain at least 2 options"}
+
+ Enum.count(options) > max_options ->
+ {:error, "Poll can't contain more than #{max_options} options"}
+
+ true ->
+ :ok
end
end
@@ -317,13 +324,13 @@ defmodule Pleroma.Web.CommonAPI.Utils do
format_asctime(date)
else
_e ->
- Logger.warn("Date #{date} in wrong format, must be ISO 8601")
+ Logger.warning("Date #{date} in wrong format, must be ISO 8601")
""
end
end
def date_to_asctime(date) do
- Logger.warn("Date #{date} in wrong format, must be ISO 8601")
+ Logger.warning("Date #{date} in wrong format, must be ISO 8601")
""
end
diff --git a/lib/pleroma/web/embed_controller.ex b/lib/pleroma/web/embed_controller.ex
index c7912bb1f..cffd6e29f 100644
--- a/lib/pleroma/web/embed_controller.ex
+++ b/lib/pleroma/web/embed_controller.ex
@@ -11,22 +11,31 @@ defmodule Pleroma.Web.EmbedController do
alias Pleroma.Web.ActivityPub.Visibility
- plug(:put_layout, :embed)
-
def show(conn, %{"id" => id}) do
- with %Activity{local: true} = activity <-
- Activity.get_by_id_with_object(id),
- true <- Visibility.is_public?(activity.object) do
+ with {:activity, %Activity{} = activity} <-
+ {:activity, Activity.get_by_id_with_object(id)},
+ {:local, true} <- {:local, activity.local},
+ {:visible, true} <- {:visible, Visibility.visible_for_user?(activity, nil)} do
{:ok, author} = User.get_or_fetch(activity.object.data["actor"])
conn
|> delete_resp_header("x-frame-options")
|> delete_resp_header("content-security-policy")
+ |> put_view(Pleroma.Web.EmbedView)
|> render("show.html",
activity: activity,
author: User.sanitize_html(author),
counts: get_counts(activity)
)
+ else
+ {:activity, _} ->
+ render_error(conn, :not_found, "Post not found")
+
+ {:local, false} ->
+ render_error(conn, :unauthorized, "Federated posts cannot be embedded")
+
+ {:visible, false} ->
+ render_error(conn, :unauthorized, "Not authorized to view this post")
end
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 057af762a..26f46cc1a 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -497,7 +497,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users =
user
|> User.muted_users_relation(_restrict_deactivated = true)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
+ |> Pleroma.Pagination.fetch_paginated(params)
conn
|> add_link_headers(users)
@@ -514,11 +514,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users =
user
|> User.blocked_users_relation(_restrict_deactivated = true)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
+ |> Pleroma.Pagination.fetch_paginated(params)
conn
|> add_link_headers(users)
- |> render("index.json", users: users, for: user, as: :user)
+ |> render("index.json",
+ users: users,
+ for: user,
+ as: :user,
+ embed_relationships: embed_relationships?(params)
+ )
end
@doc "GET /api/v1/accounts/lookup"
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index e0fa3b033..e3f91a4e3 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -124,14 +124,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
target,
&User.blocks_user?(&1, &2)
),
- blocked_by:
- UserRelationship.exists?(
- user_relationships,
- :block,
- target,
- reading_user,
- &User.blocks_user?(&1, &2)
- ),
+ blocked_by: false,
muting:
UserRelationship.exists?(
user_relationships,
diff --git a/lib/pleroma/web/media_proxy.ex b/lib/pleroma/web/media_proxy.ex
index 0b232f14b..c5087c42c 100644
--- a/lib/pleroma/web/media_proxy.ex
+++ b/lib/pleroma/web/media_proxy.ex
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.MediaProxy do
@spec url_proxiable?(String.t()) :: boolean()
def url_proxiable?(url) do
- not local?(url) and not whitelisted?(url)
+ not local?(url) and not whitelisted?(url) and not blocked?(url)
end
def preview_url(url, preview_params \\ []) do
@@ -76,13 +76,23 @@ defmodule Pleroma.Web.MediaProxy do
mediaproxy_whitelist_domains =
[:media_proxy, :whitelist]
- |> Config.get()
+ |> Config.get([])
|> Kernel.++(["#{Upload.base_url()}"])
|> Enum.map(&maybe_get_domain_from_url/1)
domain in mediaproxy_whitelist_domains
end
+ def blocked?(url) do
+ %{scheme: scheme, host: domain} = URI.parse(url)
+ # Block either the bare domain or the scheme-domain combo
+ scheme_domain = "#{scheme}://#{domain}"
+ blocklist = Config.get([:media_proxy, :blocklist])
+
+ Enum.member?(blocklist, domain) ||
+ Enum.member?(blocklist, scheme_domain)
+ end
+
defp maybe_get_domain_from_url("http" <> _ = url) do
URI.parse(url).host
end
diff --git a/lib/pleroma/web/metadata/providers/rel_me.ex b/lib/pleroma/web/metadata/providers/rel_me.ex
index f013def51..cf6a3a3ab 100644
--- a/lib/pleroma/web/metadata/providers/rel_me.ex
+++ b/lib/pleroma/web/metadata/providers/rel_me.ex
@@ -8,12 +8,20 @@ defmodule Pleroma.Web.Metadata.Providers.RelMe do
@impl Provider
def build_tags(%{user: user}) do
- bio_tree = Floki.parse_fragment!(user.bio)
+ profile_tree =
+ user.bio
+ |> append_fields_tag(user.fields)
+ |> Floki.parse_fragment!()
- (Floki.attribute(bio_tree, "link[rel~=me]", "href") ++
- Floki.attribute(bio_tree, "a[rel~=me]", "href"))
+ (Floki.attribute(profile_tree, "link[rel~=me]", "href") ++
+ Floki.attribute(profile_tree, "a[rel~=me]", "href"))
|> Enum.map(fn link ->
{:link, [rel: "me", href: link], []}
end)
end
+
+ defp append_fields_tag(bio, fields) do
+ fields
+ |> Enum.reduce(bio, fn %{"value" => v}, res -> res <> v end)
+ end
end
diff --git a/lib/pleroma/web/metadata/providers/twitter_card.ex b/lib/pleroma/web/metadata/providers/twitter_card.ex
index 79183df86..b2497d14e 100644
--- a/lib/pleroma/web/metadata/providers/twitter_card.ex
+++ b/lib/pleroma/web/metadata/providers/twitter_card.ex
@@ -20,12 +20,12 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
[
title_tag(user),
- {:meta, [property: "twitter:description", content: scrubbed_content], []}
+ {:meta, [name: "twitter:description", content: scrubbed_content], []}
] ++
if attachments == [] or Metadata.activity_nsfw?(object) do
[
image_tag(user),
- {:meta, [property: "twitter:card", content: "summary"], []}
+ {:meta, [name: "twitter:card", content: "summary"], []}
]
else
attachments
@@ -37,20 +37,19 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
[
title_tag(user),
- {:meta, [property: "twitter:description", content: truncated_bio], []},
+ {:meta, [name: "twitter:description", content: truncated_bio], []},
image_tag(user),
- {:meta, [property: "twitter:card", content: "summary"], []}
+ {:meta, [name: "twitter:card", content: "summary"], []}
]
end
end
defp title_tag(user) do
- {:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}
+ {:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []}
end
def image_tag(user) do
- {:meta, [property: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))],
- []}
+ {:meta, [name: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))], []}
end
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
@@ -60,10 +59,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" ->
[
- {:meta, [property: "twitter:card", content: "player"], []},
- {:meta, [property: "twitter:player:width", content: "480"], []},
- {:meta, [property: "twitter:player:height", content: "80"], []},
- {:meta, [property: "twitter:player", content: player_url(id)], []}
+ {:meta, [name: "twitter:card", content: "player"], []},
+ {:meta, [name: "twitter:player:width", content: "480"], []},
+ {:meta, [name: "twitter:player:height", content: "80"], []},
+ {:meta, [name: "twitter:player", content: player_url(id)], []}
| acc
]
@@ -74,10 +73,10 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
# workaround.
"image" ->
[
- {:meta, [property: "twitter:card", content: "summary_large_image"], []},
+ {:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta,
[
- property: "twitter:player",
+ name: "twitter:player",
content: MediaProxy.url(url["href"])
], []}
| acc
@@ -90,14 +89,14 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
width = url["width"] || 480
[
- {:meta, [property: "twitter:card", content: "player"], []},
- {:meta, [property: "twitter:player", content: player_url(id)], []},
- {:meta, [property: "twitter:player:width", content: "#{width}"], []},
- {:meta, [property: "twitter:player:height", content: "#{height}"], []},
- {:meta, [property: "twitter:player:stream", content: MediaProxy.url(url["href"])],
+ {:meta, [name: "twitter:card", content: "player"], []},
+ {:meta, [name: "twitter:player", content: player_url(id)], []},
+ {:meta, [name: "twitter:player:width", content: "#{width}"], []},
+ {:meta, [name: "twitter:player:height", content: "#{height}"], []},
+ {:meta, [name: "twitter:player:stream", content: MediaProxy.url(url["href"])],
[]},
- {:meta,
- [property: "twitter:player:stream:content_type", content: url["mediaType"]], []}
+ {:meta, [name: "twitter:player:stream:content_type", content: url["mediaType"]],
+ []}
| acc
]
@@ -123,8 +122,8 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
!is_nil(url["height"]) && !is_nil(url["width"]) ->
metadata ++
[
- {:meta, [property: "twitter:player:width", content: "#{url["width"]}"], []},
- {:meta, [property: "twitter:player:height", content: "#{url["height"]}"], []}
+ {:meta, [name: "twitter:player:width", content: "#{url["width"]}"], []},
+ {:meta, [name: "twitter:player:height", content: "#{url["height"]}"], []}
]
true ->
diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex
index 7308726f5..92622ef15 100644
--- a/lib/pleroma/web/metadata/utils.ex
+++ b/lib/pleroma/web/metadata/utils.ex
@@ -55,7 +55,7 @@ defmodule Pleroma.Web.Metadata.Utils do
def user_name_string(user) do
"#{user.name} " <>
if user.local do
- "(@#{user.nickname}@#{Pleroma.Web.Endpoint.host()})"
+ "(@#{user.nickname}@#{Pleroma.Web.WebFinger.domain()})"
else
"(@#{user.nickname})"
end
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
index 0933363a6..e762fcad8 100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex
@@ -41,6 +41,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
end
end
+ defp filter_allowed_user_by_ap_id(ap_ids, excluded_ap_ids) do
+ Enum.reject(ap_ids, fn ap_id ->
+ with false <- ap_id in excluded_ap_ids,
+ %{is_active: true} <- User.get_cached_by_ap_id(ap_id) do
+ false
+ else
+ _ -> true
+ end
+ end)
+ end
+
def filter_allowed_users(reactions, user, with_muted) do
exclude_ap_ids =
if is_nil(user) do
@@ -51,7 +62,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiReactionController do
end
filter_emoji = fn emoji, users, url ->
- case Enum.reject(users, &(&1 in exclude_ap_ids)) do
+ case filter_allowed_user_by_ap_id(users, exclude_ap_ids) do
[] -> nil
users -> {emoji, users, url}
end
diff --git a/lib/pleroma/web/plugs/http_security_plug.ex b/lib/pleroma/web/plugs/http_security_plug.ex
index d7cff7343..3dfc7e6a3 100644
--- a/lib/pleroma/web/plugs/http_security_plug.ex
+++ b/lib/pleroma/web/plugs/http_security_plug.ex
@@ -200,7 +200,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
def warn_if_disabled do
unless Config.get([:http_security, :enabled]) do
- Logger.warn("
+ Logger.warning("
.i;;;;i.
iYcviii;vXY:
.YXi .i1c.
diff --git a/lib/pleroma/web/plugs/http_signature_plug.ex b/lib/pleroma/web/plugs/http_signature_plug.ex
index 4ffaa6e98..488108b08 100644
--- a/lib/pleroma/web/plugs/http_signature_plug.ex
+++ b/lib/pleroma/web/plugs/http_signature_plug.ex
@@ -104,7 +104,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
:noop
any ->
- Logger.warn(
+ Logger.warning(
"expected request signature cache to return a boolean, instead got #{inspect(any)}"
)
end
diff --git a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
index f017c8bc7..e4d098a7d 100644
--- a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
@@ -34,7 +34,9 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
permissions = Enum.join(missing_scopes, " #{op} ")
error_message =
- dgettext("errors", "Insufficient permissions: %{permissions}.", permissions: permissions)
+ dgettext("errors", "Insufficient permissions: %{permissions}.",
+ permissions: permissions
+ )
conn
|> put_resp_content_type("application/json")
diff --git a/lib/pleroma/web/plugs/rate_limiter.ex b/lib/pleroma/web/plugs/rate_limiter.ex
index 3c82654b4..4bcf027d6 100644
--- a/lib/pleroma/web/plugs/rate_limiter.ex
+++ b/lib/pleroma/web/plugs/rate_limiter.ex
@@ -89,7 +89,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
end
defp handle_disabled(conn) do
- Logger.warn(
+ Logger.warning(
"Rate limiter disabled due to forwarded IP not being found. Please ensure your reverse proxy is providing the X-Forwarded-For header or disable the RemoteIP plug/rate limiter."
)
diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex
index 72f20e8de..300c33068 100644
--- a/lib/pleroma/web/plugs/uploaded_media.ex
+++ b/lib/pleroma/web/plugs/uploaded_media.ex
@@ -37,7 +37,7 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
%{query_params: %{"name" => name}} = conn ->
name = escape_header_value(name)
- put_resp_header(conn, "content-disposition", "filename=\"#{name}\"")
+ put_resp_header(conn, "content-disposition", ~s[inline; filename="#{name}"])
conn ->
conn
diff --git a/lib/pleroma/web/push.ex b/lib/pleroma/web/push.ex
index 154dae614..76e17f7cd 100644
--- a/lib/pleroma/web/push.ex
+++ b/lib/pleroma/web/push.ex
@@ -9,7 +9,7 @@ defmodule Pleroma.Web.Push do
def init do
unless enabled() do
- Logger.warn("""
+ Logger.warning("""
VAPID key pair is not found. If you wish to enabled web push, please run
mix web_push.gen.keypair
diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex
index e103cafc2..e514b4896 100644
--- a/lib/pleroma/web/push/impl.ex
+++ b/lib/pleroma/web/push/impl.ex
@@ -57,7 +57,7 @@ defmodule Pleroma.Web.Push.Impl do
end
def perform(_) do
- Logger.warn("Unknown notification type")
+ Logger.warning("Unknown notification type")
{:error, :unknown_type}
end
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index 1d4cad010..3ba0086f0 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -75,7 +75,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
end
defp log_error(url, reason) do
- Logger.warn(fn -> "Rich media error for #{url}: #{inspect(reason)}" end)
+ Logger.warning(fn -> "Rich media error for #{url}: #{inspect(reason)}" end)
end
end
@@ -151,7 +151,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
Task.await(task, 5000)
catch
:exit, {:timeout, _} ->
- Logger.warn("Timeout while fetching rich media for #{url}")
+ Logger.warning("Timeout while fetching rich media for #{url}")
{:error, :timeout}
end
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 7550eefdf..3ea3c9132 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -477,13 +477,13 @@ defmodule Pleroma.Web.Router do
pipe_through(:api)
get(
- "/api/v1/akkoma/preferred_frontend/available",
+ "/preferred_frontend/available",
FrontendSettingsController,
:available_frontends
)
put(
- "/api/v1/akkoma/preferred_frontend",
+ "/preferred_frontend",
FrontendSettingsController,
:update_preferred_frontend
)
diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex
index f009fbd9e..1c3848bfb 100644
--- a/lib/pleroma/web/streamer.ex
+++ b/lib/pleroma/web/streamer.ex
@@ -25,6 +25,7 @@ defmodule Pleroma.Web.Streamer do
def registry, do: @registry
@public_streams ["public", "public:local", "public:media", "public:local:media"]
+ @local_streams ["public:local", "public:local:media"]
@user_streams ["user", "user:notification", "direct"]
@doc "Expands and authorizes a stream, and registers the process for streaming."
@@ -41,14 +42,37 @@ defmodule Pleroma.Web.Streamer do
end
end
+ defp can_access_stream(user, oauth_token, kind) do
+ with {_, true} <- {:restrict?, Config.restrict_unauthenticated_access?(:timelines, kind)},
+ {_, %User{id: user_id}, %Token{user_id: user_id}} <- {:user, user, oauth_token},
+ {_, true} <-
+ {:scopes,
+ OAuthScopesPlug.filter_descendants(["read:statuses"], oauth_token.scopes) != []} do
+ true
+ else
+ {:restrict?, _} ->
+ true
+
+ _ ->
+ false
+ end
+ end
+
@doc "Expand and authorizes a stream"
@spec get_topic(stream :: String.t(), User.t() | nil, Token.t() | nil, Map.t()) ::
{:ok, topic :: String.t()} | {:error, :bad_topic}
def get_topic(stream, user, oauth_token, params \\ %{})
- # Allow all public steams.
- def get_topic(stream, _user, _oauth_token, _params) when stream in @public_streams do
- {:ok, stream}
+ # Allow all public steams if the instance allows unauthenticated access.
+ # Otherwise, only allow users with valid oauth tokens.
+ def get_topic(stream, user, oauth_token, _params) when stream in @public_streams do
+ kind = if stream in @local_streams, do: :local, else: :federated
+
+ if can_access_stream(user, oauth_token, kind) do
+ {:ok, stream}
+ else
+ {:error, :unauthorized}
+ end
end
# Allow all hashtags streams.
@@ -57,12 +81,20 @@ defmodule Pleroma.Web.Streamer do
end
# Allow remote instance streams.
- def get_topic("public:remote", _user, _oauth_token, %{"instance" => instance} = _params) do
- {:ok, "public:remote:" <> instance}
+ def get_topic("public:remote", user, oauth_token, %{"instance" => instance} = _params) do
+ if can_access_stream(user, oauth_token, :federated) do
+ {:ok, "public:remote:" <> instance}
+ else
+ {:error, :unauthorized}
+ end
end
- def get_topic("public:remote:media", _user, _oauth_token, %{"instance" => instance} = _params) do
- {:ok, "public:remote:media:" <> instance}
+ def get_topic("public:remote:media", user, oauth_token, %{"instance" => instance} = _params) do
+ if can_access_stream(user, oauth_token, :federated) do
+ {:ok, "public:remote:media:" <> instance}
+ else
+ {:error, :unauthorized}
+ end
end
# Expand user streams.
diff --git a/lib/pleroma/web/templates/layout/embed.html.eex b/lib/pleroma/web/templates/layout/embed.html.eex
index 8b905f070..49f2cdb5b 100644
--- a/lib/pleroma/web/templates/layout/embed.html.eex
+++ b/lib/pleroma/web/templates/layout/embed.html.eex
@@ -6,10 +6,10 @@
<%= Pleroma.Config.get([:instance, :name]) %>
<%= Phoenix.HTML.raw(assigns[:meta] || "") %>
-
+
- <%= render @view_module, @view_template, assigns %>
+ <%= render view_module(@conn), view_template(@conn), assigns %>