mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2024-12-23 00:26:30 +00:00
Merge branch 'release/2.7.0' into 'stable'
v2.7.0 See merge request pleroma/pleroma!4179
This commit is contained in:
commit
36d469cf02
1022 changed files with 16857 additions and 5935 deletions
9
.dialyzer_ignore.exs
Normal file
9
.dialyzer_ignore.exs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[
|
||||||
|
{"lib/cachex.ex", "Unknown type: Spec.cache/0."},
|
||||||
|
{"lib/pleroma/web/plugs/rate_limiter.ex", "The pattern can never match the type {:commit, _} | {:ignore, _}."},
|
||||||
|
{"lib/pleroma/web/plugs/rate_limiter.ex", "Function get_scale/2 will never be called."},
|
||||||
|
{"lib/pleroma/web/plugs/rate_limiter.ex", "Function initialize_buckets!/1 will never be called."},
|
||||||
|
{"lib/pleroma/workers/receiver_worker.ex", :call},
|
||||||
|
{"lib/pleroma/workers/receiver_worker.ex", :pattern_match},
|
||||||
|
{"lib/pleroma/workers/receiver_worker.ex", :pattern_match_cov},
|
||||||
|
]
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -6,7 +6,7 @@
|
||||||
/test/instance
|
/test/instance
|
||||||
/test/uploads
|
/test/uploads
|
||||||
/.elixir_ls
|
/.elixir_ls
|
||||||
/test/fixtures/DSCN0010_tmp.jpg
|
/test/fixtures/DSCN0010_tmp*
|
||||||
/test/fixtures/test_tmp.txt
|
/test/fixtures/test_tmp.txt
|
||||||
/test/fixtures/image_tmp.jpg
|
/test/fixtures/image_tmp.jpg
|
||||||
/test/tmp/
|
/test/tmp/
|
||||||
|
@ -57,5 +57,9 @@ pleroma.iml
|
||||||
.tool-versions
|
.tool-versions
|
||||||
|
|
||||||
# Editor temp files
|
# Editor temp files
|
||||||
/*~
|
*~
|
||||||
/*#
|
*#
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
archive-*
|
||||||
|
.gitlab-ci-local
|
||||||
|
|
150
.gitlab-ci.yml
150
.gitlab-ci.yml
|
@ -1,11 +1,13 @@
|
||||||
image: git.pleroma.social:5050/pleroma/pleroma/ci-base
|
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.13.4-otp-25
|
||||||
|
|
||||||
variables: &global_variables
|
variables: &global_variables
|
||||||
|
# Only used for the release
|
||||||
|
ELIXIR_VER: 1.13.4
|
||||||
POSTGRES_DB: pleroma_test
|
POSTGRES_DB: pleroma_test
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
DB_HOST: postgres
|
DB_HOST: postgres
|
||||||
DB_PORT: 5432
|
DB_PORT: "5432"
|
||||||
MIX_ENV: test
|
MIX_ENV: test
|
||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
|
@ -16,17 +18,16 @@ workflow:
|
||||||
- if: $CI_COMMIT_BRANCH
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
cache: &global_cache_policy
|
cache: &global_cache_policy
|
||||||
key:
|
key: $CI_JOB_IMAGE-$CI_COMMIT_SHORT_SHA
|
||||||
files:
|
|
||||||
- mix.lock
|
|
||||||
paths:
|
paths:
|
||||||
- deps
|
- deps
|
||||||
- _build
|
- _build
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- check-changelog
|
|
||||||
- build
|
- build
|
||||||
|
- lint
|
||||||
- test
|
- test
|
||||||
|
- check-changelog
|
||||||
- benchmark
|
- benchmark
|
||||||
- deploy
|
- deploy
|
||||||
- release
|
- release
|
||||||
|
@ -69,7 +70,7 @@ check-changelog:
|
||||||
tags:
|
tags:
|
||||||
- amd64
|
- amd64
|
||||||
|
|
||||||
build:
|
build-1.13.4-otp-25:
|
||||||
extends:
|
extends:
|
||||||
- .build_changes_policy
|
- .build_changes_policy
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
|
@ -77,10 +78,19 @@ build:
|
||||||
script:
|
script:
|
||||||
- mix compile --force
|
- mix compile --force
|
||||||
|
|
||||||
|
build-1.17.1-otp-26:
|
||||||
|
extends:
|
||||||
|
- .build_changes_policy
|
||||||
|
- .using-ci-base
|
||||||
|
stage: build
|
||||||
|
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.17.1-otp-26
|
||||||
|
script:
|
||||||
|
- mix compile --force
|
||||||
|
|
||||||
spec-build:
|
spec-build:
|
||||||
extends:
|
extends:
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
stage: test
|
stage: build
|
||||||
rules:
|
rules:
|
||||||
- changes:
|
- changes:
|
||||||
- ".gitlab-ci.yml"
|
- ".gitlab-ci.yml"
|
||||||
|
@ -100,7 +110,7 @@ benchmark:
|
||||||
variables:
|
variables:
|
||||||
MIX_ENV: benchmark
|
MIX_ENV: benchmark
|
||||||
services:
|
services:
|
||||||
- name: postgres:9.6-alpine
|
- name: postgres:11.22-alpine
|
||||||
alias: postgres
|
alias: postgres
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
script:
|
script:
|
||||||
|
@ -108,7 +118,7 @@ benchmark:
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- mix pleroma.load_testing
|
- mix pleroma.load_testing
|
||||||
|
|
||||||
unit-testing:
|
unit-testing-1.13.4-otp-25:
|
||||||
extends:
|
extends:
|
||||||
- .build_changes_policy
|
- .build_changes_policy
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
|
@ -116,15 +126,14 @@ unit-testing:
|
||||||
cache: &testing_cache_policy
|
cache: &testing_cache_policy
|
||||||
<<: *global_cache_policy
|
<<: *global_cache_policy
|
||||||
policy: pull
|
policy: pull
|
||||||
|
services: &testing_services
|
||||||
services:
|
|
||||||
- name: postgres:13-alpine
|
- name: postgres:13-alpine
|
||||||
alias: postgres
|
alias: postgres
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
script:
|
script: &testing_script
|
||||||
- mix ecto.create
|
- mix ecto.create
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- mix test --cover --preload-modules
|
- mix pleroma.test_runner --cover --preload-modules
|
||||||
coverage: '/^Line total: ([^ ]*%)$/'
|
coverage: '/^Line total: ([^ ]*%)$/'
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
|
@ -132,65 +141,20 @@ unit-testing:
|
||||||
coverage_format: cobertura
|
coverage_format: cobertura
|
||||||
path: coverage.xml
|
path: coverage.xml
|
||||||
|
|
||||||
unit-testing-erratic:
|
unit-testing-1.17.1-otp-26:
|
||||||
extends:
|
|
||||||
- .build_changes_policy
|
|
||||||
- .using-ci-base
|
|
||||||
stage: test
|
|
||||||
retry: 2
|
|
||||||
allow_failure: true
|
|
||||||
cache: &testing_cache_policy
|
|
||||||
<<: *global_cache_policy
|
|
||||||
policy: pull
|
|
||||||
|
|
||||||
services:
|
|
||||||
- name: postgres:13-alpine
|
|
||||||
alias: postgres
|
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
script:
|
|
||||||
- mix ecto.create
|
|
||||||
- mix ecto.migrate
|
|
||||||
- mix test --only=erratic
|
|
||||||
|
|
||||||
# Removed to fix CI issue. In this early state it wasn't adding much value anyway.
|
|
||||||
# TODO Fix and reinstate federated testing
|
|
||||||
# federated-testing:
|
|
||||||
# stage: test
|
|
||||||
# cache: *testing_cache_policy
|
|
||||||
# services:
|
|
||||||
# - name: minibikini/postgres-with-rum:12
|
|
||||||
# alias: postgres
|
|
||||||
# command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
# script:
|
|
||||||
# - mix deps.get
|
|
||||||
# - mix ecto.create
|
|
||||||
# - mix ecto.migrate
|
|
||||||
# - epmd -daemon
|
|
||||||
# - mix test --trace --only federated
|
|
||||||
|
|
||||||
unit-testing-rum:
|
|
||||||
extends:
|
extends:
|
||||||
- .build_changes_policy
|
- .build_changes_policy
|
||||||
- .using-ci-base
|
- .using-ci-base
|
||||||
stage: test
|
stage: test
|
||||||
|
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.17.1-otp-26
|
||||||
cache: *testing_cache_policy
|
cache: *testing_cache_policy
|
||||||
services:
|
services: *testing_services
|
||||||
- name: minibikini/postgres-with-rum:12
|
script: *testing_script
|
||||||
alias: postgres
|
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
variables:
|
|
||||||
<<: *global_variables
|
|
||||||
RUM_ENABLED: "true"
|
|
||||||
script:
|
|
||||||
- mix ecto.create
|
|
||||||
- mix ecto.migrate
|
|
||||||
- "mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
|
|
||||||
- mix test --preload-modules
|
|
||||||
|
|
||||||
lint:
|
formatting-1.15:
|
||||||
extends: .build_changes_policy
|
extends: .build_changes_policy
|
||||||
image: ¤t_elixir elixir:1.12-alpine
|
image: &formatting_elixir elixir:1.15-alpine
|
||||||
stage: test
|
stage: lint
|
||||||
cache: *testing_cache_policy
|
cache: *testing_cache_policy
|
||||||
before_script: ¤t_bfr_script
|
before_script: ¤t_bfr_script
|
||||||
- apk update
|
- apk update
|
||||||
|
@ -201,25 +165,38 @@ lint:
|
||||||
script:
|
script:
|
||||||
- mix format --check-formatted
|
- mix format --check-formatted
|
||||||
|
|
||||||
analysis:
|
cycles-1.15:
|
||||||
extends:
|
|
||||||
- .build_changes_policy
|
|
||||||
- .using-ci-base
|
|
||||||
stage: test
|
|
||||||
cache: *testing_cache_policy
|
|
||||||
script:
|
|
||||||
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
|
||||||
|
|
||||||
cycles:
|
|
||||||
extends: .build_changes_policy
|
extends: .build_changes_policy
|
||||||
image: *current_elixir
|
image: *formatting_elixir
|
||||||
stage: test
|
stage: lint
|
||||||
cache: {}
|
cache: {}
|
||||||
before_script: *current_bfr_script
|
before_script: *current_bfr_script
|
||||||
script:
|
script:
|
||||||
- mix compile
|
- mix compile
|
||||||
- mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}'
|
- mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}'
|
||||||
|
|
||||||
|
analysis:
|
||||||
|
extends:
|
||||||
|
- .build_changes_policy
|
||||||
|
- .using-ci-base
|
||||||
|
stage: lint
|
||||||
|
cache: *testing_cache_policy
|
||||||
|
script:
|
||||||
|
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
||||||
|
|
||||||
|
dialyzer:
|
||||||
|
extends:
|
||||||
|
- .build_changes_policy
|
||||||
|
- .using-ci-base
|
||||||
|
stage: lint
|
||||||
|
allow_failure: true
|
||||||
|
when: manual
|
||||||
|
cache: *testing_cache_policy
|
||||||
|
tags:
|
||||||
|
- feld
|
||||||
|
script:
|
||||||
|
- mix dialyzer
|
||||||
|
|
||||||
docs-deploy:
|
docs-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
cache: *testing_cache_policy
|
cache: *testing_cache_policy
|
||||||
|
@ -294,7 +271,7 @@ stop_review_app:
|
||||||
|
|
||||||
amd64:
|
amd64:
|
||||||
stage: release
|
stage: release
|
||||||
image: elixir:1.11.4
|
image: elixir:$ELIXIR_VER
|
||||||
only: &release-only
|
only: &release-only
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
|
@ -318,8 +295,9 @@ amd64:
|
||||||
- deps
|
- deps
|
||||||
variables: &release-variables
|
variables: &release-variables
|
||||||
MIX_ENV: prod
|
MIX_ENV: prod
|
||||||
|
VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
|
||||||
before_script: &before-release
|
before_script: &before-release
|
||||||
- apt-get update && apt-get install -y cmake libmagic-dev
|
- apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev
|
||||||
- echo "import Config" > config/prod.secret.exs
|
- echo "import Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
|
@ -334,13 +312,13 @@ amd64-musl:
|
||||||
stage: release
|
stage: release
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
image: elixir:1.11.4-alpine
|
image: elixir:$ELIXIR_VER-alpine
|
||||||
tags:
|
tags:
|
||||||
- amd64
|
- amd64
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: &before-release-musl
|
before_script: &before-release-musl
|
||||||
- apk add git build-base cmake file-dev openssl
|
- apk add git build-base cmake file-dev openssl vips-dev
|
||||||
- echo "import Config" > config/prod.secret.exs
|
- echo "import Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
|
@ -352,7 +330,7 @@ arm:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32-specified
|
- arm32-specified
|
||||||
image: arm32v7/elixir:1.11.4
|
image: arm32v7/elixir:$ELIXIR_VER
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -364,7 +342,7 @@ arm-musl:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32-specified
|
- arm32-specified
|
||||||
image: arm32v7/elixir:1.11.4-alpine
|
image: arm32v7/elixir:$ELIXIR_VER-alpine
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
@ -376,7 +354,7 @@ arm64:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image: arm64v8/elixir:1.11.4
|
image: arm64v8/elixir:$ELIXIR_VER
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -388,7 +366,7 @@ arm64-musl:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image: arm64v8/elixir:1.11.4-alpine
|
image: arm64v8/elixir:$ELIXIR_VER-alpine
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
`<code>` can be anything, but we recommend using a more or less unique identifier to avoid collisions, such as the branch name.
|
`<code>` can be anything, but we recommend using a more or less unique identifier to avoid collisions, such as the branch name.
|
||||||
|
|
||||||
`<type>` can be `add`, `remove`, `fix`, `security` or `skip`. `skip` is only used if there is no user-visible change in the MR (for example, only editing comments in the code). Otherwise, choose a type that corresponds to your change.
|
`<type>` can be `add`, `change`, `remove`, `fix`, `security` or `skip`. `skip` is only used if there is no user-visible change in the MR (for example, only editing comments in the code). Otherwise, choose a type that corresponds to your change.
|
||||||
|
|
||||||
In the file, write the changelog entry. For example, if an MR adds group functionality, we can create a file named `group.add` and write `Add group functionality` in it.
|
In the file, write the changelog entry. For example, if an MR adds group functionality, we can create a file named `group.add` and write `Add group functionality` in it.
|
||||||
|
|
||||||
|
|
1
.rgignore
Normal file
1
.rgignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
priv/static
|
162
CHANGELOG.md
162
CHANGELOG.md
|
@ -4,10 +4,158 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## 2.6.3
|
## 2.7.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
- HTTP Security: By default, don't allow unsafe-eval. The setting needs to be changed to allow Flash emulation.
|
||||||
- Fix webfinger spoofing.
|
- Fix webfinger spoofing.
|
||||||
|
- Use proper workers for fetching pins instead of an ad-hoc task, fixing a potential fetch loop
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Update to Phoenix 1.7
|
||||||
|
- Elixir Logger configuration is now longer permitted through AdminFE and ConfigDB
|
||||||
|
- Refactor the user backups code and improve test coverage
|
||||||
|
- Invalid activities delivered to the inbox will be rejected with a 400 Bad Request
|
||||||
|
- Support Bandit as an alternative to Cowboy for the HTTP server.
|
||||||
|
- Update Bandit to 1.5.2
|
||||||
|
- Replace eblurhash with rinpatch_blurhash. This also removes a dependency on ImageMagick.
|
||||||
|
- Elixir 1.13 is the minimum required version.
|
||||||
|
- Document maximum supported version of Erlang & Elixir
|
||||||
|
- Update and extend NetBSD installation docs
|
||||||
|
- Make `/api/v1/pleroma/federation_status` publicly available
|
||||||
|
- Increase outgoing federation parallelism
|
||||||
|
- Change Hackney connection pool timeouts to align with the values Gun uses
|
||||||
|
- Transmogrifier: handle non-validate errors on incoming Delete activities
|
||||||
|
- Remote object fetch failures will prevent the object fetch job from retrying if the object request returns 401, 403, 404, 410, or exceeds the maximum thread depth.
|
||||||
|
- - Change AccountView `last_status_at` from a datetime to a date (as done in Mastodon 3.1.0)
|
||||||
|
- Improve error logging when LDAP authentication fails.
|
||||||
|
- Publisher jobs will not retry if the error received is a 400
|
||||||
|
- PollWorker jobs will not retry if the activity no longer exists.
|
||||||
|
- Improved detecting unrecoverable errors for incoming federation jobs
|
||||||
|
- Changed some jobs to return :cancel on unrecoverable errors that should not be retried
|
||||||
|
- Discard Remote Fetcher jobs which errored due to an MRF rejection.
|
||||||
|
- Oban queues have refactored to simplify the queue design
|
||||||
|
- Ensure all Oban jobs have timeouts defined
|
||||||
|
- Optimistic Inbox reduces the processing overhead of incoming activities without instantly verifiable signatures.
|
||||||
|
- HTTP connection pool adjustments
|
||||||
|
- Disable jit by default for PostgreSQL
|
||||||
|
- Update the documentation for configuring Prometheus metrics.
|
||||||
|
- Change the prometheus library to PromEx.
|
||||||
|
- Publisher jobs now store the the activity id instead of inserting duplicate JSON data in the Oban queue for each delivery.
|
||||||
|
- Activity publishing failures will prevent the job from retrying if the publishing request returns a 403 or 410
|
||||||
|
- Publisher errors will now emit logs indicating the inbox that was not available for delivery.
|
||||||
|
- Reduce the reachability timestamp update to a single upsert query
|
||||||
|
- A 422 error is returned when attempting to reply to a deleted status
|
||||||
|
- Rich Media backfilling is now an Oban job
|
||||||
|
- Refactored Rich Media to cache the content in the database. Fetching operations that could block status rendering have been eliminated.
|
||||||
|
- Set default values on validators for transient objects (attachment, poll options)
|
||||||
|
- User profile refreshes are now asynchronous
|
||||||
|
- Change mediaproxy previews to use vips to generate thumbnails instead of ImageMagick
|
||||||
|
- Render nice web push notifications for polls
|
||||||
|
- Refactor the Mastodon /api/v1/streaming websocket handler to use Phoenix.Socket.Transport
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Uploader: Add support for uploading attachments using IPFS
|
||||||
|
- Add NSFW-detecting MRF
|
||||||
|
- Add DNSRBL MRF
|
||||||
|
- Add options to the mix prune_objects task
|
||||||
|
- Add Anti-mention Spam MRF backported from Rebased
|
||||||
|
- HTTPSignaturePlug: Add :authorized_fetch_mode_exceptions configuration
|
||||||
|
- Support /authorize-interaction route used by Mastodon
|
||||||
|
- Add an option to reject certain domains when authorized fetch is enabled.
|
||||||
|
- Include following/followers in backups
|
||||||
|
- Allow to group bookmarks in folders
|
||||||
|
- Include image description in status media cards
|
||||||
|
- Implement `/api/v1/accounts/familiar_followers`
|
||||||
|
- Add support for configuring favicon, embed favicon and PWA manifest in server-generated meta
|
||||||
|
- Implement FEP-2c59, add "webfinger" to user actor
|
||||||
|
- Framegrabs with ffmpeg will execute with a 5 second timeout and cache the URLs of failures with a TTL of 15 minutes to prevent excessive retries.
|
||||||
|
- Added a Mix task "pleroma.config fix_mrf_policies" which will remove erroneous MRF policies from ConfigDB.
|
||||||
|
- Add ForceMention MRF
|
||||||
|
- [docs] add frontends management documentation
|
||||||
|
- Implement group actors
|
||||||
|
- Add contact account to InstanceView
|
||||||
|
- Add instance rules
|
||||||
|
- Implement /api/v2/instance route
|
||||||
|
- Verify profile link ownership with rel="me"
|
||||||
|
- Logger metadata is now attached to some logs to help with troubleshooting and analysis
|
||||||
|
- Add new parameters to /api/v2/instance: configuration[accounts][max_pinned_statuses] and configuration[statuses][characters_reserved_per_url]
|
||||||
|
- Add meilisearch, make search engines pluggable
|
||||||
|
- Add missing indexes on foreign key relationships
|
||||||
|
- Startup detection for configured MRF modules that are missing or incorrectly defined
|
||||||
|
- Permit passing --chunk and --step values to the Pleroma.Search.Indexer Mix task
|
||||||
|
- Deleting, Unfavoriting, Unrepeating, or Unreacting will cancel undelivered publishing jobs for the original activity.
|
||||||
|
- Oban jobs can now be viewed in the Live Dashboard
|
||||||
|
- Add media proxy to opengraph rich media cards
|
||||||
|
- Support for Erlang OTP 26
|
||||||
|
- Prioritize mentioned recipients (i.e., those that are not just followers) when federating.
|
||||||
|
- PromEx documentation
|
||||||
|
- Expose nonAnonymous field from Smithereen polls
|
||||||
|
- Add Qdrant/OpenAI embedding search
|
||||||
|
- Adds the capability to add a URL to a scrobble (optional field)
|
||||||
|
- scrubbers/default: Add more formatting elements from HTML4 / GoToSocial (acronym, bdo, big, cite, dfn, ins, kbd, q, samp, s, tt, var, wbr)
|
||||||
|
- Monitoring of search backend health to control the processing of jobs in the search indexing Oban queue
|
||||||
|
- Display reposted replies with exclude_replies: true
|
||||||
|
- Add "status" notification type
|
||||||
|
- Support honk-style attachment summaries as alt-text.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix Emoji object IDs not always being valid
|
||||||
|
- Remove checking ImageMagick's commands for Pleroma.Upload.Filter.AnalyzeMetadata
|
||||||
|
- Ensure that StripLocation actually removes everything resembling GPS data from PNGs
|
||||||
|
- Fix authentication check on account rendering when bio is defined
|
||||||
|
- ap userview: add outbox field.
|
||||||
|
- Fix #strip_report_status_data
|
||||||
|
- Fix federation with Convergence AP Bridge
|
||||||
|
- ChatMessage: Tolerate attachment field set to an empty array
|
||||||
|
- Config: Check the permissions of the linked file instead of the symlink
|
||||||
|
- MediaProxy was setting the content-length header which is not permitted by RFC9112§6.2 when we are chunking the reply as it conflicts with the existence of the transfer-encoding header.
|
||||||
|
- Restore Cowboy's ability to stream MediaProxy responses without Chunked encoding.
|
||||||
|
- Fix the processing of email digest jobs.
|
||||||
|
- Client application data was always missing from the status
|
||||||
|
- Elixir 1.15 compatibility
|
||||||
|
- When downloading remote emojis packs, account for pagination
|
||||||
|
- Make remote emoji packs API use specifically the V1 URL. Akkoma does not understand it without V1, and it works either way with normal pleroma, so no reason to not do this
|
||||||
|
- Following HTTP Redirects when the HTTP Adapter is Finch
|
||||||
|
- Video framegrabs were not working correctly after the change to use Exile to execute ffmpeg
|
||||||
|
- Deactivated groups would still try to repeat a post.
|
||||||
|
- Fix logic error in Gun connection pooling which prevented retries even when the worker was launched with retry = true
|
||||||
|
- Connection pool errors when publishing an activity is a soft-error that will be retried shortly.
|
||||||
|
- Gun Connection Pool was not retrying to acquire a connection if the pool was full and stale connections were reclaimed
|
||||||
|
- TwitterAPI: Return proper error when healthcheck is disabled
|
||||||
|
- Handle cases when users.inbox is nil.
|
||||||
|
- Fix LDAP support
|
||||||
|
- Use correct domain for fqn and InstanceView
|
||||||
|
- The query for marking notifications as read has been simplified
|
||||||
|
- Mastodon API /api/v1/directory: Fix listing directory contents when not authenticated
|
||||||
|
- Ensure MediaProxy HTTP requests obey all the defined connection settings
|
||||||
|
- Fix a memory leak caused by Websocket connections that would not enter a state where a full garbage collection run could be triggered.
|
||||||
|
- Fix OpenGraph and Twitter metadata providers when parsing objects with no content or summary fields.
|
||||||
|
- MRF: Log sensible error for subdomains_regex
|
||||||
|
- MRF.StealEmojiPolicy: Properly add fallback extension to filenames missing one
|
||||||
|
- Federated timeline removal of hashtags via MRF HashtagPolicy
|
||||||
|
- Support objects with a null contentMap (firefish)
|
||||||
|
- Fix notifications query which was not using the index properly
|
||||||
|
- Notifications: improve performance by filtering on users table instead of activities table
|
||||||
|
- Prevent Rich Media backfill jobs from retrying in cases where it is likely they will fail again.
|
||||||
|
- Oban Jobs for refreshing users were not respecting the uniqueness setting
|
||||||
|
- Fix Optimistic Inbox for failed signatures
|
||||||
|
- MediaProxy Preview failures prevented when encountering certain video files
|
||||||
|
- pleroma_ctl: Use realpath(1) instead of readlink(1)
|
||||||
|
- ReceiverWorker: Make sure non-{:ok, _} is returned as {:error, …}
|
||||||
|
- Harden Rich Media parsing against very slow or malicious URLs
|
||||||
|
- Rich Media Preview cache eviction when the activity is updated.
|
||||||
|
- Parsing of RichMedia TTLs for Amazon URLs when query parameters are nil
|
||||||
|
- End of poll notifications were not streamed over websockets or web push
|
||||||
|
- Fix eblurhash and elixir-captcha not using system cflags
|
||||||
|
- Video thumbnails were not being generated due to a negative cache lookup logic error
|
||||||
|
- Fix web push notifications not successfully delivering
|
||||||
|
- Web Push notifications are no longer generated for muted/blocked threads and users.
|
||||||
|
- Fix validate_webfinger when running a different domain for Webfinger
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Mastodon API: Remove deprecated GET /api/v1/statuses/:id/card endpoint https://github.com/mastodon/mastodon/pull/11213
|
||||||
|
- Removed support for multiple federator modules as we only support ActivityPub
|
||||||
|
|
||||||
## 2.6.2
|
## 2.6.2
|
||||||
|
|
||||||
|
@ -72,7 +220,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.5.4
|
## 2.5.4
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem
|
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
||||||
|
|
||||||
## 2.5.3
|
## 2.5.3
|
||||||
|
|
||||||
|
@ -88,7 +236,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
## 2.5.4
|
## 2.5.4
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem
|
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
|
||||||
|
|
||||||
## 2.5.3
|
## 2.5.3
|
||||||
|
|
||||||
|
@ -128,7 +276,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Fix `block_from_stranger` setting
|
- Fix `block_from_stranger` setting
|
||||||
- Fix rel="me"
|
- Fix rel="me"
|
||||||
- Docker images will now run properly
|
- Docker images will now run properly
|
||||||
- Fix inproper content being cached in report content
|
- Fix improper content being cached in report content
|
||||||
- Notification filter on object content will not operate on the ones that inherently have no content
|
- Notification filter on object content will not operate on the ones that inherently have no content
|
||||||
- ZWNJ and double dots in links are parsed properly for Plain-text posts
|
- ZWNJ and double dots in links are parsed properly for Plain-text posts
|
||||||
- OTP releases will work on systems with a newer libcrypt
|
- OTP releases will work on systems with a newer libcrypt
|
||||||
|
@ -794,7 +942,7 @@ switched to a new configuration mechanism, however it was not officially removed
|
||||||
- Rate limiter crashes when there is no explicitly specified ip in the config
|
- Rate limiter crashes when there is no explicitly specified ip in the config
|
||||||
- 500 errors when no `Accept` header is present if Static-FE is enabled
|
- 500 errors when no `Accept` header is present if Static-FE is enabled
|
||||||
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
|
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
|
||||||
- Statuses posted with BBCode/Markdown having unncessary newlines in Pleroma-FE
|
- Statuses posted with BBCode/Markdown having unnecessary newlines in Pleroma-FE
|
||||||
- OTP: Fix some settings not being migrated to in-database config properly
|
- OTP: Fix some settings not being migrated to in-database config properly
|
||||||
- No `Cache-Control` headers on attachment/media proxy requests
|
- No `Cache-Control` headers on attachment/media proxy requests
|
||||||
- Character limit enforcement being off by 1
|
- Character limit enforcement being off by 1
|
||||||
|
@ -1114,10 +1262,10 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
|
||||||
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
|
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Expiring/ephemeral activites. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
- Expiring/ephemeral activities. All activities can have expires_at value set, which controls when they should be deleted automatically.
|
||||||
- Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour.
|
- Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour.
|
||||||
- Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
|
- Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
|
||||||
- Configuration: `ActivityExpiration.enabled` controls whether expired activites will get deleted at the appropriate time. Enabled by default.
|
- Configuration: `ActivityExpiration.enabled` controls whether expired activities will get deleted at the appropriate time. Enabled by default.
|
||||||
- Conversations: Add Pleroma-specific conversation endpoints and status posting extensions. Run the `bump_all_conversations` task again to create the necessary data.
|
- Conversations: Add Pleroma-specific conversation endpoints and status posting extensions. Run the `bump_all_conversations` task again to create the necessary data.
|
||||||
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
|
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
|
||||||
- MRF: Support for excluding specific domains from Transparency.
|
- MRF: Support for excluding specific domains from Transparency.
|
||||||
|
|
11
Dockerfile
11
Dockerfile
|
@ -1,15 +1,16 @@
|
||||||
ARG ELIXIR_IMG=hexpm/elixir
|
ARG ELIXIR_IMG=hexpm/elixir
|
||||||
ARG ELIXIR_VER=1.11.4
|
ARG ELIXIR_VER=1.13.4
|
||||||
ARG ERLANG_VER=24.2.1
|
ARG ERLANG_VER=24.3.4.15
|
||||||
ARG ALPINE_VER=3.17.0
|
ARG ALPINE_VER=3.17.5
|
||||||
|
|
||||||
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build
|
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
ENV MIX_ENV=prod
|
ENV MIX_ENV=prod
|
||||||
|
ENV VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS
|
||||||
|
|
||||||
RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
|
RUN apk add git gcc g++ musl-dev make cmake file-dev vips-dev &&\
|
||||||
echo "import Config" > config/prod.secret.exs &&\
|
echo "import Config" > config/prod.secret.exs &&\
|
||||||
mix local.hex --force &&\
|
mix local.hex --force &&\
|
||||||
mix local.rebar --force &&\
|
mix local.rebar --force &&\
|
||||||
|
@ -37,7 +38,7 @@ ARG HOME=/opt/pleroma
|
||||||
ARG DATA=/var/lib/pleroma
|
ARG DATA=/var/lib/pleroma
|
||||||
|
|
||||||
RUN apk update &&\
|
RUN apk update &&\
|
||||||
apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\
|
apk add exiftool ffmpeg vips libmagic ncurses postgresql-client &&\
|
||||||
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
|
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
|
||||||
mkdir -p ${DATA}/uploads &&\
|
mkdir -p ${DATA}/uploads &&\
|
||||||
mkdir -p ${DATA}/static &&\
|
mkdir -p ${DATA}/static &&\
|
||||||
|
|
|
@ -3,8 +3,20 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Mix.Tasks.Pleroma.Benchmark do
|
defmodule Mix.Tasks.Pleroma.Benchmark do
|
||||||
import Mix.Pleroma
|
@shortdoc "Benchmarks"
|
||||||
|
@moduledoc """
|
||||||
|
Benchmark tasks available:
|
||||||
|
|
||||||
|
adapters
|
||||||
|
render_timeline
|
||||||
|
search
|
||||||
|
tag
|
||||||
|
|
||||||
|
MIX_ENV=benchmark mix pleroma.benchmark adapters
|
||||||
|
"""
|
||||||
|
|
||||||
use Mix.Task
|
use Mix.Task
|
||||||
|
import Mix.Pleroma
|
||||||
|
|
||||||
def run(["search"]) do
|
def run(["search"]) do
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
@ -63,7 +75,7 @@ defmodule Mix.Tasks.Pleroma.Benchmark do
|
||||||
|
|
||||||
Benchee.run(
|
Benchee.run(
|
||||||
%{
|
%{
|
||||||
"Standart rendering" => fn activities ->
|
"Standard rendering" => fn activities ->
|
||||||
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
|
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
|
||||||
activities: activities,
|
activities: activities,
|
||||||
for: user,
|
for: user,
|
|
@ -1 +0,0 @@
|
||||||
Fix validate_webfinger when running a different domain for Webfinger
|
|
|
@ -1 +0,0 @@
|
||||||
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:latest --push .
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM elixir:1.11.4
|
FROM elixir:1.12.3
|
||||||
|
|
||||||
# Single RUN statement, otherwise intermediate images are created
|
# Single RUN statement, otherwise intermediate images are created
|
||||||
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
1
ci/elixir-1.12/build_and_push.sh
Executable file
1
ci/elixir-1.12/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.12 --push .
|
8
ci/elixir-1.13.4-otp-25/Dockerfile
Normal file
8
ci/elixir-1.13.4-otp-25/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM elixir:1.13.4-otp-25
|
||||||
|
|
||||||
|
# Single RUN statement, otherwise intermediate images are created
|
||||||
|
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||||
|
RUN apt-get update &&\
|
||||||
|
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
|
||||||
|
mix local.hex --force &&\
|
||||||
|
mix local.rebar --force
|
1
ci/elixir-1.13.4-otp-25/build_and_push.sh
Executable file
1
ci/elixir-1.13.4-otp-25/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.13.4-otp-25 --push .
|
8
ci/elixir-1.15.8-otp-26/Dockerfile
Normal file
8
ci/elixir-1.15.8-otp-26/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM elixir:1.15.8-otp-26
|
||||||
|
|
||||||
|
# Single RUN statement, otherwise intermediate images are created
|
||||||
|
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||||
|
RUN apt-get update &&\
|
||||||
|
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
|
||||||
|
mix local.hex --force &&\
|
||||||
|
mix local.rebar --force
|
1
ci/elixir-1.15.8-otp-26/build_and_push.sh
Executable file
1
ci/elixir-1.15.8-otp-26/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15.8-otp-26 --push .
|
8
ci/elixir-1.16.3-otp-26/Dockerfile
Normal file
8
ci/elixir-1.16.3-otp-26/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM elixir:1.16.3-otp-26
|
||||||
|
|
||||||
|
# Single RUN statement, otherwise intermediate images are created
|
||||||
|
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||||
|
RUN apt-get update &&\
|
||||||
|
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
|
||||||
|
mix local.hex --force &&\
|
||||||
|
mix local.rebar --force
|
1
ci/elixir-1.16.3-otp-26/build_and_push.sh
Executable file
1
ci/elixir-1.16.3-otp-26/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.16.3-otp-26 --push .
|
8
ci/elixir-1.17.1-otp-26/Dockerfile
Normal file
8
ci/elixir-1.17.1-otp-26/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM elixir:1.17.1-otp-26
|
||||||
|
|
||||||
|
# Single RUN statement, otherwise intermediate images are created
|
||||||
|
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
||||||
|
RUN apt-get update &&\
|
||||||
|
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
|
||||||
|
mix local.hex --force &&\
|
||||||
|
mix local.rebar --force
|
1
ci/elixir-1.17.1-otp-26/build_and_push.sh
Executable file
1
ci/elixir-1.17.1-otp-26/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.17.1-otp-26 --push .
|
3
ci/postgres-with-rum-13/Dockerfile
Normal file
3
ci/postgres-with-rum-13/Dockerfile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
FROM postgres:13-bullseye
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y postgresql-13-rum/bullseye-pgdg
|
1
ci/postgres-with-rum-13/build_and_push.sh
Executable file
1
ci/postgres-with-rum-13/build_and_push.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/postgres-with-rum-13:latest --push .
|
|
@ -14,7 +14,7 @@ config :pleroma, Pleroma.Captcha,
|
||||||
method: Pleroma.Captcha.Mock
|
method: Pleroma.Captcha.Mock
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
# Print only warnings and errors during test
|
||||||
config :logger, level: :warn
|
config :logger, level: :warning
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: []
|
config :pleroma, :auth, oauth_consumer_strategies: []
|
||||||
|
|
||||||
|
@ -79,6 +79,10 @@ IO.puts("RUM enabled: #{rum_enabled}")
|
||||||
|
|
||||||
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Application,
|
||||||
|
background_migrators: false,
|
||||||
|
streamer_registry: false
|
||||||
|
|
||||||
if File.exists?("./config/benchmark.secret.exs") do
|
if File.exists?("./config/benchmark.secret.exs") do
|
||||||
import_config "benchmark.secret.exs"
|
import_config "benchmark.secret.exs"
|
||||||
else
|
else
|
||||||
|
|
|
@ -82,6 +82,10 @@ config :ex_aws, :s3,
|
||||||
# region: "us-east-1", # may be required for Amazon AWS
|
# region: "us-east-1", # may be required for Amazon AWS
|
||||||
scheme: "https://"
|
scheme: "https://"
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Uploaders.IPFS,
|
||||||
|
post_gateway_url: "http://localhost:5001",
|
||||||
|
get_gateway_url: "http://localhost:8080"
|
||||||
|
|
||||||
config :pleroma, :emoji,
|
config :pleroma, :emoji,
|
||||||
shortcode_globs: ["/emoji/custom/**/*.png"],
|
shortcode_globs: ["/emoji/custom/**/*.png"],
|
||||||
pack_extensions: [".png", ".gif"],
|
pack_extensions: [".png", ".gif"],
|
||||||
|
@ -110,32 +114,11 @@ config :pleroma, :uri_schemes,
|
||||||
"xmpp"
|
"xmpp"
|
||||||
]
|
]
|
||||||
|
|
||||||
websocket_config = [
|
|
||||||
path: "/websocket",
|
|
||||||
serializer: [
|
|
||||||
{Phoenix.Socket.V1.JSONSerializer, "~> 1.0.0"},
|
|
||||||
{Phoenix.Socket.V2.JSONSerializer, "~> 2.0.0"}
|
|
||||||
],
|
|
||||||
timeout: 60_000,
|
|
||||||
transport_log: false,
|
|
||||||
compress: false
|
|
||||||
]
|
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
http: [
|
http: [
|
||||||
ip: {127, 0, 0, 1},
|
ip: {127, 0, 0, 1}
|
||||||
dispatch: [
|
|
||||||
{:_,
|
|
||||||
[
|
|
||||||
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
|
|
||||||
{"/websocket", Phoenix.Endpoint.CowboyWebSocket,
|
|
||||||
{Phoenix.Transports.WebSocket,
|
|
||||||
{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}},
|
|
||||||
{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
|
|
||||||
]}
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
protocol: "https",
|
protocol: "https",
|
||||||
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
|
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
|
||||||
|
@ -149,16 +132,18 @@ config :pleroma, Pleroma.Web.Endpoint,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Configures Elixir's Logger
|
# Configures Elixir's Logger
|
||||||
|
config :logger, backends: [:console]
|
||||||
|
|
||||||
config :logger, :console,
|
config :logger, :console,
|
||||||
level: :debug,
|
level: :debug,
|
||||||
format: "\n$time $metadata[$level] $message\n",
|
format: "\n$time $metadata[$level] $message\n",
|
||||||
metadata: [:request_id]
|
metadata: [:actor, :path, :type, :user]
|
||||||
|
|
||||||
config :logger, :ex_syslogger,
|
config :logger, :ex_syslogger,
|
||||||
level: :debug,
|
level: :debug,
|
||||||
ident: "pleroma",
|
ident: "pleroma",
|
||||||
format: "$metadata[$level] $message",
|
format: "$metadata[$level] $message",
|
||||||
metadata: [:request_id]
|
metadata: [:actor, :path, :type, :user]
|
||||||
|
|
||||||
config :mime, :types, %{
|
config :mime, :types, %{
|
||||||
"application/xml" => ["xml"],
|
"application/xml" => ["xml"],
|
||||||
|
@ -185,6 +170,7 @@ config :pleroma, :instance,
|
||||||
short_description: "",
|
short_description: "",
|
||||||
background_image: "/images/city.jpg",
|
background_image: "/images/city.jpg",
|
||||||
instance_thumbnail: "/instance/thumbnail.jpeg",
|
instance_thumbnail: "/instance/thumbnail.jpeg",
|
||||||
|
favicon: "/favicon.png",
|
||||||
limit: 5_000,
|
limit: 5_000,
|
||||||
description_limit: 5_000,
|
description_limit: 5_000,
|
||||||
remote_limit: 100_000,
|
remote_limit: 100_000,
|
||||||
|
@ -205,12 +191,10 @@ config :pleroma, :instance,
|
||||||
federating: true,
|
federating: true,
|
||||||
federation_incoming_replies_max_depth: 100,
|
federation_incoming_replies_max_depth: 100,
|
||||||
federation_reachability_timeout_days: 7,
|
federation_reachability_timeout_days: 7,
|
||||||
federation_publisher_modules: [
|
|
||||||
Pleroma.Web.ActivityPub.Publisher
|
|
||||||
],
|
|
||||||
allow_relay: true,
|
allow_relay: true,
|
||||||
public: true,
|
public: true,
|
||||||
quarantined_instances: [],
|
quarantined_instances: [],
|
||||||
|
rejected_instances: [],
|
||||||
static_dir: "instance/static/",
|
static_dir: "instance/static/",
|
||||||
allowed_post_formats: [
|
allowed_post_formats: [
|
||||||
"text/plain",
|
"text/plain",
|
||||||
|
@ -360,6 +344,8 @@ config :pleroma, :manifest,
|
||||||
icons: [
|
icons: [
|
||||||
%{
|
%{
|
||||||
src: "/static/logo.svg",
|
src: "/static/logo.svg",
|
||||||
|
sizes: "144x144",
|
||||||
|
purpose: "any",
|
||||||
type: "image/svg+xml"
|
type: "image/svg+xml"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -427,15 +413,33 @@ config :pleroma, :mrf_vocabulary,
|
||||||
accept: [],
|
accept: [],
|
||||||
reject: []
|
reject: []
|
||||||
|
|
||||||
|
config :pleroma, :mrf_dnsrbl,
|
||||||
|
nameserver: "127.0.0.1",
|
||||||
|
port: 53,
|
||||||
|
zone: "bl.pleroma.com"
|
||||||
|
|
||||||
# threshold of 7 days
|
# threshold of 7 days
|
||||||
config :pleroma, :mrf_object_age,
|
config :pleroma, :mrf_object_age,
|
||||||
threshold: 604_800,
|
threshold: 604_800,
|
||||||
actions: [:delist, :strip_followers]
|
actions: [:delist, :strip_followers]
|
||||||
|
|
||||||
|
config :pleroma, :mrf_nsfw_api,
|
||||||
|
url: "http://127.0.0.1:5000/",
|
||||||
|
threshold: 0.7,
|
||||||
|
mark_sensitive: true,
|
||||||
|
unlist: false,
|
||||||
|
reject: false
|
||||||
|
|
||||||
config :pleroma, :mrf_follow_bot, follower_nickname: nil
|
config :pleroma, :mrf_follow_bot, follower_nickname: nil
|
||||||
|
|
||||||
config :pleroma, :mrf_inline_quote, template: "<bdi>RT:</bdi> {url}"
|
config :pleroma, :mrf_inline_quote, template: "<bdi>RT:</bdi> {url}"
|
||||||
|
|
||||||
|
config :pleroma, :mrf_force_mention,
|
||||||
|
mention_parent: true,
|
||||||
|
mention_quoted: true
|
||||||
|
|
||||||
|
config :pleroma, :mrf_antimentionspam, user_age_limit: 30_000
|
||||||
|
|
||||||
config :pleroma, :rich_media,
|
config :pleroma, :rich_media,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ignore_hosts: [],
|
ignore_hosts: [],
|
||||||
|
@ -444,8 +448,12 @@ config :pleroma, :rich_media,
|
||||||
Pleroma.Web.RichMedia.Parsers.TwitterCard,
|
Pleroma.Web.RichMedia.Parsers.TwitterCard,
|
||||||
Pleroma.Web.RichMedia.Parsers.OEmbed
|
Pleroma.Web.RichMedia.Parsers.OEmbed
|
||||||
],
|
],
|
||||||
failure_backoff: 60_000,
|
timeout: 5_000,
|
||||||
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
|
ttl_setters: [
|
||||||
|
Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl,
|
||||||
|
Pleroma.Web.RichMedia.Parser.TTL.Opengraph
|
||||||
|
],
|
||||||
|
max_body: 5_000_000
|
||||||
|
|
||||||
config :pleroma, :media_proxy,
|
config :pleroma, :media_proxy,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
@ -514,7 +522,8 @@ config :pleroma, :http_security,
|
||||||
sts: false,
|
sts: false,
|
||||||
sts_max_age: 31_536_000,
|
sts_max_age: 31_536_000,
|
||||||
ct_max_age: 2_592_000,
|
ct_max_age: 2_592_000,
|
||||||
referrer_policy: "same-origin"
|
referrer_policy: "same-origin",
|
||||||
|
allow_unsafe_eval: false
|
||||||
|
|
||||||
config :cors_plug,
|
config :cors_plug,
|
||||||
max_age: 86_400,
|
max_age: 86_400,
|
||||||
|
@ -571,29 +580,21 @@ config :pleroma, Pleroma.User,
|
||||||
],
|
],
|
||||||
email_blacklist: []
|
email_blacklist: []
|
||||||
|
|
||||||
|
# The Pruner :max_age must be longer than Worker :unique
|
||||||
|
# value or it cannot enforce uniqueness.
|
||||||
config :pleroma, Oban,
|
config :pleroma, Oban,
|
||||||
repo: Pleroma.Repo,
|
repo: Pleroma.Repo,
|
||||||
log: false,
|
log: false,
|
||||||
queues: [
|
queues: [
|
||||||
activity_expiration: 10,
|
activity_expiration: 10,
|
||||||
token_expiration: 5,
|
|
||||||
filter_expiration: 1,
|
|
||||||
backup: 1,
|
|
||||||
federator_incoming: 5,
|
federator_incoming: 5,
|
||||||
federator_outgoing: 5,
|
federator_outgoing: 25,
|
||||||
ingestion_queue: 50,
|
|
||||||
web_push: 50,
|
web_push: 50,
|
||||||
mailer: 10,
|
background: 20,
|
||||||
transmogrifier: 20,
|
search_indexing: [limit: 10, paused: true],
|
||||||
scheduled_activities: 10,
|
slow: 5
|
||||||
poll_notifications: 10,
|
|
||||||
background: 5,
|
|
||||||
remote_fetcher: 2,
|
|
||||||
attachments_cleanup: 1,
|
|
||||||
new_users_digest: 1,
|
|
||||||
mute_expire: 5
|
|
||||||
],
|
],
|
||||||
plugins: [Oban.Plugins.Pruner],
|
plugins: [{Oban.Plugins.Pruner, max_age: 900}],
|
||||||
crontab: [
|
crontab: [
|
||||||
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
||||||
|
@ -602,7 +603,8 @@ config :pleroma, Oban,
|
||||||
config :pleroma, :workers,
|
config :pleroma, :workers,
|
||||||
retries: [
|
retries: [
|
||||||
federator_incoming: 5,
|
federator_incoming: 5,
|
||||||
federator_outgoing: 5
|
federator_outgoing: 5,
|
||||||
|
search_indexing: 2
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, Pleroma.Formatter,
|
config :pleroma, Pleroma.Formatter,
|
||||||
|
@ -660,12 +662,26 @@ config :pleroma, Pleroma.Emails.UserEmail,
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false
|
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false
|
||||||
|
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter,
|
config :pleroma, Pleroma.PromEx,
|
||||||
enabled: false,
|
disabled: false,
|
||||||
auth: false,
|
manual_metrics_start_delay: :no_delay,
|
||||||
ip_whitelist: [],
|
drop_metrics_groups: [],
|
||||||
path: "/api/pleroma/app_metrics",
|
grafana: [
|
||||||
format: :text
|
host: System.get_env("GRAFANA_HOST", "http://localhost:3000"),
|
||||||
|
auth_token: System.get_env("GRAFANA_TOKEN"),
|
||||||
|
upload_dashboards_on_start: false,
|
||||||
|
folder_name: "BEAM",
|
||||||
|
annotate_app_lifecycle: true
|
||||||
|
],
|
||||||
|
metrics_server: [
|
||||||
|
port: 4021,
|
||||||
|
path: "/metrics",
|
||||||
|
protocol: :http,
|
||||||
|
pool_size: 5,
|
||||||
|
cowboy_opts: [],
|
||||||
|
auth_strategy: :none
|
||||||
|
],
|
||||||
|
datasource: "Prometheus"
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
config :pleroma, Pleroma.ScheduledActivity,
|
||||||
daily_user_limit: 25,
|
daily_user_limit: 25,
|
||||||
|
@ -800,7 +816,7 @@ config :pleroma, :modules, runtime_dir: "instance/modules"
|
||||||
config :pleroma, configurable_from_database: false
|
config :pleroma, configurable_from_database: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
parameters: [gin_fuzzy_search_limit: "500"],
|
parameters: [gin_fuzzy_search_limit: "500", jit: "off"],
|
||||||
prepare: :unnamed
|
prepare: :unnamed
|
||||||
|
|
||||||
config :pleroma, :connections_pool,
|
config :pleroma, :connections_pool,
|
||||||
|
@ -814,22 +830,27 @@ config :pleroma, :connections_pool,
|
||||||
|
|
||||||
config :pleroma, :pools,
|
config :pleroma, :pools,
|
||||||
federation: [
|
federation: [
|
||||||
size: 50,
|
size: 75,
|
||||||
max_waiting: 10,
|
max_waiting: 20,
|
||||||
recv_timeout: 10_000
|
recv_timeout: 10_000
|
||||||
],
|
],
|
||||||
media: [
|
media: [
|
||||||
size: 50,
|
size: 75,
|
||||||
|
max_waiting: 20,
|
||||||
|
recv_timeout: 15_000
|
||||||
|
],
|
||||||
|
rich_media: [
|
||||||
|
size: 25,
|
||||||
max_waiting: 20,
|
max_waiting: 20,
|
||||||
recv_timeout: 15_000
|
recv_timeout: 15_000
|
||||||
],
|
],
|
||||||
upload: [
|
upload: [
|
||||||
size: 25,
|
size: 25,
|
||||||
max_waiting: 5,
|
max_waiting: 20,
|
||||||
recv_timeout: 15_000
|
recv_timeout: 15_000
|
||||||
],
|
],
|
||||||
default: [
|
default: [
|
||||||
size: 10,
|
size: 50,
|
||||||
max_waiting: 2,
|
max_waiting: 2,
|
||||||
recv_timeout: 5_000
|
recv_timeout: 5_000
|
||||||
]
|
]
|
||||||
|
@ -837,15 +858,19 @@ config :pleroma, :pools,
|
||||||
config :pleroma, :hackney_pools,
|
config :pleroma, :hackney_pools,
|
||||||
federation: [
|
federation: [
|
||||||
max_connections: 50,
|
max_connections: 50,
|
||||||
timeout: 150_000
|
timeout: 10_000
|
||||||
],
|
],
|
||||||
media: [
|
media: [
|
||||||
max_connections: 50,
|
max_connections: 50,
|
||||||
timeout: 150_000
|
timeout: 15_000
|
||||||
|
],
|
||||||
|
rich_media: [
|
||||||
|
max_connections: 50,
|
||||||
|
timeout: 15_000
|
||||||
],
|
],
|
||||||
upload: [
|
upload: [
|
||||||
max_connections: 25,
|
max_connections: 25,
|
||||||
timeout: 300_000
|
timeout: 15_000
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :majic_pool, size: 2
|
config :pleroma, :majic_pool, size: 2
|
||||||
|
@ -884,16 +909,44 @@ config :pleroma, Pleroma.User.Backup,
|
||||||
purge_after_days: 30,
|
purge_after_days: 30,
|
||||||
limit_days: 7,
|
limit_days: 7,
|
||||||
dir: nil,
|
dir: nil,
|
||||||
process_wait_time: 30_000,
|
process_chunk_size: 100,
|
||||||
process_chunk_size: 100
|
timeout: :timer.minutes(30)
|
||||||
|
|
||||||
config :pleroma, ConcurrentLimiter, [
|
config :pleroma, ConcurrentLimiter, [
|
||||||
{Pleroma.Web.RichMedia.Helpers, [max_running: 5, max_waiting: 5]},
|
{Pleroma.Search, [max_running: 30, max_waiting: 50]}
|
||||||
{Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy, [max_running: 5, max_waiting: 5]}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.WebFinger, domain: nil, update_nickname_on_user_fetch: true
|
config :pleroma, Pleroma.Web.WebFinger, domain: nil, update_nickname_on_user_fetch: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Search, module: Pleroma.Search.DatabaseSearch
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Search.Meilisearch,
|
||||||
|
url: "http://127.0.0.1:7700/",
|
||||||
|
private_key: nil,
|
||||||
|
initial_indexing_chunk_size: 100_000
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Application,
|
||||||
|
background_migrators: true,
|
||||||
|
internal_fetch: true,
|
||||||
|
load_custom_modules: true,
|
||||||
|
max_restarts: 3,
|
||||||
|
streamer_registry: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Uploaders.Uploader, timeout: 30_000
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Search.QdrantSearch,
|
||||||
|
qdrant_url: "http://127.0.0.1:6333/",
|
||||||
|
qdrant_api_key: "",
|
||||||
|
openai_url: "http://127.0.0.1:11345",
|
||||||
|
# The healthcheck url has to be set to nil when used with the real openai
|
||||||
|
# API, as it doesn't have a healthcheck endpoint.
|
||||||
|
openai_healthcheck_url: "http://127.0.0.1:11345/health",
|
||||||
|
openai_model: "snowflake/snowflake-arctic-embed-xs",
|
||||||
|
openai_api_key: "",
|
||||||
|
qdrant_index_configuration: %{
|
||||||
|
vectors: %{size: 384, distance: "Cosine"}
|
||||||
|
}
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
|
|
@ -136,6 +136,31 @@ config :pleroma, :config_description, [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: Pleroma.Uploaders.IPFS,
|
||||||
|
type: :group,
|
||||||
|
description: "IPFS uploader-related settings",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :get_gateway_url,
|
||||||
|
type: :string,
|
||||||
|
description: "GET Gateway URL",
|
||||||
|
suggestions: [
|
||||||
|
"https://ipfs.mydomain.com/{CID}",
|
||||||
|
"https://{CID}.ipfs.mydomain.com/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :post_gateway_url,
|
||||||
|
type: :string,
|
||||||
|
description: "POST Gateway URL",
|
||||||
|
suggestions: [
|
||||||
|
"http://localhost:5001/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: Pleroma.Uploaders.S3,
|
key: Pleroma.Uploaders.S3,
|
||||||
|
@ -566,6 +591,20 @@ config :pleroma, :config_description, [
|
||||||
"Cool instance"
|
"Cool instance"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
key: :status_page,
|
||||||
|
type: :string,
|
||||||
|
description: "A page where people can see the status of the server during an outage",
|
||||||
|
suggestions: [
|
||||||
|
"https://status.pleroma.example.org"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :contact_username,
|
||||||
|
type: :string,
|
||||||
|
description: "Instance owner username",
|
||||||
|
suggestions: ["admin"]
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
key: :limit,
|
key: :limit,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
|
@ -735,6 +774,18 @@ config :pleroma, :config_description, [
|
||||||
{"*.quarantined.com", "Reason"}
|
{"*.quarantined.com", "Reason"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
key: :rejected_instances,
|
||||||
|
type: {:list, :tuple},
|
||||||
|
key_placeholder: "instance",
|
||||||
|
value_placeholder: "reason",
|
||||||
|
description:
|
||||||
|
"List of ActivityPub instances to reject requests from if authorized_fetch_mode is enabled",
|
||||||
|
suggestions: [
|
||||||
|
{"rejected.com", "Reason"},
|
||||||
|
{"*.rejected.com", "Reason"}
|
||||||
|
]
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
key: :static_dir,
|
key: :static_dir,
|
||||||
type: :string,
|
type: :string,
|
||||||
|
@ -987,6 +1038,12 @@ config :pleroma, :config_description, [
|
||||||
"The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.",
|
"The instance thumbnail can be any image that represents your instance and is used by some apps or services when they display information about your instance.",
|
||||||
suggestions: ["/instance/thumbnail.jpeg"]
|
suggestions: ["/instance/thumbnail.jpeg"]
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
key: :favicon,
|
||||||
|
type: {:string, :image},
|
||||||
|
description: "Favicon of the instance",
|
||||||
|
suggestions: ["/favicon.png"]
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
key: :show_reactions,
|
key: :show_reactions,
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
|
@ -1171,79 +1228,6 @@ config :pleroma, :config_description, [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{
|
|
||||||
group: :logger,
|
|
||||||
type: :group,
|
|
||||||
description: "Logger-related settings",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :backends,
|
|
||||||
type: [:atom, :tuple, :module],
|
|
||||||
description:
|
|
||||||
"Where logs will be sent, :console - send logs to stdout, { ExSyslogger, :ex_syslogger } - to syslog, Quack.Logger - to Slack.",
|
|
||||||
suggestions: [:console, {ExSyslogger, :ex_syslogger}, Quack.Logger]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :logger,
|
|
||||||
type: :group,
|
|
||||||
key: :ex_syslogger,
|
|
||||||
label: "ExSyslogger",
|
|
||||||
description: "ExSyslogger-related settings",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :level,
|
|
||||||
type: {:dropdown, :atom},
|
|
||||||
description: "Log level",
|
|
||||||
suggestions: [:debug, :info, :warn, :error]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :ident,
|
|
||||||
type: :string,
|
|
||||||
description:
|
|
||||||
"A string that's prepended to every message, and is typically set to the app name",
|
|
||||||
suggestions: ["pleroma"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :format,
|
|
||||||
type: :string,
|
|
||||||
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
|
|
||||||
suggestions: ["$metadata[$level] $message"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :metadata,
|
|
||||||
type: {:list, :atom},
|
|
||||||
suggestions: [:request_id]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
group: :logger,
|
|
||||||
type: :group,
|
|
||||||
key: :console,
|
|
||||||
label: "Console Logger",
|
|
||||||
description: "Console logger settings",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :level,
|
|
||||||
type: {:dropdown, :atom},
|
|
||||||
description: "Log level",
|
|
||||||
suggestions: [:debug, :info, :warn, :error]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :format,
|
|
||||||
type: :string,
|
|
||||||
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
|
|
||||||
suggestions: ["$metadata[$level] $message"]
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
key: :metadata,
|
|
||||||
type: {:list, :atom},
|
|
||||||
suggestions: [:request_id]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :frontend_configurations,
|
key: :frontend_configurations,
|
||||||
|
@ -1438,7 +1422,7 @@ config :pleroma, :config_description, [
|
||||||
label: "Subject line behavior",
|
label: "Subject line behavior",
|
||||||
type: :string,
|
type: :string,
|
||||||
description: "Allows changing the default behaviour of subject lines in replies.
|
description: "Allows changing the default behaviour of subject lines in replies.
|
||||||
`email`: copy and preprend re:, as in email,
|
`email`: copy and prepend re:, as in email,
|
||||||
`masto`: copy verbatim, as in Mastodon,
|
`masto`: copy verbatim, as in Mastodon,
|
||||||
`noop`: don't copy the subject.",
|
`noop`: don't copy the subject.",
|
||||||
suggestions: ["email", "masto", "noop"]
|
suggestions: ["email", "masto", "noop"]
|
||||||
|
@ -1771,6 +1755,12 @@ config :pleroma, :config_description, [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Require HTTP signatures for AP fetches"
|
description: "Require HTTP signatures for AP fetches"
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
key: :authorized_fetch_mode_exceptions,
|
||||||
|
type: {:list, :string},
|
||||||
|
description:
|
||||||
|
"List of IPs (CIDR format accepted) to exempt from HTTP Signatures requirement (for example to allow debugging, you shouldn't otherwise need this)"
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
key: :note_replies_output_limit,
|
key: :note_replies_output_limit,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
|
@ -1931,7 +1921,7 @@ config :pleroma, :config_description, [
|
||||||
key: :log,
|
key: :log,
|
||||||
type: {:dropdown, :atom},
|
type: {:dropdown, :atom},
|
||||||
description: "Logs verbose mode",
|
description: "Logs verbose mode",
|
||||||
suggestions: [false, :error, :warn, :info, :debug]
|
suggestions: [false, :error, :warning, :info, :debug]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :queues,
|
key: :queues,
|
||||||
|
@ -2111,11 +2101,11 @@ config :pleroma, :config_description, [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :failure_backoff,
|
key: :timeout,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description:
|
description:
|
||||||
"Amount of milliseconds after request failure, during which the request will not be retried.",
|
"Amount of milliseconds after which the HTTP request is forcibly terminated.",
|
||||||
suggestions: [60_000]
|
suggestions: [5_000]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -3090,7 +3080,7 @@ config :pleroma, :config_description, [
|
||||||
key: :max_waiting,
|
key: :max_waiting,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description:
|
description:
|
||||||
"Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errrors when a new request is made",
|
"Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errors when a new request is made",
|
||||||
suggestions: [10]
|
suggestions: [10]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -3356,7 +3346,7 @@ config :pleroma, :config_description, [
|
||||||
%{
|
%{
|
||||||
key: :purge_after_days,
|
key: :purge_after_days,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Remove backup achives after N days",
|
description: "Remove backup archives after N days",
|
||||||
suggestions: [30]
|
suggestions: [30]
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
|
@ -3365,20 +3355,19 @@ config :pleroma, :config_description, [
|
||||||
description: "Limit user to export not more often than once per N days",
|
description: "Limit user to export not more often than once per N days",
|
||||||
suggestions: [7]
|
suggestions: [7]
|
||||||
},
|
},
|
||||||
%{
|
|
||||||
key: :process_wait_time,
|
|
||||||
type: :integer,
|
|
||||||
label: "Process Wait Time",
|
|
||||||
description:
|
|
||||||
"The amount of time to wait for backup to report progress, in milliseconds. If no progress is received from the backup job for that much time, terminate it and deem it failed.",
|
|
||||||
suggestions: [30_000]
|
|
||||||
},
|
|
||||||
%{
|
%{
|
||||||
key: :process_chunk_size,
|
key: :process_chunk_size,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
label: "Process Chunk Size",
|
label: "Process Chunk Size",
|
||||||
description: "The number of activities to fetch in the backup job for each chunk.",
|
description: "The number of activities to fetch in the backup job for each chunk.",
|
||||||
suggestions: [100]
|
suggestions: [100]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :timeout,
|
||||||
|
type: :integer,
|
||||||
|
label: "Timeout",
|
||||||
|
description: "The amount of time to wait for backup to complete in seconds.",
|
||||||
|
suggestions: [1_800]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -3466,5 +3455,48 @@ config :pleroma, :config_description, [
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: Pleroma.Search,
|
||||||
|
type: :group,
|
||||||
|
description: "General search settings.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :module,
|
||||||
|
type: :keyword,
|
||||||
|
description: "Selected search module.",
|
||||||
|
suggestion: [Pleroma.Search.DatabaseSearch, Pleroma.Search.Meilisearch]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: Pleroma.Search.Meilisearch,
|
||||||
|
type: :group,
|
||||||
|
description: "Meilisearch settings.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :url,
|
||||||
|
type: :string,
|
||||||
|
description: "Meilisearch URL.",
|
||||||
|
suggestion: ["http://127.0.0.1:7700/"]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :private_key,
|
||||||
|
type: :string,
|
||||||
|
description:
|
||||||
|
"Private key for meilisearch authentication, or `nil` to disable private key authentication.",
|
||||||
|
suggestion: [nil]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :initial_indexing_chunk_size,
|
||||||
|
type: :integer,
|
||||||
|
description:
|
||||||
|
"Amount of posts in a batch when running the initial indexing operation. Should probably not be more than 100000" <>
|
||||||
|
" since there's a limit on maximum insert size",
|
||||||
|
suggestion: [100_000]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,8 +8,7 @@ import Config
|
||||||
# with brunch.io to recompile .js and .css sources.
|
# with brunch.io to recompile .js and .css sources.
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
http: [
|
http: [
|
||||||
port: 4000,
|
port: 4000
|
||||||
protocol_options: [max_request_line_length: 8192, max_header_value_length: 8192]
|
|
||||||
],
|
],
|
||||||
protocol: "http",
|
protocol: "http",
|
||||||
debug_errors: true,
|
debug_errors: true,
|
||||||
|
@ -36,8 +35,8 @@ config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Local
|
||||||
# configured to run both http and https servers on
|
# configured to run both http and https servers on
|
||||||
# different ports.
|
# different ports.
|
||||||
|
|
||||||
# Do not include metadata nor timestamps in development logs
|
# Do not include timestamps in development logs
|
||||||
config :logger, :console, format: "[$level] $message\n"
|
config :logger, Logger.Backends.Console, format: "$metadata[$level] $message\n"
|
||||||
|
|
||||||
# Set a higher stacktrace during development. Avoid configuring such
|
# Set a higher stacktrace during development. Avoid configuring such
|
||||||
# in production as building large stacktraces may be expensive.
|
# in production as building large stacktraces may be expensive.
|
||||||
|
|
|
@ -20,6 +20,7 @@ config :pleroma, Pleroma.Web.Endpoint,
|
||||||
config :phoenix, serve_endpoints: true
|
config :phoenix, serve_endpoints: true
|
||||||
|
|
||||||
# Do not print debug messages in production
|
# Do not print debug messages in production
|
||||||
|
config :logger, Logger.Backends.Console, level: :info
|
||||||
config :logger, :console, level: :info
|
config :logger, :console, level: :info
|
||||||
config :logger, :ex_syslogger, level: :info
|
config :logger, :ex_syslogger, level: :info
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ config :pleroma, Pleroma.Captcha,
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
# Print only warnings and errors during test
|
||||||
config :logger, :console,
|
config :logger, :console,
|
||||||
level: :warn,
|
level: :warning,
|
||||||
format: "\n[$level] $message\n"
|
format: "\n[$level] $message\n"
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: []
|
config :pleroma, :auth, oauth_consumer_strategies: []
|
||||||
|
@ -49,7 +49,8 @@ config :pleroma, Pleroma.Repo,
|
||||||
hostname: System.get_env("DB_HOST") || "localhost",
|
hostname: System.get_env("DB_HOST") || "localhost",
|
||||||
port: System.get_env("DB_PORT") || "5432",
|
port: System.get_env("DB_PORT") || "5432",
|
||||||
pool: Ecto.Adapters.SQL.Sandbox,
|
pool: Ecto.Adapters.SQL.Sandbox,
|
||||||
pool_size: 50
|
pool_size: System.schedulers_online() * 2,
|
||||||
|
log: false
|
||||||
|
|
||||||
config :pleroma, :dangerzone, override_repo_pool_size: true
|
config :pleroma, :dangerzone, override_repo_pool_size: true
|
||||||
|
|
||||||
|
@ -61,7 +62,8 @@ config :tesla, adapter: Tesla.Mock
|
||||||
config :pleroma, :rich_media,
|
config :pleroma, :rich_media,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
ignore_hosts: [],
|
ignore_hosts: [],
|
||||||
ignore_tld: ["local", "localdomain", "lan"]
|
ignore_tld: ["local", "localdomain", "lan"],
|
||||||
|
max_body: 2_000_000
|
||||||
|
|
||||||
config :pleroma, :instance,
|
config :pleroma, :instance,
|
||||||
multi_factor_authentication: [
|
multi_factor_authentication: [
|
||||||
|
@ -133,10 +135,61 @@ config :pleroma, :side_effects,
|
||||||
ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
|
ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
|
||||||
logger: Pleroma.LoggerMock
|
logger: Pleroma.LoggerMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Search, module: Pleroma.Search.DatabaseSearch
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Search.Meilisearch, url: "http://127.0.0.1:7700/", private_key: nil
|
||||||
|
|
||||||
# Reduce recompilation time
|
# Reduce recompilation time
|
||||||
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
|
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
|
||||||
config :phoenix, :plug_init_mode, :runtime
|
config :phoenix, :plug_init_mode, :runtime
|
||||||
|
|
||||||
|
config :pleroma, :config_impl, Pleroma.UnstubbedConfigMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.PromEx, disabled: true
|
||||||
|
|
||||||
|
# Mox definitions. Only read during compile time.
|
||||||
|
config :pleroma, Pleroma.User.Backup, config_impl: Pleroma.UnstubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Uploaders.S3, ex_aws_impl: Pleroma.Uploaders.S3.ExAwsMock
|
||||||
|
config :pleroma, Pleroma.Uploaders.S3, config_impl: Pleroma.UnstubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Upload, config_impl: Pleroma.UnstubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.ScheduledActivity, config_impl: Pleroma.UnstubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Web.RichMedia.Helpers, config_impl: Pleroma.StaticStubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Uploaders.IPFS, config_impl: Pleroma.UnstubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Web.Plugs.HTTPSecurityPlug, config_impl: Pleroma.StaticStubbedConfigMock
|
||||||
|
config :pleroma, Pleroma.Web.Plugs.HTTPSignaturePlug, config_impl: Pleroma.StaticStubbedConfigMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Signature, http_signatures_impl: Pleroma.StubbedHTTPSignaturesMock
|
||||||
|
|
||||||
|
peer_module =
|
||||||
|
if String.to_integer(System.otp_release()) >= 25 do
|
||||||
|
:peer
|
||||||
|
else
|
||||||
|
:slave
|
||||||
|
end
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Cluster, peer_module: peer_module
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Application,
|
||||||
|
background_migrators: false,
|
||||||
|
internal_fetch: false,
|
||||||
|
load_custom_modules: false,
|
||||||
|
max_restarts: 100,
|
||||||
|
streamer_registry: false,
|
||||||
|
test_http_pools: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Streaming, sync_streaming: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Uploaders.Uploader, timeout: 1_000
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Emoji.Loader, test_emoji: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.RichMedia.Backfill,
|
||||||
|
stream_out: Pleroma.Web.ActivityPub.ActivityPubMock
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Plugs.HTTPSecurityPlug, enable: false
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.User.Backup, tempdir: "test/tmp"
|
||||||
|
|
||||||
if File.exists?("./config/test.secret.exs") do
|
if File.exists?("./config/test.secret.exs") do
|
||||||
import_config "test.secret.exs"
|
import_config "test.secret.exs"
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Transfering the config to/from the database
|
# Transferring the config to/from the database
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
- `<path>` - where to save migrated config. E.g. `--path=/tmp`. If file saved into non standart folder, you must manually copy file into directory where Pleroma can read it. For OTP install path will be `PLEROMA_CONFIG_PATH` or `/etc/pleroma`. For installation from source - `config` directory in the pleroma folder.
|
- `<path>` - where to save migrated config. E.g. `--path=/tmp`. If file saved into non-standard folder, you must manually copy file into directory where Pleroma can read it. For OTP install path will be `PLEROMA_CONFIG_PATH` or `/etc/pleroma`. For installation from source - `config` directory in the pleroma folder.
|
||||||
- `<env>` - environment, for which is migrated config. By default is `prod`.
|
- `<env>` - environment, for which is migrated config. By default is `prod`.
|
||||||
- To delete transferred settings from database optional flag `-d` can be used
|
- To delete transferred settings from database optional flag `-d` can be used
|
||||||
|
|
||||||
|
@ -154,4 +154,19 @@ This forcibly removes all saved values in the database.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mix pleroma.config [--force] reset
|
mix pleroma.config [--force] reset
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Remove invalid MRF modules from the database
|
||||||
|
|
||||||
|
This forcibly removes any enabled MRF that does not exist and will fix the ability of the instance to start.
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl config fix_mrf_policies
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
```sh
|
||||||
|
mix pleroma.config fix_mrf_policies
|
||||||
```
|
```
|
|
@ -21,16 +21,18 @@ Replaces embedded objects with references to them in the `objects` table. Only n
|
||||||
mix pleroma.database remove_embedded_objects [option ...]
|
mix pleroma.database remove_embedded_objects [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
- `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references
|
- `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references
|
||||||
|
|
||||||
## Prune old remote posts from the database
|
## Prune old remote posts from the database
|
||||||
|
|
||||||
This will prune remote posts older than 90 days (configurable with [`config :pleroma, :instance, remote_post_retention_days`](../../configuration/cheatsheet.md#instance)) from the database, they will be refetched from source when accessed.
|
This will prune remote posts older than 90 days (configurable with [`config :pleroma, :instance, remote_post_retention_days`](../../configuration/cheatsheet.md#instance)) from the database. Pruned posts may be refetched in some cases.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
The disk space will only be reclaimed after a proper vacuum. By default Postgresql does this for you on a regular basis, but if your instance has been running for a long time and there are many rows deleted, it may be advantageous to use `VACUUM FULL` (e.g. by using the `--vacuum` option).
|
||||||
|
|
||||||
!!! danger
|
!!! danger
|
||||||
The disk space will only be reclaimed after `VACUUM FULL`. You may run out of disk space during the execution of the task or vacuuming if you don't have about 1/3rds of the database size free.
|
You may run out of disk space during the execution of the task or vacuuming if you don't have about 1/3rds of the database size free. Vacuum causes a substantial increase in I/O traffic, and may lead to a degraded experience while it is running.
|
||||||
|
|
||||||
=== "OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
@ -45,7 +47,11 @@ This will prune remote posts older than 90 days (configurable with [`config :ple
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
- `--vacuum` - run `VACUUM FULL` after the objects are pruned
|
|
||||||
|
- `--keep-threads` - Don't prune posts when they are part of a thread where at least one post has seen local interaction (e.g. one of the posts is a local post, or is favourited by a local user, or has been repeated by a local user...). It also won't delete posts when at least one of the posts in that thread is kept (e.g. because one of the posts has seen recent activity).
|
||||||
|
- `--keep-non-public` - Keep non-public posts like DM's and followers-only, even if they are remote.
|
||||||
|
- `--prune-orphaned-activities` - Also prune orphaned activities afterwards. Activities are things like Like, Create, Announce, Flag (aka reports). They can significantly help reduce the database size. Note: this can take a very long time.
|
||||||
|
- `--vacuum` - Run `VACUUM FULL` after the objects are pruned. This should not be used on a regular basis, but is useful if your instance has been running for a long time before pruning.
|
||||||
|
|
||||||
## Create a conversation for all existing DMs
|
## Create a conversation for all existing DMs
|
||||||
|
|
||||||
|
@ -93,6 +99,9 @@ Can be safely re-run
|
||||||
|
|
||||||
## Vacuum the database
|
## Vacuum the database
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
By default Postgresql has an autovacuum deamon running. While the tasks described here can help in some cases, they shouldn't be needed on a regular basis. See [the Postgresql docs on vacuuming](https://www.postgresql.org/docs/current/sql-vacuum.html) for more information on this.
|
||||||
|
|
||||||
### Analyze
|
### Analyze
|
||||||
|
|
||||||
Running an `analyze` vacuum job can improve performance by updating statistics used by the query planner. **It is safe to cancel this.**
|
Running an `analyze` vacuum job can improve performance by updating statistics used by the query planner. **It is safe to cancel this.**
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
1. Optionally you can remove the users of your instance. This will trigger delete requests for their accounts and posts. Note that this is 'best effort' and doesn't mean that all traces of your instance will be gone from the fediverse.
|
1. Optionally you can remove the users of your instance. This will trigger delete requests for their accounts and posts. Note that this is 'best effort' and doesn't mean that all traces of your instance will be gone from the fediverse.
|
||||||
* You can do this from the admin-FE where you can select all local users and delete the accounts using the *Moderate multiple users* dropdown.
|
* You can do this from the admin-FE where you can select all local users and delete the accounts using the *Moderate multiple users* dropdown.
|
||||||
* You can also list local users and delete them individualy using the CLI tasks for [Managing users](./CLI_tasks/user.md).
|
* You can also list local users and delete them individually using the CLI tasks for [Managing users](./CLI_tasks/user.md).
|
||||||
2. Stop the Pleroma service `systemctl stop pleroma`
|
2. Stop the Pleroma service `systemctl stop pleroma`
|
||||||
3. Disable pleroma from systemd `systemctl disable pleroma`
|
3. Disable pleroma from systemd `systemctl disable pleroma`
|
||||||
4. Remove the files and folders you created during installation (see installation guide). This includes the pleroma, nginx and systemd files and folders.
|
4. Remove the files and folders you created during installation (see installation guide). This includes the pleroma, nginx and systemd files and folders.
|
||||||
|
|
|
@ -41,6 +41,7 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `allow_relay`: Permits remote instances to subscribe to all public posts of your instance. This may increase the visibility of your instance.
|
* `allow_relay`: Permits remote instances to subscribe to all public posts of your instance. This may increase the visibility of your instance.
|
||||||
* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. Note that there is a dependent setting restricting or allowing unauthenticated access to specific resources, see `restrict_unauthenticated` for more details.
|
* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network. Note that there is a dependent setting restricting or allowing unauthenticated access to specific resources, see `restrict_unauthenticated` for more details.
|
||||||
* `quarantined_instances`: ActivityPub instances where private (DMs, followers-only) activities will not be send.
|
* `quarantined_instances`: ActivityPub instances where private (DMs, followers-only) activities will not be send.
|
||||||
|
* `rejected_instances`: ActivityPub instances to reject requests from if authorized_fetch_mode is enabled.
|
||||||
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML).
|
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML).
|
||||||
* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with
|
* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with
|
||||||
older software for theses nicknames.
|
older software for theses nicknames.
|
||||||
|
@ -154,14 +155,15 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)).
|
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)).
|
||||||
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)).
|
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)).
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)).
|
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)).
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections.
|
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled deletions.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
|
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed.
|
* `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot.
|
* `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
|
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent`: Forces every mentioned user to be reflected in the post content.
|
* `Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent`: Forces every mentioned user to be reflected in the post content.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy`: Forces quote post URLs to be reflected in the message content inline.
|
* `Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy`: Forces quote post URLs to be reflected in the message content inline.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy`: Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)
|
* `Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy`: Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.ForceMention`: Forces posts to include a mention of the author of parent post or the author of quoted post.
|
||||||
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
||||||
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
||||||
|
|
||||||
|
@ -272,6 +274,10 @@ Notes:
|
||||||
#### :mrf_inline_quote
|
#### :mrf_inline_quote
|
||||||
* `template`: The template to append to the post. `{url}` will be replaced with the actual link to the quoted post. Default: `<bdi>RT:</bdi> {url}`
|
* `template`: The template to append to the post. `{url}` will be replaced with the actual link to the quoted post. Default: `<bdi>RT:</bdi> {url}`
|
||||||
|
|
||||||
|
#### :mrf_force_mention
|
||||||
|
* `mention_parent`: Whether to append mention of parent post author
|
||||||
|
* `mention_quoted`: Whether to append mention of parent quoted author
|
||||||
|
|
||||||
### :activitypub
|
### :activitypub
|
||||||
* `unfollow_blocked`: Whether blocks result in people getting unfollowed
|
* `unfollow_blocked`: Whether blocks result in people getting unfollowed
|
||||||
* `outgoing_blocks`: Whether to federate blocks to other instances
|
* `outgoing_blocks`: Whether to federate blocks to other instances
|
||||||
|
@ -279,6 +285,7 @@ Notes:
|
||||||
* `deny_follow_blocked`: Whether to disallow following an account that has blocked the user in question
|
* `deny_follow_blocked`: Whether to disallow following an account that has blocked the user in question
|
||||||
* `sign_object_fetches`: Sign object fetches with HTTP signatures
|
* `sign_object_fetches`: Sign object fetches with HTTP signatures
|
||||||
* `authorized_fetch_mode`: Require HTTP signatures for AP fetches
|
* `authorized_fetch_mode`: Require HTTP signatures for AP fetches
|
||||||
|
* `authorized_fetch_mode_exceptions`: List of IPs (CIDR format accepted) to exempt from HTTP Signatures requirement (for example to allow debugging, you shouldn't otherwise need this)
|
||||||
|
|
||||||
## Pleroma.User
|
## Pleroma.User
|
||||||
|
|
||||||
|
@ -429,7 +436,7 @@ config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
|
||||||
* `ignore_hosts`: list of hosts which will be ignored by the metadata parser. For example `["accounts.google.com", "xss.website"]`, defaults to `[]`.
|
* `ignore_hosts`: list of hosts which will be ignored by the metadata parser. For example `["accounts.google.com", "xss.website"]`, defaults to `[]`.
|
||||||
* `ignore_tld`: list TLDs (top-level domains) which will ignore for parse metadata. default is ["local", "localdomain", "lan"].
|
* `ignore_tld`: list TLDs (top-level domains) which will ignore for parse metadata. default is ["local", "localdomain", "lan"].
|
||||||
* `parsers`: list of Rich Media parsers.
|
* `parsers`: list of Rich Media parsers.
|
||||||
* `failure_backoff`: Amount of milliseconds after request failure, during which the request will not be retried.
|
* `timeout`: Amount of milliseconds after which the HTTP request is forcibly terminated.
|
||||||
|
|
||||||
## HTTP server
|
## HTTP server
|
||||||
|
|
||||||
|
@ -467,6 +474,7 @@ This will make Pleroma listen on `127.0.0.1` port `8080` and generate urls start
|
||||||
* ``ct_max_age``: The maximum age for the `Expect-CT` header if sent.
|
* ``ct_max_age``: The maximum age for the `Expect-CT` header if sent.
|
||||||
* ``referrer_policy``: The referrer policy to use, either `"same-origin"` or `"no-referrer"`.
|
* ``referrer_policy``: The referrer policy to use, either `"same-origin"` or `"no-referrer"`.
|
||||||
* ``report_uri``: Adds the specified url to `report-uri` and `report-to` group in CSP header.
|
* ``report_uri``: Adds the specified url to `report-uri` and `report-to` group in CSP header.
|
||||||
|
* `allow_unsafe_eval`: Adds `wasm-unsafe-eval` to the CSP header. Needed for some non-essential frontend features like Flash emulation.
|
||||||
|
|
||||||
### Pleroma.Web.Plugs.RemoteIp
|
### Pleroma.Web.Plugs.RemoteIp
|
||||||
|
|
||||||
|
@ -506,7 +514,7 @@ config :pleroma, :rate_limit,
|
||||||
Means that:
|
Means that:
|
||||||
|
|
||||||
1. In 60 seconds, 15 authentication attempts can be performed from the same IP address.
|
1. In 60 seconds, 15 authentication attempts can be performed from the same IP address.
|
||||||
2. In 1 second, 10 search requests can be performed from the same IP adress by unauthenticated users, while authenticated users can perform 30 search requests per second.
|
2. In 1 second, 10 search requests can be performed from the same IP address by unauthenticated users, while authenticated users can perform 30 search requests per second.
|
||||||
|
|
||||||
Supported rate limiters:
|
Supported rate limiters:
|
||||||
|
|
||||||
|
@ -656,6 +664,19 @@ config :ex_aws, :s3,
|
||||||
host: "s3.eu-central-1.amazonaws.com"
|
host: "s3.eu-central-1.amazonaws.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Pleroma.Uploaders.IPFS
|
||||||
|
|
||||||
|
* `post_gateway_url`: URL with port of POST Gateway (unauthenticated)
|
||||||
|
* `get_gateway_url`: URL of public GET Gateway
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, Pleroma.Uploaders.IPFS,
|
||||||
|
post_gateway_url: "http://localhost:5001",
|
||||||
|
get_gateway_url: "http://{CID}.ipfs.mydomain.com"
|
||||||
|
```
|
||||||
|
|
||||||
### Upload filters
|
### Upload filters
|
||||||
|
|
||||||
#### Pleroma.Upload.Filter.AnonymizeFilename
|
#### Pleroma.Upload.Filter.AnonymizeFilename
|
||||||
|
@ -832,7 +853,7 @@ config :logger,
|
||||||
backends: [{ExSyslogger, :ex_syslogger}]
|
backends: [{ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
config :logger, :ex_syslogger,
|
config :logger, :ex_syslogger,
|
||||||
level: :warn
|
level: :warning
|
||||||
```
|
```
|
||||||
|
|
||||||
Another example, keeping console output and adding the pid to syslog output:
|
Another example, keeping console output and adding the pid to syslog output:
|
||||||
|
@ -841,7 +862,7 @@ config :logger,
|
||||||
backends: [:console, {ExSyslogger, :ex_syslogger}]
|
backends: [:console, {ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
config :logger, :ex_syslogger,
|
config :logger, :ex_syslogger,
|
||||||
level: :warn,
|
level: :warning,
|
||||||
option: [:pid, :ndelay]
|
option: [:pid, :ndelay]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1081,7 +1102,7 @@ config :pleroma, Pleroma.Formatter,
|
||||||
|
|
||||||
## :configurable_from_database
|
## :configurable_from_database
|
||||||
|
|
||||||
Boolean, enables/disables in-database configuration. Read [Transfering the config to/from the database](../administration/CLI_tasks/config.md) for more information.
|
Boolean, enables/disables in-database configuration. Read [Transferring the config to/from the database](../administration/CLI_tasks/config.md) for more information.
|
||||||
|
|
||||||
## :database_config_whitelist
|
## :database_config_whitelist
|
||||||
|
|
||||||
|
@ -1142,7 +1163,7 @@ Control favicons for instances.
|
||||||
!!! note
|
!!! note
|
||||||
Requires enabled email
|
Requires enabled email
|
||||||
|
|
||||||
* `:purge_after_days` an integer, remove backup achives after N days.
|
* `:purge_after_days` an integer, remove backup achieves after N days.
|
||||||
* `:limit_days` an integer, limit user to export not more often than once per N days.
|
* `:limit_days` an integer, limit user to export not more often than once per N days.
|
||||||
* `:dir` a string with a path to backup temporary directory or `nil` to let Pleroma choose temporary directory in the following order:
|
* `:dir` a string with a path to backup temporary directory or `nil` to let Pleroma choose temporary directory in the following order:
|
||||||
1. the directory named by the TMPDIR environment variable
|
1. the directory named by the TMPDIR environment variable
|
||||||
|
@ -1150,6 +1171,7 @@ Control favicons for instances.
|
||||||
3. the directory named by the TMP environment variable
|
3. the directory named by the TMP environment variable
|
||||||
4. C:\TMP on Windows or /tmp on Unix-like operating systems
|
4. C:\TMP on Windows or /tmp on Unix-like operating systems
|
||||||
5. as a last resort, the current working directory
|
5. as a last resort, the current working directory
|
||||||
|
* `:timeout` an integer representing seconds
|
||||||
|
|
||||||
## Frontend management
|
## Frontend management
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ foo, /emoji/custom/foo.png
|
||||||
|
|
||||||
The files should be PNG (APNG is okay with `.png` for `image/png` Content-type) and under 50kb for compatibility with mastodon.
|
The files should be PNG (APNG is okay with `.png` for `image/png` Content-type) and under 50kb for compatibility with mastodon.
|
||||||
|
|
||||||
Default file extentions and locations for emojis are set in `config.exs`. To use different locations or file-extentions, add the `shortcode_globs` to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it. Note that not all fediverse-software will show emojis with other file extentions:
|
Default file extensions and locations for emojis are set in `config.exs`. To use different locations or file-extensions, add the `shortcode_globs` to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it. Note that not all fediverse-software will show emojis with other file extensions:
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png", "/emoji/custom/**/*.gif"]
|
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png", "/emoji/custom/**/*.gif"]
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# I2P Federation and Accessability
|
# I2P Federation and Accessibility
|
||||||
|
|
||||||
This guide is going to focus on the Pleroma federation aspect. The actual installation is neatly explained in the official documentation, and more likely to remain up-to-date.
|
This guide is going to focus on the Pleroma federation aspect. The actual installation is neatly explained in the official documentation, and more likely to remain up-to-date.
|
||||||
It might be added to this guide if there will be a need for that.
|
It might be added to this guide if there will be a need for that.
|
||||||
|
|
|
@ -29,7 +29,7 @@ HiddenServiceDir /var/lib/tor/pleroma_hidden_service/
|
||||||
HiddenServicePort 80 127.0.0.1:8099
|
HiddenServicePort 80 127.0.0.1:8099
|
||||||
HiddenServiceVersion 3 # Remove if Tor version is below 0.3 ( tor --version )
|
HiddenServiceVersion 3 # Remove if Tor version is below 0.3 ( tor --version )
|
||||||
```
|
```
|
||||||
Restart Tor to generate an adress:
|
Restart Tor to generate an address:
|
||||||
```
|
```
|
||||||
systemctl restart tor@default.service
|
systemctl restart tor@default.service
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Optimizing the BEAM
|
# Optimizing the BEAM
|
||||||
|
|
||||||
Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between procesess is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty.
|
Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between processes is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty.
|
||||||
|
|
||||||
This strategy is very successful in making a performant and responsive application, but is not desirable on Virtual Machines or hardware with few CPU cores. Pleroma instances are often deployed on the same server as the required PostgreSQL database which can lead to situations where the Pleroma application is holding the CPU in a busy-wait loop and as a result the database cannot process requests in a timely manner. The fewer CPUs available, the more this problem is exacerbated. The latency is further amplified by the OS being installed on a Virtual Machine as the Hypervisor uses CPU time-slicing to pause the entire OS and switch between other tasks.
|
This strategy is very successful in making a performant and responsive application, but is not desirable on Virtual Machines or hardware with few CPU cores. Pleroma instances are often deployed on the same server as the required PostgreSQL database which can lead to situations where the Pleroma application is holding the CPU in a busy-wait loop and as a result the database cannot process requests in a timely manner. The fewer CPUs available, the more this problem is exacerbated. The latency is further amplified by the OS being installed on a Virtual Machine as the Hypervisor uses CPU time-slicing to pause the entire OS and switch between other tasks.
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ config :pleroma, Pleroma.Repo,
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
A more detailed explaination of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>.
|
A more detailed explanation of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>.
|
||||||
|
|
||||||
## Example configurations
|
## Example configurations
|
||||||
|
|
||||||
|
|
147
docs/configuration/search.md
Normal file
147
docs/configuration/search.md
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
# Configuring search
|
||||||
|
|
||||||
|
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
||||||
|
|
||||||
|
## Built-in search
|
||||||
|
|
||||||
|
To use built-in search that has no external dependencies, set the search module to `Pleroma.Activity`:
|
||||||
|
|
||||||
|
> config :pleroma, Pleroma.Search, module: Pleroma.Search.DatabaseSearch
|
||||||
|
|
||||||
|
While it has no external dependencies, it has problems with performance and relevancy.
|
||||||
|
|
||||||
|
## QdrantSearch
|
||||||
|
|
||||||
|
This uses the vector search engine [Qdrant](https://qdrant.tech) to search the posts in a vector space. This needs a way to generate embeddings and uses the [OpenAI API](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings). This is implemented by several project besides OpenAI itself, including the python-based fastembed-server found in `supplemental/search/fastembed-api`.
|
||||||
|
|
||||||
|
The default settings will support a setup where both the fastembed server and Qdrant run on the same system as pleroma. To use it, set the search provider and run the fastembed server, see the README in `supplemental/search/fastembed-api`:
|
||||||
|
|
||||||
|
> config :pleroma, Pleroma.Search, module: Pleroma.Search.QdrantSearch
|
||||||
|
|
||||||
|
Then, start the Qdrant server, see [here](https://qdrant.tech/documentation/quick-start/) for instructions.
|
||||||
|
|
||||||
|
You will also need to create the Qdrant index once by running `mix pleroma.search.indexer create_index`. Running `mix pleroma.search.indexer index` will retroactively index the last 100_000 activities.
|
||||||
|
|
||||||
|
### Indexing and model options
|
||||||
|
|
||||||
|
To see the available configuration options, check out the QdrantSearch section in `config/config.exs`.
|
||||||
|
|
||||||
|
The default indexing option work for the default model (`snowflake-arctic-embed-xs`). To optimize for a low memory footprint, adjust the index configuration as described in the [Qdrant docs](https://qdrant.tech/documentation/guides/optimize/). See also [this blog post](https://qdrant.tech/articles/memory-consumption/) that goes into detail.
|
||||||
|
|
||||||
|
Different embedding models will need different vector size settings. You can see a list of the models supported by the fastembed server [here](https://qdrant.github.io/fastembed/examples/Supported_Models), including their vector dimensions. These vector dimensions need to be set in the `qdrant_index_configuration`.
|
||||||
|
|
||||||
|
E.g, If you want to use `sentence-transformers/all-MiniLM-L6-v2` as a model, you will not need to adjust things, because it and `snowflake-arctic-embed-xs` are both 384 dimensional models. If you want to use `snowflake/snowflake-arctic-embed-l`, you will need to adjust the `size` parameter in the `qdrant_index_configuration` to 1024, as it has a dimension of 1024.
|
||||||
|
|
||||||
|
When using a different model, you will need do drop the index and recreate it (`mix pleroma.search.indexer drop_index` and `mix pleroma.search.indexer create_index`), as the different embeddings are not compatible with each other.
|
||||||
|
|
||||||
|
## Meilisearch
|
||||||
|
|
||||||
|
Note that it's quite a bit more memory hungry than PostgreSQL (around 4-5G for ~1.2 million
|
||||||
|
posts while idle and up to 7G while indexing initially). The disk usage for this additional index is also
|
||||||
|
around 4 gigabytes. Like [RUM](./cheatsheet.md#rum-indexing-for-full-text-search) indexes, it offers considerably
|
||||||
|
higher performance and ordering by timestamp in a reasonable amount of time.
|
||||||
|
Additionally, the search results seem to be more accurate.
|
||||||
|
|
||||||
|
Due to high memory usage, it may be best to set it up on a different machine, if running pleroma on a low-resource
|
||||||
|
computer, and use private key authentication to secure the remote search instance.
|
||||||
|
|
||||||
|
To use [meilisearch](https://www.meilisearch.com/), set the search module to `Pleroma.Search.Meilisearch`:
|
||||||
|
|
||||||
|
> config :pleroma, Pleroma.Search, module: Pleroma.Search.Meilisearch
|
||||||
|
|
||||||
|
You then need to set the address of the meilisearch instance, and optionally the private key for authentication. You might
|
||||||
|
also want to change the `initial_indexing_chunk_size` to be smaller if you're server is not very powerful, but not higher than `100_000`,
|
||||||
|
because meilisearch will refuse to process it if it's too big. However, in general you want this to be as big as possible, because meilisearch
|
||||||
|
indexes faster when it can process many posts in a single batch.
|
||||||
|
|
||||||
|
> config :pleroma, Pleroma.Search.Meilisearch,
|
||||||
|
> url: "http://127.0.0.1:7700/",
|
||||||
|
> private_key: "private key",
|
||||||
|
> initial_indexing_chunk_size: 100_000
|
||||||
|
|
||||||
|
Information about setting up meilisearch can be found in the
|
||||||
|
[official documentation](https://docs.meilisearch.com/learn/getting_started/installation.html).
|
||||||
|
You probably want to start it with `MEILI_NO_ANALYTICS=true` environment variable to disable analytics.
|
||||||
|
At least version 0.25.0 is required, but you are strongly advised to use at least 0.26.0, as it introduces
|
||||||
|
the `--enable-auto-batching` option which drastically improves performance. Without this option, the search
|
||||||
|
is hardly usable on a somewhat big instance.
|
||||||
|
|
||||||
|
### Private key authentication (optional)
|
||||||
|
|
||||||
|
To set the private key, use the `MEILI_MASTER_KEY` environment variable when starting. After setting the _master key_,
|
||||||
|
you have to get the _private key_, which is actually used for authentication.
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl search.meilisearch show-keys <your master key here>
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
```sh
|
||||||
|
mix pleroma.search.meilisearch show-keys <your master key here>
|
||||||
|
```
|
||||||
|
|
||||||
|
You will see a "Default Admin API Key", this is the key you actually put into your configuration file.
|
||||||
|
|
||||||
|
### Initial indexing
|
||||||
|
|
||||||
|
After setting up the configuration, you'll want to index all of your already existing posts. Only public posts are indexed. You'll only
|
||||||
|
have to do it one time, but it might take a while, depending on the amount of posts your instance has seen. This is also a fairly RAM
|
||||||
|
consuming process for `meilisearch`, and it will take a lot of RAM when running if you have a lot of posts (seems to be around 5G for ~1.2
|
||||||
|
million posts while idle and up to 7G while indexing initially, but your experience may be different).
|
||||||
|
|
||||||
|
The sequence of actions is as follows:
|
||||||
|
|
||||||
|
1. First, change the configuration to use `Pleroma.Search.Meilisearch` as the search backend
|
||||||
|
2. Restart your instance, at this point it can be used while the search indexing is running, though search won't return anything
|
||||||
|
3. Start the initial indexing process (as described below with `index`),
|
||||||
|
and wait until the task says it sent everything from the database to index
|
||||||
|
4. Wait until everything is actually indexed (by checking with `stats` as described below),
|
||||||
|
at this point you don't have to do anything, just wait a while.
|
||||||
|
|
||||||
|
To start the initial indexing, run the `index` command:
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl search.meilisearch index
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
```sh
|
||||||
|
mix pleroma.search.meilisearch index
|
||||||
|
```
|
||||||
|
|
||||||
|
This will show you the total amount of posts to index, and then show you the amount of posts indexed currently, until the numbers eventually
|
||||||
|
become the same. The posts are indexed in big batches and meilisearch will take some time to actually index them, even after you have
|
||||||
|
inserted all the posts into it. Depending on the amount of posts, this may be as long as several hours. To get information about the status
|
||||||
|
of indexing and how many posts have actually been indexed, use the `stats` command:
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl search.meilisearch stats
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
```sh
|
||||||
|
mix pleroma.search.meilisearch stats
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clearing the index
|
||||||
|
|
||||||
|
In case you need to clear the index (for example, to re-index from scratch, if that needs to happen for some reason), you can
|
||||||
|
use the `clear` command:
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl search.meilisearch clear
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
```sh
|
||||||
|
mix pleroma.search.meilisearch clear
|
||||||
|
```
|
||||||
|
|
||||||
|
This will clear **all** the posts from the search index. Note, that deleted posts are also removed from index by the instance itself, so
|
||||||
|
there is no need to actually clear the whole index, unless you want **all** of it gone. That said, the index does not hold any information
|
||||||
|
that cannot be re-created from the database, it should also generally be a lot smaller than the size of your database. Still, the size
|
||||||
|
depends on the amount of text in posts.
|
|
@ -303,7 +303,7 @@ Removes the user(s) from follower recommendations.
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/admin/users/:nickname_or_id`
|
## `GET /api/v1/pleroma/admin/users/:nickname_or_id`
|
||||||
|
|
||||||
### Retrive the details of a user
|
### Retrieve the details of a user
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname` or `id`
|
- `nickname` or `id`
|
||||||
|
@ -313,7 +313,7 @@ Removes the user(s) from follower recommendations.
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/admin/users/:nickname_or_id/statuses`
|
## `GET /api/v1/pleroma/admin/users/:nickname_or_id/statuses`
|
||||||
|
|
||||||
### Retrive user's latest statuses
|
### Retrieve user's latest statuses
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname` or `id`
|
- `nickname` or `id`
|
||||||
|
@ -337,7 +337,7 @@ Removes the user(s) from follower recommendations.
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/admin/instances/:instance/statuses`
|
## `GET /api/v1/pleroma/admin/instances/:instance/statuses`
|
||||||
|
|
||||||
### Retrive instance's latest statuses
|
### Retrieve instance's latest statuses
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- `instance`: instance name
|
- `instance`: instance name
|
||||||
|
@ -377,7 +377,7 @@ It may take some time.
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/admin/statuses`
|
## `GET /api/v1/pleroma/admin/statuses`
|
||||||
|
|
||||||
### Retrives all latest statuses
|
### Retrieves all latest statuses
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- *optional* `page_size`: number of statuses to return (default is `20`)
|
- *optional* `page_size`: number of statuses to return (default is `20`)
|
||||||
|
@ -541,7 +541,7 @@ Response:
|
||||||
|
|
||||||
## `PATCH /api/v1/pleroma/admin/users/force_password_reset`
|
## `PATCH /api/v1/pleroma/admin/users/force_password_reset`
|
||||||
|
|
||||||
### Force passord reset for a user with a given nickname
|
### Force password reset for a user with a given nickname
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nicknames`
|
- `nicknames`
|
||||||
|
@ -1751,3 +1751,53 @@ Note that this differs from the Mastodon API variant: Mastodon API only returns
|
||||||
```json
|
```json
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## `GET /api/v1/pleroma/admin/rules`
|
||||||
|
|
||||||
|
### List rules
|
||||||
|
|
||||||
|
- Response: JSON, list of rules
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"priority": 1,
|
||||||
|
"text": "There are no rules",
|
||||||
|
"hint": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `POST /api/v1/pleroma/admin/rules`
|
||||||
|
|
||||||
|
### Create a rule
|
||||||
|
|
||||||
|
- Params:
|
||||||
|
- `text`: string, required, rule content
|
||||||
|
- `hint`: string, optional, rule description
|
||||||
|
- `priority`: integer, optional, rule ordering priority
|
||||||
|
|
||||||
|
- Response: JSON, a single rule
|
||||||
|
|
||||||
|
## `PATCH /api/v1/pleroma/admin/rules/:id`
|
||||||
|
|
||||||
|
### Update a rule
|
||||||
|
|
||||||
|
- Params:
|
||||||
|
- `text`: string, optional, rule content
|
||||||
|
- `hint`: string, optional, rule description
|
||||||
|
- `priority`: integer, optional, rule ordering priority
|
||||||
|
|
||||||
|
- Response: JSON, a single rule
|
||||||
|
|
||||||
|
## `DELETE /api/v1/pleroma/admin/rules/:id`
|
||||||
|
|
||||||
|
### Delete a rule
|
||||||
|
|
||||||
|
- Response: JSON, empty object
|
||||||
|
|
||||||
|
```json
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Differences in Mastodon API responses from vanilla Mastodon
|
# Differences in Mastodon API responses from vanilla Mastodon
|
||||||
|
|
||||||
A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance`
|
A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance` and `/api/v2/instance`
|
||||||
|
|
||||||
## Flake IDs
|
## Flake IDs
|
||||||
|
|
||||||
|
@ -39,6 +39,9 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `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: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
||||||
- `parent_visible`: If the parent of this post is visible to the user or not.
|
- `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.
|
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
|
||||||
|
- `quotes_count`: the count of status quotes.
|
||||||
|
- `non_anonymous`: true if the source post specifies the poll results are not anonymous. Currently only implemented by Smithereen.
|
||||||
|
- `bookmark_folder`: the ID of the folder bookmark is stored within (if any).
|
||||||
|
|
||||||
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
|
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
|
||||||
|
|
||||||
|
@ -64,6 +67,12 @@ Some apps operate under the assumption that no more than 4 attachments can be re
|
||||||
|
|
||||||
Pleroma does not process remote images and therefore cannot include fields such as `meta` and `blurhash`. It does not support focal points or aspect ratios. The frontend is expected to handle it.
|
Pleroma does not process remote images and therefore cannot include fields such as `meta` and `blurhash`. It does not support focal points or aspect ratios. The frontend is expected to handle it.
|
||||||
|
|
||||||
|
## Bookmarks
|
||||||
|
|
||||||
|
The `GET /api/v1/bookmarks` endpoint accepts optional parameter `folder_id` for bookmark folder ID.
|
||||||
|
|
||||||
|
The `POST /api/v1/statuses/:id/bookmark` endpoint accepts optional parameter `folder_id` for bookmark folder ID.
|
||||||
|
|
||||||
## Accounts
|
## Accounts
|
||||||
|
|
||||||
The `id` parameter can also be the `nickname` of the user. This only works in these endpoints, not the deeper nested ones for following etc.
|
The `id` parameter can also be the `nickname` of the user. This only works in these endpoints, not the deeper nested ones for following etc.
|
||||||
|
@ -304,19 +313,27 @@ Has these additional parameters (which are the same as in Pleroma-API):
|
||||||
`GET /api/v1/instance` has additional fields
|
`GET /api/v1/instance` has additional fields
|
||||||
|
|
||||||
- `max_toot_chars`: The maximum characters per post
|
- `max_toot_chars`: The maximum characters per post
|
||||||
|
- `max_media_attachments`: Maximum number of post media attachments
|
||||||
- `chat_limit`: The maximum characters per chat message
|
- `chat_limit`: The maximum characters per chat message
|
||||||
- `description_limit`: The maximum characters per image description
|
- `description_limit`: The maximum characters per image description
|
||||||
- `poll_limits`: The limits of polls
|
- `poll_limits`: The limits of polls
|
||||||
|
- `shout_limit`: The maximum characters per Shoutbox message
|
||||||
- `upload_limit`: The maximum upload file size
|
- `upload_limit`: The maximum upload file size
|
||||||
- `avatar_upload_limit`: The same for avatars
|
- `avatar_upload_limit`: The same for avatars
|
||||||
- `background_upload_limit`: The same for backgrounds
|
- `background_upload_limit`: The same for backgrounds
|
||||||
- `banner_upload_limit`: The same for banners
|
- `banner_upload_limit`: The same for banners
|
||||||
- `background_image`: A background image that frontends can use
|
- `background_image`: A background image that frontends can use
|
||||||
|
- `pleroma.metadata.account_activation_required`: Whether users are required to confirm their emails before signing in
|
||||||
|
- `pleroma.metadata.birthday_required`: Whether users are required to provide their birth day when signing in
|
||||||
|
- `pleroma.metadata.birthday_min_age`: The minimum user age (in days)
|
||||||
- `pleroma.metadata.features`: A list of supported features
|
- `pleroma.metadata.features`: A list of supported features
|
||||||
- `pleroma.metadata.federation`: The federation restrictions of this instance
|
- `pleroma.metadata.federation`: The federation restrictions of this instance
|
||||||
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
|
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
|
||||||
- `pleroma.metadata.post_formats`: A list of the allowed post format types
|
- `pleroma.metadata.post_formats`: A list of the allowed post format types
|
||||||
- `vapid_public_key`: The public key needed for push messages
|
- `pleroma.stats.mau`: Monthly active user count
|
||||||
|
- `pleroma.vapid_public_key`: The public key needed for push messages
|
||||||
|
|
||||||
|
In, `GET /api/v2/instance` Pleroma-specific fields are all moved into `pleroma` object. `max_toot_chars`, `poll_limits` and `upload_limit` are replaced with their MastoAPI counterparts.
|
||||||
|
|
||||||
## Push Subscription
|
## Push Subscription
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ The `/api/v1/pleroma/*` path is backwards compatible with `/api/pleroma/*` (`/ap
|
||||||
* method: `GET`
|
* method: `GET`
|
||||||
* Authentication: required
|
* Authentication: required
|
||||||
* OAuth scope: `write:security`
|
* OAuth scope: `write:security`
|
||||||
* Response: JSON. Returns `{"codes": codes}`when successful, otherwise HTTP 422 `{"error": "[error message]"}`
|
* Response: JSON. Returns `{"codes": codes}` when successful, otherwise HTTP 422 `{"error": "[error message]"}`
|
||||||
|
|
||||||
## `/api/v1/pleroma/admin/`
|
## `/api/v1/pleroma/admin/`
|
||||||
See [Admin-API](admin_api.md)
|
See [Admin-API](admin_api.md)
|
||||||
|
@ -251,6 +251,15 @@ See [Admin-API](admin_api.md)
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/accounts/:id/endorsements`
|
||||||
|
### Returns users endorsed by a user
|
||||||
|
* Method `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params:
|
||||||
|
* `id`: the id of the account for whom to return results
|
||||||
|
* Response: JSON, returns a list of Mastodon Account entities
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/update_*`
|
## `/api/v1/pleroma/accounts/update_*`
|
||||||
### Set and clear account avatar, banner, and background
|
### Set and clear account avatar, banner, and background
|
||||||
|
|
||||||
|
@ -266,6 +275,58 @@ See [Admin-API](admin_api.md)
|
||||||
* Authentication: not required
|
* Authentication: not required
|
||||||
* Response: 204 No Content
|
* Response: 204 No Content
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/statuses/:id/quotes`
|
||||||
|
### Gets quotes for a given status
|
||||||
|
* Method `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params:
|
||||||
|
* `id`: the id of the status
|
||||||
|
* Response: JSON, returns a list of Mastodon Status entities
|
||||||
|
|
||||||
|
## `GET /api/v1/pleroma/bookmark_folders`
|
||||||
|
### Gets user bookmark folders
|
||||||
|
* Authentication: required
|
||||||
|
|
||||||
|
* Response: JSON. Returns a list of bookmark folders.
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "9umDrYheeY451cQnEe",
|
||||||
|
"name": "Read later",
|
||||||
|
"emoji": "🕓",
|
||||||
|
"emoji_url": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `POST /api/v1/pleroma/bookmark_folders`
|
||||||
|
### Creates a bookmark folder
|
||||||
|
* Authentication: required
|
||||||
|
|
||||||
|
* Params:
|
||||||
|
* `name`: folder name
|
||||||
|
* `emoji`: folder emoji (optional)
|
||||||
|
* Response: JSON. Returns a single bookmark folder.
|
||||||
|
|
||||||
|
## `PATCH /api/v1/pleroma/bookmark_folders/:id`
|
||||||
|
### Updates a bookmark folder
|
||||||
|
* Authentication: required
|
||||||
|
|
||||||
|
* Params:
|
||||||
|
* `id`: folder id
|
||||||
|
* `name`: folder name (optional)
|
||||||
|
* `emoji`: folder emoji (optional)
|
||||||
|
* Response: JSON. Returns a single bookmark folder.
|
||||||
|
|
||||||
|
## `DELETE /api/v1/pleroma/bookmark_folders/:id`
|
||||||
|
### Deletes a bookmark folder
|
||||||
|
* Authentication: required
|
||||||
|
|
||||||
|
* Params:
|
||||||
|
* `id`: folder id
|
||||||
|
* Response: JSON. Returns a single bookmark folder.
|
||||||
|
|
||||||
## `/api/v1/pleroma/mascot`
|
## `/api/v1/pleroma/mascot`
|
||||||
### Gets user mascot image
|
### Gets user mascot image
|
||||||
* Method `GET`
|
* Method `GET`
|
||||||
|
@ -372,6 +433,15 @@ See [Admin-API](admin_api.md)
|
||||||
* `alias`: the nickname of the alias to delete, e.g. `foo@example.org`.
|
* `alias`: the nickname of the alias to delete, e.g. `foo@example.org`.
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/remote_interaction`
|
||||||
|
## Interact with profile or status from remote account
|
||||||
|
* Metod `POST`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params:
|
||||||
|
* `ap_id`: Profile or status ActivityPub ID
|
||||||
|
* `profile`: Remote profile webfinger
|
||||||
|
* Response: JSON. Returns `{"url": "[redirect url]"}` on success, `{"error": "[error message]"}` otherwise
|
||||||
|
|
||||||
# Pleroma Conversations
|
# Pleroma Conversations
|
||||||
|
|
||||||
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
||||||
|
@ -382,7 +452,7 @@ Pleroma Conversations have the same general structure that Mastodon Conversation
|
||||||
|
|
||||||
Conversations have the additional field `recipients` under the `pleroma` key. This holds a list of all the accounts that will receive a message in this conversation.
|
Conversations have the additional field `recipients` under the `pleroma` key. This holds a list of all the accounts that will receive a message in this conversation.
|
||||||
|
|
||||||
The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visiblity to direct and address only the people who are the recipients of that Conversation.
|
The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visibility to direct and address only the people who are the recipients of that Conversation.
|
||||||
|
|
||||||
⚠ Conversation IDs can be found in direct messages with the `pleroma.direct_conversation_id` key, do not confuse it with `pleroma.conversation_id`.
|
⚠ Conversation IDs can be found in direct messages with the `pleroma.direct_conversation_id` key, do not confuse it with `pleroma.conversation_id`.
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,47 @@
|
||||||
# Prometheus Metrics
|
# Prometheus / OpenTelemetry Metrics
|
||||||
|
|
||||||
Pleroma includes support for exporting metrics via the [prometheus_ex](https://github.com/deadtrickster/prometheus.ex) library.
|
Pleroma includes support for exporting metrics via the [prom_ex](https://github.com/akoutmos/prom_ex) library.
|
||||||
|
The metrics are exposed by a dedicated webserver/port to improve privacy and security.
|
||||||
|
|
||||||
Config example:
|
Config example:
|
||||||
|
|
||||||
```
|
```
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter,
|
config :pleroma, Pleroma.PromEx,
|
||||||
enabled: true,
|
disabled: false,
|
||||||
auth: {:basic, "myusername", "mypassword"},
|
manual_metrics_start_delay: :no_delay,
|
||||||
ip_whitelist: ["127.0.0.1"],
|
drop_metrics_groups: [],
|
||||||
path: "/api/pleroma/app_metrics",
|
grafana: [
|
||||||
format: :text
|
host: System.get_env("GRAFANA_HOST", "http://localhost:3000"),
|
||||||
```
|
auth_token: System.get_env("GRAFANA_TOKEN"),
|
||||||
|
upload_dashboards_on_start: false,
|
||||||
* `enabled` (Pleroma extension) enables the endpoint
|
folder_name: "BEAM",
|
||||||
* `ip_whitelist` (Pleroma extension) could be used to restrict access only to specified IPs
|
annotate_app_lifecycle: true
|
||||||
* `auth` sets the authentication (`false` for no auth; configurable to HTTP Basic Auth, see [prometheus-plugs](https://github.com/deadtrickster/prometheus-plugs#exporting) documentation)
|
],
|
||||||
* `format` sets the output format (`:text` or `:protobuf`)
|
metrics_server: [
|
||||||
* `path` sets the path to app metrics page
|
port: 4021,
|
||||||
|
path: "/metrics",
|
||||||
|
protocol: :http,
|
||||||
## `/api/pleroma/app_metrics`
|
pool_size: 5,
|
||||||
|
cowboy_opts: [],
|
||||||
### Exports Prometheus application metrics
|
auth_strategy: :none
|
||||||
|
],
|
||||||
* Method: `GET`
|
datasource: "Prometheus"
|
||||||
* Authentication: not required by default (see configuration options above)
|
|
||||||
* Params: none
|
|
||||||
* Response: text
|
|
||||||
|
|
||||||
## Grafana
|
|
||||||
|
|
||||||
### Config example
|
|
||||||
|
|
||||||
The following is a config example to use with [Grafana](https://grafana.com)
|
|
||||||
|
|
||||||
```
|
```
|
||||||
- job_name: 'beam'
|
|
||||||
metrics_path: /api/pleroma/app_metrics
|
PromEx supports the ability to automatically publish dashboards to your Grafana server as well as register Annotations. If you do not wish to configure this capability you must generate the dashboard JSON files and import them directly. You can find the mix commands in the upstream [documentation](https://hexdocs.pm/prom_ex/Mix.Tasks.PromEx.Dashboard.Export.html). You can find the list of modules enabled in Pleroma for which you should generate dashboards for by examining the contents of the `lib/pleroma/prom_ex.ex` module.
|
||||||
scheme: https
|
|
||||||
|
## prometheus.yml
|
||||||
|
|
||||||
|
The following is a bare minimum config example to use with [Prometheus](https://prometheus.io) or Prometheus-compatible software like [VictoriaMetrics](https://victoriametrics.com).
|
||||||
|
|
||||||
|
```
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'pleroma'
|
||||||
|
scheme: http
|
||||||
static_configs:
|
static_configs:
|
||||||
- targets: ['pleroma.soykaf.com']
|
- targets: ['pleroma.soykaf.com:4021']
|
||||||
```
|
```
|
||||||
|
|
|
@ -20,16 +20,16 @@ Content-Type: multipart/form-data
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- (required) `file`: The file being uploaded
|
- (required) `file`: The file being uploaded
|
||||||
- (optionnal) `description`: A plain-text description of the media, for accessibility purposes.
|
- (optional) `description`: A plain-text description of the media, for accessibility purposes.
|
||||||
|
|
||||||
Response: HTTP 201 Created with the object into the body, no `Location` header provided as it doesn't have an `id`
|
Response: HTTP 201 Created with the object into the body, no `Location` header provided as it doesn't have an `id`
|
||||||
|
|
||||||
The object given in the reponse should then be inserted into an Object's `attachment` field.
|
The object given in the response should then be inserted into an Object's `attachment` field.
|
||||||
|
|
||||||
## ChatMessages
|
## ChatMessages
|
||||||
|
|
||||||
`ChatMessage`s are the messages sent in 1-on-1 chats. They are similar to
|
`ChatMessage`s are the messages sent in 1-on-1 chats. They are similar to
|
||||||
`Note`s, but the addresing is done by having a single AP actor in the `to`
|
`Note`s, but the addressing is done by having a single AP actor in the `to`
|
||||||
field. Addressing multiple actors is not allowed. These messages are always
|
field. Addressing multiple actors is not allowed. These messages are always
|
||||||
private, there is no public version of them. They are created with a `Create`
|
private, there is no public version of them. They are created with a `Create`
|
||||||
activity.
|
activity.
|
||||||
|
|
|
@ -15,7 +15,7 @@ Pleroma requires some adjustments from the defaults for running the instance loc
|
||||||
2. Change the dev.secret.exs
|
2. Change the dev.secret.exs
|
||||||
* Change the scheme in `config :pleroma, Pleroma.Web.Endpoint` to http (see examples below)
|
* Change the scheme in `config :pleroma, Pleroma.Web.Endpoint` to http (see examples below)
|
||||||
* If you want to change other settings, you can do that too
|
* If you want to change other settings, you can do that too
|
||||||
3. You can now start the server `mix phx.server`. Once it's build and started, you can access the instance on `http://<host>:<port>` (e.g.http://localhost:4000 ) and should be able to do everything locally you normaly can.
|
3. You can now start the server `mix phx.server`. Once it's build and started, you can access the instance on `http://<host>:<port>` (e.g.http://localhost:4000 ) and should be able to do everything locally you normally can.
|
||||||
|
|
||||||
Example config to change the scheme to http. Change the port if you want to run on another port.
|
Example config to change the scheme to http. Change the port if you want to run on another port.
|
||||||
```elixir
|
```elixir
|
||||||
|
@ -38,7 +38,7 @@ config :logger, :console,
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
1. Create a `test.secret.exs` file with the content as shown below
|
1. Create a `config/test.secret.exs` file with the content as shown below
|
||||||
2. Create the database user and test database.
|
2. Create the database user and test database.
|
||||||
1. You can use the `config/setup_db.psql` as a template. Copy the file if you want and change the database name, user and password to the values for the test-database (e.g. 'pleroma_local_test' for database and user). Then run this file like you did during installation.
|
1. You can use the `config/setup_db.psql` as a template. Copy the file if you want and change the database name, user and password to the values for the test-database (e.g. 'pleroma_local_test' for database and user). Then run this file like you did during installation.
|
||||||
2. The tests will try to create the Database, so we'll have to allow our test-database user to create databases, `sudo -Hu postgres psql -c "ALTER USER pleroma_local_test WITH CREATEDB;"`
|
2. The tests will try to create the Database, so we'll have to allow our test-database user to create databases, `sudo -Hu postgres psql -c "ALTER USER pleroma_local_test WITH CREATEDB;"`
|
||||||
|
|
|
@ -12,9 +12,9 @@ Note: This article is potentially outdated because at this time we may not have
|
||||||
|
|
||||||
### 必要なソフトウェア
|
### 必要なソフトウェア
|
||||||
|
|
||||||
- PostgreSQL 9.6以上 (Ubuntu16.04では9.5しか提供されていないので,[](https://www.postgresql.org/download/linux/ubuntu/)こちらから新しいバージョンを入手してください)
|
- PostgreSQL 11.0以上 (Ubuntu16.04では9.5しか提供されていないので,[](https://www.postgresql.org/download/linux/ubuntu/)こちらから新しいバージョンを入手してください)
|
||||||
- `postgresql-contrib` 9.6以上 (同上)
|
- `postgresql-contrib` 11.0以上 (同上)
|
||||||
- Elixir 1.8 以上 ([Debianのリポジトリからインストールしないこと!!! ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
|
- Elixir 1.13 以上 ([Debianのリポジトリからインストールしないこと!!! ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
|
||||||
- `erlang-dev`
|
- `erlang-dev`
|
||||||
- `erlang-nox`
|
- `erlang-nox`
|
||||||
- `git`
|
- `git`
|
||||||
|
|
|
@ -9,7 +9,7 @@ This document was written for FreeBSD 12.1, but should be work on future release
|
||||||
This assumes the target system has `pkg(8)`.
|
This assumes the target system has `pkg(8)`.
|
||||||
|
|
||||||
```
|
```
|
||||||
# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh cmake
|
# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh cmake vips
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy the rc.d scripts to the right directory:
|
Copy the rc.d scripts to the right directory:
|
||||||
|
@ -41,6 +41,7 @@ Create a user for Pleroma:
|
||||||
```
|
```
|
||||||
# pw add user pleroma -m
|
# pw add user pleroma -m
|
||||||
# echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile
|
# echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile
|
||||||
|
# echo 'export VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS' >> /home/pleroma/.profile
|
||||||
# su -l pleroma
|
# su -l pleroma
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
## Required dependencies
|
## Required dependencies
|
||||||
|
|
||||||
* PostgreSQL >=9.6
|
* PostgreSQL >=11.0
|
||||||
* Elixir >=1.11.0 <1.15
|
* Elixir >=1.13.0 <1.17
|
||||||
* Erlang OTP >=22.2.0 <26
|
* Erlang OTP >=22.2.0 (supported: <27)
|
||||||
* git
|
* git
|
||||||
* file / libmagic
|
* file / libmagic
|
||||||
* gcc or clang
|
* gcc or clang
|
||||||
|
|
|
@ -59,7 +59,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i
|
||||||
|
|
||||||
If you would not like to install the optional packages, remove them from this line.
|
If you would not like to install the optional packages, remove them from this line.
|
||||||
|
|
||||||
If you're running this from a low-powered virtual machine, it should work though it will take some time. There were no issues on a VPS with a single core and 1GB of RAM; if you are using an even more limited device and run into issues, you can try creating a swapfile or use a more powerful machine running Gentoo to [cross build](https://wiki.gentoo.org/wiki/Cross_build_environment). If you have a wait ahead of you, now would be a good time to take a break, strech a bit, refresh your beverage of choice and/or get a snack, and reply to Arch users' posts with "I use Gentoo btw" as we do.
|
If you're running this from a low-powered virtual machine, it should work though it will take some time. There were no issues on a VPS with a single core and 1GB of RAM; if you are using an even more limited device and run into issues, you can try creating a swapfile or use a more powerful machine running Gentoo to [cross build](https://wiki.gentoo.org/wiki/Cross_build_environment). If you have a wait ahead of you, now would be a good time to take a break, stretch a bit, refresh your beverage of choice and/or get a snack, and reply to Arch users' posts with "I use Gentoo btw" as we do.
|
||||||
|
|
||||||
### Install PostgreSQL
|
### Install PostgreSQL
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ Not only does this make it much easier to deploy changes you make, as you can co
|
||||||
|
|
||||||
* Add a new system user for the Pleroma service and set up default directories:
|
* Add a new system user for the Pleroma service and set up default directories:
|
||||||
|
|
||||||
Remove `,wheel` if you do not want this user to be able to use `sudo`, however note that being able to `sudo` as the `pleroma` user will make finishing the insallation and common maintenence tasks somewhat easier:
|
Remove `,wheel` if you do not want this user to be able to use `sudo`, however note that being able to `sudo` as the `pleroma` user will make finishing the installation and common maintenance tasks somewhat easier:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# useradd -m -G users,wheel -s /bin/bash pleroma
|
# useradd -m -G users,wheel -s /bin/bash pleroma
|
||||||
|
|
|
@ -49,7 +49,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i
|
||||||
|
|
||||||
If you would not like to install the optional packages, remove them from this line.
|
If you would not like to install the optional packages, remove them from this line.
|
||||||
|
|
||||||
If you're running this from a low-powered virtual machine, it should work though it will take some time. There were no issues on a VPS with a single core and 1GB of RAM; if you are using an even more limited device and run into issues, you can try creating a swapfile or use a more powerful machine running Gentoo to [cross build](https://wiki.gentoo.org/wiki/Cross_build_environment). If you have a wait ahead of you, now would be a good time to take a break, strech a bit, refresh your beverage of choice and/or get a snack, and reply to Arch users' posts with "I use Gentoo btw" as we do.
|
If you're running this from a low-powered virtual machine, it should work though it will take some time. There were no issues on a VPS with a single core and 1GB of RAM; if you are using an even more limited device and run into issues, you can try creating a swapfile or use a more powerful machine running Gentoo to [cross build](https://wiki.gentoo.org/wiki/Cross_build_environment). If you have a wait ahead of you, now would be a good time to take a break, stretch a bit, refresh your beverage of choice and/or get a snack, and reply to Arch users' posts with "I use Gentoo btw" as we do.
|
||||||
|
|
||||||
### Setup PostgreSQL
|
### Setup PostgreSQL
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,41 @@
|
||||||
|
|
||||||
{! backend/installation/generic_dependencies.include !}
|
{! backend/installation/generic_dependencies.include !}
|
||||||
|
|
||||||
## Installing software used in this guide
|
# Installation options
|
||||||
|
|
||||||
|
Currently there are two options available for NetBSD: manual installation (from source) or using experimental package from [pkgsrc-wip](https://github.com/NetBSD/pkgsrc-wip/tree/master/pleroma).
|
||||||
|
|
||||||
|
WIP package can be installed via pkgsrc and can be crosscompiled for easier binary distribution. Source installation most probably will be restricted to a single machine.
|
||||||
|
|
||||||
|
## pkgsrc installation
|
||||||
|
|
||||||
|
WIP package creates Mix.Release (similar to how Docker images are built) but doesn't bundle Erlang runtime, listing it as a dependency instead. This allows for easier and more modular installations, especially on weaker machines. Currently this method also does not support all features of `pleroma_ctl` command (like changing installation type or managing frontends) as NetBSD is not yet a supported binary flavour of Pleroma's CI.
|
||||||
|
|
||||||
|
In any case, you can install it the same way as any other `pkgsrc-wip` package:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /usr/pkgsrc
|
||||||
|
git clone --depth 1 git://wip.pkgsrc.org/pkgsrc-wip.git wip
|
||||||
|
cp -rf wip/pleroma www
|
||||||
|
cp -rf wip/libvips graphics
|
||||||
|
cd /usr/pkgsrc/www/pleroma
|
||||||
|
bmake && bmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `bmake package` to create a binary package. This can come especially handy if you're targeting embedded or low-power systems and are crosscompiling on a more powerful machine.
|
||||||
|
|
||||||
|
> Note: Elixir has [endianness bug](https://github.com/elixir-lang/elixir/issues/2785) which requires it to be compiled on a machine with the same endianness. In other words, package crosscompiled on amd64 (little endian) won't work on powerpc or sparc machines (big endian). While _in theory™_ nothing catastrophic should happen, one can see that for example regexes won't work properly. Some distributions just strip this warning away, so it doesn't bother the users... anyway, you've been warned.
|
||||||
|
|
||||||
|
## Source installation
|
||||||
|
|
||||||
pkgin should have been installed by the NetBSD installer if you selected
|
pkgin should have been installed by the NetBSD installer if you selected
|
||||||
the right options. If it isn't installed, install it using pkg_add.
|
the right options. If it isn't installed, install it using `pkg_add`.
|
||||||
|
|
||||||
Note that `postgresql11-contrib` is needed for the Postgres extensions
|
Note that `postgresql11-contrib` is needed for the Postgres extensions
|
||||||
Pleroma uses.
|
Pleroma uses.
|
||||||
|
|
||||||
|
> Note: you can use modern versions of PostgreSQL. In this case, just use `postgresql16-contrib` and so on.
|
||||||
|
|
||||||
The `mksh` shell is needed to run the Elixir `mix` script.
|
The `mksh` shell is needed to run the Elixir `mix` script.
|
||||||
|
|
||||||
`# pkgin install acmesh elixir git-base git-docs mksh nginx postgresql11-server postgresql11-client postgresql11-contrib sudo ffmpeg4 ImageMagick`
|
`# pkgin install acmesh elixir git-base git-docs mksh nginx postgresql11-server postgresql11-client postgresql11-contrib sudo ffmpeg4 ImageMagick`
|
||||||
|
@ -29,29 +56,6 @@ shells/mksh
|
||||||
www/nginx
|
www/nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy the rc.d scripts to the right directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
# cp /usr/pkg/share/examples/rc.d/nginx /usr/pkg/share/examples/rc.d/pgsql /etc/rc.d
|
|
||||||
```
|
|
||||||
|
|
||||||
Add nginx and Postgres to `/etc/rc.conf`:
|
|
||||||
|
|
||||||
```
|
|
||||||
nginx=YES
|
|
||||||
pgsql=YES
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuring postgres
|
|
||||||
|
|
||||||
First, run `# /etc/rc.d/pgsql start`. Then, `$ sudo -Hu pgsql -g pgsql createdb`.
|
|
||||||
|
|
||||||
### Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
|
||||||
|
|
||||||
`# pkgin install ImageMagick ffmpeg4 p5-Image-ExifTool`
|
|
||||||
|
|
||||||
## Configuring Pleroma
|
|
||||||
|
|
||||||
Create a user for Pleroma:
|
Create a user for Pleroma:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -68,41 +72,98 @@ $ cd /home/pleroma
|
||||||
$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git
|
$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Configure Pleroma. Note that you need a domain name at this point:
|
Get deps and compile:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ cd /home/pleroma/pleroma
|
$ cd /home/pleroma/pleroma
|
||||||
|
$ export MIX_ENV=prod
|
||||||
$ mix deps.get
|
$ mix deps.get
|
||||||
$ MIX_ENV=prod mix pleroma.instance gen # You will be asked a few questions here.
|
$ mix compile
|
||||||
```
|
```
|
||||||
|
|
||||||
Since Postgres is configured, we can now initialize the database. There should
|
## Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
||||||
now be a file in `config/setup_db.psql` that makes this easier. Edit it, and
|
|
||||||
*change the password* to a password of your choice. Make sure it is secure, since
|
`# pkgin install ImageMagick ffmpeg4 p5-Image-ExifTool`
|
||||||
|
|
||||||
|
or via pkgsrc:
|
||||||
|
|
||||||
|
```
|
||||||
|
graphics/p5-Image-ExifTool
|
||||||
|
graphics/ImageMagick
|
||||||
|
multimedia/ffmpeg4
|
||||||
|
```
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
## Understanding $PREFIX
|
||||||
|
|
||||||
|
From now on, you may encounter `$PREFIX` variable in the paths. This variable indicates your current local pkgsrc prefix. Usually it's `/usr/pkg` unless you configured it otherwise. Translating to pkgsrc's lingo, it's called `LOCALBASE`, which essentially means the same this. You may want to set it up for your local shell session (this uses `mksh` which should already be installed as one of the required dependencies):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ export PREFIX=$(pkg_info -Q LOCALBASE mksh)
|
||||||
|
$ echo $PREFIX
|
||||||
|
/usr/pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setting up your instance
|
||||||
|
|
||||||
|
Now, you need to configure your instance. During this initial configuration, you will be asked some questions about your server. You will need a domain name at this point; it doesn't have to be deployed, but changing it later will be very cumbersome.
|
||||||
|
|
||||||
|
If you've installed via pkgsrc, `pleroma_ctl` should already be in your `PATH`; if you've installed from source, it's located at `/home/pleroma/pleroma/release/bin/pleroma_ctl`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ su -l pleroma
|
||||||
|
$ pleroma_ctl instance gen --output $PREFIX/etc/pleroma/config.exs --output-psql /tmp/setup_db.psql
|
||||||
|
```
|
||||||
|
|
||||||
|
During installation, you will be asked about static and upload directories. Don't forget to create them and update permissions:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir -p /var/lib/pleroma/uploads
|
||||||
|
chown -R pleroma:pleroma /var/lib/pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setting up the database
|
||||||
|
|
||||||
|
First, run `# /etc/rc.d/pgsql start`. Then, `$ sudo -Hu pgsql -g pgsql createdb`.
|
||||||
|
|
||||||
|
We can now initialize the database. You'll need to edit generated SQL file from the previous step. It's located at `/tmp/setup_db.psql`.
|
||||||
|
|
||||||
|
Edit this file, and *change the password* to a password of your choice. Make sure it is secure, since
|
||||||
it'll be protecting your database. Now initialize the database:
|
it'll be protecting your database. Now initialize the database:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ sudo -Hu pgsql -g pgsql psql -f config/setup_db.psql
|
$ sudo -Hu pgsql -g pgsql psql -f /tmp/setup_db.psql
|
||||||
```
|
```
|
||||||
|
|
||||||
Postgres allows connections from all users without a password by default. To
|
Postgres allows connections from all users without a password by default. To
|
||||||
fix this, edit `/usr/pkg/pgsql/data/pg_hba.conf`. Change every `trust` to
|
fix this, edit `$PREFIX/pgsql/data/pg_hba.conf`. Change every `trust` to
|
||||||
`password`.
|
`password`.
|
||||||
|
|
||||||
Once this is done, restart Postgres with `# /etc/rc.d/pgsql restart`.
|
Once this is done, restart Postgres with `# /etc/rc.d/pgsql restart`.
|
||||||
|
|
||||||
Run the database migrations.
|
Run the database migrations.
|
||||||
|
|
||||||
|
### pkgsrc installation
|
||||||
|
|
||||||
|
```
|
||||||
|
pleroma_ctl migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Source installation
|
||||||
|
|
||||||
You will need to do this whenever you update with `git pull`:
|
You will need to do this whenever you update with `git pull`:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
$ cd /home/pleroma/pleroma
|
||||||
$ MIX_ENV=prod mix ecto.migrate
|
$ MIX_ENV=prod mix ecto.migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuring nginx
|
## Configuring nginx
|
||||||
|
|
||||||
Install the example configuration file
|
Install the example configuration file
|
||||||
`/home/pleroma/pleroma/installation/pleroma.nginx` to
|
(`$PREFIX/share/examples/pleroma/pleroma.nginx` or `/home/pleroma/pleroma/installation/pleroma.nginx`) to
|
||||||
`/usr/pkg/etc/nginx.conf`.
|
`$PREFIX/etc/nginx.conf`.
|
||||||
|
|
||||||
Note that it will need to be wrapped in a `http {}` block. You should add
|
Note that it will need to be wrapped in a `http {}` block. You should add
|
||||||
settings for the nginx daemon outside of the http block, for example:
|
settings for the nginx daemon outside of the http block, for example:
|
||||||
|
@ -176,27 +237,45 @@ Let's add auto-renewal to `/etc/daily.local`
|
||||||
--stateless
|
--stateless
|
||||||
```
|
```
|
||||||
|
|
||||||
## Creating a startup script for Pleroma
|
## Autostart
|
||||||
|
|
||||||
Copy the startup script to the correct location and make sure it's executable:
|
For properly functioning instance, you will need pleroma (backend service), nginx (reverse proxy) and postgresql (database) services running. There's no requirement for them to reside on the same machine, but you have to provide autostart for each of them.
|
||||||
|
|
||||||
|
### nginx
|
||||||
|
```
|
||||||
|
# cp $PREFIX/share/examples/rc.d/nginx /etc/rc.d
|
||||||
|
# echo "nginx=YES" >> /etc/rc.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### postgresql
|
||||||
|
|
||||||
|
```
|
||||||
|
# cp $PREFIX/share/examples/rc.d/pgsql /etc/rc.d
|
||||||
|
# echo "pgsql=YES" >> /etc/rc.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### pleroma
|
||||||
|
|
||||||
|
First, copy the script (pkgsrc variant)
|
||||||
|
```
|
||||||
|
# cp $PREFIX/share/examples/pleroma/pleroma.rc /etc/rc.d/pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
or source variant
|
||||||
```
|
```
|
||||||
# cp /home/pleroma/pleroma/installation/netbsd/rc.d/pleroma /etc/rc.d/pleroma
|
# cp /home/pleroma/pleroma/installation/netbsd/rc.d/pleroma /etc/rc.d/pleroma
|
||||||
# chmod +x /etc/rc.d/pleroma
|
# chmod +x /etc/rc.d/pleroma
|
||||||
```
|
```
|
||||||
|
|
||||||
Add the following to `/etc/rc.conf`:
|
Then, add the following to `/etc/rc.conf`:
|
||||||
|
|
||||||
```
|
```
|
||||||
pleroma=YES
|
pleroma=YES
|
||||||
pleroma_home="/home/pleroma"
|
|
||||||
pleroma_user="pleroma"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `# /etc/rc.d/pleroma start` to start Pleroma.
|
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
|
Run `# /etc/rc.d/pleroma start` to start Pleroma.
|
||||||
Restart nginx with `# /etc/rc.d/nginx restart` and you should be up and running.
|
Restart nginx with `# /etc/rc.d/nginx restart` and you should be up and running.
|
||||||
|
|
||||||
Make sure your time is in sync, or other instances will receive your posts with
|
Make sure your time is in sync, or other instances will receive your posts with
|
||||||
|
|
|
@ -62,7 +62,7 @@ rcctl start postgresql
|
||||||
To check that it started properly and didn't fail right after starting, you can run `ps aux | grep postgres`, there should be multiple lines of output.
|
To check that it started properly and didn't fail right after starting, you can run `ps aux | grep postgres`, there should be multiple lines of output.
|
||||||
|
|
||||||
#### httpd
|
#### httpd
|
||||||
httpd will have three fuctions:
|
httpd will have three functions:
|
||||||
|
|
||||||
* redirect requests trying to reach the instance over http to the https URL
|
* redirect requests trying to reach the instance over http to the https URL
|
||||||
* serve a robots.txt file
|
* serve a robots.txt file
|
||||||
|
@ -225,7 +225,7 @@ pass in quick on $if inet6 proto icmp6 to ($if) icmp6-type { echoreq unreach par
|
||||||
pass in quick on $if proto tcp to ($if) port { http https } # relayd/httpd
|
pass in quick on $if proto tcp to ($if) port { http https } # relayd/httpd
|
||||||
pass in quick on $if proto tcp from $authorized_ssh_clients to ($if) port ssh
|
pass in quick on $if proto tcp from $authorized_ssh_clients to ($if) port ssh
|
||||||
```
|
```
|
||||||
Replace *<network interface\>* by your server's network interface name (which you can get with ifconfig). Consider replacing the content of the authorized\_ssh\_clients macro by, for exemple, your home IP address, to avoid SSH connection attempts from bots.
|
Replace *<network interface\>* by your server's network interface name (which you can get with ifconfig). Consider replacing the content of the authorized\_ssh\_clients macro by, for example, your home IP address, to avoid SSH connection attempts from bots.
|
||||||
|
|
||||||
Check pf's configuration by running `pfctl -nf /etc/pf.conf`, load it with `pfctl -f /etc/pf.conf` and enable pf at boot with `rcctl enable pf`.
|
Check pf's configuration by running `pfctl -nf /etc/pf.conf`, load it with `pfctl -f /etc/pf.conf` and enable pf at boot with `rcctl enable pf`.
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@ At this point if you open your (sub)domain in a browser you should see a 502 err
|
||||||
systemctl enable pleroma
|
systemctl enable pleroma
|
||||||
```
|
```
|
||||||
|
|
||||||
If everything worked, you should see Pleroma-FE when visiting your domain. If that didn't happen, try reviewing the installation steps, starting Pleroma in the foreground and seeing if there are any errrors.
|
If everything worked, you should see Pleroma-FE when visiting your domain. If that didn't happen, try reviewing the installation steps, starting Pleroma in the foreground and seeing if there are any errors.
|
||||||
|
|
||||||
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) via Matrix or **#pleroma** on **libera.chat** via IRC, you can also [file an issue on our Gitlab](https://git.pleroma.social/pleroma/pleroma-support/issues/new).
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) via Matrix or **#pleroma** on **libera.chat** via IRC, you can also [file an issue on our Gitlab](https://git.pleroma.social/pleroma/pleroma-support/issues/new).
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# PROVIDE: pleroma
|
# PROVIDE: pleroma
|
||||||
# REQUIRE: DAEMON pgsql
|
# REQUIRE: DAEMON pgsql nginx
|
||||||
|
|
||||||
if [ -f /etc/rc.subr ]; then
|
if [ -f /etc/rc.subr ]; then
|
||||||
. /etc/rc.subr
|
. /etc/rc.subr
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
pleroma_home="/home/pleroma"
|
||||||
|
pleroma_user="pleroma"
|
||||||
|
|
||||||
name="pleroma"
|
name="pleroma"
|
||||||
rcvar=${name}
|
rcvar=${name}
|
||||||
command="/usr/pkg/bin/elixir"
|
command="/usr/pkg/bin/elixir"
|
||||||
|
@ -19,10 +22,10 @@ pleroma_env="HOME=${pleroma_home} MIX_ENV=prod"
|
||||||
check_pidfile()
|
check_pidfile()
|
||||||
{
|
{
|
||||||
pid=$(pgrep -U "${pleroma_user}" /bin/beam.smp$)
|
pid=$(pgrep -U "${pleroma_user}" /bin/beam.smp$)
|
||||||
echo -n "${pid}"
|
printf '%s' "${pid}"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -f /etc/rc.subr -a -d /etc/rc.d -a -f /etc/rc.d/DAEMON ]; then
|
if [ -f /etc/rc.subr ] && [ -d /etc/rc.d ] && [ -f /etc/rc.d/DAEMON ]; then
|
||||||
# newer NetBSD
|
# newer NetBSD
|
||||||
load_rc_config ${name}
|
load_rc_config ${name}
|
||||||
run_rc_command "$1"
|
run_rc_command "$1"
|
||||||
|
@ -39,7 +42,7 @@ else
|
||||||
stop)
|
stop)
|
||||||
echo "Stopping ${name}."
|
echo "Stopping ${name}."
|
||||||
check_pidfile
|
check_pidfile
|
||||||
! [ -n ${pid} ] && kill ${pid}
|
! [ -n "${pid}" ] && kill "${pid}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
restart)
|
restart)
|
||||||
|
|
15
installation/nsfw-api.service
Normal file
15
installation/nsfw-api.service
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=NSFW API
|
||||||
|
After=docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
TimeoutStartSec=0
|
||||||
|
Restart=always
|
||||||
|
ExecStartPre=-/usr/bin/docker stop %n
|
||||||
|
ExecStartPre=-/usr/bin/docker rm %n
|
||||||
|
ExecStartPre=/usr/bin/docker pull eugencepoi/nsfw_api:latest
|
||||||
|
ExecStart=/usr/bin/docker run --rm -p 127.0.0.1:5000:5000/tcp --env PORT=5000 --name %n eugencepoi/nsfw_api:latest
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -204,7 +204,7 @@
|
||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
|
|
||||||
%% Following HTTP API is deprected, the new one abouve should be used instead
|
%% Following HTTP API is deprecated, the new one above should be used instead
|
||||||
|
|
||||||
{ {5288, "127.0.0.1"} , ejabberd_cowboy, [
|
{ {5288, "127.0.0.1"} , ejabberd_cowboy, [
|
||||||
{num_acceptors, 10},
|
{num_acceptors, 10},
|
||||||
|
@ -824,7 +824,7 @@
|
||||||
|
|
||||||
%% Enable archivization for private messages (default)
|
%% Enable archivization for private messages (default)
|
||||||
% {pm, [
|
% {pm, [
|
||||||
%% Top-level options can be overriden here if needed, for example:
|
%% Top-level options can be overridden here if needed, for example:
|
||||||
% {async_writer, false}
|
% {async_writer, false}
|
||||||
% ]},
|
% ]},
|
||||||
|
|
||||||
|
@ -834,7 +834,7 @@
|
||||||
%%
|
%%
|
||||||
% {muc, [
|
% {muc, [
|
||||||
% {host, "muc.@HOST@"}
|
% {host, "muc.@HOST@"}
|
||||||
%% As with pm, top-level options can be overriden for MUC archive
|
%% As with pm, top-level options can be overridden for MUC archive
|
||||||
% ]},
|
% ]},
|
||||||
%
|
%
|
||||||
%% Do not use a <stanza-id/> element (by default stanzaid is used)
|
%% Do not use a <stanza-id/> element (by default stanzaid is used)
|
||||||
|
|
|
@ -14,7 +14,8 @@ defmodule Mix.Pleroma do
|
||||||
:swoosh,
|
:swoosh,
|
||||||
:timex,
|
:timex,
|
||||||
:fast_html,
|
:fast_html,
|
||||||
:oban
|
:oban,
|
||||||
|
:logger_backends
|
||||||
]
|
]
|
||||||
@cachex_children ["object", "user", "scrubber", "web_resp"]
|
@cachex_children ["object", "user", "scrubber", "web_resp"]
|
||||||
@doc "Common functions to be reused in mix tasks"
|
@doc "Common functions to be reused in mix tasks"
|
||||||
|
|
|
@ -205,6 +205,35 @@ defmodule Mix.Tasks.Pleroma.Config do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Removes any policies that are not a real module
|
||||||
|
# as they will prevent the server from starting
|
||||||
|
def run(["fix_mrf_policies"]) do
|
||||||
|
check_configdb(fn ->
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
group = :pleroma
|
||||||
|
key = :mrf
|
||||||
|
|
||||||
|
%{value: value} =
|
||||||
|
group
|
||||||
|
|> ConfigDB.get_by_group_and_key(key)
|
||||||
|
|
||||||
|
policies =
|
||||||
|
Keyword.get(value, :policies, [])
|
||||||
|
|> Enum.filter(&is_atom(&1))
|
||||||
|
|> Enum.filter(fn mrf ->
|
||||||
|
case Code.ensure_compiled(mrf) do
|
||||||
|
{:module, _} -> true
|
||||||
|
{:error, _} -> false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
value = Keyword.put(value, :policies, policies)
|
||||||
|
|
||||||
|
ConfigDB.update_or_create(%{group: group, key: key, value: value})
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
@spec migrate_to_db(Path.t() | nil) :: any()
|
@spec migrate_to_db(Path.t() | nil) :: any()
|
||||||
def migrate_to_db(file_path \\ nil) do
|
def migrate_to_db(file_path \\ nil) do
|
||||||
with :ok <- Pleroma.Config.DeprecationWarnings.warn() do
|
with :ok <- Pleroma.Config.DeprecationWarnings.warn() do
|
||||||
|
|
|
@ -67,43 +67,168 @@ defmodule Mix.Tasks.Pleroma.Database do
|
||||||
OptionParser.parse(
|
OptionParser.parse(
|
||||||
args,
|
args,
|
||||||
strict: [
|
strict: [
|
||||||
vacuum: :boolean
|
vacuum: :boolean,
|
||||||
|
keep_threads: :boolean,
|
||||||
|
keep_non_public: :boolean,
|
||||||
|
prune_orphaned_activities: :boolean
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
|
||||||
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days])
|
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days])
|
||||||
|
time_deadline = NaiveDateTime.utc_now() |> NaiveDateTime.add(-(deadline * 86_400))
|
||||||
|
|
||||||
Logger.info("Pruning objects older than #{deadline} days")
|
log_message = "Pruning objects older than #{deadline} days"
|
||||||
|
|
||||||
time_deadline =
|
log_message =
|
||||||
NaiveDateTime.utc_now()
|
if Keyword.get(options, :keep_non_public) do
|
||||||
|> NaiveDateTime.add(-(deadline * 86_400))
|
log_message <> ", keeping non public posts"
|
||||||
|
else
|
||||||
|
log_message
|
||||||
|
end
|
||||||
|
|
||||||
from(o in Object,
|
log_message =
|
||||||
where:
|
if Keyword.get(options, :keep_threads) do
|
||||||
|
log_message <> ", keeping threads intact"
|
||||||
|
else
|
||||||
|
log_message
|
||||||
|
end
|
||||||
|
|
||||||
|
log_message =
|
||||||
|
if Keyword.get(options, :prune_orphaned_activities) do
|
||||||
|
log_message <> ", pruning orphaned activities"
|
||||||
|
else
|
||||||
|
log_message
|
||||||
|
end
|
||||||
|
|
||||||
|
log_message =
|
||||||
|
if Keyword.get(options, :vacuum) do
|
||||||
|
log_message <>
|
||||||
|
", doing a full vacuum (you shouldn't do this as a recurring maintanance task)"
|
||||||
|
else
|
||||||
|
log_message
|
||||||
|
end
|
||||||
|
|
||||||
|
Logger.info(log_message)
|
||||||
|
|
||||||
|
if Keyword.get(options, :keep_threads) do
|
||||||
|
# We want to delete objects from threads where
|
||||||
|
# 1. the newest post is still old
|
||||||
|
# 2. none of the activities is local
|
||||||
|
# 3. none of the activities is bookmarked
|
||||||
|
# 4. optionally none of the posts is non-public
|
||||||
|
deletable_context =
|
||||||
|
if Keyword.get(options, :keep_non_public) do
|
||||||
|
Pleroma.Activity
|
||||||
|
|> join(:left, [a], b in Pleroma.Bookmark, on: a.id == b.activity_id)
|
||||||
|
|> group_by([a], fragment("? ->> 'context'::text", a.data))
|
||||||
|
|> having(
|
||||||
|
[a],
|
||||||
|
not fragment(
|
||||||
|
# Posts (checked on Create Activity) is non-public
|
||||||
|
"bool_or((not(?->'to' \\? ? OR ?->'cc' \\? ?)) and ? ->> 'type' = 'Create')",
|
||||||
|
a.data,
|
||||||
|
^Pleroma.Constants.as_public(),
|
||||||
|
a.data,
|
||||||
|
^Pleroma.Constants.as_public(),
|
||||||
|
a.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Pleroma.Activity
|
||||||
|
|> join(:left, [a], b in Pleroma.Bookmark, on: a.id == b.activity_id)
|
||||||
|
|> group_by([a], fragment("? ->> 'context'::text", a.data))
|
||||||
|
end
|
||||||
|
|> having([a], max(a.updated_at) < ^time_deadline)
|
||||||
|
|> having([a], not fragment("bool_or(?)", a.local))
|
||||||
|
|> having([_, b], fragment("max(?::text) is null", b.id))
|
||||||
|
|> select([a], fragment("? ->> 'context'::text", a.data))
|
||||||
|
|
||||||
|
Pleroma.Object
|
||||||
|
|> where([o], fragment("? ->> 'context'::text", o.data) in subquery(deletable_context))
|
||||||
|
else
|
||||||
|
if Keyword.get(options, :keep_non_public) do
|
||||||
|
Pleroma.Object
|
||||||
|
|> where(
|
||||||
|
[o],
|
||||||
fragment(
|
fragment(
|
||||||
"?->'to' \\? ? OR ?->'cc' \\? ?",
|
"?->'to' \\? ? OR ?->'cc' \\? ?",
|
||||||
o.data,
|
o.data,
|
||||||
^Pleroma.Constants.as_public(),
|
^Pleroma.Constants.as_public(),
|
||||||
o.data,
|
o.data,
|
||||||
^Pleroma.Constants.as_public()
|
^Pleroma.Constants.as_public()
|
||||||
),
|
)
|
||||||
where: o.inserted_at < ^time_deadline,
|
)
|
||||||
where:
|
else
|
||||||
|
Pleroma.Object
|
||||||
|
end
|
||||||
|
|> where([o], o.updated_at < ^time_deadline)
|
||||||
|
|> where(
|
||||||
|
[o],
|
||||||
fragment("split_part(?->>'actor', '/', 3) != ?", o.data, ^Pleroma.Web.Endpoint.host())
|
fragment("split_part(?->>'actor', '/', 3) != ?", o.data, ^Pleroma.Web.Endpoint.host())
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|> Repo.delete_all(timeout: :infinity)
|
|> Repo.delete_all(timeout: :infinity)
|
||||||
|
|
||||||
prune_hashtags_query = """
|
if !Keyword.get(options, :keep_threads) do
|
||||||
|
# Without the --keep-threads option, it's possible that bookmarked
|
||||||
|
# objects have been deleted. We remove the corresponding bookmarks.
|
||||||
|
"""
|
||||||
|
delete from public.bookmarks
|
||||||
|
where id in (
|
||||||
|
select b.id from public.bookmarks b
|
||||||
|
left join public.activities a on b.activity_id = a.id
|
||||||
|
left join public.objects o on a."data" ->> 'object' = o.data ->> 'id'
|
||||||
|
where o.id is null
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|> Repo.query([], timeout: :infinity)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Keyword.get(options, :prune_orphaned_activities) do
|
||||||
|
# Prune activities who link to a single object
|
||||||
|
"""
|
||||||
|
delete from public.activities
|
||||||
|
where id in (
|
||||||
|
select a.id from public.activities a
|
||||||
|
left join public.objects o on a.data ->> 'object' = o.data ->> 'id'
|
||||||
|
left join public.activities a2 on a.data ->> 'object' = a2.data ->> 'id'
|
||||||
|
left join public.users u on a.data ->> 'object' = u.ap_id
|
||||||
|
where not a.local
|
||||||
|
and jsonb_typeof(a."data" -> 'object') = 'string'
|
||||||
|
and o.id is null
|
||||||
|
and a2.id is null
|
||||||
|
and u.id is null
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|> Repo.query([], timeout: :infinity)
|
||||||
|
|
||||||
|
# Prune activities who link to an array of objects
|
||||||
|
"""
|
||||||
|
delete from public.activities
|
||||||
|
where id in (
|
||||||
|
select a.id from public.activities a
|
||||||
|
join json_array_elements_text((a."data" -> 'object')::json) as j on jsonb_typeof(a."data" -> 'object') = 'array'
|
||||||
|
left join public.objects o on j.value = o.data ->> 'id'
|
||||||
|
left join public.activities a2 on j.value = a2.data ->> 'id'
|
||||||
|
left join public.users u on j.value = u.ap_id
|
||||||
|
group by a.id
|
||||||
|
having max(o.data ->> 'id') is null
|
||||||
|
and max(a2.data ->> 'id') is null
|
||||||
|
and max(u.ap_id) is null
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|> Repo.query([], timeout: :infinity)
|
||||||
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
DELETE FROM hashtags AS ht
|
DELETE FROM hashtags AS ht
|
||||||
WHERE NOT EXISTS (
|
WHERE NOT EXISTS (
|
||||||
SELECT 1 FROM hashtags_objects hto
|
SELECT 1 FROM hashtags_objects hto
|
||||||
WHERE ht.id = hto.hashtag_id)
|
WHERE ht.id = hto.hashtag_id)
|
||||||
"""
|
"""
|
||||||
|
|> Repo.query()
|
||||||
Repo.query(prune_hashtags_query)
|
|
||||||
|
|
||||||
if Keyword.get(options, :vacuum) do
|
if Keyword.get(options, :vacuum) do
|
||||||
Maintenance.vacuum("full")
|
Maintenance.vacuum("full")
|
||||||
|
@ -193,7 +318,7 @@ defmodule Mix.Tasks.Pleroma.Database do
|
||||||
"ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';"
|
"ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';"
|
||||||
)
|
)
|
||||||
|
|
||||||
# non-exist config will not raise excpetion but only give >0 messages
|
# non-exist config will not raise exception but only give >0 messages
|
||||||
if length(msg) > 0 do
|
if length(msg) > 0 do
|
||||||
shell_info("Error: #{inspect(msg, pretty: true)}")
|
shell_info("Error: #{inspect(msg, pretty: true)}")
|
||||||
else
|
else
|
||||||
|
@ -226,7 +351,7 @@ defmodule Mix.Tasks.Pleroma.Database do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
shell_info('Done.')
|
shell_info(~c"Done.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ defmodule Mix.Tasks.Pleroma.Digest do
|
||||||
shell_info("Digest email have been sent to #{nickname} (#{user.email})")
|
shell_info("Digest email have been sent to #{nickname} (#{user.email})")
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
shell_info("Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}")
|
shell_info("Couldn't find any mentions for #{nickname} since #{last_digest_emailed_at}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -61,7 +61,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.Rollback do
|
||||||
Logger.configure(level: :info)
|
Logger.configure(level: :info)
|
||||||
|
|
||||||
if opts[:env] == "test" do
|
if opts[:env] == "test" do
|
||||||
Logger.info("Rollback succesfully")
|
Logger.info("Rollback successfully")
|
||||||
else
|
else
|
||||||
{:ok, _, _} =
|
{:ok, _, _} =
|
||||||
Ecto.Migrator.with_repo(Pleroma.Repo, &Ecto.Migrator.run(&1, path, :down, opts))
|
Ecto.Migrator.with_repo(Pleroma.Repo, &Ecto.Migrator.run(&1, path, :down, opts))
|
||||||
|
|
|
@ -111,7 +111,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
|
||||||
|
|
||||||
{:ok, _} =
|
{:ok, _} =
|
||||||
:zip.unzip(binary_archive,
|
:zip.unzip(binary_archive,
|
||||||
cwd: pack_path,
|
cwd: String.to_charlist(pack_path),
|
||||||
file_list: files_to_unzip
|
file_list: files_to_unzip
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -292,7 +292,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
||||||
|
|
||||||
if db_configurable? do
|
if db_configurable? do
|
||||||
shell_info(
|
shell_info(
|
||||||
" Please transfer your config to the database after running database migrations. Refer to \"Transfering the config to/from the database\" section of the docs for more information."
|
" Please transfer your config to the database after running database migrations. Refer to \"Transferring the config to/from the database\" section of the docs for more information."
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -352,6 +352,4 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
||||||
|
|
||||||
enabled_filters
|
enabled_filters
|
||||||
end
|
end
|
||||||
|
|
||||||
defp upload_filters(_), do: []
|
|
||||||
end
|
end
|
||||||
|
|
83
lib/mix/tasks/pleroma/search/indexer.ex
Normal file
83
lib/mix/tasks/pleroma/search/indexer.ex
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Mix.Tasks.Pleroma.Search.Indexer do
|
||||||
|
import Mix.Pleroma
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
alias Pleroma.Workers.SearchIndexingWorker
|
||||||
|
|
||||||
|
def run(["create_index"]) do
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
with :ok <- Pleroma.Config.get([Pleroma.Search, :module]).create_index() do
|
||||||
|
IO.puts("Index created")
|
||||||
|
else
|
||||||
|
e -> IO.puts("Could not create index: #{inspect(e)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["drop_index"]) do
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
with :ok <- Pleroma.Config.get([Pleroma.Search, :module]).drop_index() do
|
||||||
|
IO.puts("Index dropped")
|
||||||
|
else
|
||||||
|
e -> IO.puts("Could not drop index: #{inspect(e)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["index" | options]) do
|
||||||
|
{options, [], []} =
|
||||||
|
OptionParser.parse(
|
||||||
|
options,
|
||||||
|
strict: [
|
||||||
|
chunk: :integer,
|
||||||
|
limit: :integer,
|
||||||
|
step: :integer
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
chunk_size = Keyword.get(options, :chunk, 100)
|
||||||
|
limit = Keyword.get(options, :limit, 100_000)
|
||||||
|
per_step = Keyword.get(options, :step, 1000)
|
||||||
|
|
||||||
|
chunks = max(div(limit, per_step), 1)
|
||||||
|
|
||||||
|
1..chunks
|
||||||
|
|> Enum.each(fn step ->
|
||||||
|
q =
|
||||||
|
from(a in Pleroma.Activity,
|
||||||
|
limit: ^per_step,
|
||||||
|
offset: ^per_step * (^step - 1),
|
||||||
|
select: [:id],
|
||||||
|
order_by: [desc: :id]
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, ids} =
|
||||||
|
Pleroma.Repo.transaction(fn ->
|
||||||
|
Pleroma.Repo.stream(q, timeout: :infinity)
|
||||||
|
|> Enum.map(fn a ->
|
||||||
|
a.id
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
IO.puts("Got #{length(ids)} activities, adding to indexer")
|
||||||
|
|
||||||
|
ids
|
||||||
|
|> Enum.chunk_every(chunk_size)
|
||||||
|
|> Enum.each(fn chunk ->
|
||||||
|
IO.puts("Adding #{length(chunk)} activities to indexing queue")
|
||||||
|
|
||||||
|
chunk
|
||||||
|
|> Enum.map(fn id ->
|
||||||
|
SearchIndexingWorker.new(%{"op" => "add_to_index", "activity" => id})
|
||||||
|
end)
|
||||||
|
|> Oban.insert_all()
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
145
lib/mix/tasks/pleroma/search/meilisearch.ex
Normal file
145
lib/mix/tasks/pleroma/search/meilisearch.ex
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
|
||||||
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
import Mix.Pleroma
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
import Pleroma.Search.Meilisearch,
|
||||||
|
only: [meili_post: 2, meili_put: 2, meili_get: 1, meili_delete: 1]
|
||||||
|
|
||||||
|
def run(["index"]) do
|
||||||
|
start_pleroma()
|
||||||
|
Pleroma.HTML.compile_scrubbers()
|
||||||
|
|
||||||
|
meili_version =
|
||||||
|
(
|
||||||
|
{:ok, result} = meili_get("/version")
|
||||||
|
|
||||||
|
result["pkgVersion"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# The ranking rule syntax was changed but nothing about that is mentioned in the changelog
|
||||||
|
if not Version.match?(meili_version, ">= 0.25.0") do
|
||||||
|
raise "Meilisearch <0.24.0 not supported"
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, _} =
|
||||||
|
meili_post(
|
||||||
|
"/indexes/objects/settings/ranking-rules",
|
||||||
|
[
|
||||||
|
"published:desc",
|
||||||
|
"words",
|
||||||
|
"exactness",
|
||||||
|
"proximity",
|
||||||
|
"typo",
|
||||||
|
"attribute",
|
||||||
|
"sort"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, _} =
|
||||||
|
meili_post(
|
||||||
|
"/indexes/objects/settings/searchable-attributes",
|
||||||
|
[
|
||||||
|
"content"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
IO.puts("Created indices. Starting to insert posts.")
|
||||||
|
|
||||||
|
chunk_size = Pleroma.Config.get([Pleroma.Search.Meilisearch, :initial_indexing_chunk_size])
|
||||||
|
|
||||||
|
Pleroma.Repo.transaction(
|
||||||
|
fn ->
|
||||||
|
query =
|
||||||
|
from(Pleroma.Object,
|
||||||
|
# Only index public and unlisted posts which are notes and have some text
|
||||||
|
where:
|
||||||
|
fragment("data->>'type' = 'Note'") and
|
||||||
|
(fragment("data->'to' \\? ?", ^Pleroma.Constants.as_public()) or
|
||||||
|
fragment("data->'cc' \\? ?", ^Pleroma.Constants.as_public())),
|
||||||
|
order_by: [desc: fragment("data->'published'")]
|
||||||
|
)
|
||||||
|
|
||||||
|
count = query |> Pleroma.Repo.aggregate(:count, :data)
|
||||||
|
IO.puts("Entries to index: #{count}")
|
||||||
|
|
||||||
|
Pleroma.Repo.stream(
|
||||||
|
query,
|
||||||
|
timeout: :infinity
|
||||||
|
)
|
||||||
|
|> Stream.map(&Pleroma.Search.Meilisearch.object_to_search_data/1)
|
||||||
|
|> Stream.filter(fn o -> not is_nil(o) end)
|
||||||
|
|> Stream.chunk_every(chunk_size)
|
||||||
|
|> Stream.transform(0, fn objects, acc ->
|
||||||
|
new_acc = acc + Enum.count(objects)
|
||||||
|
|
||||||
|
# Reset to the beginning of the line and rewrite it
|
||||||
|
IO.write("\r")
|
||||||
|
IO.write("Indexed #{new_acc} entries")
|
||||||
|
|
||||||
|
{[objects], new_acc}
|
||||||
|
end)
|
||||||
|
|> Stream.each(fn objects ->
|
||||||
|
result =
|
||||||
|
meili_put(
|
||||||
|
"/indexes/objects/documents",
|
||||||
|
objects
|
||||||
|
)
|
||||||
|
|
||||||
|
with {:ok, res} <- result do
|
||||||
|
if not Map.has_key?(res, "uid") do
|
||||||
|
IO.puts("\nFailed to index: #{inspect(result)}")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
e -> IO.puts("\nFailed to index due to network error: #{inspect(e)}")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Stream.run()
|
||||||
|
end,
|
||||||
|
timeout: :infinity
|
||||||
|
)
|
||||||
|
|
||||||
|
IO.write("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["clear"]) do
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
meili_delete("/indexes/objects/documents")
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["show-keys", master_key]) do
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
endpoint = Pleroma.Config.get([Pleroma.Search.Meilisearch, :url])
|
||||||
|
|
||||||
|
{:ok, result} =
|
||||||
|
Pleroma.HTTP.get(
|
||||||
|
Path.join(endpoint, "/keys"),
|
||||||
|
[{"Authorization", "Bearer #{master_key}"}]
|
||||||
|
)
|
||||||
|
|
||||||
|
decoded = Jason.decode!(result.body)
|
||||||
|
|
||||||
|
if decoded["results"] do
|
||||||
|
Enum.each(decoded["results"], fn %{"description" => desc, "key" => key} ->
|
||||||
|
IO.puts("#{desc}: #{key}")
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
IO.puts("Error fetching the keys, check the master key is correct: #{inspect(decoded)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["stats"]) do
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
{:ok, result} = meili_get("/indexes/objects/stats")
|
||||||
|
IO.puts("Number of entries: #{result["numberOfDocuments"]}")
|
||||||
|
IO.puts("Indexing? #{result["isIndexing"]}")
|
||||||
|
end
|
||||||
|
end
|
25
lib/mix/tasks/pleroma/test_runner.ex
Normal file
25
lib/mix/tasks/pleroma/test_runner.ex
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
defmodule Mix.Tasks.Pleroma.TestRunner do
|
||||||
|
@shortdoc "Retries tests once if they fail"
|
||||||
|
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
def run(args \\ []) do
|
||||||
|
case System.cmd("mix", ["test"] ++ args, into: IO.stream(:stdio, :line)) do
|
||||||
|
{_, 0} ->
|
||||||
|
:ok
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
retry(args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def retry(args) do
|
||||||
|
case System.cmd("mix", ["test", "--failed"] ++ args, into: IO.stream(:stdio, :line)) do
|
||||||
|
{_, 0} ->
|
||||||
|
:ok
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,94 +0,0 @@
|
||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Phoenix.Transports.WebSocket.Raw do
|
|
||||||
import Plug.Conn,
|
|
||||||
only: [
|
|
||||||
fetch_query_params: 1,
|
|
||||||
send_resp: 3
|
|
||||||
]
|
|
||||||
|
|
||||||
alias Phoenix.Socket.Transport
|
|
||||||
|
|
||||||
def default_config do
|
|
||||||
[
|
|
||||||
timeout: 60_000,
|
|
||||||
transport_log: false,
|
|
||||||
cowboy: Phoenix.Endpoint.CowboyWebSocket
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def init(%Plug.Conn{method: "GET"} = conn, {endpoint, handler, transport}) do
|
|
||||||
{_, opts} = handler.__transport__(transport)
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> fetch_query_params
|
|
||||||
|> Transport.transport_log(opts[:transport_log])
|
|
||||||
|> Transport.force_ssl(handler, endpoint, opts)
|
|
||||||
|> Transport.check_origin(handler, endpoint, opts)
|
|
||||||
|
|
||||||
case conn do
|
|
||||||
%{halted: false} = conn ->
|
|
||||||
case handler.connect(%{
|
|
||||||
endpoint: endpoint,
|
|
||||||
transport: transport,
|
|
||||||
options: [serializer: nil],
|
|
||||||
params: conn.params
|
|
||||||
}) do
|
|
||||||
{:ok, socket} ->
|
|
||||||
{:ok, conn, {__MODULE__, {socket, opts}}}
|
|
||||||
|
|
||||||
:error ->
|
|
||||||
send_resp(conn, :forbidden, "")
|
|
||||||
{:error, conn}
|
|
||||||
end
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:error, conn}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def init(conn, _) do
|
|
||||||
send_resp(conn, :bad_request, "")
|
|
||||||
{:error, conn}
|
|
||||||
end
|
|
||||||
|
|
||||||
def ws_init({socket, config}) do
|
|
||||||
Process.flag(:trap_exit, true)
|
|
||||||
{:ok, %{socket: socket}, config[:timeout]}
|
|
||||||
end
|
|
||||||
|
|
||||||
def ws_handle(op, data, state) do
|
|
||||||
state.socket.handler
|
|
||||||
|> apply(:handle, [op, data, state])
|
|
||||||
|> case do
|
|
||||||
{op, data} ->
|
|
||||||
{:reply, {op, data}, state}
|
|
||||||
|
|
||||||
{op, data, state} ->
|
|
||||||
{:reply, {op, data}, state}
|
|
||||||
|
|
||||||
%{} = state ->
|
|
||||||
{:ok, state}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:ok, state}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def ws_info({_, _} = tuple, state) do
|
|
||||||
{:reply, tuple, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def ws_info(_tuple, state), do: {:ok, state}
|
|
||||||
|
|
||||||
def ws_close(state) do
|
|
||||||
ws_handle(:closed, :normal, state)
|
|
||||||
end
|
|
||||||
|
|
||||||
def ws_terminate(reason, state) do
|
|
||||||
ws_handle(:closed, reason, state)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -368,7 +368,7 @@ defmodule Pleroma.Activity do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defdelegate search(user, query, options \\ []), to: Pleroma.Activity.Search
|
defdelegate search(user, query, options \\ []), to: Pleroma.Search.DatabaseSearch
|
||||||
|
|
||||||
def direct_conversation_id(activity, for_user) do
|
def direct_conversation_id(activity, for_user) do
|
||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
|
|
|
@ -28,7 +28,7 @@ defmodule Pleroma.Activity.HTML do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp add_cache_key_for(activity_id, additional_key) do
|
def add_cache_key_for(activity_id, additional_key) do
|
||||||
current = get_cache_keys_for(activity_id)
|
current = get_cache_keys_for(activity_id)
|
||||||
|
|
||||||
unless additional_key in current do
|
unless additional_key in current do
|
||||||
|
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Activity.Queries do
|
||||||
|
|
||||||
import Ecto.Query, only: [from: 2, where: 3]
|
import Ecto.Query, only: [from: 2, where: 3]
|
||||||
|
|
||||||
@type query :: Ecto.Queryable.t() | Activity.t()
|
@type query :: Ecto.Queryable.t() | Pleroma.Activity.t()
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
|
@ -23,19 +23,21 @@ defmodule Pleroma.Announcement do
|
||||||
timestamps(type: :utc_datetime)
|
timestamps(type: :utc_datetime)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change(struct, params \\ %{}) do
|
@doc "Generates changeset for %Pleroma.Announcement{}"
|
||||||
struct
|
@spec changeset(%__MODULE__{}, map()) :: %Ecto.Changeset{}
|
||||||
|> cast(validate_params(struct, params), [:data, :starts_at, :ends_at, :rendered])
|
def changeset(announcement \\ %__MODULE__{}, params \\ %{data: %{}}) do
|
||||||
|
announcement
|
||||||
|
|> cast(validate_params(announcement, params), [:data, :starts_at, :ends_at, :rendered])
|
||||||
|> validate_required([:data])
|
|> validate_required([:data])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp validate_params(struct, params) do
|
defp validate_params(announcement, params) do
|
||||||
base_data =
|
base_data =
|
||||||
%{
|
%{
|
||||||
"content" => "",
|
"content" => "",
|
||||||
"all_day" => false
|
"all_day" => false
|
||||||
}
|
}
|
||||||
|> Map.merge((struct && struct.data) || %{})
|
|> Map.merge((announcement && announcement.data) || %{})
|
||||||
|
|
||||||
merged_data =
|
merged_data =
|
||||||
Map.merge(base_data, params.data)
|
Map.merge(base_data, params.data)
|
||||||
|
@ -61,13 +63,13 @@ defmodule Pleroma.Announcement do
|
||||||
end
|
end
|
||||||
|
|
||||||
def add(params) do
|
def add(params) do
|
||||||
changeset = change(%__MODULE__{}, params)
|
changeset = changeset(%__MODULE__{}, params)
|
||||||
|
|
||||||
Repo.insert(changeset)
|
Repo.insert(changeset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(announcement, params) do
|
def update(announcement, params) do
|
||||||
changeset = change(announcement, params)
|
changeset = changeset(announcement, params)
|
||||||
|
|
||||||
Repo.update(changeset)
|
Repo.update(changeset)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,6 @@ defmodule Pleroma.Application do
|
||||||
@name Mix.Project.config()[:name]
|
@name Mix.Project.config()[:name]
|
||||||
@version Mix.Project.config()[:version]
|
@version Mix.Project.config()[:version]
|
||||||
@repository Mix.Project.config()[:source_url]
|
@repository Mix.Project.config()[:source_url]
|
||||||
@mix_env Mix.env()
|
|
||||||
|
|
||||||
def name, do: @name
|
def name, do: @name
|
||||||
def version, do: @version
|
def version, do: @version
|
||||||
|
@ -52,9 +51,12 @@ defmodule Pleroma.Application do
|
||||||
Pleroma.HTML.compile_scrubbers()
|
Pleroma.HTML.compile_scrubbers()
|
||||||
Pleroma.Config.Oban.warn()
|
Pleroma.Config.Oban.warn()
|
||||||
Config.DeprecationWarnings.warn()
|
Config.DeprecationWarnings.warn()
|
||||||
|
|
||||||
|
if Config.get([Pleroma.Web.Plugs.HTTPSecurityPlug, :enable], true) do
|
||||||
Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
||||||
|
end
|
||||||
|
|
||||||
Pleroma.ApplicationRequirements.verify!()
|
Pleroma.ApplicationRequirements.verify!()
|
||||||
setup_instrumenters()
|
|
||||||
load_custom_modules()
|
load_custom_modules()
|
||||||
Pleroma.Docs.JSON.compile()
|
Pleroma.Docs.JSON.compile()
|
||||||
limiters_setup()
|
limiters_setup()
|
||||||
|
@ -91,6 +93,7 @@ defmodule Pleroma.Application do
|
||||||
# Define workers and child supervisors to be supervised
|
# Define workers and child supervisors to be supervised
|
||||||
children =
|
children =
|
||||||
[
|
[
|
||||||
|
Pleroma.PromEx,
|
||||||
Pleroma.Repo,
|
Pleroma.Repo,
|
||||||
Config.TransferTask,
|
Config.TransferTask,
|
||||||
Pleroma.Emoji,
|
Pleroma.Emoji,
|
||||||
|
@ -98,7 +101,7 @@ defmodule Pleroma.Application do
|
||||||
{Task.Supervisor, name: Pleroma.TaskSupervisor}
|
{Task.Supervisor, name: Pleroma.TaskSupervisor}
|
||||||
] ++
|
] ++
|
||||||
cachex_children() ++
|
cachex_children() ++
|
||||||
http_children(adapter, @mix_env) ++
|
http_children(adapter) ++
|
||||||
[
|
[
|
||||||
Pleroma.Stats,
|
Pleroma.Stats,
|
||||||
Pleroma.JobQueueMonitor,
|
Pleroma.JobQueueMonitor,
|
||||||
|
@ -106,46 +109,22 @@ defmodule Pleroma.Application do
|
||||||
{Oban, Config.get(Oban)},
|
{Oban, Config.get(Oban)},
|
||||||
Pleroma.Web.Endpoint
|
Pleroma.Web.Endpoint
|
||||||
] ++
|
] ++
|
||||||
task_children(@mix_env) ++
|
task_children() ++
|
||||||
dont_run_in_test(@mix_env) ++
|
streamer_registry() ++
|
||||||
|
background_migrators() ++
|
||||||
shout_child(shout_enabled?()) ++
|
shout_child(shout_enabled?()) ++
|
||||||
[Pleroma.Gopher.Server]
|
[Pleroma.Gopher.Server] ++
|
||||||
|
[Pleroma.Search.Healthcheck]
|
||||||
|
|
||||||
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
|
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
|
||||||
# for other strategies and supported options
|
# for other strategies and supported options
|
||||||
# If we have a lot of caches, default max_restarts can cause test
|
# If we have a lot of caches, default max_restarts can cause test
|
||||||
# resets to fail.
|
# resets to fail.
|
||||||
# Go for the default 3 unless we're in test
|
# Go for the default 3 unless we're in test
|
||||||
max_restarts =
|
max_restarts = Application.get_env(:pleroma, __MODULE__)[:max_restarts]
|
||||||
if @mix_env == :test do
|
|
||||||
100
|
|
||||||
else
|
|
||||||
3
|
|
||||||
end
|
|
||||||
|
|
||||||
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
||||||
result = Supervisor.start_link(children, opts)
|
Supervisor.start_link(children, opts)
|
||||||
|
|
||||||
set_postgres_server_version()
|
|
||||||
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
defp set_postgres_server_version do
|
|
||||||
version =
|
|
||||||
with %{rows: [[version]]} <- Ecto.Adapters.SQL.query!(Pleroma.Repo, "show server_version"),
|
|
||||||
{num, _} <- Float.parse(version) do
|
|
||||||
num
|
|
||||||
else
|
|
||||||
e ->
|
|
||||||
Logger.warn(
|
|
||||||
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6"
|
|
||||||
)
|
|
||||||
|
|
||||||
9.6
|
|
||||||
end
|
|
||||||
|
|
||||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, version)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_custom_modules do
|
def load_custom_modules do
|
||||||
|
@ -159,7 +138,7 @@ defmodule Pleroma.Application do
|
||||||
raise "Invalid custom modules"
|
raise "Invalid custom modules"
|
||||||
|
|
||||||
{:ok, modules, _warnings} ->
|
{:ok, modules, _warnings} ->
|
||||||
if @mix_env != :test do
|
if Application.get_env(:pleroma, __MODULE__)[:load_custom_modules] do
|
||||||
Enum.each(modules, fn mod ->
|
Enum.each(modules, fn mod ->
|
||||||
Logger.info("Custom module loaded: #{inspect(mod)}")
|
Logger.info("Custom module loaded: #{inspect(mod)}")
|
||||||
end)
|
end)
|
||||||
|
@ -170,29 +149,6 @@ defmodule Pleroma.Application do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp setup_instrumenters do
|
|
||||||
require Prometheus.Registry
|
|
||||||
|
|
||||||
if Application.get_env(:prometheus, Pleroma.Repo.Instrumenter) do
|
|
||||||
:ok =
|
|
||||||
:telemetry.attach(
|
|
||||||
"prometheus-ecto",
|
|
||||||
[:pleroma, :repo, :query],
|
|
||||||
&Pleroma.Repo.Instrumenter.handle_event/4,
|
|
||||||
%{}
|
|
||||||
)
|
|
||||||
|
|
||||||
Pleroma.Repo.Instrumenter.setup()
|
|
||||||
end
|
|
||||||
|
|
||||||
Pleroma.Web.Endpoint.MetricsExporter.setup()
|
|
||||||
Pleroma.Web.Endpoint.PipelineInstrumenter.setup()
|
|
||||||
|
|
||||||
# Note: disabled until prometheus-phx is integrated into prometheus-phoenix:
|
|
||||||
# Pleroma.Web.Endpoint.Instrumenter.setup()
|
|
||||||
PrometheusPhx.setup()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp cachex_children do
|
defp cachex_children do
|
||||||
[
|
[
|
||||||
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
|
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
|
||||||
|
@ -205,6 +161,7 @@ defmodule Pleroma.Application do
|
||||||
build_cachex("web_resp", limit: 2500),
|
build_cachex("web_resp", limit: 2500),
|
||||||
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
|
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
|
||||||
build_cachex("failed_proxy_url", limit: 2500),
|
build_cachex("failed_proxy_url", limit: 2500),
|
||||||
|
build_cachex("failed_media_helper_url", default_ttl: :timer.minutes(15), limit: 2_500),
|
||||||
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
|
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
|
||||||
build_cachex("chat_message_id_idempotency_key",
|
build_cachex("chat_message_id_idempotency_key",
|
||||||
expiration: chat_message_id_idempotency_key_expiration(),
|
expiration: chat_message_id_idempotency_key_expiration(),
|
||||||
|
@ -237,9 +194,8 @@ defmodule Pleroma.Application do
|
||||||
|
|
||||||
defp shout_enabled?, do: Config.get([:shout, :enabled])
|
defp shout_enabled?, do: Config.get([:shout, :enabled])
|
||||||
|
|
||||||
defp dont_run_in_test(env) when env in [:test, :benchmark], do: []
|
defp streamer_registry do
|
||||||
|
if Application.get_env(:pleroma, __MODULE__)[:streamer_registry] do
|
||||||
defp dont_run_in_test(_) do
|
|
||||||
[
|
[
|
||||||
{Registry,
|
{Registry,
|
||||||
[
|
[
|
||||||
|
@ -247,14 +203,21 @@ defmodule Pleroma.Application do
|
||||||
keys: :duplicate,
|
keys: :duplicate,
|
||||||
partitions: System.schedulers_online()
|
partitions: System.schedulers_online()
|
||||||
]}
|
]}
|
||||||
] ++ background_migrators()
|
]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp background_migrators do
|
defp background_migrators do
|
||||||
|
if Application.get_env(:pleroma, __MODULE__)[:background_migrators] do
|
||||||
[
|
[
|
||||||
Pleroma.Migrators.HashtagsTableMigrator,
|
Pleroma.Migrators.HashtagsTableMigrator,
|
||||||
Pleroma.Migrators.ContextObjectsDeletionMigrator
|
Pleroma.Migrators.ContextObjectsDeletionMigrator
|
||||||
]
|
]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp shout_child(true) do
|
defp shout_child(true) do
|
||||||
|
@ -266,37 +229,43 @@ defmodule Pleroma.Application do
|
||||||
|
|
||||||
defp shout_child(_), do: []
|
defp shout_child(_), do: []
|
||||||
|
|
||||||
defp task_children(:test) do
|
defp task_children do
|
||||||
[
|
children = [
|
||||||
%{
|
%{
|
||||||
id: :web_push_init,
|
id: :web_push_init,
|
||||||
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
|
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
|
||||||
restart: :temporary
|
restart: :temporary
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
end
|
|
||||||
|
|
||||||
defp task_children(_) do
|
if Application.get_env(:pleroma, __MODULE__)[:internal_fetch] do
|
||||||
|
children ++
|
||||||
[
|
[
|
||||||
%{
|
|
||||||
id: :web_push_init,
|
|
||||||
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
|
|
||||||
restart: :temporary
|
|
||||||
},
|
|
||||||
%{
|
%{
|
||||||
id: :internal_fetch_init,
|
id: :internal_fetch_init,
|
||||||
start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
|
start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
|
||||||
restart: :temporary
|
restart: :temporary
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
else
|
||||||
|
children
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# start hackney and gun pools in tests
|
# start hackney and gun pools in tests
|
||||||
defp http_children(_, :test) do
|
defp http_children(adapter) do
|
||||||
http_children(Tesla.Adapter.Hackney, nil) ++ http_children(Tesla.Adapter.Gun, nil)
|
if Application.get_env(:pleroma, __MODULE__)[:test_http_pools] do
|
||||||
|
http_children_hackney() ++ http_children_gun()
|
||||||
|
else
|
||||||
|
cond do
|
||||||
|
match?(Tesla.Adapter.Hackney, adapter) -> http_children_hackney()
|
||||||
|
match?(Tesla.Adapter.Gun, adapter) -> http_children_gun()
|
||||||
|
true -> []
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp http_children(Tesla.Adapter.Hackney, _) do
|
defp http_children_hackney do
|
||||||
pools = [:federation, :media]
|
pools = [:federation, :media]
|
||||||
|
|
||||||
pools =
|
pools =
|
||||||
|
@ -312,18 +281,18 @@ defmodule Pleroma.Application do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp http_children(Tesla.Adapter.Gun, _) do
|
defp http_children_gun do
|
||||||
Pleroma.Gun.ConnectionPool.children() ++
|
Pleroma.Gun.ConnectionPool.children() ++
|
||||||
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
|
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp http_children(_, _), do: []
|
|
||||||
|
|
||||||
@spec limiters_setup() :: :ok
|
@spec limiters_setup() :: :ok
|
||||||
def limiters_setup do
|
def limiters_setup do
|
||||||
config = Config.get(ConcurrentLimiter, [])
|
config = Config.get(ConcurrentLimiter, [])
|
||||||
|
|
||||||
[Pleroma.Web.RichMedia.Helpers, Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
|
[
|
||||||
|
Pleroma.Search
|
||||||
|
]
|
||||||
|> Enum.each(fn module ->
|
|> Enum.each(fn module ->
|
||||||
mod_config = Keyword.get(config, module, [])
|
mod_config = Keyword.get(config, module, [])
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
The module represents the collection of validations to runs before start server.
|
The module represents the collection of validations to runs before start server.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
defmodule VerifyError, do: defexception([:message])
|
defmodule VerifyError do
|
||||||
|
defexception([:message])
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
end
|
||||||
|
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
alias Pleroma.Helpers.MediaHelper
|
alias Pleroma.Helpers.MediaHelper
|
||||||
|
@ -25,6 +28,7 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
|> check_welcome_message_config!()
|
|> check_welcome_message_config!()
|
||||||
|> check_rum!()
|
|> check_rum!()
|
||||||
|> check_repo_pool_size!()
|
|> check_repo_pool_size!()
|
||||||
|
|> check_mrfs()
|
||||||
|> handle_result()
|
|> handle_result()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
defp check_welcome_message_config!(:ok) do
|
defp check_welcome_message_config!(:ok) do
|
||||||
if Pleroma.Config.get([:welcome, :email, :enabled], false) and
|
if Pleroma.Config.get([:welcome, :email, :enabled], false) and
|
||||||
not Pleroma.Emails.Mailer.enabled?() do
|
not Pleroma.Emails.Mailer.enabled?() do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
To send welcome emails, you need to enable the mailer.
|
To send welcome emails, you need to enable the mailer.
|
||||||
Welcome emails will NOT be sent with the current config.
|
Welcome emails will NOT be sent with the current config.
|
||||||
|
|
||||||
|
@ -53,7 +57,7 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
def check_confirmation_accounts!(:ok) do
|
def check_confirmation_accounts!(:ok) do
|
||||||
if Pleroma.Config.get([:instance, :account_activation_required]) &&
|
if Pleroma.Config.get([:instance, :account_activation_required]) &&
|
||||||
not Pleroma.Emails.Mailer.enabled?() do
|
not Pleroma.Emails.Mailer.enabled?() do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
Account activation is required, but the mailer is disabled.
|
Account activation is required, but the mailer is disabled.
|
||||||
Users will NOT be able to confirm their accounts with this config.
|
Users will NOT be able to confirm their accounts with this config.
|
||||||
Either disable account activation or enable the mailer.
|
Either disable account activation or enable the mailer.
|
||||||
|
@ -168,8 +172,6 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
check_filter(Pleroma.Upload.Filter.Exiftool.ReadDescription, "exiftool"),
|
check_filter(Pleroma.Upload.Filter.Exiftool.ReadDescription, "exiftool"),
|
||||||
check_filter(Pleroma.Upload.Filter.Mogrify, "mogrify"),
|
check_filter(Pleroma.Upload.Filter.Mogrify, "mogrify"),
|
||||||
check_filter(Pleroma.Upload.Filter.Mogrifun, "mogrify"),
|
check_filter(Pleroma.Upload.Filter.Mogrifun, "mogrify"),
|
||||||
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "mogrify"),
|
|
||||||
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "convert"),
|
|
||||||
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "ffprobe")
|
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "ffprobe")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -195,8 +197,6 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp check_system_commands!(result), do: result
|
|
||||||
|
|
||||||
defp check_repo_pool_size!(:ok) do
|
defp check_repo_pool_size!(:ok) do
|
||||||
if Pleroma.Config.get([Pleroma.Repo, :pool_size], 10) != 10 and
|
if Pleroma.Config.get([Pleroma.Repo, :pool_size], 10) != 10 and
|
||||||
not Pleroma.Config.get([:dangerzone, :override_repo_pool_size], false) do
|
not Pleroma.Config.get([:dangerzone, :override_repo_pool_size], false) do
|
||||||
|
@ -235,4 +235,24 @@ defmodule Pleroma.ApplicationRequirements do
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp check_mrfs(:ok) do
|
||||||
|
mrfs = Config.get!([:mrf, :policies])
|
||||||
|
|
||||||
|
missing_mrfs =
|
||||||
|
Enum.reduce(mrfs, [], fn x, acc ->
|
||||||
|
case Code.ensure_compiled(x) do
|
||||||
|
{:module, _} -> acc
|
||||||
|
{:error, _} -> acc ++ [x]
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if Enum.empty?(missing_mrfs) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, "The following MRF modules are configured but missing: #{inspect(missing_mrfs)}"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_mrfs(result), do: result
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Bookmark do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Bookmark
|
alias Pleroma.Bookmark
|
||||||
|
alias Pleroma.BookmarkFolder
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
@ -18,33 +19,46 @@ defmodule Pleroma.Bookmark do
|
||||||
schema "bookmarks" do
|
schema "bookmarks" do
|
||||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType)
|
belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType)
|
||||||
|
belongs_to(:folder, BookmarkFolder, type: FlakeId.Ecto.CompatType)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec create(FlakeId.Ecto.CompatType.t(), FlakeId.Ecto.CompatType.t()) ::
|
@spec create(Ecto.UUID.t(), Ecto.UUID.t()) ::
|
||||||
{:ok, Bookmark.t()} | {:error, Changeset.t()}
|
{:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def create(user_id, activity_id) do
|
def create(user_id, activity_id, folder_id \\ nil) do
|
||||||
attrs = %{
|
attrs = %{
|
||||||
user_id: user_id,
|
user_id: user_id,
|
||||||
activity_id: activity_id
|
activity_id: activity_id,
|
||||||
|
folder_id: folder_id
|
||||||
}
|
}
|
||||||
|
|
||||||
%Bookmark{}
|
%Bookmark{}
|
||||||
|> cast(attrs, [:user_id, :activity_id])
|
|> cast(attrs, [:user_id, :activity_id, :folder_id])
|
||||||
|> validate_required([:user_id, :activity_id])
|
|> validate_required([:user_id, :activity_id])
|
||||||
|> unique_constraint(:activity_id, name: :bookmarks_user_id_activity_id_index)
|
|> unique_constraint(:activity_id, name: :bookmarks_user_id_activity_id_index)
|
||||||
|> Repo.insert()
|
|> Repo.insert(
|
||||||
|
on_conflict: [set: [folder_id: folder_id]],
|
||||||
|
conflict_target: [:user_id, :activity_id]
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec for_user_query(FlakeId.Ecto.CompatType.t()) :: Ecto.Query.t()
|
@spec for_user_query(Ecto.UUID.t()) :: Ecto.Query.t()
|
||||||
def for_user_query(user_id) do
|
def for_user_query(user_id, folder_id \\ nil) do
|
||||||
Bookmark
|
Bookmark
|
||||||
|> where(user_id: ^user_id)
|
|> where(user_id: ^user_id)
|
||||||
|
|> maybe_filter_by_folder(folder_id)
|
||||||
|> join(:inner, [b], activity in assoc(b, :activity))
|
|> join(:inner, [b], activity in assoc(b, :activity))
|
||||||
|> preload([b, a], activity: a)
|
|> preload([b, a], activity: a)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp maybe_filter_by_folder(query, nil), do: query
|
||||||
|
|
||||||
|
defp maybe_filter_by_folder(query, folder_id) do
|
||||||
|
query
|
||||||
|
|> where(folder_id: ^folder_id)
|
||||||
|
end
|
||||||
|
|
||||||
def get(user_id, activity_id) do
|
def get(user_id, activity_id) do
|
||||||
Bookmark
|
Bookmark
|
||||||
|> where(user_id: ^user_id)
|
|> where(user_id: ^user_id)
|
||||||
|
@ -52,8 +66,8 @@ defmodule Pleroma.Bookmark do
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec destroy(FlakeId.Ecto.CompatType.t(), FlakeId.Ecto.CompatType.t()) ::
|
@spec destroy(Ecto.UUID.t(), Ecto.UUID.t()) ::
|
||||||
{:ok, Bookmark.t()} | {:error, Changeset.t()}
|
{:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def destroy(user_id, activity_id) do
|
def destroy(user_id, activity_id) do
|
||||||
from(b in Bookmark,
|
from(b in Bookmark,
|
||||||
where: b.user_id == ^user_id,
|
where: b.user_id == ^user_id,
|
||||||
|
@ -62,4 +76,11 @@ defmodule Pleroma.Bookmark do
|
||||||
|> Repo.one()
|
|> Repo.one()
|
||||||
|> Repo.delete()
|
|> Repo.delete()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_folder(bookmark, folder_id) do
|
||||||
|
bookmark
|
||||||
|
|> cast(%{folder_id: folder_id}, [:folder_id])
|
||||||
|
|> validate_required([:folder_id])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
115
lib/pleroma/bookmark_folder.ex
Normal file
115
lib/pleroma/bookmark_folder.ex
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.BookmarkFolder do
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
alias Pleroma.BookmarkFolder
|
||||||
|
alias Pleroma.Emoji
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
||||||
|
|
||||||
|
schema "bookmark_folders" do
|
||||||
|
field(:name, :string)
|
||||||
|
field(:emoji, :string)
|
||||||
|
|
||||||
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_by_id(id), do: Repo.get_by(BookmarkFolder, id: id)
|
||||||
|
|
||||||
|
def create(user_id, name, emoji \\ nil) do
|
||||||
|
%BookmarkFolder{}
|
||||||
|
|> cast(
|
||||||
|
%{
|
||||||
|
user_id: user_id,
|
||||||
|
name: name,
|
||||||
|
emoji: emoji
|
||||||
|
},
|
||||||
|
[:user_id, :name, :emoji]
|
||||||
|
)
|
||||||
|
|> validate_required([:user_id, :name])
|
||||||
|
|> fix_emoji()
|
||||||
|
|> validate_emoji()
|
||||||
|
|> unique_constraint([:user_id, :name])
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(folder_id, name, emoji \\ nil) do
|
||||||
|
get_by_id(folder_id)
|
||||||
|
|> cast(
|
||||||
|
%{
|
||||||
|
name: name,
|
||||||
|
emoji: emoji
|
||||||
|
},
|
||||||
|
[:name, :emoji]
|
||||||
|
)
|
||||||
|
|> fix_emoji()
|
||||||
|
|> validate_emoji()
|
||||||
|
|> unique_constraint([:user_id, :name])
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fix_emoji(changeset) do
|
||||||
|
with {:emoji_field, emoji} when is_binary(emoji) <-
|
||||||
|
{:emoji_field, get_field(changeset, :emoji)},
|
||||||
|
{:fixed_emoji, emoji} <-
|
||||||
|
{:fixed_emoji,
|
||||||
|
emoji
|
||||||
|
|> Pleroma.Emoji.fully_qualify_emoji()
|
||||||
|
|> Pleroma.Emoji.maybe_quote()} do
|
||||||
|
put_change(changeset, :emoji, emoji)
|
||||||
|
else
|
||||||
|
{:emoji_field, _} -> changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp validate_emoji(changeset) do
|
||||||
|
validate_change(changeset, :emoji, fn
|
||||||
|
:emoji, nil ->
|
||||||
|
[]
|
||||||
|
|
||||||
|
:emoji, emoji ->
|
||||||
|
if Emoji.unicode?(emoji) or valid_local_custom_emoji?(emoji) do
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
[emoji: "Invalid emoji"]
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp valid_local_custom_emoji?(emoji) do
|
||||||
|
with %{file: _path} <- Emoji.get(emoji) do
|
||||||
|
true
|
||||||
|
else
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(folder_id) do
|
||||||
|
BookmarkFolder
|
||||||
|
|> Repo.get_by(id: folder_id)
|
||||||
|
|> Repo.delete()
|
||||||
|
end
|
||||||
|
|
||||||
|
def for_user(user_id) do
|
||||||
|
BookmarkFolder
|
||||||
|
|> where(user_id: ^user_id)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
|
def belongs_to_user?(folder_id, user_id) do
|
||||||
|
BookmarkFolder
|
||||||
|
|> where(id: ^folder_id, user_id: ^user_id)
|
||||||
|
|> Repo.exists?()
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,10 +8,13 @@ defmodule Pleroma.Caching do
|
||||||
@callback put(Cachex.cache(), any(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
@callback put(Cachex.cache(), any(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
||||||
@callback put(Cachex.cache(), any(), any()) :: {Cachex.status(), boolean()}
|
@callback put(Cachex.cache(), any(), any()) :: {Cachex.status(), boolean()}
|
||||||
@callback fetch!(Cachex.cache(), any(), function() | nil) :: any()
|
@callback fetch!(Cachex.cache(), any(), function() | nil) :: any()
|
||||||
|
@callback fetch(Cachex.cache(), any(), function() | nil) ::
|
||||||
|
{atom(), any()} | {atom(), any(), any()}
|
||||||
# @callback del(Cachex.cache(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
# @callback del(Cachex.cache(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
||||||
@callback del(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
@callback del(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
||||||
@callback stream!(Cachex.cache(), any()) :: Enumerable.t()
|
@callback stream!(Cachex.cache(), any()) :: Enumerable.t()
|
||||||
@callback expire_at(Cachex.cache(), binary(), number()) :: {Cachex.status(), boolean()}
|
@callback expire_at(Cachex.cache(), binary(), number()) :: {Cachex.status(), boolean()}
|
||||||
|
@callback expire(Cachex.cache(), binary(), number()) :: {Cachex.status(), boolean()}
|
||||||
@callback exists?(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
@callback exists?(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
||||||
@callback execute!(Cachex.cache(), function()) :: any()
|
@callback execute!(Cachex.cache(), function()) :: any()
|
||||||
@callback get_and_update(Cachex.cache(), any(), function()) ::
|
@callback get_and_update(Cachex.cache(), any(), function()) ::
|
||||||
|
|
|
@ -29,7 +29,7 @@ defmodule Pleroma.Captcha.Kocaptcha do
|
||||||
|
|
||||||
@impl Service
|
@impl Service
|
||||||
def validate(_token, captcha, answer_data) do
|
def validate(_token, captcha, answer_data) do
|
||||||
# Here the token is unsed, because the unencrypted captcha answer is just passed to method
|
# Here the token is unused, because the unencrypted captcha answer is just passed to method
|
||||||
if not is_nil(captcha) and
|
if not is_nil(captcha) and
|
||||||
:crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data),
|
:crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data),
|
||||||
do: :ok,
|
do: :ok,
|
||||||
|
|
|
@ -42,7 +42,7 @@ defmodule Pleroma.Chat do
|
||||||
|> unique_constraint(:user_id, name: :chats_user_id_recipient_index)
|
|> unique_constraint(:user_id, name: :chats_user_id_recipient_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_by_user_and_id(User.t(), FlakeId.Ecto.CompatType.t()) ::
|
@spec get_by_user_and_id(User.t(), Ecto.UUID.t()) ::
|
||||||
{:ok, t()} | {:error, :not_found}
|
{:ok, t()} | {:error, :not_found}
|
||||||
def get_by_user_and_id(%User{id: user_id}, id) do
|
def get_by_user_and_id(%User{id: user_id}, id) do
|
||||||
from(c in __MODULE__,
|
from(c in __MODULE__,
|
||||||
|
@ -52,17 +52,17 @@ defmodule Pleroma.Chat do
|
||||||
|> Repo.find_resource()
|
|> Repo.find_resource()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_by_id(FlakeId.Ecto.CompatType.t()) :: t() | nil
|
@spec get_by_id(Ecto.UUID.t()) :: t() | nil
|
||||||
def get_by_id(id) do
|
def get_by_id(id) do
|
||||||
Repo.get(__MODULE__, id)
|
Repo.get(__MODULE__, id)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get(FlakeId.Ecto.CompatType.t(), String.t()) :: t() | nil
|
@spec get(Ecto.UUID.t(), String.t()) :: t() | nil
|
||||||
def get(user_id, recipient) do
|
def get(user_id, recipient) do
|
||||||
Repo.get_by(__MODULE__, user_id: user_id, recipient: recipient)
|
Repo.get_by(__MODULE__, user_id: user_id, recipient: recipient)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_or_create(FlakeId.Ecto.CompatType.t(), String.t()) ::
|
@spec get_or_create(Ecto.UUID.t(), String.t()) ::
|
||||||
{:ok, t()} | {:error, Ecto.Changeset.t()}
|
{:ok, t()} | {:error, Ecto.Changeset.t()}
|
||||||
def get_or_create(user_id, recipient) do
|
def get_or_create(user_id, recipient) do
|
||||||
%__MODULE__{}
|
%__MODULE__{}
|
||||||
|
@ -75,7 +75,7 @@ defmodule Pleroma.Chat do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec bump_or_create(FlakeId.Ecto.CompatType.t(), String.t()) ::
|
@spec bump_or_create(Ecto.UUID.t(), String.t()) ::
|
||||||
{:ok, t()} | {:error, Ecto.Changeset.t()}
|
{:ok, t()} | {:error, Ecto.Changeset.t()}
|
||||||
def bump_or_create(user_id, recipient) do
|
def bump_or_create(user_id, recipient) do
|
||||||
%__MODULE__{}
|
%__MODULE__{}
|
||||||
|
@ -87,7 +87,7 @@ defmodule Pleroma.Chat do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec for_user_query(FlakeId.Ecto.CompatType.t()) :: Ecto.Query.t()
|
@spec for_user_query(Ecto.UUID.t()) :: Ecto.Query.t()
|
||||||
def for_user_query(user_id) do
|
def for_user_query(user_id) do
|
||||||
from(c in Chat,
|
from(c in Chat,
|
||||||
where: c.user_id == ^user_id,
|
where: c.user_id == ^user_id,
|
||||||
|
|
|
@ -24,7 +24,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
filters = Config.get([Pleroma.Upload]) |> Keyword.get(:filters, [])
|
filters = Config.get([Pleroma.Upload]) |> Keyword.get(:filters, [])
|
||||||
|
|
||||||
if Pleroma.Upload.Filter.Exiftool in filters do
|
if Pleroma.Upload.Filter.Exiftool in filters do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later:
|
Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later:
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
|> Enum.any?(fn {_, v} -> Enum.any?(v, &is_binary/1) end)
|
|> Enum.any?(fn {_, v} -> Enum.any?(v, &is_binary/1) end)
|
||||||
|
|
||||||
if has_strings do
|
if has_strings do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION 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:
|
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:
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
has_strings = Config.get([:instance, :quarantined_instances]) |> Enum.any?(&is_binary/1)
|
has_strings = Config.get([:instance, :quarantined_instances]) |> Enum.any?(&is_binary/1)
|
||||||
|
|
||||||
if has_strings do
|
if has_strings do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION 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:
|
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:
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
has_strings = Config.get([:mrf, :transparency_exclusions]) |> Enum.any?(&is_binary/1)
|
has_strings = Config.get([:mrf, :transparency_exclusions]) |> Enum.any?(&is_binary/1)
|
||||||
|
|
||||||
if has_strings do
|
if has_strings do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION 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:
|
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:
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
|
|
||||||
```
|
```
|
||||||
config :pleroma, :mrf,
|
config :pleroma, :mrf,
|
||||||
transparency_exclusions: [{"instance.tld", "Reason to exlude transparency"}]
|
transparency_exclusions: [{"instance.tld", "Reason to exclude transparency"}]
|
||||||
```
|
```
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
|
|
||||||
def check_hellthread_threshold do
|
def check_hellthread_threshold do
|
||||||
if Config.get([:mrf_hellthread, :threshold]) do
|
if Config.get([:mrf_hellthread, :threshold]) do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
|
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
|
||||||
""")
|
""")
|
||||||
|
@ -213,7 +213,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
check_gun_pool_options(),
|
check_gun_pool_options(),
|
||||||
check_activity_expiration_config(),
|
check_activity_expiration_config(),
|
||||||
check_remote_ip_plug_name(),
|
check_remote_ip_plug_name(),
|
||||||
check_uploders_s3_public_endpoint(),
|
check_uploaders_s3_public_endpoint(),
|
||||||
check_old_chat_shoutbox(),
|
check_old_chat_shoutbox(),
|
||||||
check_quarantined_instances_tuples(),
|
check_quarantined_instances_tuples(),
|
||||||
check_transparency_exclusions_tuples(),
|
check_transparency_exclusions_tuples(),
|
||||||
|
@ -256,7 +256,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
move_namespace_and_warn(@mrf_config_map, warning_preface)
|
move_namespace_and_warn(@mrf_config_map, warning_preface)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec move_namespace_and_warn([config_map()], String.t()) :: :ok | nil
|
@spec move_namespace_and_warn([config_map()], String.t()) :: :ok | :error
|
||||||
def move_namespace_and_warn(config_map, warning_preface) do
|
def move_namespace_and_warn(config_map, warning_preface) do
|
||||||
warning =
|
warning =
|
||||||
Enum.reduce(config_map, "", fn
|
Enum.reduce(config_map, "", fn
|
||||||
|
@ -274,17 +274,17 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
if warning == "" do
|
if warning == "" do
|
||||||
:ok
|
:ok
|
||||||
else
|
else
|
||||||
Logger.warn(warning_preface <> warning)
|
Logger.warning(warning_preface <> warning)
|
||||||
:error
|
:error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec check_media_proxy_whitelist_config() :: :ok | nil
|
@spec check_media_proxy_whitelist_config() :: :ok | :error
|
||||||
def check_media_proxy_whitelist_config do
|
def check_media_proxy_whitelist_config do
|
||||||
whitelist = Config.get([:media_proxy, :whitelist])
|
whitelist = Config.get([:media_proxy, :whitelist])
|
||||||
|
|
||||||
if Enum.any?(whitelist, &(not String.starts_with?(&1, "http"))) do
|
if Enum.any?(whitelist, &(not String.starts_with?(&1, "http"))) do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION 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.
|
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.
|
||||||
""")
|
""")
|
||||||
|
@ -299,7 +299,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
pool_config = Config.get(:connections_pool)
|
pool_config = Config.get(:connections_pool)
|
||||||
|
|
||||||
if timeout = pool_config[:await_up_timeout] do
|
if timeout = pool_config[:await_up_timeout] do
|
||||||
Logger.warn("""
|
Logger.warning("""
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
Your config is using old setting `config :pleroma, :connections_pool, await_up_timeout`. Please change to `config :pleroma, :connections_pool, connect_timeout` to ensure compatibility with future releases.
|
Your config is using old setting `config :pleroma, :connections_pool, await_up_timeout`. Please change to `config :pleroma, :connections_pool, connect_timeout` to ensure compatibility with future releases.
|
||||||
""")
|
""")
|
||||||
|
@ -331,7 +331,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
"\n* `:timeout` options in #{pool_name} pool is now `:recv_timeout`"
|
"\n* `:timeout` options in #{pool_name} pool is now `:recv_timeout`"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Logger.warn(Enum.join([warning_preface | pool_warnings]))
|
Logger.warning(Enum.join([warning_preface | pool_warnings]))
|
||||||
|
|
||||||
Config.put(:pools, updated_config)
|
Config.put(:pools, updated_config)
|
||||||
:error
|
:error
|
||||||
|
@ -340,7 +340,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec check_activity_expiration_config() :: :ok | nil
|
@spec check_activity_expiration_config() :: :ok | :error
|
||||||
def check_activity_expiration_config do
|
def check_activity_expiration_config do
|
||||||
warning_preface = """
|
warning_preface = """
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
|
@ -356,7 +356,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec check_remote_ip_plug_name() :: :ok | nil
|
@spec check_remote_ip_plug_name() :: :ok | :error
|
||||||
def check_remote_ip_plug_name do
|
def check_remote_ip_plug_name do
|
||||||
warning_preface = """
|
warning_preface = """
|
||||||
!!!DEPRECATION WARNING!!!
|
!!!DEPRECATION WARNING!!!
|
||||||
|
@ -372,8 +372,8 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec check_uploders_s3_public_endpoint() :: :ok | nil
|
@spec check_uploaders_s3_public_endpoint() :: :ok | :error
|
||||||
def check_uploders_s3_public_endpoint do
|
def check_uploaders_s3_public_endpoint do
|
||||||
s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3])
|
s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3])
|
||||||
|
|
||||||
use_old_config = Keyword.has_key?(s3_config, :public_endpoint)
|
use_old_config = Keyword.has_key?(s3_config, :public_endpoint)
|
||||||
|
@ -393,7 +393,7 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec check_old_chat_shoutbox() :: :ok | nil
|
@spec check_old_chat_shoutbox() :: :ok | :error
|
||||||
def check_old_chat_shoutbox do
|
def check_old_chat_shoutbox do
|
||||||
instance_config = Pleroma.Config.get([:instance])
|
instance_config = Pleroma.Config.get([:instance])
|
||||||
chat_config = Pleroma.Config.get([:chat]) || []
|
chat_config = Pleroma.Config.get([:chat]) || []
|
||||||
|
|
|
@ -5,4 +5,11 @@
|
||||||
defmodule Pleroma.Config.Getting do
|
defmodule Pleroma.Config.Getting do
|
||||||
@callback get(any()) :: any()
|
@callback get(any()) :: any()
|
||||||
@callback get(any(), any()) :: any()
|
@callback get(any(), any()) :: any()
|
||||||
|
|
||||||
|
def get(key), do: get(key, nil)
|
||||||
|
def get(key, default), do: impl().get(key, default)
|
||||||
|
|
||||||
|
def impl do
|
||||||
|
Application.get_env(:pleroma, :config_impl, Pleroma.Config)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,7 @@ defmodule Pleroma.Config.Oban do
|
||||||
You are using old workers in Oban crontab settings, which were removed.
|
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)}
|
Please, remove setting from crontab in your config file (prod.secret.exs): #{inspect(setting)}
|
||||||
"""
|
"""
|
||||||
|> Logger.warn()
|
|> Logger.warning()
|
||||||
|
|
||||||
List.delete(acc, setting)
|
List.delete(acc, setting)
|
||||||
else
|
else
|
||||||
|
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.Config.ReleaseRuntimeProvider do
|
||||||
with_runtime_config =
|
with_runtime_config =
|
||||||
if File.exists?(config_path) do
|
if File.exists?(config_path) do
|
||||||
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
|
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
|
||||||
%File.Stat{mode: mode} = File.lstat!(config_path)
|
%File.Stat{mode: mode} = File.stat!(config_path)
|
||||||
|
|
||||||
if Bitwise.band(mode, 0o007) > 0 do
|
if Bitwise.band(mode, 0o007) > 0 do
|
||||||
raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"
|
raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Pleroma: A lightweight social networking server
|
# Pleroma: A lightweight social networking server
|
||||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Config.TransferTask do
|
defmodule Pleroma.Config.TransferTask do
|
||||||
|
@ -44,19 +44,13 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
with {_, true} <- {:configurable, Config.get(:configurable_from_database)} do
|
with {_, true} <- {:configurable, Config.get(:configurable_from_database)} do
|
||||||
# We need to restart applications for loaded settings take effect
|
# We need to restart applications for loaded settings take effect
|
||||||
|
|
||||||
{logger, other} =
|
settings =
|
||||||
(Repo.all(ConfigDB) ++ deleted_settings)
|
(Repo.all(ConfigDB) ++ deleted_settings)
|
||||||
|> Enum.map(&merge_with_default/1)
|
|> Enum.map(&merge_with_default/1)
|
||||||
|> Enum.split_with(fn {group, _, _, _} -> group in [:logger] end)
|
|
||||||
|
|
||||||
logger
|
|
||||||
|> Enum.sort()
|
|
||||||
|> Enum.each(&configure/1)
|
|
||||||
|
|
||||||
started_applications = Application.started_applications()
|
started_applications = Application.started_applications()
|
||||||
|
|
||||||
# TODO: some problem with prometheus after restart!
|
reject = [nil, :postgrex]
|
||||||
reject = [nil, :prometheus, :postgrex]
|
|
||||||
|
|
||||||
reject =
|
reject =
|
||||||
if restart_pleroma? do
|
if restart_pleroma? do
|
||||||
|
@ -65,7 +59,7 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
[:pleroma | reject]
|
[:pleroma | reject]
|
||||||
end
|
end
|
||||||
|
|
||||||
other
|
settings
|
||||||
|> Enum.map(&update/1)
|
|> Enum.map(&update/1)
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|> Enum.reject(&(&1 in reject))
|
|> Enum.reject(&(&1 in reject))
|
||||||
|
@ -103,38 +97,6 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
{group, key, value, merged}
|
{group, key, value, merged}
|
||||||
end
|
end
|
||||||
|
|
||||||
# change logger configuration in runtime, without restart
|
|
||||||
defp configure({_, :backends, _, merged}) do
|
|
||||||
# removing current backends
|
|
||||||
Enum.each(Application.get_env(:logger, :backends), &Logger.remove_backend/1)
|
|
||||||
|
|
||||||
Enum.each(merged, &Logger.add_backend/1)
|
|
||||||
|
|
||||||
:ok = update_env(:logger, :backends, merged)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp configure({_, key, _, merged}) when key in [:console, :ex_syslogger] do
|
|
||||||
merged =
|
|
||||||
if key == :console do
|
|
||||||
put_in(merged[:format], merged[:format] <> "\n")
|
|
||||||
else
|
|
||||||
merged
|
|
||||||
end
|
|
||||||
|
|
||||||
backend =
|
|
||||||
if key == :ex_syslogger,
|
|
||||||
do: {ExSyslogger, :ex_syslogger},
|
|
||||||
else: key
|
|
||||||
|
|
||||||
Logger.configure_backend(backend, merged)
|
|
||||||
:ok = update_env(:logger, key, merged)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp configure({_, key, _, merged}) do
|
|
||||||
Logger.configure([{key, merged}])
|
|
||||||
:ok = update_env(:logger, key, merged)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp update({group, key, value, merged}) do
|
defp update({group, key, value, merged}) do
|
||||||
try do
|
try do
|
||||||
:ok = update_env(group, key, merged)
|
:ok = update_env(group, key, merged)
|
||||||
|
@ -145,7 +107,7 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
error_msg =
|
error_msg =
|
||||||
"updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}"
|
"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
|
nil
|
||||||
end
|
end
|
||||||
|
@ -179,12 +141,12 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
:ok = Application.start(app)
|
:ok = Application.start(app)
|
||||||
else
|
else
|
||||||
nil ->
|
nil ->
|
||||||
Logger.warn("#{app} is not started.")
|
Logger.warning("#{app} is not started.")
|
||||||
|
|
||||||
error ->
|
error ->
|
||||||
error
|
error
|
||||||
|> inspect()
|
|> inspect()
|
||||||
|> Logger.warn()
|
|> Logger.warning()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ defmodule Pleroma.ConfigDB do
|
||||||
@spec get_by_params(map()) :: ConfigDB.t() | nil
|
@spec get_by_params(map()) :: ConfigDB.t() | nil
|
||||||
def get_by_params(%{group: _, key: _} = params), do: Repo.get_by(ConfigDB, params)
|
def get_by_params(%{group: _, key: _} = params), do: Repo.get_by(ConfigDB, params)
|
||||||
|
|
||||||
@spec changeset(ConfigDB.t(), map()) :: Changeset.t()
|
@spec changeset(ConfigDB.t(), map()) :: Ecto.Changeset.t()
|
||||||
def changeset(config, params \\ %{}) do
|
def changeset(config, params \\ %{}) do
|
||||||
config
|
config
|
||||||
|> cast(params, [:key, :group, :value])
|
|> cast(params, [:key, :group, :value])
|
||||||
|
@ -138,7 +138,7 @@ defmodule Pleroma.ConfigDB do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
@spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def update_or_create(params) do
|
def update_or_create(params) do
|
||||||
params = Map.put(params, :value, to_elixir_types(params[:value]))
|
params = Map.put(params, :value, to_elixir_types(params[:value]))
|
||||||
search_opts = Map.take(params, [:group, :key])
|
search_opts = Map.take(params, [:group, :key])
|
||||||
|
@ -165,8 +165,7 @@ defmodule Pleroma.ConfigDB do
|
||||||
{:pleroma, :ecto_repos},
|
{:pleroma, :ecto_repos},
|
||||||
{:mime, :types},
|
{:mime, :types},
|
||||||
{:cors_plug, [:max_age, :methods, :expose, :headers]},
|
{:cors_plug, [:max_age, :methods, :expose, :headers]},
|
||||||
{:swarm, :node_blacklist},
|
{:swarm, :node_blacklist}
|
||||||
{:logger, :backends}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
Enum.any?(full_key_update, fn
|
Enum.any?(full_key_update, fn
|
||||||
|
@ -175,7 +174,7 @@ defmodule Pleroma.ConfigDB do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
@spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def delete(%ConfigDB{} = config), do: Repo.delete(config)
|
def delete(%ConfigDB{} = config), do: Repo.delete(config)
|
||||||
|
|
||||||
def delete(params) do
|
def delete(params) do
|
||||||
|
@ -385,7 +384,12 @@ defmodule Pleroma.ConfigDB do
|
||||||
|
|
||||||
@spec module_name?(String.t()) :: boolean()
|
@spec module_name?(String.t()) :: boolean()
|
||||||
def module_name?(string) do
|
def module_name?(string) do
|
||||||
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Ueberauth|Swoosh)\./, string) or
|
if String.contains?(string, ".") do
|
||||||
string in ["Oban", "Ueberauth", "ExSyslogger", "ConcurrentLimiter"]
|
[name | _] = String.split(string, ".", parts: 2)
|
||||||
|
|
||||||
|
name in ~w[Pleroma Phoenix Tesla Ueberauth Swoosh Logger LoggerBackends]
|
||||||
|
else
|
||||||
|
string in ~w[Oban Ueberauth ExSyslogger ConcurrentLimiter]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,8 @@ defmodule Pleroma.Constants do
|
||||||
"context_id",
|
"context_id",
|
||||||
"deleted_activity_id",
|
"deleted_activity_id",
|
||||||
"pleroma_internal",
|
"pleroma_internal",
|
||||||
"generator"
|
"generator",
|
||||||
|
"rules"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,6 +77,14 @@ defmodule Pleroma.Constants do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const(allowed_user_actor_types,
|
||||||
|
do: [
|
||||||
|
"Person",
|
||||||
|
"Service",
|
||||||
|
"Group"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# basic regex, just there to weed out potential mistakes
|
# basic regex, just there to weed out potential mistakes
|
||||||
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
|
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
|
||||||
const(mime_regex,
|
const(mime_regex,
|
||||||
|
|
|
@ -57,7 +57,7 @@ defmodule Pleroma.Conversation do
|
||||||
3. Bump all relevant participations to 'unread'
|
3. Bump all relevant participations to 'unread'
|
||||||
"""
|
"""
|
||||||
def create_or_bump_for(activity, opts \\ []) do
|
def create_or_bump_for(activity, opts \\ []) do
|
||||||
with true <- Pleroma.Web.ActivityPub.Visibility.is_direct?(activity),
|
with true <- Pleroma.Web.ActivityPub.Visibility.direct?(activity),
|
||||||
"Create" <- activity.data["type"],
|
"Create" <- activity.data["type"],
|
||||||
%Object{} = object <- Object.normalize(activity, fetch: false),
|
%Object{} = object <- Object.normalize(activity, fetch: false),
|
||||||
true <- object.data["type"] in ["Note", "Question"],
|
true <- object.data["type"] in ["Note", "Question"],
|
||||||
|
|
|
@ -12,6 +12,8 @@ defmodule Pleroma.Conversation.Participation do
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
schema "conversation_participations" do
|
schema "conversation_participations" do
|
||||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||||
belongs_to(:conversation, Conversation)
|
belongs_to(:conversation, Conversation)
|
||||||
|
|
|
@ -12,6 +12,8 @@ defmodule Pleroma.DataMigration do
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
schema "data_migrations" do
|
schema "data_migrations" do
|
||||||
field(:name, :string)
|
field(:name, :string)
|
||||||
field(:state, State, default: :pending)
|
field(:state, State, default: :pending)
|
||||||
|
|
|
@ -15,8 +15,10 @@ defmodule Pleroma.Docs.Generator do
|
||||||
:code.all_loaded()
|
:code.all_loaded()
|
||||||
|> Enum.filter(fn {module, _} ->
|
|> Enum.filter(fn {module, _} ->
|
||||||
# This shouldn't be needed as all modules are expected to have module_info/1,
|
# This shouldn't be needed as all modules are expected to have module_info/1,
|
||||||
# but in test enviroments some transient modules `:elixir_compiler_XX`
|
# but in test environments some transient modules `:elixir_compiler_XX`
|
||||||
# are loaded for some reason (where XX is a random integer).
|
# are loaded for some reason (where XX is a random integer).
|
||||||
|
Code.ensure_loaded(module)
|
||||||
|
|
||||||
if function_exported?(module, :module_info, 1) do
|
if function_exported?(module, :module_info, 1) do
|
||||||
module.module_info(:attributes)
|
module.module_info(:attributes)
|
||||||
|> Keyword.get_values(:behaviour)
|
|> Keyword.get_values(:behaviour)
|
||||||
|
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Docs.JSON do
|
||||||
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(descriptions))
|
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(descriptions))
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec compiled_descriptions :: Map.t()
|
@spec compiled_descriptions :: map()
|
||||||
def compiled_descriptions do
|
def compiled_descriptions do
|
||||||
:persistent_term.get(@term)
|
:persistent_term.get(@term)
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,11 +27,3 @@ defenum(Pleroma.DataMigration.State,
|
||||||
failed: 4,
|
failed: 4,
|
||||||
manual: 5
|
manual: 5
|
||||||
)
|
)
|
||||||
|
|
||||||
defenum(Pleroma.User.Backup.State,
|
|
||||||
pending: 1,
|
|
||||||
running: 2,
|
|
||||||
complete: 3,
|
|
||||||
failed: 4,
|
|
||||||
invalid: 5
|
|
||||||
)
|
|
||||||
|
|
|
@ -8,10 +8,12 @@ defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri do
|
||||||
def type, do: :string
|
def type, do: :string
|
||||||
|
|
||||||
def cast(uri) when is_binary(uri) do
|
def cast(uri) when is_binary(uri) do
|
||||||
case URI.parse(uri) do
|
parsed = URI.parse(uri)
|
||||||
%URI{scheme: nil} -> :error
|
|
||||||
%URI{} -> {:ok, uri}
|
if is_nil(parsed.scheme) do
|
||||||
_ -> :error
|
:error
|
||||||
|
else
|
||||||
|
{:ok, uri}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -345,37 +345,22 @@ defmodule Pleroma.Emails.UserEmail do
|
||||||
Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
|
Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def backup_is_ready_email(backup, admin_user_id \\ nil) do
|
def backup_is_ready_email(backup) do
|
||||||
%{user: user} = Pleroma.Repo.preload(backup, :user)
|
%{user: user} = Pleroma.Repo.preload(backup, :user)
|
||||||
|
|
||||||
Gettext.with_locale_or_default user.language do
|
Gettext.with_locale_or_default user.language do
|
||||||
download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup)
|
download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup)
|
||||||
|
|
||||||
html_body =
|
html_body =
|
||||||
if is_nil(admin_user_id) do
|
|
||||||
Gettext.dpgettext(
|
Gettext.dpgettext(
|
||||||
"static_pages",
|
"static_pages",
|
||||||
"account archive email body - self-requested",
|
"account archive email body",
|
||||||
"""
|
"""
|
||||||
<p>You requested a full backup of your Pleroma account. It's ready for download:</p>
|
<p>A full backup of your Pleroma account was requested. It's ready for download:</p>
|
||||||
<p><a href="%{download_url}">%{download_url}</a></p>
|
<p><a href="%{download_url}">%{download_url}</a></p>
|
||||||
""",
|
""",
|
||||||
download_url: download_url
|
download_url: download_url
|
||||||
)
|
)
|
||||||
else
|
|
||||||
admin = Pleroma.Repo.get(User, admin_user_id)
|
|
||||||
|
|
||||||
Gettext.dpgettext(
|
|
||||||
"static_pages",
|
|
||||||
"account archive email body - admin requested",
|
|
||||||
"""
|
|
||||||
<p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>
|
|
||||||
<p><a href="%{download_url}">%{download_url}</a></p>
|
|
||||||
""",
|
|
||||||
admin_nickname: admin.nickname,
|
|
||||||
download_url: download_url
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
new()
|
new()
|
||||||
|> to(recipient(user))
|
|> to(recipient(user))
|
||||||
|
|
|
@ -24,6 +24,8 @@ defmodule Pleroma.Emoji do
|
||||||
|
|
||||||
defstruct [:code, :file, :tags, :safe_code, :safe_file]
|
defstruct [:code, :file, :tags, :safe_code, :safe_file]
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
@doc "Build emoji struct"
|
@doc "Build emoji struct"
|
||||||
def build({code, file, tags}) do
|
def build({code, file, tags}) do
|
||||||
%__MODULE__{
|
%__MODULE__{
|
||||||
|
@ -49,12 +51,12 @@ defmodule Pleroma.Emoji do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "Returns the path of the emoji `name`."
|
@doc "Returns the path of the emoji `name`."
|
||||||
@spec get(String.t()) :: String.t() | nil
|
@spec get(String.t()) :: Pleroma.Emoji.t() | nil
|
||||||
def get(name) do
|
def get(name) do
|
||||||
name = maybe_strip_name(name)
|
name = maybe_strip_name(name)
|
||||||
|
|
||||||
case :ets.lookup(@ets, name) do
|
case :ets.lookup(@ets, name) do
|
||||||
[{_, path}] -> path
|
[{_, emoji}] -> emoji
|
||||||
_ -> nil
|
_ -> nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -136,23 +138,23 @@ defmodule Pleroma.Emoji do
|
||||||
emojis = emojis ++ regional_indicators
|
emojis = emojis ++ regional_indicators
|
||||||
|
|
||||||
for emoji <- emojis do
|
for emoji <- emojis do
|
||||||
def is_unicode_emoji?(unquote(emoji)), do: true
|
def unicode?(unquote(emoji)), do: true
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_unicode_emoji?(_), do: false
|
def unicode?(_), do: false
|
||||||
|
|
||||||
@emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/
|
@emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/
|
||||||
|
|
||||||
def is_custom_emoji?(s) when is_binary(s), do: Regex.match?(@emoji_regex, s)
|
def custom?(s) when is_binary(s), do: Regex.match?(@emoji_regex, s)
|
||||||
|
|
||||||
def is_custom_emoji?(_), do: false
|
def custom?(_), do: false
|
||||||
|
|
||||||
def maybe_strip_name(name) when is_binary(name), do: String.trim(name, ":")
|
def maybe_strip_name(name) when is_binary(name), do: String.trim(name, ":")
|
||||||
|
|
||||||
def maybe_strip_name(name), do: name
|
def maybe_strip_name(name), do: name
|
||||||
|
|
||||||
def maybe_quote(name) when is_binary(name) do
|
def maybe_quote(name) when is_binary(name) do
|
||||||
if is_unicode_emoji?(name) do
|
if unicode?(name) do
|
||||||
name
|
name
|
||||||
else
|
else
|
||||||
if String.starts_with?(name, ":") do
|
if String.starts_with?(name, ":") do
|
||||||
|
|
|
@ -15,8 +15,6 @@ defmodule Pleroma.Emoji.Loader do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@mix_env Mix.env()
|
|
||||||
|
|
||||||
@type pattern :: Regex.t() | module() | String.t()
|
@type pattern :: Regex.t() | module() | String.t()
|
||||||
@type patterns :: pattern() | [pattern()]
|
@type patterns :: pattern() | [pattern()]
|
||||||
@type group_patterns :: keyword(patterns())
|
@type group_patterns :: keyword(patterns())
|
||||||
|
@ -59,7 +57,7 @@ defmodule Pleroma.Emoji.Loader do
|
||||||
Logger.info("Found emoji packs: #{Enum.join(packs, ", ")}")
|
Logger.info("Found emoji packs: #{Enum.join(packs, ", ")}")
|
||||||
|
|
||||||
if not Enum.empty?(files) do
|
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, ", ")}"
|
"Found files in the emoji folder. These will be ignored, please move them to a subdirectory\nFound files: #{Enum.join(files, ", ")}"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -79,7 +77,7 @@ defmodule Pleroma.Emoji.Loader do
|
||||||
|
|
||||||
# for testing emoji.txt entries we do not want exposed in normal operation
|
# for testing emoji.txt entries we do not want exposed in normal operation
|
||||||
test_emoji =
|
test_emoji =
|
||||||
if @mix_env == :test do
|
if Application.get_env(:pleroma, __MODULE__)[:test_emoji] do
|
||||||
load_from_file("test/config/emoji.txt", emoji_groups)
|
load_from_file("test/config/emoji.txt", emoji_groups)
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -100,7 +100,7 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
{:ok, _emoji_files} =
|
{:ok, _emoji_files} =
|
||||||
:zip.unzip(
|
:zip.unzip(
|
||||||
to_charlist(file.path),
|
to_charlist(file.path),
|
||||||
[{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, tmp_dir}]
|
[{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, String.to_charlist(tmp_dir)}]
|
||||||
)
|
)
|
||||||
|
|
||||||
{_, updated_pack} =
|
{_, updated_pack} =
|
||||||
|
@ -209,7 +209,9 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
|
|
||||||
with :ok <- validate_shareable_packs_available(uri) do
|
with :ok <- validate_shareable_packs_available(uri) do
|
||||||
uri
|
uri
|
||||||
|> URI.merge("/api/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}")
|
|> URI.merge(
|
||||||
|
"/api/v1/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}"
|
||||||
|
)
|
||||||
|> http_get()
|
|> http_get()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -249,8 +251,12 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
uri = url |> String.trim() |> URI.parse()
|
uri = url |> String.trim() |> URI.parse()
|
||||||
|
|
||||||
with :ok <- validate_shareable_packs_available(uri),
|
with :ok <- validate_shareable_packs_available(uri),
|
||||||
|
{:ok, %{"files_count" => files_count}} <-
|
||||||
|
uri |> URI.merge("/api/v1/pleroma/emoji/pack?name=#{name}&page_size=0") |> http_get(),
|
||||||
{:ok, remote_pack} <-
|
{:ok, remote_pack} <-
|
||||||
uri |> URI.merge("/api/pleroma/emoji/pack?name=#{name}") |> http_get(),
|
uri
|
||||||
|
|> URI.merge("/api/v1/pleroma/emoji/pack?name=#{name}&page_size=#{files_count}")
|
||||||
|
|> http_get(),
|
||||||
{:ok, %{sha: sha, url: url} = pack_info} <- fetch_pack_info(remote_pack, uri, name),
|
{:ok, %{sha: sha, url: url} = pack_info} <- fetch_pack_info(remote_pack, uri, name),
|
||||||
{:ok, archive} <- download_archive(url, sha),
|
{:ok, archive} <- download_archive(url, sha),
|
||||||
pack <- copy_as(remote_pack, as || name),
|
pack <- copy_as(remote_pack, as || name),
|
||||||
|
@ -410,10 +416,10 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp create_archive_and_cache(pack, hash) do
|
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}} =
|
{: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])
|
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
|
||||||
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
|
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
|
||||||
|
@ -580,7 +586,7 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
with :ok <- File.mkdir_p!(local_pack.path) do
|
with :ok <- File.mkdir_p!(local_pack.path) do
|
||||||
files = Enum.map(remote_pack["files"], fn {_, path} -> to_charlist(path) end)
|
files = Enum.map(remote_pack["files"], fn {_, path} -> to_charlist(path) end)
|
||||||
# Fallback cannot contain a pack.json file
|
# 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)
|
:zip.unzip(archive, cwd: to_charlist(local_pack.path), file_list: files)
|
||||||
end
|
end
|
||||||
|
@ -592,7 +598,7 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
{:ok,
|
{:ok,
|
||||||
%{
|
%{
|
||||||
sha: sha,
|
sha: sha,
|
||||||
url: URI.merge(uri, "/api/pleroma/emoji/packs/archive?name=#{name}") |> to_string()
|
url: URI.merge(uri, "/api/v1/pleroma/emoji/packs/archive?name=#{name}") |> to_string()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
%{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) ->
|
%{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) ->
|
||||||
|
|
|
@ -216,9 +216,6 @@ defmodule Pleroma.Filter do
|
||||||
|
|
||||||
:re ->
|
:re ->
|
||||||
~r/\b#{phrases}\b/i
|
~r/\b#{phrases}\b/i
|
||||||
|
|
||||||
_ ->
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -199,8 +199,8 @@ defmodule Pleroma.FollowingRelationship do
|
||||||
|> preload([:follower])
|
|> preload([:follower])
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|> Enum.map(fn following_relationship ->
|
|> Enum.map(fn following_relationship ->
|
||||||
Pleroma.Web.CommonAPI.follow(following_relationship.follower, target)
|
Pleroma.Web.CommonAPI.follow(target, following_relationship.follower)
|
||||||
Pleroma.Web.CommonAPI.unfollow(following_relationship.follower, origin)
|
Pleroma.Web.CommonAPI.unfollow(origin, following_relationship.follower)
|
||||||
end)
|
end)
|
||||||
|> case do
|
|> case do
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -241,13 +241,13 @@ defmodule Pleroma.FollowingRelationship do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
For a query with joined activity,
|
For a query with joined activity's actor,
|
||||||
keeps rows where activity's actor is followed by user -or- is NOT domain-blocked by user.
|
keeps rows where actor is followed by user -or- is NOT domain-blocked by user.
|
||||||
"""
|
"""
|
||||||
def keep_following_or_not_domain_blocked(query, user) do
|
def keep_following_or_not_domain_blocked(query, user) do
|
||||||
where(
|
where(
|
||||||
query,
|
query,
|
||||||
[_, activity],
|
[_, user_actor: user_actor],
|
||||||
fragment(
|
fragment(
|
||||||
# "(actor's domain NOT in domain_blocks) OR (actor IS in followed AP IDs)"
|
# "(actor's domain NOT in domain_blocks) OR (actor IS in followed AP IDs)"
|
||||||
"""
|
"""
|
||||||
|
@ -255,9 +255,9 @@ defmodule Pleroma.FollowingRelationship do
|
||||||
? = ANY(SELECT ap_id FROM users AS u INNER JOIN following_relationships AS fr
|
? = ANY(SELECT ap_id FROM users AS u INNER JOIN following_relationships AS fr
|
||||||
ON u.id = fr.following_id WHERE fr.follower_id = ? AND fr.state = ?)
|
ON u.id = fr.following_id WHERE fr.follower_id = ? AND fr.state = ?)
|
||||||
""",
|
""",
|
||||||
activity.actor,
|
user_actor.ap_id,
|
||||||
^user.domain_blocks,
|
^user.domain_blocks,
|
||||||
activity.actor,
|
user_actor.ap_id,
|
||||||
^User.binary_id(user.id),
|
^User.binary_id(user.id),
|
||||||
^accept_state_code()
|
^accept_state_code()
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,10 +43,6 @@ defmodule Pleroma.Frontend do
|
||||||
{:download_or_unzip, _} ->
|
{:download_or_unzip, _} ->
|
||||||
Logger.info("Could not download or unzip the frontend")
|
Logger.info("Could not download or unzip the frontend")
|
||||||
{:error, "Could not download or unzip the frontend"}
|
{:error, "Could not download or unzip the frontend"}
|
||||||
|
|
||||||
_e ->
|
|
||||||
Logger.info("Could not install the frontend")
|
|
||||||
{:error, "Could not install the frontend"}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
||||||
|
|
||||||
def response("/notices/" <> id) do
|
def response("/notices/" <> id) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id(id),
|
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||||
true <- Visibility.is_public?(activity) do
|
true <- Visibility.public?(activity) do
|
||||||
activities =
|
activities =
|
||||||
ActivityPub.fetch_activities_for_context(activity.data["context"])
|
ActivityPub.fetch_activities_for_context(activity.data["context"])
|
||||||
|> render_activities
|
|> render_activities
|
||||||
|
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.Gun.Conn do
|
||||||
{:ok, conn, protocol}
|
{:ok, conn, protocol}
|
||||||
else
|
else
|
||||||
error ->
|
error ->
|
||||||
Logger.warn(
|
Logger.warning(
|
||||||
"Opening proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
"Opening proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ defmodule Pleroma.Gun.Conn do
|
||||||
{:ok, conn, protocol}
|
{:ok, conn, protocol}
|
||||||
else
|
else
|
||||||
error ->
|
error ->
|
||||||
Logger.warn(
|
Logger.warning(
|
||||||
"Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
"Opening socks proxied connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ defmodule Pleroma.Gun.Conn do
|
||||||
{:ok, conn, protocol}
|
{:ok, conn, protocol}
|
||||||
else
|
else
|
||||||
error ->
|
error ->
|
||||||
Logger.warn(
|
Logger.warning(
|
||||||
"Opening connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
"Opening connection to #{compose_uri_log(uri)} failed with error #{inspect(error)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue