diff --git a/.gitignore b/.gitignore
index d8e5ed553..355cea069 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,9 +56,6 @@ pleroma.iml
# asdf
.tool-versions
-# mise
-mise.toml
-
# Editor temp files
*~
*#
diff --git a/.woodpecker/changelog.yaml b/.woodpecker/changelog.yaml
index 64062f17e..4f38ce618 100644
--- a/.woodpecker/changelog.yaml
+++ b/.woodpecker/changelog.yaml
@@ -1,19 +1,9 @@
when:
- event: pull_request
-labels:
- platform: linux/amd64
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
-
steps:
check-changelog:
image: docker.io/alpine:3.23
- entrypoint: *script_file_entrypoint
commands:
- apk add --no-cache git
- sh ./tools/check-changelog
diff --git a/.woodpecker/docker-combine.yaml b/.woodpecker/docker-combine.yaml
deleted file mode 100644
index 6c91d26e9..000000000
--- a/.woodpecker/docker-combine.yaml
+++ /dev/null
@@ -1,60 +0,0 @@
-when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**", "Dockerfile" ]
- - event: tag
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: stable
-
-depends_on:
- - docker
-
-skip_clone: true
-
-labels:
- platform: linux/amd64
-
-steps:
- docker-develop-combine:
- image: git.fluffytail.org/phnt/wpc-docker-tagger:latest
- when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- settings: &docker_settings
- registry: "git.pleroma.social"
- image: "pleroma/pleroma"
- architectures: [amd64, arm64]
- tags:
- - latest
- - develop
- - ${CI_COMMIT_SHA:0:8}
- username:
- from_secret: pleroma-ci-user
- password:
- from_secret: pleroma-ci-password
-
- docker-stable-combine:
- image: git.fluffytail.org/phnt/wpc-docker-tagger:latest
- when:
- - evaluate: 'CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG == ""'
- settings:
- <<: *docker_settings
- tags: &stable_docker_tags
- - latest
- - stable
- - ${CI_COMMIT_SHA:0:8}
-
- docker-stable-tag-combine:
- image: git.fluffytail.org/phnt/wpc-docker-tagger:latest
- when:
- - event: tag
- - evaluate: 'CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG != ""'
- settings:
- <<: *docker_settings
- tags:
- - <<: *stable_docker_tags
- - ${CI_COMMIT_TAG}
diff --git a/.woodpecker/docker.yaml b/.woodpecker/docker.yaml
deleted file mode 100644
index abc6bfa3b..000000000
--- a/.woodpecker/docker.yaml
+++ /dev/null
@@ -1,96 +0,0 @@
-when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**", "Dockerfile" ]
- - event: tag
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: stable
-
-matrix:
- platform:
- - linux/amd64
- - linux/arm64
-
-# This is needed for the when clauses below.
-labels:
- platform: ${platform}
- memory: 'high'
-
-variables:
- docker_variables: &docker_variables
- repo: pleroma/pleroma
- registry: git.pleroma.social
- username:
- from_secret: pleroma-ci-user
- password:
- from_secret: pleroma-ci-password
- kaniko_image: &kaniko_image woodpeckerci/plugin-kaniko:2.3.1
-
-steps:
- docker-develop-amd64:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - evaluate: 'platform == "linux/amd64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- settings:
- <<: *docker_variables
- tags:
- - latest-amd64
- - develop-amd64
- - ${CI_COMMIT_SHA:0:8}-amd64
-
- docker-develop-arm64:
- image: woodpeckerci/plugin-kaniko:2.3.1
- when:
- - evaluate: 'platform == "linux/arm64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- settings:
- <<: *docker_variables
- tags:
- - latest-arm64
- - develop-arm64
- - ${CI_COMMIT_SHA:0:8}-arm64
-
- docker-stable-amd64:
- image: *kaniko_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG == ""'
- settings:
- <<: *docker_variables
- tags: &amd64_tags
- - latest-amd64
- - stable-amd64
- - ${CI_COMMIT_SHA:0:8}-amd64
-
- docker-stable-tag-amd64:
- image: *kaniko_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG != ""'
- settings:
- <<: *docker_variables
- tags:
- - <<: *amd64_tags
- - ${CI_COMMIT_TAG}-amd64
-
- docker-stable-arm64:
- image: *kaniko_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG == ""'
- settings:
- <<: *docker_variables
- tags: &arm64_tags
- - latest-arm64
- - stable-arm64
- - ${CI_COMMIT_SHA:0:8}-arm64
-
- docker-stable-tag-arm64:
- image: *kaniko_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable" && CI_COMMIT_TAG != ""'
- settings:
- <<: *docker_variables
- tags:
- - <<: *arm64_tags
- - ${CI_COMMIT_TAG}-arm64
diff --git a/.woodpecker/lint.yaml b/.woodpecker/lint.yaml
index 0ab7441a8..b96d584ee 100644
--- a/.woodpecker/lint.yaml
+++ b/.woodpecker/lint.yaml
@@ -1,24 +1,14 @@
when:
- event: pull_request
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
- event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
-
-labels:
- platform: linux/amd64
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
steps:
mix-format:
image: &elixir-image
docker.io/elixir:1.15-alpine
- entrypoint: *script_file_entrypoint
failure: ignore
commands:
- |
@@ -29,7 +19,6 @@ steps:
credo:
image: *elixir-image
- entrypoint: *script_file_entrypoint
failure: ignore
environment:
MIX_ENV: test
@@ -66,7 +55,6 @@ steps:
ensure-status:
image: *elixir-image
- entrypoint: *script_file_entrypoint
commands: |
if test -f fail.stamp; then
echo "One or more previous steps fails. Failing workflow..."
diff --git a/.woodpecker/otp-musl.yaml b/.woodpecker/otp-musl.yaml
deleted file mode 100644
index 60558b893..000000000
--- a/.woodpecker/otp-musl.yaml
+++ /dev/null
@@ -1,292 +0,0 @@
-when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
- - event: tag
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: stable
-
-matrix:
- platform:
- - linux/amd64
- - linux/arm
- - linux/arm64
-
-# This is needed for the when clauses below.
-# When the platform clause is fixed, this might not be needed anymore
-labels:
- platform: ${platform}
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
- build_cmds: &build_cmds
- - apk add git build-base cmake file-dev openssl vips-dev zip
- - echo "import Config" > config/prod.secret.exs
- - mix local.hex --force
- - mix local.rebar --force
- - mix deps.get --only prod
- - mkdir release
- - export PLEROMA_BUILD_BRANCH=${CI_COMMIT_BRANCH}
- - mix release --path release
- build_image_amd64: &build_image_amd64 docker.io/hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
- build_image_arm: &build_image_arm docker.io/arm32v7/elixir:1.17.3-alpine
- build_image_arm64: &build_image_arm64 docker.io/hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
- artifacts_uploader_image: &artifacts_uploader_image docker.io/woodpeckercommunity/plugin-gitea-package:0.5.0
- artifacts_uploader_settings: &artifacts_uploader_settings
- user:
- from_secret: pleroma-ci-user
- password:
- from_secret: pleroma-ci-password
- owner: 'pleroma'
- env: &env
- MIX_ENV: prod
- VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
-
-steps:
- otp-develop-amd64-musl:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &amd64_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64-musl.zip release
-
- otp-stable-amd64-musl:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *amd64_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-amd64-musl:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-amd64-musl.zip release
-
- otp-develop-arm-musl:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &arm_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm-musl.zip release
-
- otp-stable-arm-musl:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *arm_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-arm-musl:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-arm-musl.zip release
-
- otp-develop-arm64-musl:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &arm64_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64-musl.zip release
-
- otp-stable-arm64-musl:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *arm64_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-arm64-musl:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-arm64-musl.zip release
-
- upload-artifacts-amd64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-amd64-musl
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64-musl
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- update: 'true'
-
- upload-latest-amd64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-amd64-musl
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-amd64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-amd64-musl
- package_version: stable-${CI_COMMIT_SHA:0:8}-amd64-musl
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-amd64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-amd64-musl
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-amd64-musl.zip
- file_name: pleroma.zip
- update: 'true'
-
- upload-artifacts-arm-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm-musl
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm-musl
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- update: 'true'
-
- upload-latest-arm-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm-musl
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-arm-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm-musl
- package_version: stable-${CI_COMMIT_SHA:0:8}-arm-musl
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-arm-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm-musl
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm-musl.zip
- file_name: pleroma.zip
- update: 'true'
-
- upload-artifacts-arm64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm64-musl
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64-musl
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- update: 'true'
-
- upload-latest-arm64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm64-musl
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-arm64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm64-musl
- package_version: stable-${CI_COMMIT_SHA:0:8}-arm64-musl
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-arm64-musl:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm64-musl
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm64-musl.zip
- file_name: pleroma.zip
- update: 'true'
diff --git a/.woodpecker/otp.yaml b/.woodpecker/otp.yaml
deleted file mode 100644
index 9a33c228e..000000000
--- a/.woodpecker/otp.yaml
+++ /dev/null
@@ -1,293 +0,0 @@
-when:
- - event: push
- branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
- - event: tag
- - event: manual
- branch: ${CI_REPO_DEFAULT_BRANCH}
- - event: manual
- branch: stable
-
-matrix:
- platform:
- - linux/amd64
- - linux/arm
- - linux/arm64
-
-# This is needed for the when clauses below.
-# When the platform clause is fixed, this might not be needed anymore
-labels:
- platform: ${platform}
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
- build_cmds: &build_cmds
- - apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev git build-essential zip
- - echo "import Config" > config/prod.secret.exs
- - mix local.hex --force
- - mix local.rebar --force
- - mix deps.get --only prod
- - mkdir release
- - export PLEROMA_BUILD_BRANCH=${CI_COMMIT_BRANCH}
- - mix release --path release
- build_image_amd64: &build_image_amd64 docker.io/hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
- build_image_arm: &build_image_arm docker.io/arm32v7/elixir:1.17.3
- build_image_arm64: &build_image_arm64 docker.io/hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
- artifacts_uploader_image: &artifacts_uploader_image docker.io/woodpeckercommunity/plugin-gitea-package:0.5.0
- artifacts_uploader_settings: &artifacts_uploader_settings
- user:
- from_secret: pleroma-ci-user
- password:
- from_secret: pleroma-ci-password
- owner: 'pleroma'
- env: &env
- MIX_ENV: prod
- VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
- DEBIAN_FRONTEND: noninteractive
-
-steps:
- otp-develop-amd64:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &amd64_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64.zip release
-
- otp-stable-amd64:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *amd64_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-amd64:
- image: *build_image_amd64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-amd64.zip release
-
- otp-develop-arm:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &arm_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm.zip release
-
- otp-stable-arm:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *arm_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-arm:
- image: *build_image_arm
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-arm.zip release
-
- otp-develop-arm64:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- environment: *env
- commands: &arm64_build
- - <<: *build_cmds
- - zip -9rq ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64.zip release
-
- otp-stable-arm64:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual" && CI_COMMIT_BRANCH == "stable"'
- environment: *env
- commands: *arm64_build
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- otp-stable-tag-arm64:
- image: *build_image_arm64
- entrypoint: *script_file_entrypoint
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- environment: *env
- commands:
- - <<: *build_cmds
- - zip -9rq stable-${CI_COMMIT_SHA:0:8}-arm64.zip release
-
- upload-artifacts-amd64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-amd64
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64.zip
- update: 'true'
-
- upload-latest-amd64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-amd64
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-amd64.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-amd64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-amd64
- package_version: stable-${CI_COMMIT_SHA:0:8}-amd64
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-amd64.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-amd64.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-amd64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/amd64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-amd64
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-amd64.zip
- file_name: pleroma.zip
- update: 'true'
-
- upload-artifacts-arm:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm.zip
- update: 'true'
-
- upload-latest-arm:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-arm:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm
- package_version: stable-${CI_COMMIT_SHA:0:8}-arm
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-arm.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-arm:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm.zip
- file_name: pleroma.zip
- update: 'true'
-
- upload-artifacts-arm64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm64
- package_version: ${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64.zip
- file_name: pleroma-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64.zip
- update: 'true'
-
- upload-latest-arm64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "push" && CI_COMMIT_BRANCH == "${CI_REPO_DEFAULT_BRANCH}"'
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "manual"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-${CI_COMMIT_BRANCH}-arm64
- package_version: latest
- file_source: ./${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}-arm64.zip
- file_name: pleroma.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-artifacts-tag-arm64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm64
- package_version: stable-${CI_COMMIT_SHA:0:8}-arm64
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm64.zip
- file_name: pleroma-stable-${CI_COMMIT_SHA:0:8}-arm64.zip
- update: 'true'
-
- # Tag events don't have CI_COMMIT_BRANCH set, hardcode stable
- upload-latest-tag-arm64:
- image: *artifacts_uploader_image
- when:
- - evaluate: 'platform == "linux/arm64" && CI_PIPELINE_EVENT == "tag"'
- settings:
- <<: *artifacts_uploader_settings
- package_name: pleroma-otp-stable-arm64
- package_version: latest
- file_source: ./stable-${CI_COMMIT_SHA:0:8}-arm64.zip
- file_name: pleroma.zip
- update: 'true'
diff --git a/.woodpecker/unit-testing-elixir-1.15.yaml b/.woodpecker/unit-testing-elixir-1.15.yaml
index a4a8fc266..84046be41 100644
--- a/.woodpecker/unit-testing-elixir-1.15.yaml
+++ b/.woodpecker/unit-testing-elixir-1.15.yaml
@@ -1,26 +1,16 @@
when:
- event: pull_request
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
- event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
depends_on:
- lint
-labels:
- platform: linux/amd64
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
-
steps:
unit-testing-elixir-1.15:
image: elixir:1.15-alpine
- entrypoint: *script_file_entrypoint
environment:
MIX_ENV: test
DB_HOST: postgres
diff --git a/.woodpecker/unit-testing-elixir-1.18.yaml b/.woodpecker/unit-testing-elixir-1.18.yaml
index 9ad9eebc9..8dcec62fb 100644
--- a/.woodpecker/unit-testing-elixir-1.18.yaml
+++ b/.woodpecker/unit-testing-elixir-1.18.yaml
@@ -1,26 +1,16 @@
when:
- event: pull_request
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
- event: push
branch: ${CI_REPO_DEFAULT_BRANCH}
- path: [ "**/*.ex", "**/*.eex", "**/*.exs", "mix.lock", ".woodpecker/**" ]
+ path: [ "*.ex", "*.eex", "*.exs", "mix.lock", ".woodpecker/**" ]
depends_on:
- lint
-labels:
- platform: linux/amd64
-
-variables:
- script_file_entrypoint: &script_file_entrypoint
- - /bin/sh
- - -c
- - 'printf "%s" "$CI_SCRIPT" | base64 -d > /tmp/ci-script.sh && /bin/sh -xe /tmp/ci-script.sh'
-
steps:
unit-testing-elixir-1.18:
image: elixir:1.18-otp-27-alpine
- entrypoint: *script_file_entrypoint
environment:
MIX_ENV: test
DB_HOST: postgres
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f03be3f29..adc76c767 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,60 +4,6 @@ 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/).
-## 2.10.2
-
-### Security
-
-- ActivityPub: Fixed failed-signature inbox retry handling and signer identity checks to prevent spoofed remote activities from being processed
-
-## 2.10.1
-
-### Changed
-
-- Move avatar_description and header_description fields to the account object
-- Update Bandit to 1.10.4
-- No-op code correctness improvements detected by Elixir 1.19 compiler
-- Downgrade Hackney to 1.20.1
-- Use a custom redirect handler to ensure MediaProxy redirects are followed with Hackney
-- Update Hackney, the default HTTP client, to the latest release which supports Happy Eyeballs for improved IPv6 federation
-- Paginate follow requests
-- Moved Phoenix LiveDashboard to /pleroma/live_dashboard
-- Add mute/block expiry to the relationship object
-- Filter indexable activities before inserting indexing jobs into the queue.
-
-### Added
-
-- Allow assigning users to reports
-- Allow fine-grained announce visibilities
-- Add immutable tag on cache-control header for several endpoints that's serving the same exact things.
-- Add reasonable defaults for :database_config_whitelist
-- Support lists `exclusive` param
-- Add v1/instance/domain_blocks endpoint
-- Add /api/v2/instance profile fields limits info used by Mastodon
-- Added Oban Web dashboard located at /pleroma/oban
-- Add instructions on how to run a release in docker, to make it easier to run on older distros.
-
-### Fixed
-
-- Fix the daily email digest job which was not executing
-- Encode custom emoji URLs in EmojiReact activity tags.
-- Gopher: Fix Ranch listener not being stopped properly on Pleroma restart when database configuration is enabled
-- Fix fetching Hubzilla Actors with alsoKnownAs as string
-- Fix /phoenix/live_dashboard redirect not working when user added a path segment
-- Fix 404 error codes for missing static files
-- Fix OAuth app registration to accept `redirect_uris` as an array of strings (RFC 7591), while keeping backwards compatibility with string input.
-- Correct old migrations for expiring activities and user access tokens.
-- Federate `votersCount` correctly
-- DB prune: Check if user follows hashtag with no objects before deletion
-- Stop the rate limiter from crashing when run with wrong settings.
-- Restore embeds route
-- ReverseProxy: Recursively follow redirects until redirect_limit is reached
-- Fix compilation with vips-8.18.0 with bumping to vix 0.36.0
-
-### Removed
-
-- Docs: Removed outdated, incorrect, unmaintained and inappropriate installation documentation (Arch, NetBSD, NixOS)
-
## 2.10
### Security
diff --git a/changelog.d/assign-users.add b/changelog.d/assign-users.add
new file mode 100644
index 000000000..f50ad94c6
--- /dev/null
+++ b/changelog.d/assign-users.add
@@ -0,0 +1 @@
+Allow assigning users to reports
\ No newline at end of file
diff --git a/changelog.d/avatar-description-mastodon-api.change b/changelog.d/avatar-description-mastodon-api.change
new file mode 100644
index 000000000..6a454c01e
--- /dev/null
+++ b/changelog.d/avatar-description-mastodon-api.change
@@ -0,0 +1 @@
+Move avatar_description and header_description fields to the account object
diff --git a/changelog.d/bandit.change b/changelog.d/bandit.change
new file mode 100644
index 000000000..3831a02c2
--- /dev/null
+++ b/changelog.d/bandit.change
@@ -0,0 +1 @@
+Update Bandit to 1.10.4
diff --git a/changelog.d/bookmark-folders.ignore b/changelog.d/bookmark-folders.ignore
new file mode 100644
index 000000000..8705ac00b
--- /dev/null
+++ b/changelog.d/bookmark-folders.ignore
@@ -0,0 +1 @@
+Various bookmark folders-related improvements
diff --git a/changelog.d/boost-visibilities.add b/changelog.d/boost-visibilities.add
new file mode 100644
index 000000000..317d9840d
--- /dev/null
+++ b/changelog.d/boost-visibilities.add
@@ -0,0 +1 @@
+Allow fine-grained announce visibilities
diff --git a/changelog.d/cache-control-immutable.add b/changelog.d/cache-control-immutable.add
new file mode 100644
index 000000000..516db67bf
--- /dev/null
+++ b/changelog.d/cache-control-immutable.add
@@ -0,0 +1 @@
+Add immutable tag on cache-control header for several endpoints that's serving the same exact things.
\ No newline at end of file
diff --git a/changelog.d/ci-artifacts.skip b/changelog.d/ci-artifacts.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/context-cleanup.skip b/changelog.d/context-cleanup.skip
deleted file mode 100644
index ae609602d..000000000
--- a/changelog.d/context-cleanup.skip
+++ /dev/null
@@ -1 +0,0 @@
-litepub-0.1.jsonld cleanup
diff --git a/changelog.d/credo-aliases-sort-fixes.skip b/changelog.d/credo-aliases-sort-fixes.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/database-config-whitelist.add b/changelog.d/database-config-whitelist.add
new file mode 100644
index 000000000..a78960c98
--- /dev/null
+++ b/changelog.d/database-config-whitelist.add
@@ -0,0 +1 @@
+Add reasonable defaults for :database_config_whitelist
\ No newline at end of file
diff --git a/changelog.d/elixir-1.19-cherrypicks.change b/changelog.d/elixir-1.19-cherrypicks.change
new file mode 100644
index 000000000..7e56be008
--- /dev/null
+++ b/changelog.d/elixir-1.19-cherrypicks.change
@@ -0,0 +1 @@
+No-op code correctness improvements detected by Elixir 1.19 compiler
diff --git a/changelog.d/email_digest.fix b/changelog.d/email_digest.fix
new file mode 100644
index 000000000..cd15874a2
--- /dev/null
+++ b/changelog.d/email_digest.fix
@@ -0,0 +1 @@
+Fix the daily email digest job which was not executing
diff --git a/changelog.d/emoji-reaction-url-escape.fix b/changelog.d/emoji-reaction-url-escape.fix
new file mode 100644
index 000000000..c3a1c8823
--- /dev/null
+++ b/changelog.d/emoji-reaction-url-escape.fix
@@ -0,0 +1 @@
+Encode custom emoji URLs in EmojiReact activity tags.
diff --git a/changelog.d/exclusive-lists.add b/changelog.d/exclusive-lists.add
new file mode 100644
index 000000000..bbd722f07
--- /dev/null
+++ b/changelog.d/exclusive-lists.add
@@ -0,0 +1 @@
+Support lists `exclusive` param
diff --git a/changelog.d/gopher-genserver-crash-on-boot.fix b/changelog.d/gopher-genserver-crash-on-boot.fix
new file mode 100644
index 000000000..3b51662be
--- /dev/null
+++ b/changelog.d/gopher-genserver-crash-on-boot.fix
@@ -0,0 +1 @@
+Gopher: Fix Ranch listener not being stopped properly on Pleroma restart when database configuration is enabled
diff --git a/changelog.d/hackney-downgrade.change b/changelog.d/hackney-downgrade.change
new file mode 100644
index 000000000..a98710692
--- /dev/null
+++ b/changelog.d/hackney-downgrade.change
@@ -0,0 +1 @@
+Downgrade Hackney to 1.20.1
diff --git a/changelog.d/hackney-mediaproxy.change b/changelog.d/hackney-mediaproxy.change
new file mode 100644
index 000000000..10dfb0775
--- /dev/null
+++ b/changelog.d/hackney-mediaproxy.change
@@ -0,0 +1 @@
+Use a custom redirect handler to ensure MediaProxy redirects are followed with Hackney
diff --git a/changelog.d/hackney.change b/changelog.d/hackney.change
new file mode 100644
index 000000000..3158cfc77
--- /dev/null
+++ b/changelog.d/hackney.change
@@ -0,0 +1 @@
+Update Hackney, the default HTTP client, to the latest release which supports Happy Eyeballs for improved IPv6 federation
diff --git a/changelog.d/hubzilla-alsoknownas.fix b/changelog.d/hubzilla-alsoknownas.fix
new file mode 100644
index 000000000..2a2969807
--- /dev/null
+++ b/changelog.d/hubzilla-alsoknownas.fix
@@ -0,0 +1 @@
+Fix fetching Hubzilla Actors with alsoKnownAs as string
diff --git a/changelog.d/inappropriate-docs.remove b/changelog.d/inappropriate-docs.remove
new file mode 100644
index 000000000..699c9186a
--- /dev/null
+++ b/changelog.d/inappropriate-docs.remove
@@ -0,0 +1 @@
+Docs: Removed outdated, incorrect, unmaintained and inappropriate installation documentation (Arch, NetBSD, NixOS)
diff --git a/changelog.d/instance-domain-blocks.add b/changelog.d/instance-domain-blocks.add
new file mode 100644
index 000000000..85f01c5c2
--- /dev/null
+++ b/changelog.d/instance-domain-blocks.add
@@ -0,0 +1 @@
+Add v1/instance/domain_blocks endpoint
diff --git a/changelog.d/instance-profile-fields.add b/changelog.d/instance-profile-fields.add
new file mode 100644
index 000000000..712bd68d9
--- /dev/null
+++ b/changelog.d/instance-profile-fields.add
@@ -0,0 +1 @@
+Add /api/v2/instance profile fields limits info used by Mastodon
diff --git a/changelog.d/lint-warnings.skip b/changelog.d/lint-warnings.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/live-dashboard-redirect.fix b/changelog.d/live-dashboard-redirect.fix
new file mode 100644
index 000000000..10588d89e
--- /dev/null
+++ b/changelog.d/live-dashboard-redirect.fix
@@ -0,0 +1 @@
+Fix /phoenix/live_dashboard redirect not working when user added a path segment
diff --git a/changelog.d/map-side-effects.skip b/changelog.d/map-side-effects.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/mfm-backend.add b/changelog.d/mfm-backend.add
deleted file mode 100644
index f815c6828..000000000
--- a/changelog.d/mfm-backend.add
+++ /dev/null
@@ -1 +0,0 @@
-Add backend support for Misskey Markdown (MFM) posts
diff --git a/changelog.d/missing-static-file.fix b/changelog.d/missing-static-file.fix
new file mode 100644
index 000000000..c7ef805aa
--- /dev/null
+++ b/changelog.d/missing-static-file.fix
@@ -0,0 +1 @@
+Fix 404 error codes for missing static files
diff --git a/changelog.d/mix-exs-fix.skip b/changelog.d/mix-exs-fix.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/mix-exs-update.skip b/changelog.d/mix-exs-update.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/oauth-registration-redirect_uris.fix b/changelog.d/oauth-registration-redirect_uris.fix
new file mode 100644
index 000000000..76ace55df
--- /dev/null
+++ b/changelog.d/oauth-registration-redirect_uris.fix
@@ -0,0 +1 @@
+Fix OAuth app registration to accept `redirect_uris` as an array of strings (RFC 7591), while keeping backwards compatibility with string input.
diff --git a/changelog.d/oban-web.add b/changelog.d/oban-web.add
new file mode 100644
index 000000000..c59e2ebca
--- /dev/null
+++ b/changelog.d/oban-web.add
@@ -0,0 +1 @@
+Added Oban Web dashboard located at /pleroma/oban
diff --git a/changelog.d/old-migrations.fix b/changelog.d/old-migrations.fix
new file mode 100644
index 000000000..49566c896
--- /dev/null
+++ b/changelog.d/old-migrations.fix
@@ -0,0 +1 @@
+Correct old migrations for expiring activities and user access tokens.
diff --git a/changelog.d/paginate-follow-requests.change b/changelog.d/paginate-follow-requests.change
new file mode 100644
index 000000000..1a88995b7
--- /dev/null
+++ b/changelog.d/paginate-follow-requests.change
@@ -0,0 +1 @@
+Paginate follow requests
diff --git a/changelog.d/phoenix-livedashboard-move.change b/changelog.d/phoenix-livedashboard-move.change
new file mode 100644
index 000000000..116b1523a
--- /dev/null
+++ b/changelog.d/phoenix-livedashboard-move.change
@@ -0,0 +1 @@
+Moved Phoenix LiveDashboard to /pleroma/live_dashboard
diff --git a/changelog.d/pleroma-fe-link.fix b/changelog.d/pleroma-fe-link.fix
deleted file mode 100644
index de93f86dd..000000000
--- a/changelog.d/pleroma-fe-link.fix
+++ /dev/null
@@ -1 +0,0 @@
-Updated Pleroma-FE build URL after Forgejo migration
diff --git a/changelog.d/plug-test-typo.skip b/changelog.d/plug-test-typo.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/poll-voters-count-inflation.fix b/changelog.d/poll-voters-count-inflation.fix
deleted file mode 100644
index 7eae41f13..000000000
--- a/changelog.d/poll-voters-count-inflation.fix
+++ /dev/null
@@ -1 +0,0 @@
-Fix votersCount inflation when same voter picks multiple options
diff --git a/changelog.d/poll-voters-count.fix b/changelog.d/poll-voters-count.fix
new file mode 100644
index 000000000..2dbc81b5d
--- /dev/null
+++ b/changelog.d/poll-voters-count.fix
@@ -0,0 +1 @@
+Federate `votersCount` correctly
diff --git a/changelog.d/prune-hashtag-follow-3376.fix b/changelog.d/prune-hashtag-follow-3376.fix
new file mode 100644
index 000000000..cdb4e9a79
--- /dev/null
+++ b/changelog.d/prune-hashtag-follow-3376.fix
@@ -0,0 +1 @@
+DB prune: Check if user follows hashtag with no objects before deletion
diff --git a/changelog.d/rate-limiter-hardening.fix b/changelog.d/rate-limiter-hardening.fix
new file mode 100644
index 000000000..a3af8fcc4
--- /dev/null
+++ b/changelog.d/rate-limiter-hardening.fix
@@ -0,0 +1 @@
+Stop the rate limiter from crashing when run with wrong settings.
diff --git a/changelog.d/reduce-flaky-tests.skip b/changelog.d/reduce-flaky-tests.skip
new file mode 100644
index 000000000..0375762c0
--- /dev/null
+++ b/changelog.d/reduce-flaky-tests.skip
@@ -0,0 +1 @@
+Reduce the number of flaky tests by making them sync if they affect the global state, and silence noisy test output.
diff --git a/changelog.d/relationship-expires-at.change b/changelog.d/relationship-expires-at.change
new file mode 100644
index 000000000..286dba197
--- /dev/null
+++ b/changelog.d/relationship-expires-at.change
@@ -0,0 +1 @@
+Add mute/block expiry to the relationship object
diff --git a/changelog.d/release-to-docker.add b/changelog.d/release-to-docker.add
new file mode 100644
index 000000000..5fbf611a5
--- /dev/null
+++ b/changelog.d/release-to-docker.add
@@ -0,0 +1 @@
+Add instructions on how to run a release in docker, to make it easier to run on older distros.
diff --git a/changelog.d/restore-embeds.fix b/changelog.d/restore-embeds.fix
new file mode 100644
index 000000000..5a2a1c4fe
--- /dev/null
+++ b/changelog.d/restore-embeds.fix
@@ -0,0 +1 @@
+Restore embeds route
diff --git a/changelog.d/reverseproxy-recursive-redirect.fix b/changelog.d/reverseproxy-recursive-redirect.fix
new file mode 100644
index 000000000..744109fd6
--- /dev/null
+++ b/changelog.d/reverseproxy-recursive-redirect.fix
@@ -0,0 +1 @@
+ReverseProxy: Recursively follow redirects until redirect_limit is reached
diff --git a/changelog.d/search-indexing.change b/changelog.d/search-indexing.change
new file mode 100644
index 000000000..766934f3f
--- /dev/null
+++ b/changelog.d/search-indexing.change
@@ -0,0 +1 @@
+Filter indexable activities before inserting indexing jobs into the queue.
diff --git a/changelog.d/search-indexing.skip b/changelog.d/search-indexing.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/twitter-api.skip b/changelog.d/twitter-api.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/changelog.d/update-comment.ignore b/changelog.d/update-comment.ignore
new file mode 100644
index 000000000..733e813b3
--- /dev/null
+++ b/changelog.d/update-comment.ignore
@@ -0,0 +1 @@
+Update comment for prepare_object, rename prepare_outgoing
diff --git a/changelog.d/user-view.ignore b/changelog.d/user-view.ignore
new file mode 100644
index 000000000..37e9a7e09
--- /dev/null
+++ b/changelog.d/user-view.ignore
@@ -0,0 +1 @@
+Avoid code duplication in UserView
diff --git a/changelog.d/vix-0.36.0.fix b/changelog.d/vix-0.36.0.fix
new file mode 100644
index 000000000..43a8dd8f8
--- /dev/null
+++ b/changelog.d/vix-0.36.0.fix
@@ -0,0 +1 @@
+Fix compilation with vips-8.18.0 with bumping to vix 0.36.0
diff --git a/changelog.d/woodpecker-pr-pipeline.skip b/changelog.d/woodpecker-pr-pipeline.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/config/config.exs b/config/config.exs
index 2d38e3ebe..5bf2c5c2e 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -203,8 +203,7 @@ config :pleroma, :instance,
"text/plain",
"text/html",
"text/markdown",
- "text/bbcode",
- "text/x.misskeymarkdown"
+ "text/bbcode"
],
autofollowed_nicknames: [],
autofollowing_nicknames: [],
@@ -776,7 +775,7 @@ config :pleroma, :frontends,
"name" => "pleroma-fe",
"git" => "https://git.pleroma.social/pleroma/pleroma-fe",
"build_url" =>
- "https://git.pleroma.social/api/packages/pleroma/generic/pleroma-fe-builds/${ref}/latest.zip",
+ "https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/${ref}/download?job=build",
"ref" => "develop"
},
"fedi-fe" => %{
diff --git a/config/description.exs b/config/description.exs
index 6e4348907..c388d17c3 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -815,8 +815,7 @@ config :pleroma, :config_description, [
"text/plain",
"text/html",
"text/markdown",
- "text/bbcode",
- "text/x.misskeymarkdown"
+ "text/bbcode"
]
},
%{
@@ -1395,13 +1394,7 @@ config :pleroma, :config_description, [
label: "Post Content Type",
type: {:dropdown, :atom},
description: "Default post formatting option",
- suggestions: [
- "text/plain",
- "text/html",
- "text/markdown",
- "text/bbcode",
- "text/x.misskeymarkdown"
- ]
+ suggestions: ["text/plain", "text/html", "text/markdown", "text/bbcode"]
},
%{
key: :redirectRootNoLogin,
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 4bf2f6b95..11d5af2fb 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -127,13 +127,6 @@ defmodule Pleroma.Formatter do
Earmark.as_html!(text, %Earmark.Options{compact_output: true, smartypants: false})
end
- def markdown_to_html(text, opts) do
- Earmark.as_html!(
- text,
- %Earmark.Options{compact_output: true, smartypants: false} |> Map.merge(opts)
- )
- end
-
def html_escape({text, mentions, hashtags}, type) do
{html_escape(text, type), mentions, hashtags}
end
@@ -142,10 +135,6 @@ defmodule Pleroma.Formatter do
HTML.filter_tags(text)
end
- def html_escape(text, "text/x.misskeymarkdown") do
- HTML.filter_tags(text)
- end
-
def html_escape(text, "text/plain") do
Regex.split(@link_regex, text, include_captures: true)
|> Enum.map_every(2, fn chunk ->
diff --git a/lib/pleroma/frontend.ex b/lib/pleroma/frontend.ex
index e37a3fefe..e651d7d9d 100644
--- a/lib/pleroma/frontend.ex
+++ b/lib/pleroma/frontend.ex
@@ -75,8 +75,8 @@ defmodule Pleroma.Frontend do
end
defp download_build(frontend_info, dest) do
+ Logger.info("Downloading pre-built bundle for #{frontend_info["name"]}")
url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
- Logger.info("Downloading pre-built bundle for #{frontend_info["name"]} from #{url}")
with {:ok, %{status: 200, body: zip_body}} <-
Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index 5e9314446..f1e07a257 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -372,21 +372,13 @@ defmodule Pleroma.Object do
option
end)
- existing_voters = object.data["voters"] || []
- voters = [actor | existing_voters] |> Enum.uniq()
- new_voter? = actor not in existing_voters
- existing_voters_count = object.data["votersCount"]
+ voters = [actor | object.data["voters"] || []] |> Enum.uniq()
voters_count =
- cond do
- is_integer(existing_voters_count) and new_voter? ->
- existing_voters_count + 1
-
- is_integer(existing_voters_count) ->
- existing_voters_count
-
- true ->
- length(voters)
+ if Map.has_key?(object.data, "votersCount") do
+ object.data["votersCount"] + 1
+ else
+ length(voters)
end
data =
diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex
index 49400940f..af2d35c8f 100644
--- a/lib/pleroma/release_tasks.ex
+++ b/lib/pleroma/release_tasks.ex
@@ -5,10 +5,7 @@
defmodule Pleroma.ReleaseTasks do
@repo Pleroma.Repo
- # TODO: Kept for some backwards compatibility with buggy pleroma_ctl,
- # if a mismatch between pleroma_ctl and Pleroma accidentaly happens.
- # Remove in the future.
- def run(args) when is_binary(args) do
+ def run(args) do
[task | args] = String.split(args)
case task do
@@ -19,20 +16,6 @@ defmodule Pleroma.ReleaseTasks do
end
end
- # HACK: Script arguments need to be received as a list, otherwise (quoted) arguments with
- # whitespace will be broken. Previously the broken string form above was used,
- # escaping in the shell does not help.
- def run(args) when is_list(args) do
- [task | args] = args
-
- case task do
- "migrate" -> migrate(args)
- "create" -> create()
- "rollback" -> rollback(args)
- task -> mix_task(task, args)
- end
- end
-
def find_module(task) do
module_name =
task
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 0b513ee16..071d634db 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -1677,80 +1677,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
show_birthday = !!birthday
- with {:ok, nickname} <- nickname_from_actor(data, additional) do
- {:ok,
- %{
- ap_id: data["id"],
- uri: get_actor_url(data["url"]),
- banner: normalize_image(data["image"]),
- fields: fields,
- emoji: emojis,
- is_locked: is_locked,
- is_discoverable: is_discoverable,
- invisible: invisible,
- avatar: normalize_image(data["icon"]),
- name: data["name"],
- follower_address: data["followers"],
- following_address: data["following"],
- featured_address: featured_address,
- bio: data["summary"] || "",
- actor_type: actor_type,
- also_known_as: normalize_also_known_as(data["alsoKnownAs"]),
- public_key: public_key,
- inbox: data["inbox"],
- shared_inbox: shared_inbox,
- accepts_chat_messages: accepts_chat_messages,
- birthday: birthday,
- show_birthday: show_birthday,
- pinned_objects: pinned_objects,
- nickname: nickname
- }}
- end
- end
+ # if WebFinger request was already done, we probably have acct, otherwise
+ # we request WebFinger here
+ nickname = additional[:nickname_from_acct] || generate_nickname(data)
- defp nickname_from_actor(data, additional) do
- generated = generated_nickname(data)
-
- case additional[:nickname_from_acct] do
- ^generated when is_binary(generated) ->
- {:ok, generated}
-
- acct when is_binary(acct) ->
- with ^acct <- webfinger_nickname(data) do
- {:ok, acct}
- else
- _ -> {:error, {:webfinger_actor_mismatch, acct, data["id"]}}
- end
-
- _ ->
- {:ok, generate_nickname(data)}
- end
- end
-
- defp generated_nickname(%{"preferredUsername" => username, "id" => ap_id})
- when is_binary(username) and is_binary(ap_id) do
- case URI.parse(ap_id) do
- %URI{host: host} when is_binary(host) -> "#{username}@#{host}"
- _ -> nil
- end
- end
-
- defp generated_nickname(_), do: nil
-
- defp webfinger_nickname(data) do
- with generated when is_binary(generated) <- generated_nickname(data),
- {:ok, %{"subject" => "acct:" <> acct, "ap_id" => ap_id}} <- WebFinger.finger(generated),
- true <- ap_id == data["id"] do
- acct
- end
+ %{
+ ap_id: data["id"],
+ uri: get_actor_url(data["url"]),
+ banner: normalize_image(data["image"]),
+ fields: fields,
+ emoji: emojis,
+ is_locked: is_locked,
+ is_discoverable: is_discoverable,
+ invisible: invisible,
+ avatar: normalize_image(data["icon"]),
+ name: data["name"],
+ follower_address: data["followers"],
+ following_address: data["following"],
+ featured_address: featured_address,
+ bio: data["summary"] || "",
+ actor_type: actor_type,
+ also_known_as: normalize_also_known_as(data["alsoKnownAs"]),
+ public_key: public_key,
+ inbox: data["inbox"],
+ shared_inbox: shared_inbox,
+ accepts_chat_messages: accepts_chat_messages,
+ birthday: birthday,
+ show_birthday: show_birthday,
+ pinned_objects: pinned_objects,
+ nickname: nickname
+ }
end
defp generate_nickname(%{"preferredUsername" => username} = data) when is_binary(username) do
- generated = generated_nickname(data)
+ generated = "#{username}@#{URI.parse(data["id"]).host}"
if Config.get([WebFinger, :update_nickname_on_user_fetch]) do
- case webfinger_nickname(data) do
- acct when is_binary(acct) -> acct
+ case WebFinger.finger(generated) do
+ {:ok, %{"subject" => "acct:" <> acct}} -> acct
_ -> generated
end
else
@@ -1830,11 +1794,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp collection_private(_data), do: {:ok, true}
def user_data_from_user_object(data, additional \\ []) do
- with {:ok, data} <- MRF.filter(data),
- {:ok, data} <- object_to_user_data(data, additional) do
- {:ok, data}
+ with {:ok, data} <- MRF.filter(data) do
+ {:ok, object_to_user_data(data, additional)}
else
- {:error, _} = e -> e
e -> {:error, e}
end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 2bfff6968..4f1613a07 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -348,7 +348,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
def inbox(%{assigns: %{valid_signature: false}} = conn, params) do
- Federator.incoming_failed_signature_ap_doc(%{
+ Federator.incoming_ap_doc(%{
method: conn.method,
req_headers: conn.req_headers,
request_path: conn.request_path,
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 844ad2c8f..c0626ce4d 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
@@ -6,12 +6,9 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
- alias Pleroma.HTML
- alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.CommonAPI.Utils
import Ecto.Changeset
@@ -29,7 +26,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
end
field(:replies, {:array, ObjectValidators.ObjectID}, default: [])
- field(:source, :map)
end
def cast_and_apply(data) do
@@ -84,113 +80,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
def fix_attachments(data), do: data
- defp remote_mention_resolver(
- %{"id" => ap_id, "tag" => tags},
- "@" <> nickname = mention,
- buffer,
- opts,
- acc
- )
- when is_binary(ap_id) and is_list(tags) do
- initial_host =
- ap_id
- |> URI.parse()
- |> Map.get(:host)
-
- with mention_tag when not is_nil(mention_tag) <-
- Enum.find(tags, &mention_tag?(&1, mention, initial_host)),
- href when is_binary(href) <- mention_tag["href"],
- %User{} = user <- User.get_cached_by_ap_id(href) do
- link = Pleroma.Formatter.mention_from_user(user, opts)
- {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
- else
- _ -> {buffer, acc}
- end
- end
-
- defp remote_mention_resolver(_object, _mention, buffer, _opts, acc), do: {buffer, acc}
-
- defp mention_tag?(%{"type" => "Mention", "name" => name}, mention, initial_host)
- when is_binary(name) do
- name == mention || mention == "#{name}@#{initial_host}"
- end
-
- defp mention_tag?(_tag, _mention, _initial_host), do: false
-
- defp scrub_content(%{"content" => content} = object) when is_binary(content) do
- Map.put(object, "content", HTML.filter_tags(content))
- end
-
- defp scrub_content(object), do: object
-
- defp mfm_parse_limit do
- min(Pleroma.Config.get([:instance, :limit]), Pleroma.Config.get([:instance, :remote_limit]))
- end
-
- defp normalize_source(%{"source" => source} = object) when is_binary(source) do
- object
- |> Map.put("source", %{"content" => source})
- |> normalize_source()
- end
-
- defp normalize_source(%{"source" => source} = object) when is_map(source) do
- source =
- case source["content"] do
- content when is_binary(content) ->
- if String.length(content) <= mfm_parse_limit() do
- source
- else
- Map.delete(source, "content")
- end
-
- nil ->
- source
-
- _ ->
- Map.delete(source, "content")
- end
-
- Map.put(object, "source", source)
- end
-
- defp normalize_source(object), do: object
-
- defp fix_misskey_content(%{"htmlMfm" => true, "content" => content} = object)
- when is_binary(content) do
- Map.put(object, "content", HTML.filter_tags(content))
- end
-
- defp fix_misskey_content(%{"htmlMfm" => true} = object), do: object
-
- defp fix_misskey_content(
- %{"source" => %{"mediaType" => "text/x.misskeymarkdown", "content" => content}} = object
- )
- when is_binary(content) do
- mention_handler = fn nick, buffer, opts, acc ->
- remote_mention_resolver(object, nick, buffer, opts, acc)
- end
-
- {linked, _mentions, _tags} =
- Utils.format_input(content, "text/x.misskeymarkdown", mention_handler: mention_handler)
-
- Map.put(object, "content", linked)
- end
-
- defp fix_misskey_content(%{"source" => %{"mediaType" => "text/x.misskeymarkdown"}} = object),
- do: scrub_content(object)
-
- defp fix_misskey_content(%{"_misskey_content" => content} = object) when is_binary(content) do
- object
- |> Map.put("source", %{
- "content" => content,
- "mediaType" => "text/x.misskeymarkdown"
- })
- |> Map.delete("_misskey_content")
- |> fix_misskey_content()
- end
-
- defp fix_misskey_content(object), do: object
-
defp fix(data) do
data
|> CommonFixes.fix_actor()
@@ -199,8 +88,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|> fix_tag()
|> fix_replies()
|> fix_attachments()
- |> normalize_source()
- |> fix_misskey_content()
|> CommonFixes.fix_quote_url()
|> CommonFixes.fix_likes()
|> Transmogrifier.fix_emoji()
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
index 9b8580200..22cf0cc05 100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
@@ -32,7 +32,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
quote bind_quoted: binding() do
field(:content, :string)
field(:contentMap, ObjectValidators.ContentLanguageMap)
- field(:htmlMfm, :boolean)
field(:published, ObjectValidators.DateTime)
field(:updated, ObjectValidators.DateTime)
diff --git a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
index 4c0d9dff7..aab90235f 100644
--- a/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/update_validator.ex
@@ -75,40 +75,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator do
end
end
- # For remote Updates, verify the Actor is the same
+ # For remote Updates, verify the host is the same.
def validate_updating_rights_remote(cng) do
with actor = get_field(cng, :actor),
object = get_field(cng, :object),
{:ok, object_id} <- ObjectValidators.ObjectID.cast(object),
- entity <-
- Object.normalize(object_id, fetch: false) || User.get_cached_by_ap_id(object_id) do
- case entity do
- # Actor must own Object to update it
- %Object{} ->
- if actor == entity.data["actor"] do
- cng
- else
- cng
- |> add_error(:object, "Can't be updated by this actor")
- end
-
- # Actor must only be allowed to update itself
- %User{} ->
- if actor == entity.ap_id do
- cng
- else
- cng
- |> add_error(:object, "Can't be updated by this actor")
- end
-
- nil ->
- cng
- |> add_error(:object, "Can't be updated by this actor")
-
- _ ->
- cng
- |> add_error(:object, "Update is neither for Object or Actor")
- end
+ actor_uri <- URI.parse(actor),
+ object_uri <- URI.parse(object_id),
+ true <- actor_uri.host == object_uri.host do
+ cng
else
_e ->
cng
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 0af4ceaf5..43c0f456d 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -120,8 +120,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"https://www.w3.org/ns/activitystreams",
"#{Endpoint.url()}/schemas/litepub-0.1.jsonld",
%{
- "@language" => get_language(data),
- "htmlMfm" => "https://w3id.org/fep/c16b#htmlMfm"
+ "@language" => get_language(data)
}
]
}
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index 6072fff6b..16489663a 100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -317,7 +317,6 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
emoji = Map.merge(emoji, summary_emoji)
- media_type = Utils.get_content_type(draft.params[:content_type])
{:ok, note_data, _meta} = Builder.note(draft)
object =
@@ -325,18 +324,14 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
|> Map.put("emoji", emoji)
|> Map.put("source", %{
"content" => draft.status,
- "mediaType" => media_type
+ "mediaType" => Utils.get_content_type(draft.params[:content_type])
})
- |> maybe_put("htmlMfm", true, media_type == "text/x.misskeymarkdown")
|> Map.put("generator", draft.params[:generator])
|> Map.put("language", draft.language)
%{draft | object: object}
end
- defp maybe_put(map, key, value, true), do: Map.put(map, key, value)
- defp maybe_put(map, _key, _value, _condition), do: map
-
defp preview?(%__MODULE__{} = draft) do
preview? = Pleroma.Web.Utils.Params.truthy_param?(draft.params[:preview])
%{draft | preview?: preview?}
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 26034d685..32572a721 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -322,14 +322,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|> Formatter.linkify(options)
end
- def format_input(text, "text/x.misskeymarkdown", options) do
- text
- |> Formatter.markdown_to_html(%{breaks: true})
- |> safe_mfm_to_html()
- |> Formatter.linkify(options)
- |> Formatter.html_escape("text/x.misskeymarkdown")
- end
-
def format_input(text, "text/markdown", options) do
text
|> Formatter.mentions_escape(options)
@@ -338,16 +330,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|> Formatter.html_escape("text/html")
end
- defp safe_mfm_to_html(html) do
- html
- |> MfmParser.Parser.parse()
- |> MfmParser.Encoder.to_html()
- rescue
- _ -> html
- catch
- _, _ -> html
- end
-
def format_naive_asctime(date) do
date |> DateTime.from_naive!("Etc/UTC") |> format_asctime
end
diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex
index 90cd2e54a..676fc5137 100644
--- a/lib/pleroma/web/federator.ex
+++ b/lib/pleroma/web/federator.ex
@@ -11,7 +11,6 @@ defmodule Pleroma.Web.Federator do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Workers.PublisherWorker
alias Pleroma.Workers.ReceiverWorker
- alias Pleroma.Workers.SignatureRetryWorker
require Logger
@@ -36,21 +35,12 @@ defmodule Pleroma.Web.Federator do
end
# Client API
- def incoming_failed_signature_ap_doc(%{
- method: method,
- params: params,
- req_headers: req_headers,
- request_path: request_path,
- query_string: query_string
- }) do
- SignatureRetryWorker.new(
+ def incoming_ap_doc(%{params: params, req_headers: req_headers}) do
+ ReceiverWorker.new(
%{
- "op" => "incoming_failed_signature_ap_doc",
- "method" => method,
+ "op" => "incoming_ap_doc",
"req_headers" => req_headers,
"params" => params,
- "request_path" => request_path,
- "query_string" => query_string,
"timeout" => :timer.seconds(20)
},
priority: 2
diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex
index f047804e2..3b4271227 100644
--- a/lib/pleroma/web/mastodon_api/views/poll_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex
@@ -71,12 +71,12 @@ defmodule Pleroma.Web.MastodonAPI.PollView do
end)
end
- defp voters_count(%{data: %{"votersCount" => voters}}) when is_integer(voters), do: voters
-
defp voters_count(%{data: %{"voters" => [_ | _] = voters}}) do
length(voters)
end
+ defp voters_count(%{data: %{"votersCount" => voters}}), do: voters
+
defp voters_count(_), do: 0
defp voted_and_own_votes(%{object: object} = params, options) do
diff --git a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
index a688b1780..c6d531086 100644
--- a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
+++ b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
@@ -32,8 +32,8 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
# remove me once testsuite uses mapped capabilities instead of what we do now
{:user, nil} ->
Logger.debug("Failed to map identity from signature (lookup failure)")
- Logger.debug("key_id=#{inspect(key_id_from_conn(conn))}, actor=#{inspect(actor)}")
- assign(conn, :valid_signature, false)
+ Logger.debug("key_id=#{inspect(key_id_from_conn(conn))}, actor=#{actor}")
+ conn
end
end
diff --git a/lib/pleroma/workers/receiver_worker.ex b/lib/pleroma/workers/receiver_worker.ex
index 3afbe138d..e2c950967 100644
--- a/lib/pleroma/workers/receiver_worker.ex
+++ b/lib/pleroma/workers/receiver_worker.ex
@@ -4,37 +4,40 @@
defmodule Pleroma.Workers.ReceiverWorker do
alias Pleroma.Instances
+ alias Pleroma.Signature
+ alias Pleroma.User
alias Pleroma.Web.Federator
- alias Pleroma.Workers.SignatureRetryWorker
use Oban.Worker, queue: :federator_incoming, max_attempts: 5, unique: [period: :infinity]
@impl true
- def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params} = args} = job) do
- if signature_retry_job?(args) do
- perform_signature_retry(job)
- else
- perform_incoming(params)
- end
- end
- def perform(%Job{args: %{"op" => "incoming_ap_doc"} = args} = job) do
- if signature_retry_job?(args) do
- perform_signature_retry(job)
- else
- process_errors(:missing_incoming_ap_doc_params)
- end
- end
+ def perform(%Job{
+ args: %{
+ "op" => "incoming_ap_doc",
+ "method" => method,
+ "params" => params,
+ "req_headers" => req_headers,
+ "request_path" => request_path,
+ "query_string" => query_string
+ }
+ }) do
+ # Oban's serialization converts our tuple headers to lists.
+ # Revert it for the signature validation.
+ req_headers = Enum.into(req_headers, [], &List.to_tuple(&1))
- defp perform_signature_retry(%Job{args: args} = job) do
- SignatureRetryWorker.perform(%Job{
- job
- | args: Map.put(args, "op", "incoming_failed_signature_ap_doc")
- })
- end
+ conn_data = %Plug.Conn{
+ method: method,
+ params: params,
+ req_headers: req_headers,
+ request_path: request_path,
+ query_string: query_string
+ }
- defp perform_incoming(params) do
- with {:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
+ with {:ok, %User{}} <- User.get_or_fetch_by_ap_id(conn_data.params["actor"]),
+ {:ok, _public_key} <- Signature.refetch_public_key(conn_data),
+ {:signature, true} <- {:signature, Signature.validate_signature(conn_data)},
+ {:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
unless Instances.reachable?(params["actor"]) do
domain = URI.parse(params["actor"]).host
Oban.insert(Pleroma.Workers.ReachabilityWorker.new(%{"domain" => domain}))
@@ -46,8 +49,17 @@ defmodule Pleroma.Workers.ReceiverWorker do
end
end
- defp signature_retry_job?(args) do
- Enum.any?(~w(method req_headers request_path query_string), &Map.has_key?(args, &1))
+ def perform(%Job{args: %{"op" => "incoming_ap_doc", "params" => params}}) do
+ with {:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
+ unless Instances.reachable?(params["actor"]) do
+ domain = URI.parse(params["actor"]).host
+ Oban.insert(Pleroma.Workers.ReachabilityWorker.new(%{"domain" => domain}))
+ end
+
+ {:ok, res}
+ else
+ e -> process_errors(e)
+ end
end
@impl true
@@ -73,12 +85,10 @@ defmodule Pleroma.Workers.ReceiverWorker do
{:error, {:reject, _} = reason} -> {:cancel, reason}
# HTTP Sigs
{:signature, false} -> {:cancel, :invalid_signature}
- {:same_actor, false} -> {:cancel, :actor_signature_mismatch}
# Origin / URL validation failed somewhere possibly due to spoofing
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
# Unclear if this can be reached
{:error, {:side_effects, {:error, :no_object_actor}} = reason} -> {:cancel, reason}
- :missing_incoming_ap_doc_params -> {:cancel, :missing_incoming_ap_doc_params}
# Catchall
{:error, _} = e -> e
e -> {:error, e}
diff --git a/lib/pleroma/workers/signature_retry_worker.ex b/lib/pleroma/workers/signature_retry_worker.ex
deleted file mode 100644
index 2c4c097dd..000000000
--- a/lib/pleroma/workers/signature_retry_worker.ex
+++ /dev/null
@@ -1,254 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors
$[spin.speed=1s 13:37]
" - - {:ok, activity} = - CommonAPI.post(user, %{ - status: post, - content_type: "text/x.misskeymarkdown" - }) - - object = Object.normalize(activity, fetch: false) - - assert object.data["htmlMfm"] == true - - assert object.data["source"] == %{ - "content" => post, - "mediaType" => "text/x.misskeymarkdown" - } - - assert object.data["content"] =~ ~s(class="mfm-spin") - assert object.data["content"] =~ ~s(data-mfm-speed="1s") - assert object.data["content"] =~ "13:37" - refute object.data["content"] =~ "scrub-this" - end - - test "it falls back safely for malformed MFM" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "$[spin.speed=1s=boom malformed]", - content_type: "text/x.misskeymarkdown" - }) - - object = Object.normalize(activity, fetch: false) - - refute object.data["content"] =~ ~s(class="mfm-spin") - assert object.data["content"] =~ "malformed" - end - test "it does not allow replies to direct messages that are not direct messages themselves" do user = insert(:user) diff --git a/test/pleroma/web/mastodon_api/views/poll_view_test.exs b/test/pleroma/web/mastodon_api/views/poll_view_test.exs index 6cb5934de..16281393d 100644 --- a/test/pleroma/web/mastodon_api/views/poll_view_test.exs +++ b/test/pleroma/web/mastodon_api/views/poll_view_test.exs @@ -180,179 +180,4 @@ defmodule Pleroma.Web.MastodonAPI.PollViewTest do assert result[:pleroma][:non_anonymous] == true end - - test "prefers votersCount over voters list when both are present" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Which flavor?", - poll: %{options: ["chocolate", "vanilla"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - voter = insert(:user) - {:ok, _, object} = CommonAPI.vote(object, voter, [0]) - - assert object.data["votersCount"] == 1 - assert length(object.data["voters"]) == 1 - - object = %{ - object - | data: Map.put(object.data, "votersCount", 42) - } - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 42 - end - - test "falls back to voters list when votersCount is absent" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Which flavor?", - poll: %{options: ["chocolate", "vanilla"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - voter = insert(:user) - {:ok, _, object} = CommonAPI.vote(object, voter, [0]) - - assert length(object.data["voters"]) == 1 - - data = Map.delete(object.data, "votersCount") - object = %{object | data: data} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 1 - end - - test "returns 0 when both votersCount and voters are absent" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Which flavor?", - poll: %{options: ["chocolate", "vanilla"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - data = - object.data - |> Map.delete("votersCount") - |> Map.delete("voters") - - object = %{object | data: data} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 0 - end - - test "returns 0 when voters list is empty" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Which flavor?", - poll: %{options: ["chocolate", "vanilla"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - data = - object.data - |> Map.delete("votersCount") - |> Map.put("voters", []) - - object = %{object | data: data} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 0 - end - - test "does not inflate votersCount when same voter picks multiple options" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Pick several", - poll: %{options: ["a", "b", "c"], expires_in: 20, multiple: true} - }) - - object = Object.normalize(activity, fetch: false) - - voter = insert(:user) - {:ok, _, object} = CommonAPI.vote(object, voter, [0, 2]) - - assert object.data["votersCount"] == 1 - assert length(object.data["voters"]) == 1 - end - - test "preserves votersCount from remote source when existing voter picks another option" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Pick several", - poll: %{options: ["a", "b"], expires_in: 20, multiple: true} - }) - - object = Object.normalize(activity, fetch: false) - - voter = insert(:user) - {:ok, _, object} = CommonAPI.vote(object, voter, [0, 1]) - - object = %{object | data: Map.put(object.data, "votersCount", 14)} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 14 - end - - test "returns 0 when votersCount is explicitly 0" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Pick one", - poll: %{options: ["a", "b"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - object = %{object | data: Map.put(object.data, "votersCount", 0)} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == 0 - end - - test "falls back to voters list when votersCount is nil" do - user = insert(:user) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Pick one", - poll: %{options: ["a", "b"], expires_in: 20} - }) - - object = Object.normalize(activity, fetch: false) - - voter = insert(:user) - {:ok, _, object} = CommonAPI.vote(object, voter, [0]) - - object = %{object | data: Map.put(object.data, "votersCount", nil)} - - result = PollView.render("show.json", %{object: object}) - - assert result[:voters_count] == length(object.data["voters"]) - end end diff --git a/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs b/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs index df713762c..33eff1bc5 100644 --- a/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs +++ b/test/pleroma/web/plugs/mapped_signature_to_identity_plug_test.exs @@ -47,27 +47,13 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlugTest do assert %{valid_signature: false} == conn.assigns end + @tag skip: "known breakage; the testsuite presently depends on it" test "it considers a mapped identity to be invalid when the identity cannot be found" do - actor = "http://niu.moe/users/rye" - conn = - build_conn(:post, "/doesntmattter", %{"actor" => actor}) - |> set_signature(actor) + build_conn(:post, "/doesntmattter", %{"actor" => "http://mastodon.example.org/users/admin"}) + |> set_signature("http://niu.moe/users/rye") |> MappedSignatureToIdentityPlug.call(%{}) - assert conn.assigns.valid_signature == false - refute Map.has_key?(conn.assigns, :user) - end - - test "it considers a mapped identity to be invalid when embedded actor identity cannot be found" do - actor = "http://niu.moe/users/rye" - - conn = - build_conn(:post, "/doesntmattter", %{"actor" => %{"id" => actor}}) - |> set_signature(actor) - |> MappedSignatureToIdentityPlug.call(%{}) - - assert conn.assigns.valid_signature == false - refute Map.has_key?(conn.assigns, :user) + assert %{valid_signature: false} == conn.assigns end end diff --git a/test/pleroma/workers/receiver_worker_test.exs b/test/pleroma/workers/receiver_worker_test.exs index ea05f38f1..12abc1a27 100644 --- a/test/pleroma/workers/receiver_worker_test.exs +++ b/test/pleroma/workers/receiver_worker_test.exs @@ -11,27 +11,9 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do alias Pleroma.User alias Pleroma.Web.CommonAPI + alias Pleroma.Web.Federator alias Pleroma.Workers.ReceiverWorker - defp signature_headers_for(%User{} = signer) do - [ - {"host", "local.test"}, - {"date", "Thu, 25 Jul 2024 13:33:31 GMT"}, - {"digest", "SHA-256=fake-digest"}, - {"content-type", "application/activity+json"}, - { - "signature", - "keyId=\"#{signer.ap_id}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"fake-signature\"" - } - ] - end - - defp perform_incoming(params) do - ReceiverWorker.perform(%Oban.Job{ - args: %{"op" => "incoming_ap_doc", "params" => params} - }) - end - test "it does not retry MRF reject" do params = insert(:note).data @@ -99,7 +81,16 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do insert(:note_activity).data |> Map.put("actor", "https://springfield.social/users/bart") - assert {:cancel, {:error, :forbidden}} = perform_incoming(params) + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:cancel, {:error, :forbidden}} = ReceiverWorker.perform(oban_job) end test "when request returns a 404" do @@ -107,7 +98,16 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do insert(:note_activity).data |> Map.put("actor", "https://springfield.social/users/troymcclure") - assert {:cancel, {:error, :not_found}} = perform_incoming(params) + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:cancel, {:error, :not_found}} = ReceiverWorker.perform(oban_job) end test "when request returns a 410" do @@ -115,7 +115,16 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do insert(:note_activity).data |> Map.put("actor", "https://springfield.social/users/hankscorpio") - assert {:cancel, {:error, :not_found}} = perform_incoming(params) + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:cancel, {:error, :not_found}} = ReceiverWorker.perform(oban_job) end test "when user account is disabled" do @@ -129,16 +138,86 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do {:ok, %User{}} = User.set_activation(user, false) - assert {:cancel, {:user_active, false}} = perform_incoming(params) + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:cancel, {:user_active, false}} = ReceiverWorker.perform(oban_job) end end + test "it can validate the signature" do + Tesla.Mock.mock(fn + %{url: "https://phpc.social/users/denniskoch"} -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/denniskoch.json"), + headers: [{"content-type", "application/activity+json"}] + } + + %{url: "https://phpc.social/users/denniskoch/collections/featured"} -> + %Tesla.Env{ + status: 200, + headers: [{"content-type", "application/activity+json"}], + body: + File.read!("test/fixtures/users_mock/masto_featured.json") + |> String.replace("{{domain}}", "phpc.social") + |> String.replace("{{nickname}}", "denniskoch") + } + end) + + params = + File.read!("test/fixtures/receiver_worker_signature_activity.json") |> Jason.decode!() + + req_headers = [ + ["accept-encoding", "gzip"], + ["content-length", "5184"], + ["content-type", "application/activity+json"], + ["date", "Thu, 25 Jul 2024 13:33:31 GMT"], + ["digest", "SHA-256=ouge/6HP2/QryG6F3JNtZ6vzs/hSwMk67xdxe87eH7A="], + ["host", "bikeshed.party"], + [ + "signature", + "keyId=\"https://mastodon.social/users/bastianallgeier#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"ymE3vn5Iw50N6ukSp8oIuXJB5SBjGAGjBasdTDvn+ahZIzq2SIJfmVCsIIzyqIROnhWyQoTbavTclVojEqdaeOx+Ejz2wBnRBmhz5oemJLk4RnnCH0lwMWyzeY98YAvxi9Rq57Gojuv/1lBqyGa+rDzynyJpAMyFk17XIZpjMKuTNMCbjMDy76ILHqArykAIL/v1zxkgwxY/+ELzxqMpNqtZ+kQ29znNMUBB3eVZ/mNAHAz6o33Y9VKxM2jw+08vtuIZOusXyiHbRiaj2g5HtN2WBUw1MzzfRfHF2/yy7rcipobeoyk5RvP5SyHV3WrIeZ3iyoNfmv33y8fxllF0EA==\"" + ], + [ + "user-agent", + "http.rb/5.2.0 (Mastodon/4.3.0-nightly.2024-07-25; +https://mastodon.social/)" + ] + ] + + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: req_headers, + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:ok, %Pleroma.Activity{}} = ReceiverWorker.perform(oban_job) + end + test "cancels due to origin containment" do params = insert(:note_activity).data |> Map.put("id", "https://notorigindomain.com/activity") - assert {:cancel, :origin_containment_failed} = perform_incoming(params) + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) + + assert {:cancel, :origin_containment_failed} = ReceiverWorker.perform(oban_job) end test "canceled due to deleted object" do @@ -154,114 +233,16 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do } end) - assert {:cancel, _} = perform_incoming(params) - end + {:ok, oban_job} = + Federator.incoming_ap_doc(%{ + method: "POST", + req_headers: [], + request_path: "/inbox", + params: params, + query_string: "" + }) - test "delegates legacy failed-signature metadata jobs instead of processing them as trusted" do - alice = insert(:user, local: false, ap_id: "https://one.com/users/alice") - bob = insert(:user, local: false, ap_id: "https://two.com/users/bob") - object_id = "https://two.com/objects/legacy-forged-note" - - create = %{ - "type" => "Create", - "actor" => bob.ap_id, - "id" => "https://two.com/activities/legacy-forged-create", - "context" => "https://two.com/contexts/legacy-forged-create", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "object" => %{ - "type" => "Note", - "id" => object_id, - "actor" => bob.ap_id, - "attributedTo" => bob.ap_id, - "context" => "https://two.com/contexts/legacy-forged-create", - "content" => "forged post", - "published" => "2024-07-25T13:33:31Z", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [] - } - } - - assert {:cancel, :actor_signature_mismatch} = - ReceiverWorker.perform(%Oban.Job{ - args: %{ - "op" => "incoming_ap_doc", - "method" => "POST", - "params" => create, - "req_headers" => signature_headers_for(alice), - "request_path" => "/inbox", - "query_string" => "" - } - }) - - refute Pleroma.Activity.get_by_ap_id(create["id"]) - refute Pleroma.Object.get_by_ap_id(object_id) - end - - test "fails closed for the old persisted failed-signature job shape" do - alice = insert(:user, local: false, ap_id: "https://one.com/users/alice") - bob = insert(:user, local: false, ap_id: "https://two.com/users/bob") - object_id = "https://two.com/objects/old-shape-forged-note" - - create = %{ - "type" => "Create", - "actor" => bob.ap_id, - "id" => "https://two.com/activities/old-shape-forged-create", - "context" => "https://two.com/contexts/old-shape-forged-create", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "object" => %{ - "type" => "Note", - "id" => object_id, - "actor" => bob.ap_id, - "attributedTo" => bob.ap_id, - "context" => "https://two.com/contexts/old-shape-forged-create", - "content" => "forged post", - "published" => "2024-07-25T13:33:31Z", - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [] - } - } - - assert {:cancel, :missing_signature_retry_metadata} = - ReceiverWorker.perform(%Oban.Job{ - args: %{ - "op" => "incoming_ap_doc", - "params" => create, - "req_headers" => signature_headers_for(alice), - "timeout" => 20_000 - } - }) - - refute Pleroma.Activity.get_by_ap_id(create["id"]) - refute Pleroma.Object.get_by_ap_id(object_id) - end - - test "fails closed for legacy retry jobs missing one metadata field" do - alice = insert(:user, local: false, ap_id: "https://one.com/users/alice") - params = insert(:note_activity).data - - assert {:cancel, :missing_signature_retry_metadata} = - ReceiverWorker.perform(%Oban.Job{ - args: %{ - "op" => "incoming_ap_doc", - "method" => "POST", - "params" => params, - "req_headers" => signature_headers_for(alice), - "request_path" => "/inbox" - } - }) - end - - test "fails closed for malformed legacy metadata jobs without params" do - assert {:cancel, :missing_signature_retry_metadata} = - ReceiverWorker.perform(%Oban.Job{ - args: %{ - "op" => "incoming_ap_doc", - "req_headers" => [], - "timeout" => 20_000 - } - }) + assert {:cancel, _} = ReceiverWorker.perform(oban_job) end describe "Server reachability:" do diff --git a/test/pleroma/workers/signature_retry_worker_test.exs b/test/pleroma/workers/signature_retry_worker_test.exs deleted file mode 100644 index 94dd5f6c1..000000000 --- a/test/pleroma/workers/signature_retry_worker_test.exs +++ /dev/null @@ -1,574 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors