forked from AkkomaGang/akkoma
Merge branch 'develop' into feature/gen-magic
This commit is contained in:
commit
55562ca936
836 changed files with 22077 additions and 16442 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@
|
||||||
/*.ez
|
/*.ez
|
||||||
/test/uploads
|
/test/uploads
|
||||||
/.elixir_ls
|
/.elixir_ls
|
||||||
|
/test/fixtures/DSCN0010_tmp.jpg
|
||||||
/test/fixtures/test_tmp.txt
|
/test/fixtures/test_tmp.txt
|
||||||
/test/fixtures/image_tmp.jpg
|
/test/fixtures/image_tmp.jpg
|
||||||
/test/tmp/
|
/test/tmp/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
image: elixir:1.8.1
|
image: elixir:1.9.4
|
||||||
|
|
||||||
variables: &global_variables
|
variables: &global_variables
|
||||||
POSTGRES_DB: pleroma_test
|
POSTGRES_DB: pleroma_test
|
||||||
|
@ -22,6 +22,7 @@ stages:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- apt-get update && apt-get install -y cmake
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
- apt-get -qq update
|
- apt-get -qq update
|
||||||
|
@ -60,6 +61,7 @@ unit-testing:
|
||||||
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:
|
||||||
|
- apt-get update && apt-get install -y libimage-exiftool-perl
|
||||||
- mix deps.get
|
- mix deps.get
|
||||||
- mix ecto.create
|
- mix ecto.create
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
|
@ -93,6 +95,7 @@ unit-testing-rum:
|
||||||
<<: *global_variables
|
<<: *global_variables
|
||||||
RUM_ENABLED: "true"
|
RUM_ENABLED: "true"
|
||||||
script:
|
script:
|
||||||
|
- apt-get update && apt-get install -y libimage-exiftool-perl
|
||||||
- mix deps.get
|
- mix deps.get
|
||||||
- mix ecto.create
|
- mix ecto.create
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
|
@ -172,8 +175,7 @@ stop_review_app:
|
||||||
|
|
||||||
amd64:
|
amd64:
|
||||||
stage: release
|
stage: release
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
image: elixir:1.10.3
|
||||||
image: rinpatch/elixir:1.9.0-rc.0
|
|
||||||
only: &release-only
|
only: &release-only
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
|
@ -196,6 +198,7 @@ amd64:
|
||||||
variables: &release-variables
|
variables: &release-variables
|
||||||
MIX_ENV: prod
|
MIX_ENV: prod
|
||||||
before_script: &before-release
|
before_script: &before-release
|
||||||
|
- apt-get update && apt-get install -y cmake
|
||||||
- echo "import Mix.Config" > config/prod.secret.exs
|
- echo "import Mix.Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
|
@ -210,12 +213,11 @@ amd64-musl:
|
||||||
stage: release
|
stage: release
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
image: elixir:1.10.3-alpine
|
||||||
image: rinpatch/elixir:1.9.0-rc.0-alpine
|
|
||||||
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 gcc g++ musl-dev make
|
- apk add git gcc g++ musl-dev make cmake
|
||||||
- echo "import Mix.Config" > config/prod.secret.exs
|
- echo "import Mix.Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
|
@ -227,8 +229,7 @@ arm:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32
|
- arm32
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
image: elixir:1.10.3
|
||||||
image: rinpatch/elixir:1.9.0-rc.0-arm
|
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -240,8 +241,7 @@ arm-musl:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32
|
- arm32
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
image: elixir:1.10.3-alpine
|
||||||
image: rinpatch/elixir:1.9.0-rc.0-arm-alpine
|
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
@ -253,8 +253,7 @@ arm64:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
image: elixir:1.10.3
|
||||||
image: rinpatch/elixir:1.9.0-rc.0-arm64
|
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -267,7 +266,7 @@ arm64-musl:
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
# TODO: Replace with upstream image when 1.9.0 comes out
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
image: rinpatch/elixir:1.9.0-rc.0-arm64-alpine
|
image: elixir:1.10.3-alpine
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
@ -285,6 +284,8 @@ docker:
|
||||||
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
||||||
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
|
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
|
||||||
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
|
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
|
||||||
|
DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64
|
||||||
|
DOCKER_BUILDX_HASH: 71a7d01439aa8c165a25b59c44d3f016fddbd98b
|
||||||
before_script: &before-docker
|
before_script: &before-docker
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||||
- docker pull $IMAGE_TAG_SLUG || true
|
- docker pull $IMAGE_TAG_SLUG || true
|
||||||
|
@ -292,10 +293,14 @@ docker:
|
||||||
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
|
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
|
- mkdir -p /root/.docker/cli-plugins
|
||||||
- docker push $IMAGE_TAG
|
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
||||||
- docker push $IMAGE_TAG_SLUG
|
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
||||||
- docker push $IMAGE_TAG_LATEST
|
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- docker buildx create --name mbuilder --driver docker-container --use
|
||||||
|
- docker buildx inspect --bootstrap
|
||||||
|
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
|
||||||
tags:
|
tags:
|
||||||
- dind
|
- dind
|
||||||
only:
|
only:
|
||||||
|
@ -310,10 +315,14 @@ docker-stable:
|
||||||
before_script: *before-docker
|
before_script: *before-docker
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
|
- mkdir -p /root/.docker/cli-plugins
|
||||||
- docker push $IMAGE_TAG
|
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
||||||
- docker push $IMAGE_TAG_SLUG
|
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
||||||
- docker push $IMAGE_TAG_LATEST_STABLE
|
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- docker buildx create --name mbuilder --driver docker-container --use
|
||||||
|
- docker buildx inspect --bootstrap
|
||||||
|
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
|
||||||
tags:
|
tags:
|
||||||
- dind
|
- dind
|
||||||
only:
|
only:
|
||||||
|
@ -328,9 +337,15 @@ docker-release:
|
||||||
before_script: *before-docker
|
before_script: *before-docker
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- docker build --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
|
script:
|
||||||
- docker push $IMAGE_TAG
|
- mkdir -p /root/.docker/cli-plugins
|
||||||
- docker push $IMAGE_TAG_SLUG
|
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
||||||
|
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
||||||
|
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- docker buildx create --name mbuilder --driver docker-container --use
|
||||||
|
- docker buildx inspect --bootstrap
|
||||||
|
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
|
||||||
tags:
|
tags:
|
||||||
- dind
|
- dind
|
||||||
only:
|
only:
|
||||||
|
|
|
@ -8,13 +8,11 @@
|
||||||
|
|
||||||
### Environment
|
### Environment
|
||||||
|
|
||||||
* Installation type:
|
* Installation type (OTP or From Source):
|
||||||
- [ ] OTP
|
|
||||||
- [ ] From source
|
|
||||||
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
|
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
|
||||||
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
|
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
|
||||||
* Operating system:
|
* Operating system:
|
||||||
* PostgreSQL version (`postgres -V`):
|
* PostgreSQL version (`psql -V`):
|
||||||
|
|
||||||
|
|
||||||
### Bug description
|
### Bug description
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
* [ ] Compile a changelog
|
* [ ] Compile a changelog
|
||||||
* [ ] Create an MR with an announcement to pleroma.social
|
* [ ] Create an MR with an announcement to pleroma.social
|
||||||
* [ ] Tag the release
|
* [ ] Tag the release
|
||||||
|
* [ ] Merge `stable` into `develop` (in case the fixes are already in develop, use `git merge -s ours --no-commit` and manually merge the changelogs)
|
||||||
|
|
395
CC-BY-4.0
Normal file
395
CC-BY-4.0
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
Attribution 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution 4.0 International Public License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution 4.0 International Public License ("Public License"). To the
|
||||||
|
extent this Public License may be interpreted as a contract, You are
|
||||||
|
granted the Licensed Rights in consideration of Your acceptance of
|
||||||
|
these terms and conditions, and the Licensor grants You such rights in
|
||||||
|
consideration of benefits the Licensor receives from making the
|
||||||
|
Licensed Material available under these terms and conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
d. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
f. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
g. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
h. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
i. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
j. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
k. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
4. If You Share Adapted Material You produce, the Adapter's
|
||||||
|
License You apply must not prevent recipients of the Adapted
|
||||||
|
Material from complying with this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material; and
|
||||||
|
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public
|
||||||
|
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||||
|
its public licenses to material it publishes and in those instances
|
||||||
|
will be considered the “Licensor.” The text of the Creative Commons
|
||||||
|
public licenses is dedicated to the public domain under the CC0 Public
|
||||||
|
Domain Dedication. Except for the limited purpose of indicating that
|
||||||
|
material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the
|
||||||
|
public licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
189
CHANGELOG.md
189
CHANGELOG.md
|
@ -3,21 +3,105 @@ 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/).
|
||||||
|
|
||||||
## [unreleased]
|
## Unreleased
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- **Breaking** Requires `libmagic` (or `file`) to guess file types.
|
||||||
|
- Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated.
|
||||||
|
- Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- **Breaking:** `Pleroma.Workers.Cron.StatsWorker` setting from Oban `:crontab` (moved to a simpler implementation).
|
||||||
|
- **Breaking:** `Pleroma.Workers.Cron.ClearOauthTokenWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
||||||
|
- **Breaking:** `Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker` setting from Oban `:crontab` (moved to scheduled jobs).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option).
|
||||||
|
|
||||||
|
## [2.1.1] - 2020-09-08
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Fix possible DoS in Mastodon API user search due to an error in match clauses, leading to an infinite recursion and subsequent OOM with certain inputs.
|
||||||
|
- Fix metadata leak for accounts and statuses on private instances.
|
||||||
|
- Fix possible DoS in Admin API search using an atom leak vulnerability. Authentication with admin rights was required to exploit.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Breaking:** The metadata providers RelMe and Feed are no longer configurable. RelMe should always be activated and Feed only provides a <link> header tag for the actual RSS/Atom feed when the instance is public.
|
||||||
|
- Improved error message when cmake is not available at build stage.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Rich media failure tracking (along with `:failure_backoff` option).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Default HTTP adapter not respecting pool setting, leading to possible OOM.
|
||||||
|
- Fixed uploading webp images when the Exiftool Upload Filter is enabled by skipping them
|
||||||
|
- Mastodon API: Search parameter `following` now correctly returns the followings rather than the followers
|
||||||
|
- Mastodon API: Timelines hanging for (`number of posts with links * rich media timeout`) in the worst case.
|
||||||
|
Reduced to just rich media timeout.
|
||||||
|
- Mastodon API: Cards being wrong for preview statuses due to cache key collision.
|
||||||
|
- Password resets no longer processed for deactivated accounts.
|
||||||
|
- Favicon scraper raising exceptions on URLs longer than 255 characters.
|
||||||
|
|
||||||
|
## [2.1.0] - 2020-08-28
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Breaking:** The default descriptions on uploads are now empty. The old behavior (filename as default) can be configured, see the cheat sheet.
|
||||||
|
- **Breaking:** Added the ObjectAgePolicy to the default set of MRFs. This will delist and strip the follower collection of any message received that is older than 7 days. This will stop users from seeing very old messages in the timelines. The messages can still be viewed on the user's page and in conversations. They also still trigger notifications.
|
||||||
|
- **Breaking:** Elixir >=1.9 is now required (was >= 1.8)
|
||||||
|
- **Breaking:** Configuration: `:auto_linker, :opts` moved to `:pleroma, Pleroma.Formatter`. Old config namespace is deprecated.
|
||||||
|
- **Breaking:** Configuration: `:instance, welcome_user_nickname` moved to `:welcome, :direct_message, :sender_nickname`, `:instance, :welcome_message` moved to `:welcome, :direct_message, :message`. Old config namespace is deprecated.
|
||||||
|
- **Breaking:** LDAP: Fallback to local database authentication has been removed for security reasons and lack of a mechanism to ensure the passwords are synchronized when LDAP passwords are updated.
|
||||||
|
- **Breaking** Changed defaults for `:restrict_unauthenticated` so that when `:instance, :public` is set to `false` then all `:restrict_unauthenticated` items be effectively set to `true`. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
|
||||||
|
- In Conversations, return only direct messages as `last_status`
|
||||||
|
- Using the `only_media` filter on timelines will now exclude reblog media
|
||||||
- MFR policy to set global expiration for all local Create activities
|
- MFR policy to set global expiration for all local Create activities
|
||||||
- OGP rich media parser merged with TwitterCard
|
- OGP rich media parser merged with TwitterCard
|
||||||
- **Breaking** Requires `libmagic` (or `file`) to guess file types.
|
- Configuration: `:instance, rewrite_policy` moved to `:mrf, policies`, `:instance, :mrf_transparency` moved to `:mrf, :transparency`, `:instance, :mrf_transparency_exclusions` moved to `:mrf, :transparency_exclusions`. Old config namespace is deprecated.
|
||||||
|
- Configuration: `:media_proxy, whitelist` format changed to host with scheme (e.g. `http://example.com` instead of `example.com`). Domain format is deprecated.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
|
- **Breaking:** Pleroma API: The routes to update avatar, banner and background have been removed.
|
||||||
|
- **Breaking:** Image description length is limited now.
|
||||||
- **Breaking:** Emoji API: changed methods and renamed routes.
|
- **Breaking:** Emoji API: changed methods and renamed routes.
|
||||||
|
- **Breaking:** Notification Settings API for suppressing notifications has been simplified down to `block_from_strangers`.
|
||||||
|
- **Breaking:** Notification Settings API option for hiding push notification contents has been renamed to `hide_notification_contents`.
|
||||||
|
- MastodonAPI: Allow removal of avatar, banner and background.
|
||||||
|
- Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
|
||||||
|
- Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
|
||||||
|
- Mastodon API: On deletion, returns the original post text.
|
||||||
|
- Mastodon API: Add `pleroma.unread_count` to the Marker entity.
|
||||||
|
- Mastodon API: Added `pleroma.metadata.post_formats` to /api/v1/instance
|
||||||
|
- Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone`
|
||||||
|
- Mastodon API: Make notifications about statuses from muted users and threads read automatically
|
||||||
|
- Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Admin API Changes</summary>
|
||||||
|
|
||||||
|
- **Breaking** Changed relay `/api/pleroma/admin/relay` endpoints response format.
|
||||||
|
- Status visibility stats: now can return stats per instance.
|
||||||
|
- Mix task to refresh counter cache (`mix pleroma.refresh_counter_cache`)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- **Breaking:** removed `with_move` parameter from notifications timeline.
|
- **Breaking:** removed `with_move` parameter from notifications timeline.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Frontends: Add mix task to install frontends.
|
||||||
|
- Frontends: Add configurable frontends for primary and admin fe.
|
||||||
|
- Configuration: Added a blacklist for email servers.
|
||||||
|
- Chats: Added `accepts_chat_messages` field to user, exposed in APIs and federation.
|
||||||
- Chats: Added support for federated chats. For details, see the docs.
|
- Chats: Added support for federated chats. For details, see the docs.
|
||||||
- ActivityPub: Added support for existing AP ids for instances migrated from Mastodon.
|
- ActivityPub: Added support for existing AP ids for instances migrated from Mastodon.
|
||||||
- Instance: Add `background_image` to configuration and `/api/v1/instance`
|
- Instance: Add `background_image` to configuration and `/api/v1/instance`
|
||||||
|
@ -33,18 +117,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Notifications: Added `follow_request` notification type.
|
- Notifications: Added `follow_request` notification type.
|
||||||
- Added `:reject_deletes` group to SimplePolicy
|
- Added `:reject_deletes` group to SimplePolicy
|
||||||
- MRF (`EmojiStealPolicy`): New MRF Policy which allows to automatically download emojis from remote instances
|
- MRF (`EmojiStealPolicy`): New MRF Policy which allows to automatically download emojis from remote instances
|
||||||
|
- Support pagination in emoji packs API (for packs and for files in pack)
|
||||||
|
- Support for viewing instances favicons next to posts and accounts
|
||||||
|
- Added Pleroma.Upload.Filter.Exiftool as an alternate EXIF stripping mechanism targeting GPS/location metadata.
|
||||||
|
- "By approval" registrations mode.
|
||||||
|
- Configuration: Added `:welcome` settings for the welcome message to newly registered users. You can send a welcome message as a direct message, chat or email.
|
||||||
|
- Ability to hide favourites and emoji reactions in the API with `[:instance, :show_reactions]` config.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
|
- Mastodon API: Add pleroma.parent_visible field to statuses.
|
||||||
- Mastodon API: Extended `/api/v1/instance`.
|
- Mastodon API: Extended `/api/v1/instance`.
|
||||||
- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
|
- Mastodon API: Support for `include_types` in `/api/v1/notifications`.
|
||||||
- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
|
- Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
|
||||||
- Mastodon API: Add support for filtering replies in public and home timelines
|
- Mastodon API: Add support for filtering replies in public and home timelines.
|
||||||
|
- Mastodon API: Support for `bot` field in `/api/v1/accounts/update_credentials`.
|
||||||
|
- Mastodon API: Support irreversible property for filters.
|
||||||
|
- Mastodon API: Add pleroma.favicon field to accounts.
|
||||||
- Admin API: endpoints for create/update/delete OAuth Apps.
|
- Admin API: endpoints for create/update/delete OAuth Apps.
|
||||||
- Admin API: endpoint for status view.
|
- Admin API: endpoint for status view.
|
||||||
- OTP: Add command to reload emoji packs
|
- OTP: Add command to reload emoji packs
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Fix list pagination and other list issues.
|
||||||
- Support pagination in conversations API
|
- Support pagination in conversations API
|
||||||
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
|
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
|
||||||
- Fix follower/blocks import when nicknames starts with @
|
- Fix follower/blocks import when nicknames starts with @
|
||||||
|
@ -52,12 +149,87 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Resolving Peertube accounts with Webfinger
|
- Resolving Peertube accounts with Webfinger
|
||||||
- `blob:` urls not being allowed by connect-src CSP
|
- `blob:` urls not being allowed by connect-src CSP
|
||||||
- Mastodon API: fix `GET /api/v1/notifications` not returning the full result set
|
- Mastodon API: fix `GET /api/v1/notifications` not returning the full result set
|
||||||
|
- Rich Media Previews for Twitter links
|
||||||
|
- Admin API: fix `GET /api/pleroma/admin/users/:nickname/credentials` returning 404 when getting the credentials of a remote user while `:instance, :limit_to_local_content` is set to `:unauthenticated`
|
||||||
|
- Fix CSP policy generation to include remote Captcha services
|
||||||
|
- Fix edge case where MediaProxy truncates media, usually caused when Caddy is serving content for the other Federated instance.
|
||||||
|
- Emoji Packs could not be listed when instance was set to `public: false`
|
||||||
|
- Fix whole_word always returning false on filter get requests
|
||||||
|
- Migrations not working on OTP releases if the database was connected over ssl
|
||||||
|
- Fix relay following
|
||||||
|
|
||||||
## [Unreleased (patch)]
|
## [2.0.7] - 2020-06-13
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- CSP: not allowing images/media from every host when mediaproxy is disabled
|
||||||
|
- CSP: not adding mediaproxy base url to image/media hosts
|
||||||
|
- StaticFE missing the CSS file
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
|
||||||
|
1. Restart Pleroma
|
||||||
|
|
||||||
|
## [2.0.6] - 2020-06-09
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- CSP: harden `image-src` and `media-src` when MediaProxy is used
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- AP C2S: Fix pagination in inbox/outbox
|
||||||
|
- Various compilation errors on OTP 23
|
||||||
|
- Mastodon API streaming: Repeats from muted threads not being filtered
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Various database performance improvements
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
1. Run database migrations (inside Pleroma directory):
|
||||||
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
|
- From Source: `mix ecto.migrate`
|
||||||
|
2. Restart Pleroma
|
||||||
|
|
||||||
|
## [2.0.5] - 2020-05-13
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Fix possible private status leaks in Mastodon Streaming API
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Crashes when trying to block a user if block federation is disabled
|
||||||
|
- Not being able to start the instance without `erlang-eldap` installed
|
||||||
|
- Users with bios over the limit getting rejected
|
||||||
|
- Follower counters not being updated on incoming follow accepts
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
|
||||||
|
1. Restart Pleroma
|
||||||
|
|
||||||
|
## [2.0.4] - 2020-05-10
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- AP C2S: Fix a potential DoS by creating nonsensical objects that break timelines
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Peertube user lookups not working
|
||||||
|
- `InsertSkeletonsForDeletedUsers` migration failing on some instances
|
||||||
- Healthcheck reporting the number of memory currently used, rather than allocated in total
|
- Healthcheck reporting the number of memory currently used, rather than allocated in total
|
||||||
- `InsertSkeletonsForDeletedUsers` failing on some instances
|
- LDAP not being usable in OTP releases
|
||||||
|
- Default apache configuration having tls chain issues
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
|
||||||
|
#### Apache only
|
||||||
|
|
||||||
|
1. Remove the following line from your config:
|
||||||
|
```
|
||||||
|
SSLCertificateFile /etc/letsencrypt/live/${servername}/cert.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Everyone
|
||||||
|
|
||||||
|
1. Restart Pleroma
|
||||||
|
|
||||||
## [2.0.3] - 2020-05-02
|
## [2.0.3] - 2020-05-02
|
||||||
|
|
||||||
|
@ -90,6 +262,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
2. Run database migrations (inside Pleroma directory):
|
2. Run database migrations (inside Pleroma directory):
|
||||||
- OTP: `./bin/pleroma_ctl migrate`
|
- OTP: `./bin/pleroma_ctl migrate`
|
||||||
- From Source: `mix ecto.migrate`
|
- From Source: `mix ecto.migrate`
|
||||||
|
3. Reset status visibility counters (inside Pleroma directory):
|
||||||
|
- OTP: `./bin/pleroma_ctl refresh_counter_cache`
|
||||||
|
- From Source: `mix pleroma.refresh_counter_cache`
|
||||||
|
|
||||||
|
|
||||||
## [2.0.2] - 2020-04-08
|
## [2.0.2] - 2020-04-08
|
||||||
|
@ -112,6 +287,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Static-FE: Fix remote posts not being sanitized
|
- Static-FE: Fix remote posts not being sanitized
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
=======
|
||||||
|
- 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 unncessary newlines in Pleroma-FE
|
||||||
|
@ -145,6 +322,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- **Breaking**: Using third party engines for user recommendation
|
- **Breaking**: Using third party engines for user recommendation
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
- **Breaking**: AdminAPI: migrate_from_db endpoint
|
- **Breaking**: AdminAPI: migrate_from_db endpoint
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -190,7 +368,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Mastodon API: `pleroma.thread_muted` to the Status entity
|
- Mastodon API: `pleroma.thread_muted` to the Status entity
|
||||||
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
||||||
- Mastodon API, streaming: Add `pleroma.direct_conversation_id` to the `conversation` stream event payload.
|
- Mastodon API, streaming: Add `pleroma.direct_conversation_id` to the `conversation` stream event payload.
|
||||||
- Mastodon API: Add `pleroma.unread_count` to the Marker entity
|
|
||||||
- Admin API: Render whole status in grouped reports
|
- Admin API: Render whole status in grouped reports
|
||||||
- Mastodon API: User timelines will now respect blocks, unless you are getting the user timeline of somebody you blocked (which would be empty otherwise).
|
- Mastodon API: User timelines will now respect blocks, unless you are getting the user timeline of somebody you blocked (which would be empty otherwise).
|
||||||
- Mastodon API: Favoriting / Repeating a post multiple times will now return the identical response every time. Before, executing that action twice would return an error ("already favorited") on the second try.
|
- Mastodon API: Favoriting / Repeating a post multiple times will now return the identical response every time. Before, executing that action twice would return an error ("already favorited") on the second try.
|
||||||
|
|
|
@ -4,7 +4,7 @@ COPY . .
|
||||||
|
|
||||||
ENV MIX_ENV=prod
|
ENV MIX_ENV=prod
|
||||||
|
|
||||||
RUN apk add git gcc g++ musl-dev make &&\
|
RUN apk add git gcc g++ musl-dev make cmake &&\
|
||||||
echo "import Mix.Config" > config/prod.secret.exs &&\
|
echo "import Mix.Config" > config/prod.secret.exs &&\
|
||||||
mix local.hex --force &&\
|
mix local.hex --force &&\
|
||||||
mix local.rebar --force &&\
|
mix local.rebar --force &&\
|
||||||
|
@ -31,9 +31,9 @@ LABEL maintainer="ops@pleroma.social" \
|
||||||
ARG HOME=/opt/pleroma
|
ARG HOME=/opt/pleroma
|
||||||
ARG DATA=/var/lib/pleroma
|
ARG DATA=/var/lib/pleroma
|
||||||
|
|
||||||
RUN echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
|
RUN echo "https://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories &&\
|
||||||
apk update &&\
|
apk update &&\
|
||||||
apk add imagemagick ncurses postgresql-client &&\
|
apk add exiftool imagemagick 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 &&\
|
||||||
|
|
10
README.md
10
README.md
|
@ -34,6 +34,16 @@ Currently Pleroma is not packaged by any OS/Distros, but if you want to package
|
||||||
### Docker
|
### Docker
|
||||||
While we don’t provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://glitch.sh/sn0w/pleroma-docker>.
|
While we don’t provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://glitch.sh/sn0w/pleroma-docker>.
|
||||||
|
|
||||||
|
### Compilation Troubleshooting
|
||||||
|
If you ever encounter compilation issues during the updating of Pleroma, you can try these commands and see if they fix things:
|
||||||
|
|
||||||
|
- `mix deps.clean --all`
|
||||||
|
- `mix local.rebar`
|
||||||
|
- `mix local.hex`
|
||||||
|
- `rm -r _build`
|
||||||
|
|
||||||
|
If you are not developing Pleroma, it is better to use the OTP release, which comes with everything precompiled.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
- Latest Released revision: <https://docs.pleroma.social>
|
- Latest Released revision: <https://docs.pleroma.social>
|
||||||
- Latest Git revision: <https://docs-develop.pleroma.social>
|
- Latest Git revision: <https://docs-develop.pleroma.social>
|
||||||
|
|
16
SECURITY.md
Normal file
16
SECURITY.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Pleroma backend security policy
|
||||||
|
|
||||||
|
## Supported versions
|
||||||
|
|
||||||
|
Currently, Pleroma offers bugfixes and security patches only for the latest minor release.
|
||||||
|
|
||||||
|
| Version | Support
|
||||||
|
|---------| --------
|
||||||
|
| 2.1 | Bugfixes and security patches
|
||||||
|
|
||||||
|
## Reporting a vulnerability
|
||||||
|
|
||||||
|
Please use confidential issues (tick the "This issue is confidential and should only be visible to team members with at least Reporter access." box when submitting) at our [bugtracker](https://git.pleroma.social/pleroma/pleroma/-/issues/new) for reporting vulnerabilities.
|
||||||
|
## Announcements
|
||||||
|
|
||||||
|
New releases are announced at [pleroma.social](https://pleroma.social/announcements/). All security releases are tagged with ["Security"](https://pleroma.social/announcements/tags/security/). You can be notified of them by subscribing to an Atom feed at <https://pleroma.social/announcements/tags/security/feed.xml>.
|
|
@ -24,6 +24,7 @@ defmodule Pleroma.LoadTesting.Activities do
|
||||||
@visibility ~w(public private direct unlisted)
|
@visibility ~w(public private direct unlisted)
|
||||||
@types [
|
@types [
|
||||||
:simple,
|
:simple,
|
||||||
|
:simple_filtered,
|
||||||
:emoji,
|
:emoji,
|
||||||
:mentions,
|
:mentions,
|
||||||
:hell_thread,
|
:hell_thread,
|
||||||
|
@ -242,6 +243,15 @@ defp insert_activity(:simple, visibility, group, users, _opts) do
|
||||||
insert_local_activity(visibility, group, users, "Simple status")
|
insert_local_activity(visibility, group, users, "Simple status")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp insert_activity(:simple_filtered, visibility, group, users, _opts)
|
||||||
|
when group in @remote_groups do
|
||||||
|
insert_remote_activity(visibility, group, users, "Remote status which must be filtered")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp insert_activity(:simple_filtered, visibility, group, users, _opts) do
|
||||||
|
insert_local_activity(visibility, group, users, "Simple status which must be filtered")
|
||||||
|
end
|
||||||
|
|
||||||
defp insert_activity(:emoji, visibility, group, users, _opts)
|
defp insert_activity(:emoji, visibility, group, users, _opts)
|
||||||
when group in @remote_groups do
|
when group in @remote_groups do
|
||||||
insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:")
|
insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:")
|
||||||
|
|
|
@ -32,10 +32,22 @@ defp fetch_user(user) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp create_filter(user) do
|
||||||
|
Pleroma.Filter.create(%Pleroma.Filter{
|
||||||
|
user_id: user.id,
|
||||||
|
phrase: "must be filtered",
|
||||||
|
hide: true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp delete_filter(filter), do: Repo.delete(filter)
|
||||||
|
|
||||||
defp fetch_timelines(user) do
|
defp fetch_timelines(user) do
|
||||||
fetch_home_timeline(user)
|
fetch_home_timeline(user)
|
||||||
|
fetch_home_timeline_with_filter(user)
|
||||||
fetch_direct_timeline(user)
|
fetch_direct_timeline(user)
|
||||||
fetch_public_timeline(user)
|
fetch_public_timeline(user)
|
||||||
|
fetch_public_timeline_with_filter(user)
|
||||||
fetch_public_timeline(user, :with_blocks)
|
fetch_public_timeline(user, :with_blocks)
|
||||||
fetch_public_timeline(user, :local)
|
fetch_public_timeline(user, :local)
|
||||||
fetch_public_timeline(user, :tag)
|
fetch_public_timeline(user, :tag)
|
||||||
|
@ -61,7 +73,7 @@ defp opts_for_home_timeline(user) do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch_home_timeline(user) do
|
defp fetch_home_timeline(user, title_end \\ "") do
|
||||||
opts = opts_for_home_timeline(user)
|
opts = opts_for_home_timeline(user)
|
||||||
|
|
||||||
recipients = [user.ap_id | User.following(user)]
|
recipients = [user.ap_id | User.following(user)]
|
||||||
|
@ -84,9 +96,11 @@ defp fetch_home_timeline(user) do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|> List.last()
|
|> List.last()
|
||||||
|
|
||||||
|
title = "home timeline " <> title_end
|
||||||
|
|
||||||
Benchee.run(
|
Benchee.run(
|
||||||
%{
|
%{
|
||||||
"home timeline" => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
|
title => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
|
||||||
},
|
},
|
||||||
inputs: %{
|
inputs: %{
|
||||||
"1 page" => opts,
|
"1 page" => opts,
|
||||||
|
@ -108,6 +122,14 @@ defp fetch_home_timeline(user) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp fetch_home_timeline_with_filter(user) do
|
||||||
|
{:ok, filter} = create_filter(user)
|
||||||
|
|
||||||
|
fetch_home_timeline(user, "with filters")
|
||||||
|
|
||||||
|
delete_filter(filter)
|
||||||
|
end
|
||||||
|
|
||||||
defp opts_for_direct_timeline(user) do
|
defp opts_for_direct_timeline(user) do
|
||||||
%{
|
%{
|
||||||
visibility: "direct",
|
visibility: "direct",
|
||||||
|
@ -210,6 +232,14 @@ defp fetch_public_timeline(user) do
|
||||||
fetch_public_timeline(opts, "public timeline")
|
fetch_public_timeline(opts, "public timeline")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp fetch_public_timeline_with_filter(user) do
|
||||||
|
{:ok, filter} = create_filter(user)
|
||||||
|
opts = opts_for_public_timeline(user)
|
||||||
|
|
||||||
|
fetch_public_timeline(opts, "public timeline with filters")
|
||||||
|
delete_filter(filter)
|
||||||
|
end
|
||||||
|
|
||||||
defp fetch_public_timeline(user, :local) do
|
defp fetch_public_timeline(user, :local) do
|
||||||
opts = opts_for_public_timeline(user, :local)
|
opts = opts_for_public_timeline(user, :local)
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,8 @@
|
||||||
pool: :upload
|
pool: :upload
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
filename_display_max_length: 30
|
filename_display_max_length: 30,
|
||||||
|
default_description: nil
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@
|
||||||
"dat",
|
"dat",
|
||||||
"dweb",
|
"dweb",
|
||||||
"gopher",
|
"gopher",
|
||||||
|
"hyper",
|
||||||
"ipfs",
|
"ipfs",
|
||||||
"ipns",
|
"ipns",
|
||||||
"irc",
|
"irc",
|
||||||
|
@ -186,7 +188,9 @@
|
||||||
notify_email: "noreply@example.com",
|
notify_email: "noreply@example.com",
|
||||||
description: "Pleroma: An efficient and flexible fediverse server",
|
description: "Pleroma: An efficient and flexible fediverse server",
|
||||||
background_image: "/images/city.jpg",
|
background_image: "/images/city.jpg",
|
||||||
|
instance_thumbnail: "/instance/thumbnail.jpeg",
|
||||||
limit: 5_000,
|
limit: 5_000,
|
||||||
|
description_limit: 5_000,
|
||||||
chat_limit: 5_000,
|
chat_limit: 5_000,
|
||||||
remote_limit: 100_000,
|
remote_limit: 100_000,
|
||||||
upload_limit: 16_000_000,
|
upload_limit: 16_000_000,
|
||||||
|
@ -202,6 +206,7 @@
|
||||||
registrations_open: true,
|
registrations_open: true,
|
||||||
invites_enabled: false,
|
invites_enabled: false,
|
||||||
account_activation_required: false,
|
account_activation_required: false,
|
||||||
|
account_approval_required: false,
|
||||||
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,
|
||||||
|
@ -209,7 +214,6 @@
|
||||||
Pleroma.Web.ActivityPub.Publisher
|
Pleroma.Web.ActivityPub.Publisher
|
||||||
],
|
],
|
||||||
allow_relay: true,
|
allow_relay: true,
|
||||||
rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
|
|
||||||
public: true,
|
public: true,
|
||||||
quarantined_instances: [],
|
quarantined_instances: [],
|
||||||
managed_config: true,
|
managed_config: true,
|
||||||
|
@ -220,13 +224,9 @@
|
||||||
"text/markdown",
|
"text/markdown",
|
||||||
"text/bbcode"
|
"text/bbcode"
|
||||||
],
|
],
|
||||||
mrf_transparency: true,
|
|
||||||
mrf_transparency_exclusions: [],
|
|
||||||
autofollowed_nicknames: [],
|
autofollowed_nicknames: [],
|
||||||
max_pinned_statuses: 1,
|
max_pinned_statuses: 1,
|
||||||
attachment_links: false,
|
attachment_links: false,
|
||||||
welcome_user_nickname: nil,
|
|
||||||
welcome_message: nil,
|
|
||||||
max_report_comment_size: 1000,
|
max_report_comment_size: 1000,
|
||||||
safe_dm_mentions: false,
|
safe_dm_mentions: false,
|
||||||
healthcheck: false,
|
healthcheck: false,
|
||||||
|
@ -239,6 +239,7 @@
|
||||||
max_remote_account_fields: 20,
|
max_remote_account_fields: 20,
|
||||||
account_field_name_length: 512,
|
account_field_name_length: 512,
|
||||||
account_field_value_length: 2048,
|
account_field_value_length: 2048,
|
||||||
|
registration_reason_length: 500,
|
||||||
external_user_synchronization: true,
|
external_user_synchronization: true,
|
||||||
extended_nickname_format: true,
|
extended_nickname_format: true,
|
||||||
cleanup_attachments: false,
|
cleanup_attachments: false,
|
||||||
|
@ -252,6 +253,26 @@
|
||||||
number: 5,
|
number: 5,
|
||||||
length: 16
|
length: 16
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
show_reactions: true
|
||||||
|
|
||||||
|
config :pleroma, :welcome,
|
||||||
|
direct_message: [
|
||||||
|
enabled: false,
|
||||||
|
sender_nickname: nil,
|
||||||
|
message: nil
|
||||||
|
],
|
||||||
|
chat_message: [
|
||||||
|
enabled: false,
|
||||||
|
sender_nickname: nil,
|
||||||
|
message: nil
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
enabled: false,
|
||||||
|
sender: nil,
|
||||||
|
subject: "Welcome to <%= instance_name %>",
|
||||||
|
html: "Welcome to <%= instance_name %>",
|
||||||
|
text: "Welcome to <%= instance_name %>"
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :feed,
|
config :pleroma, :feed,
|
||||||
|
@ -359,6 +380,7 @@
|
||||||
federated_timeline_removal: [],
|
federated_timeline_removal: [],
|
||||||
report_removal: [],
|
report_removal: [],
|
||||||
reject: [],
|
reject: [],
|
||||||
|
followers_only: [],
|
||||||
accept: [],
|
accept: [],
|
||||||
avatar_removal: [],
|
avatar_removal: [],
|
||||||
banner_removal: [],
|
banner_removal: [],
|
||||||
|
@ -377,8 +399,9 @@
|
||||||
accept: [],
|
accept: [],
|
||||||
reject: []
|
reject: []
|
||||||
|
|
||||||
|
# threshold of 7 days
|
||||||
config :pleroma, :mrf_object_age,
|
config :pleroma, :mrf_object_age,
|
||||||
threshold: 172_800,
|
threshold: 604_800,
|
||||||
actions: [:delist, :strip_followers]
|
actions: [:delist, :strip_followers]
|
||||||
|
|
||||||
config :pleroma, :rich_media,
|
config :pleroma, :rich_media,
|
||||||
|
@ -389,6 +412,7 @@
|
||||||
Pleroma.Web.RichMedia.Parsers.TwitterCard,
|
Pleroma.Web.RichMedia.Parsers.TwitterCard,
|
||||||
Pleroma.Web.RichMedia.Parsers.OEmbed
|
Pleroma.Web.RichMedia.Parsers.OEmbed
|
||||||
],
|
],
|
||||||
|
failure_backoff: 60_000,
|
||||||
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
|
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
|
||||||
|
|
||||||
config :pleroma, :media_proxy,
|
config :pleroma, :media_proxy,
|
||||||
|
@ -407,6 +431,13 @@
|
||||||
],
|
],
|
||||||
whitelist: []
|
whitelist: []
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
|
||||||
|
method: :purge,
|
||||||
|
headers: [],
|
||||||
|
options: []
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script, script_path: nil
|
||||||
|
|
||||||
config :pleroma, :chat, enabled: true
|
config :pleroma, :chat, enabled: true
|
||||||
|
|
||||||
config :phoenix, :format_encoders, json: Jason
|
config :phoenix, :format_encoders, json: Jason
|
||||||
|
@ -423,12 +454,15 @@
|
||||||
config :pleroma, Pleroma.Web.Metadata,
|
config :pleroma, Pleroma.Web.Metadata,
|
||||||
providers: [
|
providers: [
|
||||||
Pleroma.Web.Metadata.Providers.OpenGraph,
|
Pleroma.Web.Metadata.Providers.OpenGraph,
|
||||||
Pleroma.Web.Metadata.Providers.TwitterCard,
|
Pleroma.Web.Metadata.Providers.TwitterCard
|
||||||
Pleroma.Web.Metadata.Providers.RelMe,
|
|
||||||
Pleroma.Web.Metadata.Providers.Feed
|
|
||||||
],
|
],
|
||||||
unfurl_nsfw: false
|
unfurl_nsfw: false
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Preload,
|
||||||
|
providers: [
|
||||||
|
Pleroma.Web.Preload.Providers.Instance
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sts: false,
|
sts: false,
|
||||||
|
@ -481,15 +515,22 @@
|
||||||
"user-search",
|
"user-search",
|
||||||
"user_exists",
|
"user_exists",
|
||||||
"users",
|
"users",
|
||||||
"web"
|
"web",
|
||||||
]
|
"verify_credentials",
|
||||||
|
"update_credentials",
|
||||||
|
"relationships",
|
||||||
|
"search",
|
||||||
|
"confirmation_resend",
|
||||||
|
"mfa"
|
||||||
|
],
|
||||||
|
email_blacklist: []
|
||||||
|
|
||||||
config :pleroma, Oban,
|
config :pleroma, Oban,
|
||||||
repo: Pleroma.Repo,
|
repo: Pleroma.Repo,
|
||||||
verbose: false,
|
log: false,
|
||||||
prune: {:maxlen, 1500},
|
|
||||||
queues: [
|
queues: [
|
||||||
activity_expiration: 10,
|
activity_expiration: 10,
|
||||||
|
token_expiration: 5,
|
||||||
federator_incoming: 50,
|
federator_incoming: 50,
|
||||||
federator_outgoing: 50,
|
federator_outgoing: 50,
|
||||||
web_push: 50,
|
web_push: 50,
|
||||||
|
@ -501,10 +542,8 @@
|
||||||
attachments_cleanup: 5,
|
attachments_cleanup: 5,
|
||||||
new_users_digest: 1
|
new_users_digest: 1
|
||||||
],
|
],
|
||||||
|
plugins: [Oban.Plugins.Pruner],
|
||||||
crontab: [
|
crontab: [
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
|
|
||||||
{"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
|
|
||||||
{"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker},
|
|
||||||
{"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}
|
||||||
]
|
]
|
||||||
|
@ -515,16 +554,14 @@
|
||||||
federator_outgoing: 5
|
federator_outgoing: 5
|
||||||
]
|
]
|
||||||
|
|
||||||
config :auto_linker,
|
config :pleroma, Pleroma.Formatter,
|
||||||
opts: [
|
|
||||||
extra: true,
|
|
||||||
# TODO: Set to :no_scheme when it works properly
|
|
||||||
validate_tld: true,
|
|
||||||
class: false,
|
class: false,
|
||||||
strip_prefix: false,
|
rel: "ugc",
|
||||||
new_window: false,
|
new_window: false,
|
||||||
rel: "ugc"
|
truncate: false,
|
||||||
]
|
strip_prefix: false,
|
||||||
|
extra: true,
|
||||||
|
validate_tld: :no_scheme
|
||||||
|
|
||||||
config :pleroma, :ldap,
|
config :pleroma, :ldap,
|
||||||
enabled: System.get_env("LDAP_ENABLED") == "true",
|
enabled: System.get_env("LDAP_ENABLED") == "true",
|
||||||
|
@ -617,12 +654,65 @@
|
||||||
account_confirmation_resend: {8_640_000, 5},
|
account_confirmation_resend: {8_640_000, 5},
|
||||||
ap_routes: {60_000, 15}
|
ap_routes: {60_000, 15}
|
||||||
|
|
||||||
config :pleroma, Pleroma.ActivityExpiration, enabled: true
|
config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifetime: 600
|
||||||
|
|
||||||
config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
|
config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
|
||||||
|
|
||||||
config :pleroma, :static_fe, enabled: false
|
config :pleroma, :static_fe, enabled: false
|
||||||
|
|
||||||
|
# Example of frontend configuration
|
||||||
|
# This example will make us serve the primary frontend from the
|
||||||
|
# frontends directory within your `:pleroma, :instance, static_dir`.
|
||||||
|
# e.g., instance/static/frontends/pleroma/develop/
|
||||||
|
#
|
||||||
|
# With no frontend configuration, the bundled files from the `static` directory will
|
||||||
|
# be used.
|
||||||
|
#
|
||||||
|
# config :pleroma, :frontends,
|
||||||
|
# primary: %{"name" => "pleroma-fe", "ref" => "develop"},
|
||||||
|
# admin: %{"name" => "admin-fe", "ref" => "stable"},
|
||||||
|
# available: %{...}
|
||||||
|
|
||||||
|
config :pleroma, :frontends,
|
||||||
|
available: %{
|
||||||
|
"kenoma" => %{
|
||||||
|
"name" => "kenoma",
|
||||||
|
"git" => "https://git.pleroma.social/lambadalambda/kenoma",
|
||||||
|
"build_url" =>
|
||||||
|
"https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
|
||||||
|
"ref" => "master"
|
||||||
|
},
|
||||||
|
"pleroma-fe" => %{
|
||||||
|
"name" => "pleroma-fe",
|
||||||
|
"git" => "https://git.pleroma.social/pleroma/pleroma-fe",
|
||||||
|
"build_url" =>
|
||||||
|
"https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/${ref}/download?job=build",
|
||||||
|
"ref" => "develop"
|
||||||
|
},
|
||||||
|
"fedi-fe" => %{
|
||||||
|
"name" => "fedi-fe",
|
||||||
|
"git" => "https://git.pleroma.social/pleroma/fedi-fe",
|
||||||
|
"build_url" =>
|
||||||
|
"https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
|
||||||
|
"ref" => "master"
|
||||||
|
},
|
||||||
|
"admin-fe" => %{
|
||||||
|
"name" => "admin-fe",
|
||||||
|
"git" => "https://git.pleroma.social/pleroma/admin-fe",
|
||||||
|
"build_url" =>
|
||||||
|
"https://git.pleroma.social/pleroma/admin-fe/-/jobs/artifacts/${ref}/download?job=build",
|
||||||
|
"ref" => "develop"
|
||||||
|
},
|
||||||
|
"soapbox-fe" => %{
|
||||||
|
"name" => "soapbox-fe",
|
||||||
|
"git" => "https://gitlab.com/soapbox-pub/soapbox-fe",
|
||||||
|
"build_url" =>
|
||||||
|
"https://gitlab.com/soapbox-pub/soapbox-fe/-/jobs/artifacts/${ref}/download?job=build-production",
|
||||||
|
"ref" => "v1.0.0",
|
||||||
|
"build_dir" => "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
config :pleroma, :web_cache_ttl,
|
config :pleroma, :web_cache_ttl,
|
||||||
activity_pub: nil,
|
activity_pub: nil,
|
||||||
activity_pub_question: 30_000
|
activity_pub_question: 30_000
|
||||||
|
@ -636,32 +726,34 @@
|
||||||
prepare: :unnamed
|
prepare: :unnamed
|
||||||
|
|
||||||
config :pleroma, :connections_pool,
|
config :pleroma, :connections_pool,
|
||||||
checkin_timeout: 250,
|
reclaim_multiplier: 0.1,
|
||||||
|
connection_acquisition_wait: 250,
|
||||||
|
connection_acquisition_retries: 5,
|
||||||
max_connections: 250,
|
max_connections: 250,
|
||||||
retry: 1,
|
max_idle_time: 30_000,
|
||||||
retry_timeout: 1000,
|
retry: 0,
|
||||||
await_up_timeout: 5_000
|
connect_timeout: 5_000
|
||||||
|
|
||||||
config :pleroma, :pools,
|
config :pleroma, :pools,
|
||||||
federation: [
|
federation: [
|
||||||
size: 50,
|
size: 50,
|
||||||
max_overflow: 10,
|
max_waiting: 10,
|
||||||
timeout: 150_000
|
recv_timeout: 10_000
|
||||||
],
|
],
|
||||||
media: [
|
media: [
|
||||||
size: 50,
|
size: 50,
|
||||||
max_overflow: 10,
|
max_waiting: 10,
|
||||||
timeout: 150_000
|
recv_timeout: 10_000
|
||||||
],
|
],
|
||||||
upload: [
|
upload: [
|
||||||
size: 25,
|
size: 25,
|
||||||
max_overflow: 5,
|
max_waiting: 5,
|
||||||
timeout: 300_000
|
recv_timeout: 15_000
|
||||||
],
|
],
|
||||||
default: [
|
default: [
|
||||||
size: 10,
|
size: 10,
|
||||||
max_overflow: 2,
|
max_waiting: 2,
|
||||||
timeout: 10_000
|
recv_timeout: 5_000
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :hackney_pools,
|
config :pleroma, :hackney_pools,
|
||||||
|
@ -680,13 +772,30 @@
|
||||||
|
|
||||||
config :pleroma, :majic_pool, size: 2
|
config :pleroma, :majic_pool, size: 2
|
||||||
|
|
||||||
|
private_instance? = :if_instance_is_private
|
||||||
|
|
||||||
config :pleroma, :restrict_unauthenticated,
|
config :pleroma, :restrict_unauthenticated,
|
||||||
timelines: %{local: false, federated: false},
|
timelines: %{local: private_instance?, federated: private_instance?},
|
||||||
profiles: %{local: false, remote: false},
|
profiles: %{local: private_instance?, remote: private_instance?},
|
||||||
activities: %{local: false, remote: false}
|
activities: %{local: private_instance?, remote: private_instance?}
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
||||||
|
|
||||||
|
config :pleroma, :mrf,
|
||||||
|
policies: Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy,
|
||||||
|
transparency: true,
|
||||||
|
transparency_exclusions: []
|
||||||
|
|
||||||
|
config :tzdata, :http_client, Pleroma.HTTP.Tzdata
|
||||||
|
|
||||||
|
config :ex_aws, http_client: Pleroma.HTTP.ExAws
|
||||||
|
|
||||||
|
config :pleroma, :instances_favicons, enabled: false
|
||||||
|
|
||||||
|
config :floki, :html_parser, Floki.HTMLParser.FastHtml
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator
|
||||||
|
|
||||||
# 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"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,10 @@
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: []
|
config :pleroma, :auth, oauth_consumer_strategies: []
|
||||||
|
|
||||||
config :pleroma, Pleroma.Upload, filters: [], link_name: false
|
config :pleroma, Pleroma.Upload,
|
||||||
|
filters: [],
|
||||||
|
link_name: false,
|
||||||
|
default_description: :filename
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
||||||
|
|
||||||
|
@ -79,8 +82,8 @@
|
||||||
|
|
||||||
config :pleroma, Oban,
|
config :pleroma, Oban,
|
||||||
queues: false,
|
queues: false,
|
||||||
prune: :disabled,
|
crontab: false,
|
||||||
crontab: false
|
plugins: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
config :pleroma, Pleroma.ScheduledActivity,
|
||||||
daily_user_limit: 2,
|
daily_user_limit: 2,
|
||||||
|
@ -111,6 +114,15 @@
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
|
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Uploaders.S3,
|
||||||
|
bucket: nil,
|
||||||
|
streaming_enabled: true,
|
||||||
|
public_endpoint: nil
|
||||||
|
|
||||||
|
config :tzdata, :autoupdate, :disabled
|
||||||
|
|
||||||
|
config :pleroma, :mrf, policies: []
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -19,6 +19,7 @@ Configuration options:
|
||||||
- `local`: only local users
|
- `local`: only local users
|
||||||
- `external`: only external users
|
- `external`: only external users
|
||||||
- `active`: only active users
|
- `active`: only active users
|
||||||
|
- `need_approval`: only unapproved users
|
||||||
- `deactivated`: only deactivated users
|
- `deactivated`: only deactivated users
|
||||||
- `is_admin`: users with admin role
|
- `is_admin`: users with admin role
|
||||||
- `is_moderator`: users with moderator role
|
- `is_moderator`: users with moderator role
|
||||||
|
@ -46,7 +47,10 @@ Configuration options:
|
||||||
"local": bool,
|
"local": bool,
|
||||||
"tags": array,
|
"tags": array,
|
||||||
"avatar": string,
|
"avatar": string,
|
||||||
"display_name": string
|
"display_name": string,
|
||||||
|
"confirmation_pending": bool,
|
||||||
|
"approval_pending": bool,
|
||||||
|
"registration_reason": string,
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
|
@ -242,6 +246,24 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `PATCH /api/pleroma/admin/users/approve`
|
||||||
|
|
||||||
|
### Approve user
|
||||||
|
|
||||||
|
- Params:
|
||||||
|
- `nicknames`: nicknames array
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
users: [
|
||||||
|
{
|
||||||
|
// user object
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/users/:nickname_or_id`
|
## `GET /api/pleroma/admin/users/:nickname_or_id`
|
||||||
|
|
||||||
### Retrive the details of a user
|
### Retrive the details of a user
|
||||||
|
@ -291,31 +313,53 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- On failure: `Not found`
|
- On failure: `Not found`
|
||||||
- On success: JSON array of user's latest statuses
|
- On success: JSON array of user's latest statuses
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/relay`
|
||||||
|
|
||||||
|
### List Relays
|
||||||
|
|
||||||
|
Params: none
|
||||||
|
Response:
|
||||||
|
|
||||||
|
* On success: JSON array of relays
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{"actor": "https://example.com/relay", "followed_back": true},
|
||||||
|
{"actor": "https://example2.com/relay", "followed_back": false}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## `POST /api/pleroma/admin/relay`
|
## `POST /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Follow a Relay
|
### Follow a Relay
|
||||||
|
|
||||||
- Params:
|
Params:
|
||||||
- `relay_url`
|
|
||||||
- Response:
|
* `relay_url`
|
||||||
- On success: URL of the followed relay
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
* On success: relay json object
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"actor": "https://example.com/relay", "followed_back": true}
|
||||||
|
```
|
||||||
|
|
||||||
## `DELETE /api/pleroma/admin/relay`
|
## `DELETE /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Unfollow a Relay
|
### Unfollow a Relay
|
||||||
|
|
||||||
- Params:
|
Params:
|
||||||
- `relay_url`
|
|
||||||
- Response:
|
|
||||||
- On success: URL of the unfollowed relay
|
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/relay`
|
* `relay_url`
|
||||||
|
|
||||||
### List Relays
|
Response:
|
||||||
|
|
||||||
- Params: none
|
* On success: URL of the unfollowed relay
|
||||||
- Response:
|
|
||||||
- On success: JSON array of relays
|
```json
|
||||||
|
{"https://example.com/relay"}
|
||||||
|
```
|
||||||
|
|
||||||
## `POST /api/pleroma/admin/users/invite_token`
|
## `POST /api/pleroma/admin/users/invite_token`
|
||||||
|
|
||||||
|
@ -488,35 +532,39 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
|
|
||||||
### Change the user's email, password, display and settings-related fields
|
### Change the user's email, password, display and settings-related fields
|
||||||
|
|
||||||
- Params:
|
* Params:
|
||||||
- `email`
|
* `email`
|
||||||
- `password`
|
* `password`
|
||||||
- `name`
|
* `name`
|
||||||
- `bio`
|
* `bio`
|
||||||
- `avatar`
|
* `avatar`
|
||||||
- `locked`
|
* `locked`
|
||||||
- `no_rich_text`
|
* `no_rich_text`
|
||||||
- `default_scope`
|
* `default_scope`
|
||||||
- `banner`
|
* `banner`
|
||||||
- `hide_follows`
|
* `hide_follows`
|
||||||
- `hide_followers`
|
* `hide_followers`
|
||||||
- `hide_followers_count`
|
* `hide_followers_count`
|
||||||
- `hide_follows_count`
|
* `hide_follows_count`
|
||||||
- `hide_favorites`
|
* `hide_favorites`
|
||||||
- `allow_following_move`
|
* `allow_following_move`
|
||||||
- `background`
|
* `background`
|
||||||
- `show_role`
|
* `show_role`
|
||||||
- `skip_thread_containment`
|
* `skip_thread_containment`
|
||||||
- `fields`
|
* `fields`
|
||||||
- `discoverable`
|
* `discoverable`
|
||||||
- `actor_type`
|
* `actor_type`
|
||||||
|
|
||||||
- Response:
|
* Responses:
|
||||||
|
|
||||||
|
Status: 200
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"status": "success"}
|
{"status": "success"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Status: 400
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"errors":
|
{"errors":
|
||||||
{"actor_type": "is invalid"},
|
{"actor_type": "is invalid"},
|
||||||
|
@ -525,8 +573,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Status: 404
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"error": "Unable to update user."}
|
{"error": "Not found"}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `GET /api/pleroma/admin/reports`
|
## `GET /api/pleroma/admin/reports`
|
||||||
|
@ -1112,6 +1162,10 @@ Loads json generated from `config/descriptions.exs`.
|
||||||
|
|
||||||
### Stats
|
### Stats
|
||||||
|
|
||||||
|
- Query Params:
|
||||||
|
- *optional* `instance`: **string** instance hostname (without protocol) to get stats for
|
||||||
|
- Example: `https://mypleroma.org/api/pleroma/admin/stats?instance=lain.com`
|
||||||
|
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
@ -1225,3 +1279,58 @@ Loads json generated from `config/descriptions.exs`.
|
||||||
- On success: `204`, empty response
|
- On success: `204`, empty response
|
||||||
- On failure:
|
- On failure:
|
||||||
- 400 Bad Request `"Invalid parameters"` when `status` is missing
|
- 400 Bad Request `"Invalid parameters"` when `status` is missing
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/media_proxy_caches`
|
||||||
|
|
||||||
|
### Get a list of all banned MediaProxy URLs in Cachex
|
||||||
|
|
||||||
|
- Authentication: required
|
||||||
|
- Params:
|
||||||
|
- *optional* `page`: **integer** page number
|
||||||
|
- *optional* `page_size`: **integer** number of log entries per page (default is `50`)
|
||||||
|
- *optional* `query`: **string** search term
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
``` json
|
||||||
|
{
|
||||||
|
"page_size": integer,
|
||||||
|
"count": integer,
|
||||||
|
"urls": [
|
||||||
|
"http://example.com/media/a688346.jpg",
|
||||||
|
"http://example.com/media/fb1f4d.jpg"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## `POST /api/pleroma/admin/media_proxy_caches/delete`
|
||||||
|
|
||||||
|
### Remove a banned MediaProxy URL from Cachex
|
||||||
|
|
||||||
|
- Authentication: required
|
||||||
|
- Params:
|
||||||
|
- `urls` (array)
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
``` json
|
||||||
|
{ }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## `POST /api/pleroma/admin/media_proxy_caches/purge`
|
||||||
|
|
||||||
|
### Purge a MediaProxy URL
|
||||||
|
|
||||||
|
- Authentication: required
|
||||||
|
- Params:
|
||||||
|
- `urls` (array)
|
||||||
|
- `ban` (boolean)
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
``` json
|
||||||
|
{ }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
|
@ -27,6 +27,7 @@ Has these additional fields under the `pleroma` object:
|
||||||
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
||||||
- `thread_muted`: true if the thread the post belongs to is muted
|
- `thread_muted`: true if the thread the post belongs to is muted
|
||||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 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.
|
||||||
|
|
||||||
## Media Attachments
|
## Media Attachments
|
||||||
|
|
||||||
|
@ -51,21 +52,27 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `ap_id`: nullable URL string, ActivityPub id of the user
|
||||||
|
- `background_image`: nullable URL string, background image of the user
|
||||||
- `tags`: Lists an array of tags for the user
|
- `tags`: Lists an array of tags for the user
|
||||||
- `relationship{}`: Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
|
- `relationship` (object): Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
|
||||||
- `is_moderator`: boolean, nullable, true if user is a moderator
|
- `is_moderator`: boolean, nullable, true if user is a moderator
|
||||||
- `is_admin`: boolean, nullable, true if user is an admin
|
- `is_admin`: boolean, nullable, true if user is an admin
|
||||||
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
||||||
|
- `hide_favorites`: boolean, true when the user has hiding favorites enabled
|
||||||
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
||||||
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
||||||
- `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
|
- `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
|
||||||
- `hide_follows_count`: boolean, true when the user has follow stat hiding enabled
|
- `hide_follows_count`: boolean, true when the user has follow stat hiding enabled
|
||||||
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
|
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `/api/v1/accounts/verify_credentials` and `/api/v1/accounts/update_credentials`
|
||||||
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
|
- `chat_token`: The token needed for Pleroma chat. Only returned in `/api/v1/accounts/verify_credentials`
|
||||||
- `deactivated`: boolean, true when the user is deactivated
|
- `deactivated`: boolean, true when the user is deactivated
|
||||||
- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
|
- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
|
||||||
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
||||||
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
|
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
|
||||||
|
- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
|
||||||
|
- `accepts_chat_messages`: boolean, but can be null if we don't have that information about a user
|
||||||
|
- `favicon`: nullable URL string, Favicon image of the user's instance
|
||||||
|
|
||||||
### Source
|
### Source
|
||||||
|
|
||||||
|
@ -162,7 +169,7 @@ Returns: array of Status.
|
||||||
|
|
||||||
The maximum number of statuses is limited to 100 per request.
|
The maximum number of statuses is limited to 100 per request.
|
||||||
|
|
||||||
## PATCH `/api/v1/update_credentials`
|
## PATCH `/api/v1/accounts/update_credentials`
|
||||||
|
|
||||||
Additional parameters can be added to the JSON body/Form data:
|
Additional parameters can be added to the JSON body/Form data:
|
||||||
|
|
||||||
|
@ -177,9 +184,12 @@ Additional parameters can be added to the JSON body/Form data:
|
||||||
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
||||||
- `skip_thread_containment` - if true, skip filtering out broken threads
|
- `skip_thread_containment` - if true, skip filtering out broken threads
|
||||||
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
||||||
- `pleroma_background_image` - sets the background image of the user.
|
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
|
||||||
- `discoverable` - if true, discovery of this account in search results and other services is allowed.
|
- `discoverable` - if true, discovery of this account in search results and other services is allowed.
|
||||||
- `actor_type` - the type of this account.
|
- `actor_type` - the type of this account.
|
||||||
|
- `accepts_chat_messages` - if false, this account will reject all chat messages.
|
||||||
|
|
||||||
|
All images (avatar, banner and background) can be reset to the default by sending an empty string ("") instead of a file.
|
||||||
|
|
||||||
### Pleroma Settings Store
|
### Pleroma Settings Store
|
||||||
|
|
||||||
|
@ -187,7 +197,7 @@ Pleroma has mechanism that allows frontends to save blobs of json for each user
|
||||||
|
|
||||||
The parameter should have a form of `{frontend_name: {...}}`, with `frontend_name` identifying your type of client, e.g. `pleroma_fe`. It will overwrite everything under this property, but will not overwrite other frontend's settings.
|
The parameter should have a form of `{frontend_name: {...}}`, with `frontend_name` identifying your type of client, e.g. `pleroma_fe`. It will overwrite everything under this property, but will not overwrite other frontend's settings.
|
||||||
|
|
||||||
This information is returned in the `verify_credentials` endpoint.
|
This information is returned in the `/api/v1/accounts/verify_credentials` endpoint.
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
|
@ -215,6 +225,8 @@ Has theses 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
|
||||||
|
- `chat_limit`: The maximum characters per chat message
|
||||||
|
- `description_limit`: The maximum characters per image description
|
||||||
- `poll_limits`: The limits of polls
|
- `poll_limits`: The limits of polls
|
||||||
- `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
|
||||||
|
@ -223,6 +235,8 @@ Has theses additional parameters (which are the same as in Pleroma-API):
|
||||||
- `background_image`: A background image that frontends can use
|
- `background_image`: A background image that frontends can use
|
||||||
- `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.post_formats`: A list of the allowed post format types
|
||||||
- `vapid_public_key`: The public key needed for push messages
|
- `vapid_public_key`: The public key needed for push messages
|
||||||
|
|
||||||
## Markers
|
## Markers
|
||||||
|
@ -234,3 +248,43 @@ Has these additional fields under the `pleroma` object:
|
||||||
## Streaming
|
## Streaming
|
||||||
|
|
||||||
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
||||||
|
|
||||||
|
## Not implemented
|
||||||
|
|
||||||
|
Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer features and non-essential features are omitted. These features usually return an HTTP 200 status code, but with an empty response. While they may be added in the future, they are considered low priority.
|
||||||
|
|
||||||
|
### Suggestions
|
||||||
|
|
||||||
|
*Added in Mastodon 2.4.3*
|
||||||
|
|
||||||
|
- `GET /api/v1/suggestions`: Returns an empty array, `[]`
|
||||||
|
|
||||||
|
### Trends
|
||||||
|
|
||||||
|
*Added in Mastodon 3.0.0*
|
||||||
|
|
||||||
|
- `GET /api/v1/trends`: Returns an empty array, `[]`
|
||||||
|
|
||||||
|
### Identity proofs
|
||||||
|
|
||||||
|
*Added in Mastodon 2.8.0*
|
||||||
|
|
||||||
|
- `GET /api/v1/identity_proofs`: Returns an empty array, `[]`
|
||||||
|
|
||||||
|
### Endorsements
|
||||||
|
|
||||||
|
*Added in Mastodon 2.5.0*
|
||||||
|
|
||||||
|
- `GET /api/v1/endorsements`: Returns an empty array, `[]`
|
||||||
|
|
||||||
|
### Profile directory
|
||||||
|
|
||||||
|
*Added in Mastodon 3.0.0*
|
||||||
|
|
||||||
|
- `GET /api/v1/directory`: Returns HTTP 404
|
||||||
|
|
||||||
|
### Featured tags
|
||||||
|
|
||||||
|
*Added in Mastodon 3.0.0*
|
||||||
|
|
||||||
|
- `GET /api/v1/featured_tags`: Returns HTTP 404
|
||||||
|
|
|
@ -50,7 +50,7 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi
|
||||||
* Authentication: not required
|
* Authentication: not required
|
||||||
* Params: none
|
* Params: none
|
||||||
* Response: Provider specific JSON, the only guaranteed parameter is `type`
|
* Response: Provider specific JSON, the only guaranteed parameter is `type`
|
||||||
* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint"}`
|
* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint", "seconds_valid": 300}`
|
||||||
|
|
||||||
## `/api/pleroma/delete_account`
|
## `/api/pleroma/delete_account`
|
||||||
### Delete an account
|
### Delete an account
|
||||||
|
@ -287,11 +287,8 @@ See [Admin-API](admin_api.md)
|
||||||
* Method `PUT`
|
* Method `PUT`
|
||||||
* Authentication: required
|
* Authentication: required
|
||||||
* Params:
|
* Params:
|
||||||
* `followers`: BOOLEAN field, receives notifications from followers
|
* `block_from_strangers`: BOOLEAN field, blocks notifications from accounts you do not follow
|
||||||
* `follows`: BOOLEAN field, receives notifications from people the user follows
|
* `hide_notification_contents`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
|
||||||
* `remote`: BOOLEAN field, receives notifications from people on remote instances
|
|
||||||
* `local`: BOOLEAN field, receives notifications from people on the local instance
|
|
||||||
* `privacy_option`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
|
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
|
||||||
|
|
||||||
## `/api/pleroma/healthcheck`
|
## `/api/pleroma/healthcheck`
|
||||||
|
@ -450,18 +447,44 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
|
||||||
* Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message.
|
* Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message.
|
||||||
|
|
||||||
## `GET /api/pleroma/emoji/packs`
|
## `GET /api/pleroma/emoji/packs`
|
||||||
|
|
||||||
### Lists local custom emoji packs
|
### Lists local custom emoji packs
|
||||||
|
|
||||||
* Method `GET`
|
* Method `GET`
|
||||||
* Authentication: not required
|
* Authentication: not required
|
||||||
* Params: None
|
* Params:
|
||||||
* Response: JSON, "ok" and 200 status and the JSON hashmap of pack name to pack contents
|
* `page`: page number for packs (default 1)
|
||||||
|
* `page_size`: page size for packs (default 50)
|
||||||
|
* Response: `packs` key with JSON hashmap of pack name to pack contents and `count` key for count of packs.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"packs": {
|
||||||
|
"pack_name": {...}, // pack contents
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"count": 0 // packs count
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## `GET /api/pleroma/emoji/packs/:name`
|
## `GET /api/pleroma/emoji/packs/:name`
|
||||||
|
|
||||||
### Get pack.json for the pack
|
### Get pack.json for the pack
|
||||||
|
|
||||||
* Method `GET`
|
* Method `GET`
|
||||||
* Authentication: not required
|
* Authentication: not required
|
||||||
* Params: None
|
* Params:
|
||||||
* Response: JSON, pack json with `files` and `pack` keys with 200 status or 404 if the pack does not exist
|
* `page`: page number for files (default 1)
|
||||||
|
* `page_size`: page size for files (default 30)
|
||||||
|
* Response: JSON, pack json with `files`, `files_count` and `pack` keys with 200 status or 404 if the pack does not exist.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"files": {...},
|
||||||
|
"files_count": 0, // emoji count in pack
|
||||||
|
"pack": {...}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## `GET /api/pleroma/emoji/packs/:name/archive`
|
## `GET /api/pleroma/emoji/packs/:name/archive`
|
||||||
### Requests a local pack archive from the instance
|
### Requests a local pack archive from the instance
|
||||||
|
|
|
@ -11,15 +11,18 @@
|
||||||
config :pleroma, configurable_from_database: true
|
config :pleroma, configurable_from_database: true
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl config migrate_to_db
|
./bin/pleroma_ctl config migrate_to_db
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.config migrate_to_db
|
mix pleroma.config migrate_to_db
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Transfer config from DB to `config/env.exported_from_db.secret.exs`
|
## Transfer config from DB to `config/env.exported_from_db.secret.exs`
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
|
@ -31,10 +34,12 @@ mix pleroma.config migrate_to_db
|
||||||
|
|
||||||
To delete transfered settings from database optional flag `-d` can be used. `<env>` is `prod` by default.
|
To delete transfered settings from database optional flag `-d` can be used. `<env>` is `prod` by default.
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl config migrate_from_db [--env=<env>] [-d]
|
./bin/pleroma_ctl config migrate_from_db [--env=<env>] [-d]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
```sh
|
||||||
mix pleroma.config migrate_from_db [--env=<env>] [-d]
|
mix pleroma.config migrate_from_db [--env=<env>] [-d]
|
||||||
```
|
```
|
||||||
|
|
|
@ -9,14 +9,19 @@
|
||||||
|
|
||||||
Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once if the instance was created before Pleroma 1.0.5. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration.
|
Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once if the instance was created before Pleroma 1.0.5. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration.
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database remove_embedded_objects [option ...]
|
./bin/pleroma_ctl database remove_embedded_objects [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
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
|
||||||
|
|
||||||
|
@ -27,11 +32,15 @@ This will prune remote posts older than 90 days (configurable with [`config :ple
|
||||||
!!! 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.
|
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.
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database prune_objects [option ...]
|
./bin/pleroma_ctl database prune_objects [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database prune_objects [option ...]
|
mix pleroma.database prune_objects [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -42,31 +51,43 @@ mix pleroma.database prune_objects [option ...]
|
||||||
|
|
||||||
Can be safely re-run
|
Can be safely re-run
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database bump_all_conversations
|
./bin/pleroma_ctl database bump_all_conversations
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database bump_all_conversations
|
mix pleroma.database bump_all_conversations
|
||||||
```
|
```
|
||||||
|
|
||||||
## Remove duplicated items from following and update followers count for all users
|
## Remove duplicated items from following and update followers count for all users
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database update_users_following_followers_counts
|
./bin/pleroma_ctl database update_users_following_followers_counts
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database update_users_following_followers_counts
|
mix pleroma.database update_users_following_followers_counts
|
||||||
```
|
```
|
||||||
|
|
||||||
## Fix the pre-existing "likes" collections for all objects
|
## Fix the pre-existing "likes" collections for all objects
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database fix_likes_collections
|
./bin/pleroma_ctl database fix_likes_collections
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database fix_likes_collections
|
mix pleroma.database fix_likes_collections
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -76,11 +97,15 @@ mix pleroma.database fix_likes_collections
|
||||||
|
|
||||||
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.**
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database vacuum analyze
|
./bin/pleroma_ctl database vacuum analyze
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database vacuum analyze
|
mix pleroma.database vacuum analyze
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -91,10 +116,28 @@ and more compact files with an optimized layout. This process will take a long t
|
||||||
it builds the files side-by-side the existing database files. It can make your database faster and use less disk space,
|
it builds the files side-by-side the existing database files. It can make your database faster and use less disk space,
|
||||||
but should only be run if necessary. **It is safe to cancel this.**
|
but should only be run if necessary. **It is safe to cancel this.**
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl database vacuum full
|
./bin/pleroma_ctl database vacuum full
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.database vacuum full
|
mix pleroma.database vacuum full
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Add expiration to all local statuses
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl database ensure_expiration
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mix pleroma.database ensure_expiration
|
||||||
|
```
|
||||||
|
|
|
@ -4,22 +4,30 @@
|
||||||
|
|
||||||
## Send digest email since given date (user registration date by default) ignoring user activity status.
|
## Send digest email since given date (user registration date by default) ignoring user activity status.
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl digest test <nickname> [since_date]
|
./bin/pleroma_ctl digest test <nickname> [since_date]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.digest test <nickname> [since_date]
|
mix pleroma.digest test <nickname> [since_date]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl digest test donaldtheduck 2019-05-20
|
./bin/pleroma_ctl digest test donaldtheduck 2019-05-20
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.digest test donaldtheduck 2019-05-20
|
mix pleroma.digest test donaldtheduck 2019-05-20
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -4,21 +4,29 @@
|
||||||
|
|
||||||
## Send test email (instance email by default)
|
## Send test email (instance email by default)
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl email test [--to <destination email address>]
|
./bin/pleroma_ctl email test [--to <destination email address>]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.email test [--to <destination email address>]
|
mix pleroma.email test [--to <destination email address>]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl email test --to root@example.org
|
./bin/pleroma_ctl email test --to root@example.org
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.email test --to root@example.org
|
mix pleroma.email test --to root@example.org
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
|
|
||||||
## Lists emoji packs and metadata specified in the manifest
|
## Lists emoji packs and metadata specified in the manifest
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl emoji ls-packs [option ...]
|
./bin/pleroma_ctl emoji ls-packs [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
```sh
|
||||||
mix pleroma.emoji ls-packs [option ...]
|
mix pleroma.emoji ls-packs [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -18,11 +20,13 @@ mix pleroma.emoji ls-packs [option ...]
|
||||||
|
|
||||||
## Fetch, verify and install the specified packs from the manifest into `STATIC-DIR/emoji/PACK-NAME`
|
## Fetch, verify and install the specified packs from the manifest into `STATIC-DIR/emoji/PACK-NAME`
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl emoji get-packs [option ...] <pack ...>
|
./bin/pleroma_ctl emoji get-packs [option ...] <pack ...>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
```sh
|
||||||
mix pleroma.emoji get-packs [option ...] <pack ...>
|
mix pleroma.emoji get-packs [option ...] <pack ...>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -31,11 +35,13 @@ mix pleroma.emoji get-packs [option ...] <pack ...>
|
||||||
|
|
||||||
## Create a new manifest entry and a file list from the specified remote pack file
|
## Create a new manifest entry and a file list from the specified remote pack file
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl emoji gen-pack PACK-URL
|
./bin/pleroma_ctl emoji gen-pack PACK-URL
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
```sh
|
||||||
mix pleroma.emoji gen-pack PACK-URL
|
mix pleroma.emoji gen-pack PACK-URL
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -47,7 +53,8 @@ Currently, only .zip archives are recognized as remote pack files and packs are
|
||||||
|
|
||||||
## Reload emoji packs
|
## Reload emoji packs
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl emoji reload
|
./bin/pleroma_ctl emoji reload
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
69
docs/administration/CLI_tasks/frontend.md
Normal file
69
docs/administration/CLI_tasks/frontend.md
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
# Managing frontends
|
||||||
|
|
||||||
|
`mix pleroma.frontend install <frontend> [--ref <ref>] [--file <file>] [--build-url <build-url>] [--path <path>] [--build-dir <build-dir>]`
|
||||||
|
|
||||||
|
Frontend can be installed either from local zip file, or automatically downloaded from the web.
|
||||||
|
|
||||||
|
You can give all the options directly on the command like, but missing information will be filled out by looking at the data configured under `frontends.available` in the config files.
|
||||||
|
|
||||||
|
Currently known `<frontend>` values are:
|
||||||
|
- [admin-fe](https://git.pleroma.social/pleroma/admin-fe)
|
||||||
|
- [kenoma](http://git.pleroma.social/lambadalambda/kenoma)
|
||||||
|
- [pleroma-fe](http://git.pleroma.social/pleroma/pleroma-fe)
|
||||||
|
- [fedi-fe](https://git.pleroma.social/pleroma/fedi-fe)
|
||||||
|
- [soapbox-fe](https://gitlab.com/soapbox-pub/soapbox-fe)
|
||||||
|
|
||||||
|
You can still install frontends that are not configured, see below.
|
||||||
|
|
||||||
|
## Example installations for a known frontend
|
||||||
|
|
||||||
|
For a frontend configured under the `available` key, it's enough to install it by name.
|
||||||
|
|
||||||
|
```sh tab="OTP"
|
||||||
|
./bin/pleroma_ctl frontend install pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh tab="From Source"
|
||||||
|
mix pleroma.frontend install pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
This will download the latest build for the the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
|
||||||
|
|
||||||
|
You can override any of the details. To install a pleroma build from a different url, you could do this:
|
||||||
|
|
||||||
|
```sh tab="OPT"
|
||||||
|
./bin/pleroma_ctl frontend install pleroma --ref 2hu_edition --build-url https://example.org/raymoo.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh tab="From Source"
|
||||||
|
mix pleroma.frontend install pleroma --ref 2hu_edition --build-url https://example.org/raymoo.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, you can also install from a local zip file.
|
||||||
|
|
||||||
|
```sh tab="OTP"
|
||||||
|
./bin/pleroma_ctl frontend install pleroma --ref mybuild --file ~/Downloads/doomfe.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh tab="From Source"
|
||||||
|
mix pleroma.frontend install pleroma --ref mybuild --file ~/Downloads/doomfe.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting frontend will always be installed into a folder of this template: `${instance_static}/frontends/${name}/${ref}`
|
||||||
|
|
||||||
|
Careful: This folder will be completely replaced on installation
|
||||||
|
|
||||||
|
## Example installation for an unknown frontend
|
||||||
|
|
||||||
|
The installation process is the same, but you will have to give all the needed options on the commond line. For example:
|
||||||
|
|
||||||
|
```sh tab="OTP"
|
||||||
|
./bin/pleroma_ctl frontend install gensokyo --ref master --build-url https://gensokyo.2hu/builds/marisa.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh tab="From Source"
|
||||||
|
mix pleroma.frontend install gensokyo --ref master --build-url https://gensokyo.2hu/builds/marisa.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't have a zip file but just want to install a frontend from a local path, you can simply copy the files over a folder of this template: `${instance_static}/frontends/${name}/${ref}`
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
||||||
|
|
||||||
## Generate a new configuration file
|
## Generate a new configuration file
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl instance gen [option ...]
|
./bin/pleroma_ctl instance gen [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.instance gen [option ...]
|
mix pleroma.instance gen [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,14 @@
|
||||||
Optional params:
|
Optional params:
|
||||||
* `-s SCOPES` - scopes for app, e.g. `read,write,follow,push`.
|
* `-s SCOPES` - scopes for app, e.g. `read,write,follow,push`.
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl app create -n APP_NAME -r REDIRECT_URI
|
./bin/pleroma_ctl app create -n APP_NAME -r REDIRECT_URI
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.app create -n APP_NAME -r REDIRECT_URI
|
mix pleroma.app create -n APP_NAME -r REDIRECT_URI
|
||||||
```
|
```
|
|
@ -4,30 +4,42 @@
|
||||||
|
|
||||||
## Follow a relay
|
## Follow a relay
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl relay follow <relay_url>
|
./bin/pleroma_ctl relay follow <relay_url>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.relay follow <relay_url>
|
mix pleroma.relay follow <relay_url>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Unfollow a remote relay
|
## Unfollow a remote relay
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl relay unfollow <relay_url>
|
./bin/pleroma_ctl relay unfollow <relay_url>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.relay unfollow <relay_url>
|
mix pleroma.relay unfollow <relay_url>
|
||||||
```
|
```
|
||||||
|
|
||||||
## List relay subscriptions
|
## List relay subscriptions
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl relay list
|
./bin/pleroma_ctl relay list
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.relay list
|
mix pleroma.relay list
|
||||||
```
|
```
|
||||||
|
|
21
docs/administration/CLI_tasks/robots_txt.md
Normal file
21
docs/administration/CLI_tasks/robots_txt.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Managing robots.txt
|
||||||
|
|
||||||
|
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
||||||
|
|
||||||
|
## Generate a new robots.txt file and add it to the static directory
|
||||||
|
|
||||||
|
The `robots.txt` that ships by default is permissive. It allows well-behaved search engines to index all of your instance's URIs.
|
||||||
|
|
||||||
|
If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance [static directory](../../../configuration/static_dir/).
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl robots_txt disallow_all
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mix pleroma.robots_txt disallow_all
|
||||||
|
```
|
|
@ -3,11 +3,15 @@
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
||||||
|
|
||||||
## Migrate uploads from local to remote storage
|
## Migrate uploads from local to remote storage
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl uploads migrate_local <target_uploader> [option ...]
|
./bin/pleroma_ctl uploads migrate_local <target_uploader> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.uploads migrate_local <target_uploader> [option ...]
|
mix pleroma.uploads migrate_local <target_uploader> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
|
|
||||||
## Create a user
|
## Create a user
|
||||||
|
|
||||||
```sh tab="OTP"
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user new <nickname> <email> [option ...]
|
./bin/pleroma_ctl user new <nickname> <email> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user new <nickname> <email> [option ...]
|
mix pleroma.user new <nickname> <email> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -22,21 +26,31 @@ mix pleroma.user new <nickname> <email> [option ...]
|
||||||
- `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions
|
- `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions
|
||||||
|
|
||||||
## List local users
|
## List local users
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user list
|
./bin/pleroma_ctl user list
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user list
|
mix pleroma.user list
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Generate an invite link
|
## Generate an invite link
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user invite [option ...]
|
./bin/pleroma_ctl user invite [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user invite [option ...]
|
mix pleroma.user invite [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -46,111 +60,166 @@ mix pleroma.user invite [option ...]
|
||||||
- `--max-use NUMBER` - maximum numbers of token uses
|
- `--max-use NUMBER` - maximum numbers of token uses
|
||||||
|
|
||||||
## List generated invites
|
## List generated invites
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user invites
|
./bin/pleroma_ctl user invites
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user invites
|
mix pleroma.user invites
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Revoke invite
|
## Revoke invite
|
||||||
```sh tab="OTP"
|
|
||||||
./bin/pleroma_ctl user revoke_invite <token_or_id>
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./bin/pleroma_ctl user revoke_invite <token>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
mix pleroma.user revoke_invite <token_or_id>
|
|
||||||
|
```sh
|
||||||
|
mix pleroma.user revoke_invite <token>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Delete a user
|
## Delete a user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user rm <nickname>
|
./bin/pleroma_ctl user rm <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user rm <nickname>
|
mix pleroma.user rm <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Delete user's posts and interactions
|
## Delete user's posts and interactions
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user delete_activities <nickname>
|
./bin/pleroma_ctl user delete_activities <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user delete_activities <nickname>
|
mix pleroma.user delete_activities <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Sign user out from all applications (delete user's OAuth tokens and authorizations)
|
## Sign user out from all applications (delete user's OAuth tokens and authorizations)
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user sign_out <nickname>
|
./bin/pleroma_ctl user sign_out <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user sign_out <nickname>
|
mix pleroma.user sign_out <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Deactivate or activate a user
|
## Deactivate or activate a user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user toggle_activated <nickname>
|
./bin/pleroma_ctl user toggle_activated <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user toggle_activated <nickname>
|
mix pleroma.user toggle_activated <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Deactivate a user and unsubscribes local users from the user
|
## Deactivate a user and unsubscribes local users from the user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user deactivate NICKNAME
|
./bin/pleroma_ctl user deactivate NICKNAME
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user deactivate NICKNAME
|
mix pleroma.user deactivate NICKNAME
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Deactivate all accounts from an instance and unsubscribe local users on it
|
## Deactivate all accounts from an instance and unsubscribe local users on it
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user deactivate_all_from_instance <instance>
|
./bin/pleroma_ctl user deactivate_all_from_instance <instance>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user deactivate_all_from_instance <instance>
|
mix pleroma.user deactivate_all_from_instance <instance>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Create a password reset link for user
|
## Create a password reset link for user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user reset_password <nickname>
|
./bin/pleroma_ctl user reset_password <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user reset_password <nickname>
|
mix pleroma.user reset_password <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Disable Multi Factor Authentication (MFA/2FA) for a user
|
## Disable Multi Factor Authentication (MFA/2FA) for a user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user reset_mfa <nickname>
|
./bin/pleroma_ctl user reset_mfa <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user reset_mfa <nickname>
|
mix pleroma.user reset_mfa <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Set the value of the given user's settings
|
## Set the value of the given user's settings
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user set <nickname> [option ...]
|
./bin/pleroma_ctl user set <nickname> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user set <nickname> [option ...]
|
mix pleroma.user set <nickname> [option ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -160,30 +229,45 @@ mix pleroma.user set <nickname> [option ...]
|
||||||
- `--admin`/`--no-admin` - whether the user should be an admin
|
- `--admin`/`--no-admin` - whether the user should be an admin
|
||||||
|
|
||||||
## Add tags to a user
|
## Add tags to a user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user tag <nickname> <tags>
|
./bin/pleroma_ctl user tag <nickname> <tags>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user tag <nickname> <tags>
|
mix pleroma.user tag <nickname> <tags>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Delete tags from a user
|
## Delete tags from a user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user untag <nickname> <tags>
|
./bin/pleroma_ctl user untag <nickname> <tags>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user untag <nickname> <tags>
|
mix pleroma.user untag <nickname> <tags>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Toggle confirmation status of the user
|
## Toggle confirmation status of the user
|
||||||
```sh tab="OTP"
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```sh
|
||||||
./bin/pleroma_ctl user toggle_confirmed <nickname>
|
./bin/pleroma_ctl user toggle_confirmed <nickname>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="From Source"
|
=== "From Source"
|
||||||
|
|
||||||
|
```sh
|
||||||
mix pleroma.user toggle_confirmed <nickname>
|
mix pleroma.user toggle_confirmed <nickname>
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Updating your instance
|
# Updating your instance
|
||||||
|
|
||||||
You should **always check the release notes/changelog** in case there are config deprecations, special update special update steps, etc.
|
You should **always check the [release notes/changelog](https://git.pleroma.social/pleroma/pleroma/-/releases)** in case there are config deprecations, special update steps, etc.
|
||||||
|
|
||||||
Besides that, doing the following is generally enough:
|
Besides that, doing the following is generally enough:
|
||||||
|
|
||||||
|
@ -18,9 +18,10 @@ su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate"
|
||||||
|
|
||||||
1. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
1. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
||||||
2. Run `git pull`. This pulls the latest changes from upstream.
|
2. Run `git pull`. This pulls the latest changes from upstream.
|
||||||
3. Run `mix deps.get`. This pulls in any new dependencies.
|
3. Run `mix deps.get` [^1]. This pulls in any new dependencies.
|
||||||
4. Stop the Pleroma service.
|
4. Stop the Pleroma service.
|
||||||
5. Run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any.
|
5. Run `mix ecto.migrate` [^1] [^2]. This task performs database migrations, if there were any.
|
||||||
6. Start the Pleroma service.
|
6. Start the Pleroma service.
|
||||||
|
|
||||||
[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
[^1]: Depending on which install guide you followed (for example on Debian/Ubuntu), you want to run `mix` tasks as `pleroma` user by adding `sudo -Hu pleroma` before the command.
|
||||||
|
[^2]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
||||||
|
|
|
@ -6,11 +6,11 @@ Feel free to contact us to be added to this list!
|
||||||
### Roma for Desktop
|
### Roma for Desktop
|
||||||
- Homepage: <https://www.pleroma.com/#desktopApp>
|
- Homepage: <https://www.pleroma.com/#desktopApp>
|
||||||
- Source Code: <https://github.com/roma-apps/roma-desktop>
|
- Source Code: <https://github.com/roma-apps/roma-desktop>
|
||||||
- Platforms: Windows, Mac, (Linux?)
|
- Platforms: Windows, Mac, Linux
|
||||||
- Features: Streaming Ready
|
- Features: Streaming Ready
|
||||||
|
|
||||||
### Social
|
### Social
|
||||||
- Source Code: <https://gitlab.gnome.org/BrainBlasted/Social>
|
- Source Code: <https://gitlab.gnome.org/World/Social>
|
||||||
- Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)
|
- Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)
|
||||||
- Platforms: Linux (GNOME)
|
- Platforms: Linux (GNOME)
|
||||||
- Note(2019-01-28): Not at a pre-alpha stage yet
|
- Note(2019-01-28): Not at a pre-alpha stage yet
|
||||||
|
@ -48,16 +48,9 @@ Feel free to contact us to be added to this list!
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: No Streaming, Emoji Reactions, Text Formatting, FE Stickers
|
- Features: No Streaming, Emoji Reactions, Text Formatting, FE Stickers
|
||||||
|
|
||||||
### Nekonium
|
|
||||||
- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/)
|
|
||||||
- Source: <https://gogs.gdgd.jp.net/lin/nekonium>
|
|
||||||
- Contact: [@lin@pleroma.gdgd.jp.net](https://pleroma.gdgd.jp.net/users/lin)
|
|
||||||
- Platforms: Android
|
|
||||||
- Features: Streaming Ready
|
|
||||||
|
|
||||||
### Fedi
|
### Fedi
|
||||||
- Homepage: <https://www.fediapp.com/>
|
- Homepage: <https://www.fediapp.com/>
|
||||||
- Source Code: Proprietary, but free
|
- Source Code: Proprietary, but gratis
|
||||||
- Platforms: iOS, Android
|
- Platforms: iOS, Android
|
||||||
- Features: Pleroma-specific features like Reactions
|
- Features: Pleroma-specific features like Reactions
|
||||||
|
|
||||||
|
@ -70,9 +63,16 @@ Feel free to contact us to be added to this list!
|
||||||
|
|
||||||
### Twidere
|
### Twidere
|
||||||
- Homepage: <https://twidere.mariotaku.org/>
|
- Homepage: <https://twidere.mariotaku.org/>
|
||||||
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>, <https://github.com/TwidereProject/Twidere-iOS/>
|
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>
|
||||||
- Contact: <me@mariotaku.org>
|
- Contact: <me@mariotaku.org>
|
||||||
- Platform: Android, iOS
|
- Platform: Android
|
||||||
|
- Features: No Streaming
|
||||||
|
|
||||||
|
### Indigenous
|
||||||
|
- Homepage: <https://indigenous.realize.be/>
|
||||||
|
- Source Code: <https://github.com/swentel/indigenous-android/>
|
||||||
|
- Contact: [@realize.be@realize.be](@realize.be@realize.be)
|
||||||
|
- Platforms: Android
|
||||||
- Features: No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
## Alternative Web Interfaces
|
## Alternative Web Interfaces
|
||||||
|
@ -82,11 +82,6 @@ Feel free to contact us to be added to this list!
|
||||||
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
|
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
|
||||||
- Features: No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Feather
|
|
||||||
- Source Code: <https://github.com/kaniini/feather>
|
|
||||||
- Contact: [@kaniini@pleroma.site](https://pleroma.site/kaniini)
|
|
||||||
- Features: No Streaming
|
|
||||||
|
|
||||||
### Halcyon
|
### Halcyon
|
||||||
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
|
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
|
||||||
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
|
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
|
||||||
|
@ -100,6 +95,15 @@ Feel free to contact us to be added to this list!
|
||||||
- Features: No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Sengi
|
### Sengi
|
||||||
|
- Homepage: <https://nicolasconstant.github.io/sengi/>
|
||||||
- Source Code: <https://github.com/NicolasConstant/sengi>
|
- Source Code: <https://github.com/NicolasConstant/sengi>
|
||||||
- Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app)
|
- Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app)
|
||||||
- Note(2019-01-28): The development is currently in a early stage.
|
|
||||||
|
### DashFE
|
||||||
|
- Source Code: <https://notabug.org/daisuke/DashboardFE>
|
||||||
|
- Contact: [@dashfe@stereophonic.space](https://stereophonic.space/users/dashfe)
|
||||||
|
|
||||||
|
### BloatFE
|
||||||
|
- Source Code: <https://git.freesoftwareextremist.com/bloat/>
|
||||||
|
- Contact: [@r@freesoftwareextremist.com](https://freesoftwareextremist.com/users/r)
|
||||||
|
- Features: Does not requires JavaScript
|
||||||
|
|
|
@ -18,6 +18,7 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `notify_email`: Email used for notifications.
|
* `notify_email`: Email used for notifications.
|
||||||
* `description`: The instance’s description, can be seen in nodeinfo and ``/api/v1/instance``.
|
* `description`: The instance’s description, can be seen in nodeinfo and ``/api/v1/instance``.
|
||||||
* `limit`: Posts character limit (CW/Subject included in the counter).
|
* `limit`: Posts character limit (CW/Subject included in the counter).
|
||||||
|
* `discription_limit`: The character limit for image descriptions.
|
||||||
* `chat_limit`: Character limit of the instance chat messages.
|
* `chat_limit`: Character limit of the instance chat messages.
|
||||||
* `remote_limit`: Hard character limit beyond which remote posts will be dropped.
|
* `remote_limit`: Hard character limit beyond which remote posts will be dropped.
|
||||||
* `upload_limit`: File size limit of uploads (except for avatar, background, banner).
|
* `upload_limit`: File size limit of uploads (except for avatar, background, banner).
|
||||||
|
@ -32,37 +33,20 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `registrations_open`: Enable registrations for anyone, invitations can be enabled when false.
|
* `registrations_open`: Enable registrations for anyone, invitations can be enabled when false.
|
||||||
* `invites_enabled`: Enable user invitations for admins (depends on `registrations_open: false`).
|
* `invites_enabled`: Enable user invitations for admins (depends on `registrations_open: false`).
|
||||||
* `account_activation_required`: Require users to confirm their emails before signing in.
|
* `account_activation_required`: Require users to confirm their emails before signing in.
|
||||||
|
* `account_approval_required`: Require users to be manually approved by an admin before signing in.
|
||||||
* `federating`: Enable federation with other instances.
|
* `federating`: Enable federation with other instances.
|
||||||
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.
|
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.
|
||||||
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
|
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
|
||||||
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance.
|
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance.
|
||||||
* `rewrite_policy`: Message Rewrite Policy, either one or a list. Here are the ones available by default:
|
* `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.
|
||||||
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.DropPolicy`: Drops all activities. It generally doesn’t makes sense to use in production.
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.SimplePolicy`: Restrict the visibility of activities from certain instances (See [`:mrf_simple`](#mrf_simple)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.TagPolicy`: Applies policies to individual users based on tags, which can be set using pleroma-fe/admin-fe/any other app that supports Pleroma Admin API. For example it allows marking posts from individual users nsfw (sensitive).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.SubchainPolicy`: Selectively runs other MRF policies when messages match (See [`:mrf_subchain`](#mrf_subchain)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic`: Drops posts with non-public visibility settings (See [`:mrf_rejectnonpublic`](#mrf_rejectnonpublic)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.EnsureRePrepended`: Rewrites posts to ensure that replies to posts with subjects do not have an identical subject and instead begin with re:.
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy`: Rejects posts from likely spambots by rejecting posts from new users that contain links.
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`: Crawls attachments using their MediaProxy URLs so that the MediaProxy cache is primed.
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)).
|
|
||||||
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Adds expiration to all local Create activities (see [`:mrf_activity_expiration`](#mrf_activity_expiration)).
|
|
||||||
* `public`: Makes the client API in authenticated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network.
|
|
||||||
* `quarantined_instances`: List of ActivityPub instances where private (DMs, followers-only) activities will not be send.
|
* `quarantined_instances`: List of ActivityPub instances where private (DMs, followers-only) activities will not be send.
|
||||||
* `managed_config`: Whenether the config for pleroma-fe is configured in [:frontend_configurations](#frontend_configurations) or in ``static/config.json``.
|
* `managed_config`: Whenether the config for pleroma-fe is configured in [:frontend_configurations](#frontend_configurations) or in ``static/config.json``.
|
||||||
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML).
|
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML).
|
||||||
* `mrf_transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
|
||||||
* `mrf_transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
|
||||||
* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with
|
* `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.
|
||||||
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
|
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
|
||||||
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
|
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
|
||||||
* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses.
|
* `attachment_links`: Set to true to enable automatically adding attachment link text to statuses.
|
||||||
* `welcome_message`: A message that will be send to a newly registered users as a direct message.
|
|
||||||
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
|
|
||||||
* `max_report_comment_size`: The maximum size of the report comment (Default: `1000`).
|
* `max_report_comment_size`: The maximum size of the report comment (Default: `1000`).
|
||||||
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). Default: `false`.
|
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). Default: `false`.
|
||||||
* `healthcheck`: If set to true, system data will be shown on ``/api/pleroma/healthcheck``.
|
* `healthcheck`: If set to true, system data will be shown on ``/api/pleroma/healthcheck``.
|
||||||
|
@ -75,14 +59,71 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `max_remote_account_fields`: The maximum number of custom fields in the remote user profile (default: `20`).
|
* `max_remote_account_fields`: The maximum number of custom fields in the remote user profile (default: `20`).
|
||||||
* `account_field_name_length`: An account field name maximum length (default: `512`).
|
* `account_field_name_length`: An account field name maximum length (default: `512`).
|
||||||
* `account_field_value_length`: An account field value maximum length (default: `2048`).
|
* `account_field_value_length`: An account field value maximum length (default: `2048`).
|
||||||
|
* `registration_reason_length`: Maximum registration reason length (default: `500`).
|
||||||
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
|
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
|
||||||
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
|
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
|
||||||
|
* `show_reactions`: Let favourites and emoji reactions be viewed through the API (default: `true`).
|
||||||
|
|
||||||
|
## Welcome
|
||||||
|
* `direct_message`: - welcome message sent as a direct message.
|
||||||
|
* `enabled`: Enables the send a direct message to a newly registered user. Defaults to `false`.
|
||||||
|
* `sender_nickname`: The nickname of the local user that sends the welcome message.
|
||||||
|
* `message`: A message that will be send to a newly registered users as a direct message.
|
||||||
|
* `chat_message`: - welcome message sent as a chat message.
|
||||||
|
* `enabled`: Enables the send a chat message to a newly registered user. Defaults to `false`.
|
||||||
|
* `sender_nickname`: The nickname of the local user that sends the welcome message.
|
||||||
|
* `message`: A message that will be send to a newly registered users as a chat message.
|
||||||
|
* `email`: - welcome message sent as a email.
|
||||||
|
* `enabled`: Enables the send a welcome email to a newly registered user. Defaults to `false`.
|
||||||
|
* `sender`: The email address or tuple with `{nickname, email}` that will use as sender to the welcome email.
|
||||||
|
* `subject`: A subject of welcome email.
|
||||||
|
* `html`: A html that will be send to a newly registered users as a email.
|
||||||
|
* `text`: A text that will be send to a newly registered users as a email.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :welcome,
|
||||||
|
direct_message: [
|
||||||
|
enabled: true,
|
||||||
|
sender_nickname: "lain",
|
||||||
|
message: "Hi! Welcome on board!"
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
enabled: true,
|
||||||
|
sender: {"Pleroma App", "welcome@pleroma.app"},
|
||||||
|
subject: "Welcome to <%= instance_name %>",
|
||||||
|
html: "Welcome to <%= instance_name %>",
|
||||||
|
text: "Welcome to <%= instance_name %>"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Message rewrite facility
|
||||||
|
|
||||||
|
### :mrf
|
||||||
|
* `policies`: Message Rewrite Policy, either one or a list. Here are the ones available by default:
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.DropPolicy`: Drops all activities. It generally doesn’t makes sense to use in production.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.SimplePolicy`: Restrict the visibility of activities from certains instances (See [`:mrf_simple`](#mrf_simple)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.TagPolicy`: Applies policies to individual users based on tags, which can be set using pleroma-fe/admin-fe/any other app that supports Pleroma Admin API. For example it allows marking posts from individual users nsfw (sensitive).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.SubchainPolicy`: Selectively runs other MRF policies when messages match (See [`:mrf_subchain`](#mrf_subchain)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic`: Drops posts with non-public visibility settings (See [`:mrf_rejectnonpublic`](#mrf_rejectnonpublic)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.EnsureRePrepended`: Rewrites posts to ensure that replies to posts with subjects do not have an identical subject and instead begin with re:.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy`: Rejects posts from likely spambots by rejecting posts from new users that contain links.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`: Crawls attachments using their MediaProxy URLs so that the MediaProxy cache is primed.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)).
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.ActivityExpiration` to be enabled for processing the scheduled delections.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
|
||||||
|
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
||||||
|
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
||||||
|
|
||||||
## Federation
|
## Federation
|
||||||
### MRF policies
|
### MRF policies
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Configuring MRF policies is not enough for them to take effect. You have to enable them by specifying their module in `rewrite_policy` under [:instance](#instance) section.
|
Configuring MRF policies is not enough for them to take effect. You have to enable them by specifying their module in `policies` under [:mrf](#mrf) section.
|
||||||
|
|
||||||
#### :mrf_simple
|
#### :mrf_simple
|
||||||
* `media_removal`: List of instances to remove media from.
|
* `media_removal`: List of instances to remove media from.
|
||||||
|
@ -90,6 +131,7 @@ To add configuration to your config file, you can copy it from the base config.
|
||||||
* `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline.
|
* `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline.
|
||||||
* `reject`: List of instances to reject any activities from.
|
* `reject`: List of instances to reject any activities from.
|
||||||
* `accept`: List of instances to accept any activities from.
|
* `accept`: List of instances to accept any activities from.
|
||||||
|
* `followers_only`: List of instances to decrease post visibility to only the followers, including for DM mentions.
|
||||||
* `report_removal`: List of instances to reject reports from.
|
* `report_removal`: List of instances to reject reports from.
|
||||||
* `avatar_removal`: List of instances to strip avatars from.
|
* `avatar_removal`: List of instances to strip avatars from.
|
||||||
* `banner_removal`: List of instances to strip banners from.
|
* `banner_removal`: List of instances to strip banners from.
|
||||||
|
@ -151,7 +193,7 @@ config :pleroma, :mrf_user_allowlist, %{
|
||||||
* `:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines
|
* `:strip_followers` removes followers from the ActivityPub recipient list, ensuring they won't be delivered to home timelines
|
||||||
* `:reject` rejects the message entirely
|
* `:reject` rejects the message entirely
|
||||||
|
|
||||||
#### mrf_steal_emoji
|
#### :mrf_steal_emoji
|
||||||
* `hosts`: List of hosts to steal emojis from
|
* `hosts`: List of hosts to steal emojis from
|
||||||
* `rejected_shortcodes`: Regex-list of shortcodes to reject
|
* `rejected_shortcodes`: Regex-list of shortcodes to reject
|
||||||
* `size_limit`: File size limit (in bytes), checked before an emoji is saved to the disk
|
* `size_limit`: File size limit (in bytes), checked before an emoji is saved to the disk
|
||||||
|
@ -167,6 +209,11 @@ config :pleroma, :mrf_user_allowlist, %{
|
||||||
* `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
|
||||||
|
|
||||||
|
## Pleroma.User
|
||||||
|
|
||||||
|
* `restricted_nicknames`: List of nicknames users may not register with.
|
||||||
|
* `email_blacklist`: List of email domains users may not register with.
|
||||||
|
|
||||||
## Pleroma.ScheduledActivity
|
## Pleroma.ScheduledActivity
|
||||||
|
|
||||||
* `daily_user_limit`: the number of scheduled activities a user is allowed to create in a single day (Default: `25`)
|
* `daily_user_limit`: the number of scheduled activities a user is allowed to create in a single day (Default: `25`)
|
||||||
|
@ -175,6 +222,8 @@ config :pleroma, :mrf_user_allowlist, %{
|
||||||
|
|
||||||
## Pleroma.ActivityExpiration
|
## Pleroma.ActivityExpiration
|
||||||
|
|
||||||
|
Enables the worker which processes posts scheduled for deletion. Pinned posts are exempt from expiration.
|
||||||
|
|
||||||
* `enabled`: whether expired activities will be sent to the job queue to be deleted
|
* `enabled`: whether expired activities will be sent to the job queue to be deleted
|
||||||
|
|
||||||
## Frontends
|
## Frontends
|
||||||
|
@ -248,6 +297,7 @@ This section describe PWA manifest instance-specific values. Currently this opti
|
||||||
* `background_color`: Describe the background color of the app. (Example: `"#191b22"`, `"aliceblue"`).
|
* `background_color`: Describe the background color of the app. (Example: `"#191b22"`, `"aliceblue"`).
|
||||||
|
|
||||||
## :emoji
|
## :emoji
|
||||||
|
|
||||||
* `shortcode_globs`: Location of custom emoji files. `*` can be used as a wildcard. Example `["/emoji/custom/**/*.png"]`
|
* `shortcode_globs`: Location of custom emoji files. `*` can be used as a wildcard. Example `["/emoji/custom/**/*.png"]`
|
||||||
* `pack_extensions`: A list of file extensions for emojis, when no emoji.txt for a pack is present. Example `[".png", ".gif"]`
|
* `pack_extensions`: A list of file extensions for emojis, when no emoji.txt for a pack is present. Example `[".png", ".gif"]`
|
||||||
* `groups`: Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the groupname and the value the location or array of locations. `*` can be used as a wildcard. Example `[Custom: ["/emoji/*.png", "/emoji/custom/*.png"]]`
|
* `groups`: Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the groupname and the value the location or array of locations. `*` can be used as a wildcard. Example `[Custom: ["/emoji/*.png", "/emoji/custom/*.png"]]`
|
||||||
|
@ -256,10 +306,11 @@ This section describe PWA manifest instance-specific values. Currently this opti
|
||||||
memory for this amount of seconds multiplied by the number of files.
|
memory for this amount of seconds multiplied by the number of files.
|
||||||
|
|
||||||
## :media_proxy
|
## :media_proxy
|
||||||
|
|
||||||
* `enabled`: Enables proxying of remote media to the instance’s proxy
|
* `enabled`: Enables proxying of remote media to the instance’s proxy
|
||||||
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
|
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
|
||||||
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
|
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
|
||||||
* `whitelist`: List of domains to bypass the mediaproxy
|
* `whitelist`: List of hosts with scheme to bypass the mediaproxy (e.g. `https://example.com`)
|
||||||
* `invalidation`: options for remove media from cache after delete object:
|
* `invalidation`: options for remove media from cache after delete object:
|
||||||
* `enabled`: Enables purge cache
|
* `enabled`: Enables purge cache
|
||||||
* `provider`: Which one of the [purge cache strategy](#purge-cache-strategy) to use.
|
* `provider`: Which one of the [purge cache strategy](#purge-cache-strategy) to use.
|
||||||
|
@ -268,12 +319,13 @@ This section describe PWA manifest instance-specific values. Currently this opti
|
||||||
|
|
||||||
#### Pleroma.Web.MediaProxy.Invalidation.Script
|
#### Pleroma.Web.MediaProxy.Invalidation.Script
|
||||||
|
|
||||||
This strategy allow perform external bash script to purge cache.
|
This strategy allow perform external shell script to purge cache.
|
||||||
Urls of attachments pass to script as arguments.
|
Urls of attachments pass to script as arguments.
|
||||||
|
|
||||||
* `script_path`: path to external script.
|
* `script_path`: path to external script.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script,
|
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script,
|
||||||
script_path: "./installation/nginx-cache-purge.example"
|
script_path: "./installation/nginx-cache-purge.example"
|
||||||
|
@ -284,8 +336,8 @@ config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script,
|
||||||
This strategy allow perform custom http request to purge cache.
|
This strategy allow perform custom http request to purge cache.
|
||||||
|
|
||||||
* `method`: http method. default is `purge`
|
* `method`: http method. default is `purge`
|
||||||
* `headers`: http headers. default is empty
|
* `headers`: http headers.
|
||||||
* `options`: request options. default is empty
|
* `options`: request options.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```elixir
|
```elixir
|
||||||
|
@ -301,8 +353,6 @@ config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
|
||||||
* `providers`: a list of metadata providers to enable. Providers available:
|
* `providers`: a list of metadata providers to enable. Providers available:
|
||||||
* `Pleroma.Web.Metadata.Providers.OpenGraph`
|
* `Pleroma.Web.Metadata.Providers.OpenGraph`
|
||||||
* `Pleroma.Web.Metadata.Providers.TwitterCard`
|
* `Pleroma.Web.Metadata.Providers.TwitterCard`
|
||||||
* `Pleroma.Web.Metadata.Providers.RelMe` - add links from user bio with rel=me into the `<header>` as `<link rel=me>`.
|
|
||||||
* `Pleroma.Web.Metadata.Providers.Feed` - add a link to a user's Atom feed into the `<header>` as `<link rel=alternate>`.
|
|
||||||
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews.
|
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews.
|
||||||
|
|
||||||
### :rich_media (consumer)
|
### :rich_media (consumer)
|
||||||
|
@ -310,6 +360,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.
|
||||||
|
|
||||||
## HTTP server
|
## HTTP server
|
||||||
|
|
||||||
|
@ -441,37 +492,32 @@ For each pool, the options are:
|
||||||
|
|
||||||
*For `gun` adapter*
|
*For `gun` adapter*
|
||||||
|
|
||||||
Advanced settings for connections pool. Pool with opened connections. These connections can be reused in worker pools.
|
Settings for HTTP connection pool.
|
||||||
|
|
||||||
For big instances it's recommended to increase `config :pleroma, :connections_pool, max_connections: 500` up to 500-1000.
|
* `:connection_acquisition_wait` - Timeout to acquire a connection from pool.The total max time is this value multiplied by the number of retries.
|
||||||
It will increase memory usage, but federation would work faster.
|
* `connection_acquisition_retries` - Number of attempts to acquire the connection from the pool if it is overloaded. Each attempt is timed `:connection_acquisition_wait` apart.
|
||||||
|
* `:max_connections` - Maximum number of connections in the pool.
|
||||||
* `:checkin_timeout` - timeout to checkin connection from pool. Default: 250ms.
|
* `:connect_timeout` - Timeout to connect to the host.
|
||||||
* `:max_connections` - maximum number of connections in the pool. Default: 250 connections.
|
* `:reclaim_multiplier` - Multiplied by `:max_connections` this will be the maximum number of idle connections that will be reclaimed in case the pool is overloaded.
|
||||||
* `:retry` - number of retries, while `gun` will try to reconnect if connection goes down. Default: 1.
|
|
||||||
* `:retry_timeout` - time between retries when `gun` will try to reconnect in milliseconds. Default: 1000ms.
|
|
||||||
* `:await_up_timeout` - timeout while `gun` will wait until connection is up. Default: 5000ms.
|
|
||||||
|
|
||||||
### :pools
|
### :pools
|
||||||
|
|
||||||
*For `gun` adapter*
|
*For `gun` adapter*
|
||||||
|
|
||||||
Advanced settings for workers pools.
|
Settings for request pools. These pools are limited on top of `:connections_pool`.
|
||||||
|
|
||||||
There are four pools used:
|
There are four pools used:
|
||||||
|
|
||||||
* `:federation` for the federation jobs.
|
* `:federation` for the federation jobs. You may want this pool's max_connections to be at least equal to the number of federator jobs + retry queue jobs.
|
||||||
You may want this pool max_connections to be at least equal to the number of federator jobs + retry queue jobs.
|
* `:media` - for rich media, media proxy.
|
||||||
* `:media` for rich media, media proxy
|
* `:upload` - for proxying media when a remote uploader is used and `proxy_remote: true`.
|
||||||
* `:upload` for uploaded media (if using a remote uploader and `proxy_remote: true`)
|
* `:default` - for other requests.
|
||||||
* `:default` for other requests
|
|
||||||
|
|
||||||
For each pool, the options are:
|
For each pool, the options are:
|
||||||
|
|
||||||
* `:size` - how much workers the pool can hold
|
* `:size` - limit to how much requests can be concurrently executed.
|
||||||
* `:timeout` - timeout while `gun` will wait for response
|
* `:recv_timeout` - timeout while `gun` will wait for response
|
||||||
* `:max_overflow` - additional workers if pool is under load
|
* `:max_waiting` - limit to how much requests can be waiting for others to finish, after this is reached, subsequent requests will be dropped.
|
||||||
|
|
||||||
|
|
||||||
## Captcha
|
## Captcha
|
||||||
|
|
||||||
|
@ -490,7 +536,7 @@ A built-in captcha provider. Enabled by default.
|
||||||
#### Pleroma.Captcha.Kocaptcha
|
#### Pleroma.Captcha.Kocaptcha
|
||||||
|
|
||||||
Kocaptcha is a very simple captcha service with a single API endpoint,
|
Kocaptcha is a very simple captcha service with a single API endpoint,
|
||||||
the source code is here: https://github.com/koto-bank/kocaptcha. The default endpoint
|
the source code is here: [kocaptcha](https://github.com/koto-bank/kocaptcha). The default endpoint
|
||||||
`https://captcha.kotobank.ch` is hosted by the developer.
|
`https://captcha.kotobank.ch` is hosted by the developer.
|
||||||
|
|
||||||
* `endpoint`: the Kocaptcha endpoint to use.
|
* `endpoint`: the Kocaptcha endpoint to use.
|
||||||
|
@ -498,6 +544,7 @@ the source code is here: https://github.com/koto-bank/kocaptcha. The default end
|
||||||
## Uploads
|
## Uploads
|
||||||
|
|
||||||
### Pleroma.Upload
|
### Pleroma.Upload
|
||||||
|
|
||||||
* `uploader`: Which one of the [uploaders](#uploaders) to use.
|
* `uploader`: Which one of the [uploaders](#uploaders) to use.
|
||||||
* `filters`: List of [upload filters](#upload-filters) to use.
|
* `filters`: List of [upload filters](#upload-filters) to use.
|
||||||
* `link_name`: When enabled Pleroma will add a `name` parameter to the url of the upload, for example `https://instance.tld/media/corndog.png?name=corndog.png`. This is needed to provide the correct filename in Content-Disposition headers when using filters like `Pleroma.Upload.Filter.Dedupe`
|
* `link_name`: When enabled Pleroma will add a `name` parameter to the url of the upload, for example `https://instance.tld/media/corndog.png?name=corndog.png`. This is needed to provide the correct filename in Content-Disposition headers when using filters like `Pleroma.Upload.Filter.Dedupe`
|
||||||
|
@ -505,15 +552,21 @@ the source code is here: https://github.com/koto-bank/kocaptcha. The default end
|
||||||
* `proxy_remote`: If you're using a remote uploader, Pleroma will proxy media requests instead of redirecting to it.
|
* `proxy_remote`: If you're using a remote uploader, Pleroma will proxy media requests instead of redirecting to it.
|
||||||
* `proxy_opts`: Proxy options, see `Pleroma.ReverseProxy` documentation.
|
* `proxy_opts`: Proxy options, see `Pleroma.ReverseProxy` documentation.
|
||||||
* `filename_display_max_length`: Set max length of a filename to display. 0 = no limit. Default: 30.
|
* `filename_display_max_length`: Set max length of a filename to display. 0 = no limit. Default: 30.
|
||||||
|
* `default_description`: Sets which default description an image has if none is set explicitly. Options: nil (default) - Don't set a default, :filename - use the filename of the file, a string (e.g. "attachment") - Use this string
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
`strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
|
`strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
|
||||||
|
|
||||||
### Uploaders
|
### Uploaders
|
||||||
|
|
||||||
#### Pleroma.Uploaders.Local
|
#### Pleroma.Uploaders.Local
|
||||||
|
|
||||||
* `uploads`: Which directory to store the user-uploads in, relative to pleroma’s working directory.
|
* `uploads`: Which directory to store the user-uploads in, relative to pleroma’s working directory.
|
||||||
|
|
||||||
#### Pleroma.Uploaders.S3
|
#### Pleroma.Uploaders.S3
|
||||||
|
|
||||||
|
Don't forget to configure [Ex AWS S3](#ex-aws-s3-settings)
|
||||||
|
|
||||||
* `bucket`: S3 bucket name.
|
* `bucket`: S3 bucket name.
|
||||||
* `bucket_namespace`: S3 bucket namespace.
|
* `bucket_namespace`: S3 bucket namespace.
|
||||||
* `public_endpoint`: S3 endpoint that the user finally accesses(ex. "https://s3.dualstack.ap-northeast-1.amazonaws.com")
|
* `public_endpoint`: S3 endpoint that the user finally accesses(ex. "https://s3.dualstack.ap-northeast-1.amazonaws.com")
|
||||||
|
@ -522,17 +575,23 @@ For example, when using CDN to S3 virtual host format, set "".
|
||||||
At this time, write CNAME to CDN in public_endpoint.
|
At this time, write CNAME to CDN in public_endpoint.
|
||||||
* `streaming_enabled`: Enable streaming uploads, when enabled the file will be sent to the server in chunks as it's being read. This may be unsupported by some providers, try disabling this if you have upload problems.
|
* `streaming_enabled`: Enable streaming uploads, when enabled the file will be sent to the server in chunks as it's being read. This may be unsupported by some providers, try disabling this if you have upload problems.
|
||||||
|
|
||||||
|
#### Ex AWS S3 settings
|
||||||
|
|
||||||
|
* `access_key_id`: Access key ID
|
||||||
|
* `secret_access_key`: Secret access key
|
||||||
|
* `host`: S3 host
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :ex_aws, :s3,
|
||||||
|
access_key_id: "xxxxxxxxxx",
|
||||||
|
secret_access_key: "yyyyyyyyyy",
|
||||||
|
host: "s3.eu-central-1.amazonaws.com"
|
||||||
|
```
|
||||||
|
|
||||||
### Upload filters
|
### Upload filters
|
||||||
|
|
||||||
#### Pleroma.Upload.Filter.Mogrify
|
|
||||||
|
|
||||||
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
|
|
||||||
|
|
||||||
#### Pleroma.Upload.Filter.Dedupe
|
|
||||||
|
|
||||||
No specific configuration.
|
|
||||||
|
|
||||||
#### Pleroma.Upload.Filter.AnonymizeFilename
|
#### Pleroma.Upload.Filter.AnonymizeFilename
|
||||||
|
|
||||||
This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
|
This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
|
||||||
|
@ -540,6 +599,20 @@ This filter replaces the filename (not the path) of an upload. For complete obfu
|
||||||
|
|
||||||
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used. You can get the original filename extension by using `{extension}`, for example `custom-file-name.{extension}`.
|
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used. You can get the original filename extension by using `{extension}`, for example `custom-file-name.{extension}`.
|
||||||
|
|
||||||
|
#### Pleroma.Upload.Filter.Dedupe
|
||||||
|
|
||||||
|
No specific configuration.
|
||||||
|
|
||||||
|
#### Pleroma.Upload.Filter.Exiftool
|
||||||
|
|
||||||
|
This filter only strips the GPS and location metadata with Exiftool leaving color profiles and attributes intact.
|
||||||
|
|
||||||
|
No specific configuration.
|
||||||
|
|
||||||
|
#### Pleroma.Upload.Filter.Mogrify
|
||||||
|
|
||||||
|
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
|
||||||
|
|
||||||
## Email
|
## Email
|
||||||
|
|
||||||
### Pleroma.Emails.Mailer
|
### Pleroma.Emails.Mailer
|
||||||
|
@ -600,8 +673,7 @@ Email notifications settings.
|
||||||
Configuration options described in [Oban readme](https://github.com/sorentwo/oban#usage):
|
Configuration options described in [Oban readme](https://github.com/sorentwo/oban#usage):
|
||||||
|
|
||||||
* `repo` - app's Ecto repo (`Pleroma.Repo`)
|
* `repo` - app's Ecto repo (`Pleroma.Repo`)
|
||||||
* `verbose` - logs verbosity
|
* `log` - logs verbosity
|
||||||
* `prune` - non-retryable jobs [pruning settings](https://github.com/sorentwo/oban#pruning) (`:disabled` / `{:maxlen, value}` / `{:maxage, value}`)
|
|
||||||
* `queues` - job queues (see below)
|
* `queues` - job queues (see below)
|
||||||
* `crontab` - periodic jobs, see [`Oban.Cron`](#obancron)
|
* `crontab` - periodic jobs, see [`Oban.Cron`](#obancron)
|
||||||
|
|
||||||
|
@ -619,9 +691,8 @@ Pleroma has the following queues:
|
||||||
|
|
||||||
Pleroma has these periodic job workers:
|
Pleroma has these periodic job workers:
|
||||||
|
|
||||||
`Pleroma.Workers.Cron.ClearOauthTokenWorker` - a job worker to cleanup expired oauth tokens.
|
* `Pleroma.Workers.Cron.DigestEmailsWorker` - digest emails for users with new mentions and follows
|
||||||
|
* `Pleroma.Workers.Cron.NewUsersDigestWorker` - digest emails for admins with new registrations
|
||||||
Example:
|
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, Oban,
|
config :pleroma, Oban,
|
||||||
|
@ -633,7 +704,8 @@ config :pleroma, Oban,
|
||||||
federator_outgoing: 50
|
federator_outgoing: 50
|
||||||
],
|
],
|
||||||
crontab: [
|
crontab: [
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker}
|
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
||||||
|
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -786,10 +858,9 @@ or
|
||||||
curl -H "X-Admin-Token: somerandomtoken" "http://localhost:4000/api/pleroma/admin/users/invites"
|
curl -H "X-Admin-Token: somerandomtoken" "http://localhost:4000/api/pleroma/admin/users/invites"
|
||||||
```
|
```
|
||||||
|
|
||||||
### :auth
|
Warning: it's discouraged to use this feature because of the associated security risk: static / rarely changed instance-wide token is much weaker compared to email-password pair of a real admin user; consider using HTTP Basic Auth or OAuth-based authentication instead.
|
||||||
|
|
||||||
* `Pleroma.Web.Auth.PleromaAuthenticator`: default database authenticator.
|
### :auth
|
||||||
* `Pleroma.Web.Auth.LDAPAuthenticator`: LDAP authentication.
|
|
||||||
|
|
||||||
Authentication / authorization settings.
|
Authentication / authorization settings.
|
||||||
|
|
||||||
|
@ -820,6 +891,9 @@ Pleroma account will be created with the same name as the LDAP user name.
|
||||||
* `base`: LDAP base, e.g. "dc=example,dc=com"
|
* `base`: LDAP base, e.g. "dc=example,dc=com"
|
||||||
* `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base"
|
* `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base"
|
||||||
|
|
||||||
|
Note, if your LDAP server is an Active Directory server the correct value is commonly `uid: "cn"`, but if you use an
|
||||||
|
OpenLDAP server the value may be `uid: "uid"`.
|
||||||
|
|
||||||
### OAuth consumer mode
|
### OAuth consumer mode
|
||||||
|
|
||||||
OAuth consumer mode allows sign in / sign up via external OAuth providers (e.g. Twitter, Facebook, Google, Microsoft, etc.).
|
OAuth consumer mode allows sign in / sign up via external OAuth providers (e.g. Twitter, Facebook, Google, Microsoft, etc.).
|
||||||
|
@ -898,37 +972,36 @@ Configure OAuth 2 provider capabilities:
|
||||||
|
|
||||||
* `token_expires_in` - The lifetime in seconds of the access token.
|
* `token_expires_in` - The lifetime in seconds of the access token.
|
||||||
* `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token.
|
* `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token.
|
||||||
* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`. Interval settings sets in configuration periodic jobs [`Oban.Cron`](#obancron)
|
* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`.
|
||||||
|
|
||||||
## Link parsing
|
## Link parsing
|
||||||
|
|
||||||
### :uri_schemes
|
### :uri_schemes
|
||||||
* `valid_schemes`: List of the scheme part that is considered valid to be an URL.
|
* `valid_schemes`: List of the scheme part that is considered valid to be an URL.
|
||||||
|
|
||||||
### :auto_linker
|
### Pleroma.Formatter
|
||||||
|
|
||||||
Configuration for the `auto_linker` library:
|
Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs.
|
||||||
|
|
||||||
* `class: "auto-linker"` - specify the class to be added to the generated link. false to clear.
|
* `class` - specify the class to be added to the generated link (default: `false`)
|
||||||
* `rel: "noopener noreferrer"` - override the rel attribute. false to clear.
|
* `rel` - specify the rel attribute (default: `ugc`)
|
||||||
* `new_window: true` - set to false to remove `target='_blank'` attribute.
|
* `new_window` - adds `target="_blank"` attribute (default: `false`)
|
||||||
* `scheme: false` - Set to true to link urls with schema `http://google.com`.
|
* `truncate` - Set to a number to truncate URLs longer then the number. Truncated URLs will end in `...` (default: `false`)
|
||||||
* `truncate: false` - Set to a number to truncate urls longer then the number. Truncated urls will end in `..`.
|
* `strip_prefix` - Strip the scheme prefix (default: `false`)
|
||||||
* `strip_prefix: true` - Strip the scheme prefix.
|
* `extra` - link URLs with rarely used schemes (magnet, ipfs, irc, etc.) (default: `true`)
|
||||||
* `extra: false` - link urls with rarely used schemes (magnet, ipfs, irc, etc.).
|
* `validate_tld` - Set to false to disable TLD validation for URLs/emails. Can be set to :no_scheme to validate TLDs only for urls without a scheme (e.g `example.com` will be validated, but `http://example.loki` won't) (default: `:no_scheme`)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :auto_linker,
|
config :pleroma, Pleroma.Formatter,
|
||||||
opts: [
|
|
||||||
scheme: true,
|
|
||||||
extra: true,
|
|
||||||
class: false,
|
class: false,
|
||||||
strip_prefix: false,
|
rel: "ugc",
|
||||||
new_window: false,
|
new_window: false,
|
||||||
rel: "ugc"
|
truncate: false,
|
||||||
]
|
strip_prefix: false,
|
||||||
|
extra: true,
|
||||||
|
validate_tld: :no_scheme
|
||||||
```
|
```
|
||||||
|
|
||||||
## Custom Runtime Modules (`:modules`)
|
## Custom Runtime Modules (`:modules`)
|
||||||
|
@ -967,19 +1040,61 @@ config :pleroma, :database_config_whitelist, [
|
||||||
|
|
||||||
### :restrict_unauthenticated
|
### :restrict_unauthenticated
|
||||||
|
|
||||||
Restrict access for unauthenticated users to timelines (public and federate), user profiles and statuses.
|
Restrict access for unauthenticated users to timelines (public and federated), user profiles and statuses.
|
||||||
|
|
||||||
* `timelines` - public and federated timelines
|
* `timelines`: public and federated timelines
|
||||||
* `local` - public timeline
|
* `local`: public timeline
|
||||||
* `federated`
|
* `federated`: federated timeline (includes public timeline)
|
||||||
* `profiles` - user profiles
|
* `profiles`: user profiles
|
||||||
* `local`
|
* `local`
|
||||||
* `remote`
|
* `remote`
|
||||||
* `activities` - statuses
|
* `activities`: statuses
|
||||||
* `local`
|
* `local`
|
||||||
* `remote`
|
* `remote`
|
||||||
|
|
||||||
|
Note: when `:instance, :public` is set to `false`, all `:restrict_unauthenticated` items be effectively set to `true` by default. If you'd like to allow unauthenticated access to specific API endpoints on a private instance, please explicitly set `:restrict_unauthenticated` to non-default value in `config/prod.secret.exs`.
|
||||||
|
|
||||||
|
Note: setting `restrict_unauthenticated/timelines/local` to `true` has no practical sense if `restrict_unauthenticated/timelines/federated` is set to `false` (since local public activities will still be delivered to unauthenticated users as part of federated timeline).
|
||||||
|
|
||||||
## Pleroma.Web.ApiSpec.CastAndValidate
|
## Pleroma.Web.ApiSpec.CastAndValidate
|
||||||
|
|
||||||
* `:strict` a boolean, enables strict input validation (useful in development, not recommended in production). Defaults to `false`.
|
* `:strict` a boolean, enables strict input validation (useful in development, not recommended in production). Defaults to `false`.
|
||||||
|
|
||||||
|
## :instances_favicons
|
||||||
|
|
||||||
|
Control favicons for instances.
|
||||||
|
|
||||||
|
* `enabled`: Allow/disallow displaying and getting instances favicons
|
||||||
|
|
||||||
|
## Frontend management
|
||||||
|
|
||||||
|
Frontends in Pleroma are swappable - you can specify which one to use here.
|
||||||
|
|
||||||
|
You can set a frontends for the key `primary` and `admin` and the options of `name` and `ref`. This will then make Pleroma serve the frontend from a folder constructed by concatenating the instance static path, `frontends` and the name and ref.
|
||||||
|
|
||||||
|
The key `primary` refers to the frontend that will be served by default for general requests. The key `admin` refers to the frontend that will be served at the `/pleroma/admin` path.
|
||||||
|
|
||||||
|
If you don't set anything here, the bundled frontends will be used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :frontends,
|
||||||
|
primary: %{
|
||||||
|
"name" => "pleroma",
|
||||||
|
"ref" => "stable"
|
||||||
|
},
|
||||||
|
admin: %{
|
||||||
|
"name" => "admin",
|
||||||
|
"ref" => "develop"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This would serve the frontend from the the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit.
|
||||||
|
|
||||||
|
## Ephemeral activities (Pleroma.Workers.PurgeExpiredActivity)
|
||||||
|
|
||||||
|
Settings to enable and configure expiration for ephemeral activities
|
||||||
|
|
||||||
|
* `:enabled` - enables ephemeral activities creation
|
||||||
|
* `:min_lifetime` - minimum lifetime for ephemeral activities (in seconds). Default: 10 minutes.
|
||||||
|
|
153
docs/configuration/howto_database_config.md
Normal file
153
docs/configuration/howto_database_config.md
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
# How to activate Pleroma in-database configuration
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
The configuration of Pleroma has traditionally been managed with a config file, e.g. `config/prod.secret.exs`. This method requires a restart of the application for any configuration changes to take effect. We have made it possible to control most settings in the AdminFE interface after running a migration script.
|
||||||
|
|
||||||
|
## Migration to database config
|
||||||
|
|
||||||
|
1. Run the mix task to migrate to the database. You'll receive some debugging output and a few messages informing you of what happened.
|
||||||
|
|
||||||
|
**Source:**
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mix pleroma.config migrate_to_db
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
**OTP:**
|
||||||
|
|
||||||
|
*Note: OTP users need Pleroma to be running for `pleroma_ctl` commands to work*
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/pleroma_ctl config migrate_to_db
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
10:04:34.155 [debug] QUERY OK source="config" db=1.6ms decode=2.0ms queue=33.5ms idle=0.0ms
|
||||||
|
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
|
||||||
|
Migrating settings from file: /home/pleroma/config/dev.secret.exs
|
||||||
|
|
||||||
|
10:04:34.240 [debug] QUERY OK db=4.5ms queue=0.3ms idle=92.2ms
|
||||||
|
TRUNCATE config; []
|
||||||
|
|
||||||
|
10:04:34.244 [debug] QUERY OK db=2.8ms queue=0.3ms idle=97.2ms
|
||||||
|
ALTER SEQUENCE config_id_seq RESTART; []
|
||||||
|
|
||||||
|
10:04:34.256 [debug] QUERY OK source="config" db=0.8ms queue=1.4ms idle=109.8ms
|
||||||
|
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 WHERE ((c0."group" = $1) AND (c0."key" = $2)) [":pleroma", ":instance"]
|
||||||
|
|
||||||
|
10:04:34.292 [debug] QUERY OK db=2.6ms queue=1.7ms idle=137.7ms
|
||||||
|
INSERT INTO "config" ("group","key","value","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [":pleroma", ":instance", <<131, 108, 0, 0, 0, 1, 104, 2, 100, 0, 4, 110, 97, 109, 101, 109, 0, 0, 0, 7, 66, 108, 101, 114, 111, 109, 97, 106>>, ~N[2020-07-12 15:04:34], ~N[2020-07-12 15:04:34]]
|
||||||
|
Settings for key instance migrated.
|
||||||
|
Settings for group :pleroma migrated.
|
||||||
|
```
|
||||||
|
|
||||||
|
2. It is recommended to backup your config file now.
|
||||||
|
|
||||||
|
```
|
||||||
|
cp config/dev.secret.exs config/dev.secret.exs.orig
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Edit your Pleroma config to enable database configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, configurable_from_database: true
|
||||||
|
```
|
||||||
|
|
||||||
|
4. ⚠️ **THIS IS NOT REQUIRED** ⚠️
|
||||||
|
|
||||||
|
Now you can edit your config file and strip it down to the only settings which are not possible to control in the database. e.g., the Postgres (Repo) and webserver (Endpoint) settings cannot be controlled in the database because the application needs the settings to start up and access the database.
|
||||||
|
|
||||||
|
Any settings in the database will override those in the config file, but you may find it less confusing if the setting is only declared in one place.
|
||||||
|
|
||||||
|
A non-exhaustive list of settings that are only possible in the config file include the following:
|
||||||
|
|
||||||
|
* config :pleroma, Pleroma.Web.Endpoint
|
||||||
|
* config :pleroma, Pleroma.Repo
|
||||||
|
* config :pleroma, configurable\_from\_database
|
||||||
|
* config :pleroma, :database, rum_enabled
|
||||||
|
* config :pleroma, :connections_pool
|
||||||
|
|
||||||
|
Here is an example of a server config stripped down after migration:
|
||||||
|
|
||||||
|
```
|
||||||
|
use Mix.Config
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
url: [host: "cool.pleroma.site", scheme: "https", port: 443]
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Repo,
|
||||||
|
adapter: Ecto.Adapters.Postgres,
|
||||||
|
username: "pleroma",
|
||||||
|
password: "MySecretPassword",
|
||||||
|
database: "pleroma_prod",
|
||||||
|
hostname: "localhost"
|
||||||
|
|
||||||
|
config :pleroma, configurable_from_database: true
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Restart your instance and you can now access the Settings tab in AdminFE.
|
||||||
|
|
||||||
|
|
||||||
|
## Reverting back from database config
|
||||||
|
|
||||||
|
1. Run the mix task to migrate back from the database. You'll receive some debugging output and a few messages informing you of what happened.
|
||||||
|
|
||||||
|
**Source:**
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mix pleroma.config migrate_from_db
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
**OTP:**
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/pleroma_ctl config migrate_from_db
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
10:26:30.593 [debug] QUERY OK source="config" db=9.8ms decode=1.2ms queue=26.0ms idle=0.0ms
|
||||||
|
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
|
||||||
|
|
||||||
|
10:26:30.659 [debug] QUERY OK source="config" db=1.1ms idle=80.7ms
|
||||||
|
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
|
||||||
|
Database configuration settings have been saved to config/dev.exported_from_db.secret.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Remove `config :pleroma, configurable_from_database: true` from your config. The in-database configuration still exists, but it will not be used. Future migrations will erase the database config before importing your config file again.
|
||||||
|
|
||||||
|
3. Restart your instance.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Clearing database config
|
||||||
|
You can clear the database config by truncating the `config` table in the database. e.g.,
|
||||||
|
|
||||||
|
```
|
||||||
|
psql -d pleroma_dev
|
||||||
|
pleroma_dev=# TRUNCATE config;
|
||||||
|
TRUNCATE TABLE
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, every time you migrate the configuration to the database the config table is automatically truncated to ensure a clean migration.
|
||||||
|
|
||||||
|
### Manually removing a setting
|
||||||
|
If you encounter a situation where the server cannot run properly because of an invalid setting in the database and this is preventing you from accessing AdminFE, you can manually remove the offending setting if you know which one it is.
|
||||||
|
|
||||||
|
e.g., here is an example showing a minimal configuration in the database. Only the `config :pleroma, :instance` settings are in the table:
|
||||||
|
|
||||||
|
```
|
||||||
|
psql -d pleroma_dev
|
||||||
|
pleroma_dev=# select * from config;
|
||||||
|
id | key | value | inserted_at | updated_at | group
|
||||||
|
----+-----------+------------------------------------------------------------+---------------------+---------------------+----------
|
||||||
|
1 | :instance | \x836c0000000168026400046e616d656d00000007426c65726f6d616a | 2020-07-12 15:33:29 | 2020-07-12 15:33:29 | :pleroma
|
||||||
|
(1 row)
|
||||||
|
pleroma_dev=# delete from config where key = ':instance' and group = ':pleroma';
|
||||||
|
DELETE 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Now the `config :pleroma, :instance` settings have been removed from the database.
|
|
@ -60,7 +60,7 @@ Example of `my-awesome-theme.json` where we add the name "My Awesome Theme"
|
||||||
|
|
||||||
### Set as default theme
|
### Set as default theme
|
||||||
|
|
||||||
Now we can set the new theme as default in the [Pleroma FE configuration](General-tips-for-customizing-Pleroma-FE.md).
|
Now we can set the new theme as default in the [Pleroma FE configuration](../../../frontend/CONFIGURATION).
|
||||||
|
|
||||||
Example of adding the new theme in the back-end config files
|
Example of adding the new theme in the back-end config files
|
||||||
```elixir
|
```elixir
|
||||||
|
|
|
@ -34,9 +34,9 @@ config :pleroma, :instance,
|
||||||
To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this:
|
To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, :instance,
|
config :pleroma, :mrf,
|
||||||
[...]
|
[...]
|
||||||
rewrite_policy: Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
policies: Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||||
```
|
```
|
||||||
|
|
||||||
Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are:
|
Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are:
|
||||||
|
@ -58,8 +58,8 @@ Servers should be configured as lists.
|
||||||
This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`:
|
This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, :instance,
|
config :pleroma, :mrf,
|
||||||
rewrite_policy: [Pleroma.Web.ActivityPub.MRF.SimplePolicy]
|
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy]
|
||||||
|
|
||||||
config :pleroma, :mrf_simple,
|
config :pleroma, :mrf_simple,
|
||||||
media_removal: ["illegalporn.biz"],
|
media_removal: ["illegalporn.biz"],
|
||||||
|
@ -75,7 +75,7 @@ The effects of MRF policies can be very drastic. It is important to use this fun
|
||||||
|
|
||||||
## Writing your own MRF Policy
|
## Writing your own MRF Policy
|
||||||
|
|
||||||
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `rewrite_policy` config setting.
|
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `policies` config setting.
|
||||||
|
|
||||||
For example, here is a sample policy module which rewrites all messages to "new message content":
|
For example, here is a sample policy module which rewrites all messages to "new message content":
|
||||||
|
|
||||||
|
@ -125,8 +125,8 @@ end
|
||||||
If you save this file as `lib/pleroma/web/activity_pub/mrf/rewrite_policy.ex`, it will be included when you next rebuild Pleroma. You can enable it in the configuration like so:
|
If you save this file as `lib/pleroma/web/activity_pub/mrf/rewrite_policy.ex`, it will be included when you next rebuild Pleroma. You can enable it in the configuration like so:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :pleroma, :instance,
|
config :pleroma, :mrf,
|
||||||
rewrite_policy: [
|
policies: [
|
||||||
Pleroma.Web.ActivityPub.MRF.SimplePolicy,
|
Pleroma.Web.ActivityPub.MRF.SimplePolicy,
|
||||||
Pleroma.Web.ActivityPub.MRF.RewritePolicy
|
Pleroma.Web.ActivityPub.MRF.RewritePolicy
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,45 +1,61 @@
|
||||||
# Static Directory
|
# Static Directory
|
||||||
|
|
||||||
Static frontend files are shipped in `priv/static/` and tracked by version control in this repository. If you want to overwrite or update these without the possibility of merge conflicts, you can write your custom versions to `instance/static/`.
|
Static frontend files are shipped with pleroma. If you want to overwrite or update these without problems during upgrades, you can write your custom versions to the static directory.
|
||||||
|
|
||||||
```
|
You can find the location of the static directory in the [configuration](../cheatsheet/#instance).
|
||||||
|
|
||||||
|
=== "OTP"
|
||||||
|
|
||||||
|
```elixir
|
||||||
config :pleroma, :instance,
|
config :pleroma, :instance,
|
||||||
static_dir: "instance/static/",
|
static_dir: "/var/lib/pleroma/static/"
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, edit `instance/static/instance/panel.html` .
|
=== "From Source"
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :instance,
|
||||||
|
static_dir: "instance/static/"
|
||||||
|
```
|
||||||
|
|
||||||
Alternatively, you can overwrite this value in your configuration to use a different static instance directory.
|
Alternatively, you can overwrite this value in your configuration to use a different static instance directory.
|
||||||
|
|
||||||
This document is written assuming `instance/static/`.
|
This document is written using `$static_dir` as the value of the `config :pleroma, :instance, static_dir` setting.
|
||||||
|
|
||||||
Or, if you want to manage your custom file in git repository, basically remove the `instance/` entry from `.gitignore`.
|
If you use a From Source installation and want to manage your custom files in the git repository, you can remove the `instance/` entry from `.gitignore`.
|
||||||
|
|
||||||
## robots.txt
|
## robots.txt
|
||||||
|
|
||||||
By default, the `robots.txt` that ships in `priv/static/` is permissive. It allows well-behaved search engines to index all of your instance's URIs.
|
There's a mix tasks to [generate a new robot.txt](../../administration/CLI_tasks/robots_txt/).
|
||||||
|
|
||||||
If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance static directory.
|
For more complex things, you can write your own robots.txt to `$static_dir/robots.txt`.
|
||||||
|
|
||||||
|
E.g. if you want to block all crawlers except for [fediverse.network](https://fediverse.network/about) you can use
|
||||||
|
|
||||||
```
|
```
|
||||||
mix pleroma.robots_txt disallow_all
|
User-Agent: *
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
User-Agent: crawler-us-il-1.fediverse.network
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-Agent: makhnovtchina.random.sh
|
||||||
|
Allow: /
|
||||||
```
|
```
|
||||||
|
|
||||||
## Thumbnail
|
## Thumbnail
|
||||||
|
|
||||||
Put on `instance/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html).
|
Add `$static_dir/instance/thumbnail.jpeg` with your selfie or other neat picture. It will be available on `http://your-domain.tld/instance/thumbnail.jpeg` and can be used by external applications.
|
||||||
|
|
||||||
## Instance-specific panel
|
## Instance-specific panel
|
||||||
|
|
||||||
![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png)
|
Create and Edit your file at `$static_dir/instance/panel.html`.
|
||||||
|
|
||||||
Create and Edit your file on `instance/static/instance/panel.html`.
|
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
You can change the background of your Pleroma instance by uploading it to `instance/static/`, and then changing `background` in `config/prod.secret.exs` accordingly.
|
You can change the background of your Pleroma instance by uploading it to `$static_dir/`, and then changing `background` in [your configuration](../cheatsheet/#frontend_configurations) accordingly.
|
||||||
|
|
||||||
If you put `instance/static/images/background.jpg`
|
E.g. if you put `$static_dir/images/background.jpg`
|
||||||
|
|
||||||
```
|
```
|
||||||
config :pleroma, :frontend_configurations,
|
config :pleroma, :frontend_configurations,
|
||||||
|
@ -50,12 +66,14 @@ config :pleroma, :frontend_configurations,
|
||||||
|
|
||||||
## Logo
|
## Logo
|
||||||
|
|
||||||
![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png)
|
!!! important
|
||||||
|
Note the extra `static` folder for the default logo.png location
|
||||||
|
|
||||||
If you want to give a brand to your instance, You can change the logo of your instance by uploading it to `instance/static/`.
|
If you want to give a brand to your instance, You can change the logo of your instance by uploading it to the static directory `$static_dir/static/logo.png`.
|
||||||
|
|
||||||
Alternatively, you can specify the path with config.
|
Alternatively, you can specify the path to your logo in [your configuration](../cheatsheet/#frontend_configurations).
|
||||||
If you put `instance/static/static/mylogo-file.png`
|
|
||||||
|
E.g. if you put `$static_dir/static/mylogo-file.png`
|
||||||
|
|
||||||
```
|
```
|
||||||
config :pleroma, :frontend_configurations,
|
config :pleroma, :frontend_configurations,
|
||||||
|
@ -66,4 +84,7 @@ config :pleroma, :frontend_configurations,
|
||||||
|
|
||||||
## Terms of Service
|
## Terms of Service
|
||||||
|
|
||||||
Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `instance/static/static/terms-of-service.html`.
|
!!! important
|
||||||
|
Note the extra `static` folder for the terms-of-service.html
|
||||||
|
|
||||||
|
Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by adding and changing `$static_dir/static/terms-of-service.html`.
|
||||||
|
|
|
@ -33,6 +33,6 @@ as soon as the post is received by your instance.
|
||||||
Add to your `prod.secret.exs`:
|
Add to your `prod.secret.exs`:
|
||||||
|
|
||||||
```
|
```
|
||||||
config :pleroma, :instance,
|
config :pleroma, :mrf,
|
||||||
rewrite_policy: [Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
|
policies: [Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
|
||||||
```
|
```
|
||||||
|
|
|
@ -20,4 +20,4 @@ This document contains notes and guidelines for Pleroma developers.
|
||||||
|
|
||||||
## Auth-related configuration, OAuth consumer mode etc.
|
## Auth-related configuration, OAuth consumer mode etc.
|
||||||
|
|
||||||
See `Authentication` section of [`docs/configuration/cheatsheet.md`](docs/configuration/cheatsheet.md#authentication).
|
See `Authentication` section of [the configuration cheatsheet](configuration/cheatsheet.md#authentication).
|
||||||
|
|
26
docs/index.md
Normal file
26
docs/index.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Introduction to Pleroma
|
||||||
|
## What is Pleroma?
|
||||||
|
Pleroma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
|
||||||
|
It actually consists of two components: a backend, named simply Pleroma, and a user-facing frontend, named Pleroma-FE. It also includes the Mastodon frontend, if that's your thing.
|
||||||
|
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
|
||||||
|
One account on an instance is enough to talk to the entire fediverse!
|
||||||
|
|
||||||
|
## How can I use it?
|
||||||
|
|
||||||
|
Pleroma instances are already widely deployed, a list can be found at <https://the-federation.info/pleroma> and <https://fediverse.network/pleroma>.
|
||||||
|
|
||||||
|
If you don't feel like joining an existing instance, but instead prefer to deploy your own instance, that's easy too!
|
||||||
|
Installation instructions can be found in the installation section of these docs.
|
||||||
|
|
||||||
|
## I got an account, now what?
|
||||||
|
Great! Now you can explore the fediverse! Open the login page for your Pleroma instance (e.g. <https://pleroma.soykaf.com>) and login with your username and password. (If you don't have an account yet, click on Register)
|
||||||
|
|
||||||
|
### Pleroma-FE
|
||||||
|
The default front-end used by Pleroma is Pleroma-FE. You can find more information on what it is and how to use it in the [Introduction to Pleroma-FE](../frontend).
|
||||||
|
|
||||||
|
### Mastodon interface
|
||||||
|
If the Pleroma interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
|
||||||
|
Just add a "/web" after your instance url (e.g. <https://pleroma.soycaf.com/web>) and you'll end on the Mastodon web interface, but with a Pleroma backend! MAGIC!
|
||||||
|
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.
|
||||||
|
|
||||||
|
Remember, what you see is only the frontend part of Mastodon, the backend is still Pleroma.
|
|
@ -15,6 +15,7 @@ It assumes that you have administrative rights, either as root or a user with [s
|
||||||
* `git`
|
* `git`
|
||||||
* `file-dev`
|
* `file-dev`
|
||||||
* Development Tools
|
* Development Tools
|
||||||
|
* `cmake`
|
||||||
|
|
||||||
#### Optional packages used in this guide
|
#### Optional packages used in this guide
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ sudo apk upgrade
|
||||||
* Install some tools, which are needed later:
|
* Install some tools, which are needed later:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apk add git build-base file-dev
|
sudo apk add git build-base cmake file-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install Elixir and Erlang
|
### Install Elixir and Erlang
|
||||||
|
@ -226,10 +227,7 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ This guide will assume that you have administrative rights, either as root or a
|
||||||
* `elixir`
|
* `elixir`
|
||||||
* `git`
|
* `git`
|
||||||
* `base-devel`
|
* `base-devel`
|
||||||
|
* `cmake`
|
||||||
* `file`
|
* `file`
|
||||||
|
|
||||||
#### Optional packages used in this guide
|
#### Optional packages used in this guide
|
||||||
|
@ -27,7 +28,7 @@ sudo pacman -Syu
|
||||||
* Install some of the above mentioned programs:
|
* Install some of the above mentioned programs:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo pacman -S git base-devel elixir file
|
sudo pacman -S git base-devel elixir cmake file
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install PostgreSQL
|
### Install PostgreSQL
|
||||||
|
@ -201,10 +202,7 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ This guide will assume you are on Debian Stretch. This guide should also work wi
|
||||||
* `libmagic-dev`
|
* `libmagic-dev`
|
||||||
* `git`
|
* `git`
|
||||||
* `build-essential`
|
* `build-essential`
|
||||||
|
* `cmake`
|
||||||
|
|
||||||
#### Optional packages used in this guide
|
#### Optional packages used in this guide
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ sudo apt full-upgrade
|
||||||
* Install some of the above mentioned programs:
|
* Install some of the above mentioned programs:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apt install git build-essential postgresql postgresql-contrib libmagic-devel
|
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install Elixir and Erlang
|
### Install Elixir and Erlang
|
||||||
|
@ -187,10 +188,7 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
- `erlang-nox`
|
- `erlang-nox`
|
||||||
- `git`
|
- `git`
|
||||||
- `build-essential`
|
- `build-essential`
|
||||||
|
- `cmake`
|
||||||
- `libmagic-dev`
|
- `libmagic-dev`
|
||||||
|
|
||||||
#### このガイドで利用している追加パッケージ
|
#### このガイドで利用している追加パッケージ
|
||||||
|
@ -33,7 +34,7 @@ sudo apt full-upgrade
|
||||||
|
|
||||||
* 上記に挙げたパッケージをインストールしておきます。
|
* 上記に挙げたパッケージをインストールしておきます。
|
||||||
```
|
```
|
||||||
sudo apt install git build-essential postgresql postgresql-contrib libmagic-dev
|
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,10 +177,7 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### その他の設定とカスタマイズ
|
#### その他の設定とカスタマイズ
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## 質問ある?
|
## 質問ある?
|
||||||
|
|
||||||
|
|
210
docs/installation/freebsd_en.md
Normal file
210
docs/installation/freebsd_en.md
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
# Installing on FreeBSD
|
||||||
|
|
||||||
|
This document was written for FreeBSD 12.1, but should be work on future releases.
|
||||||
|
|
||||||
|
## Required software
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the rc.d scripts to the right directory:
|
||||||
|
|
||||||
|
Setup the required services to automatically start at boot, using `sysrc(8)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
# sysrc nginx_enable=YES
|
||||||
|
# sysrc postgresql_enable=YES
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initialize postgres
|
||||||
|
|
||||||
|
```
|
||||||
|
# service postgresql initdb
|
||||||
|
# service postgresql start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring Pleroma
|
||||||
|
|
||||||
|
Create a user for Pleroma:
|
||||||
|
|
||||||
|
```
|
||||||
|
# pw add user pleroma -m
|
||||||
|
# echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile
|
||||||
|
# su -l pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
Clone the repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd $HOME # Should be the same as /home/pleroma
|
||||||
|
$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure Pleroma. Note that you need a domain name at this point:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd /home/pleroma/pleroma
|
||||||
|
$ mix deps.get # Enter "y" when asked to install Hex
|
||||||
|
$ mix pleroma.instance gen # You will be asked a few questions here.
|
||||||
|
$ cp config/generated_config.exs config/prod.secret.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
Since Postgres is configured, we can now initialize the database. There should
|
||||||
|
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
|
||||||
|
it'll be protecting your database. As root, you can now initialize the database:
|
||||||
|
|
||||||
|
```
|
||||||
|
# cd /home/pleroma/pleroma
|
||||||
|
# sudo -Hu postgres -g postgres psql -f config/setup_db.psql
|
||||||
|
```
|
||||||
|
|
||||||
|
Postgres allows connections from all users without a password by default. To
|
||||||
|
fix this, edit `/var/db/postgres/data12/pg_hba.conf`. Change every `trust` to
|
||||||
|
`password`.
|
||||||
|
|
||||||
|
Once this is done, restart Postgres with:
|
||||||
|
```
|
||||||
|
# service postgresql restart
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the database migrations.
|
||||||
|
|
||||||
|
Back as the pleroma user, run the following to implement any database migrations.
|
||||||
|
|
||||||
|
```
|
||||||
|
# su -l pleroma
|
||||||
|
$ cd /home/pleroma/pleroma
|
||||||
|
$ MIX_ENV=prod mix ecto.migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
You will need to do this whenever you update with `git pull`:
|
||||||
|
|
||||||
|
## Configuring acme.sh
|
||||||
|
|
||||||
|
We'll be using acme.sh in Stateless Mode for TLS certificate renewal.
|
||||||
|
|
||||||
|
First, as root, allow the user `acme` to have access to the acme log file, as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
# touch /var/log/acme.sh.log
|
||||||
|
# chown acme:acme /var/log/acme.sh.log
|
||||||
|
# chmod 600 /var/log/acme.sh.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, obtain your account fingerprint:
|
||||||
|
|
||||||
|
```
|
||||||
|
# sudo -Hu acme -g acme acme.sh --register-account
|
||||||
|
```
|
||||||
|
|
||||||
|
You need to add the following to your nginx configuration for the server
|
||||||
|
running on port 80:
|
||||||
|
|
||||||
|
```
|
||||||
|
location ~ ^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$ {
|
||||||
|
default_type text/plain;
|
||||||
|
return 200 "$1.6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace the string after after `$1.` with your fingerprint.
|
||||||
|
|
||||||
|
Start nginx:
|
||||||
|
|
||||||
|
```
|
||||||
|
# service nginx start
|
||||||
|
```
|
||||||
|
|
||||||
|
It should now be possible to issue a cert (replace `example.com`
|
||||||
|
with your domain name):
|
||||||
|
|
||||||
|
```
|
||||||
|
# sudo -Hu acme -g acme acme.sh --issue -d example.com --stateless
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's add auto-renewal to `/etc/crontab`
|
||||||
|
(replace `example.com` with your domain):
|
||||||
|
|
||||||
|
```
|
||||||
|
/usr/local/bin/sudo -Hu acme -g acme /usr/local/sbin/acme.sh -r -d example.com --stateless
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring nginx
|
||||||
|
|
||||||
|
FreeBSD's default nginx configuration does not contain an include directive, which is
|
||||||
|
typically used for multiple sites. Therefore, you will need to first create the required
|
||||||
|
directory as follows:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
# mkdir -p /usr/local/etc/nginx/sites-available
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, add an `include` directive to `/usr/local/etc/nginx/nginx.conf`, within the `http {}`
|
||||||
|
block, as follows:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
http {
|
||||||
|
...
|
||||||
|
include /usr/local/etc/nginx/sites-available/*;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As root, copy `/home/pleroma/pleroma/installation/pleroma.nginx` to
|
||||||
|
`/usr/local/etc/nginx/sites-available/pleroma.nginx`.
|
||||||
|
|
||||||
|
Edit the defaults of `/usr/local/etc/nginx/sites-available/pleroma.nginx`:
|
||||||
|
|
||||||
|
* Change `ssl_trusted_certificate` to `/var/db/acme/certs/example.tld/example.tld.cer`.
|
||||||
|
* Change `ssl_certificate` to `/var/db/acme/certs/example.tld/fullchain.cer`.
|
||||||
|
* Change `ssl_certificate_key` to `/var/db/acme/certs/example.tld/example.tld.key`.
|
||||||
|
* Change all references of `example.tld` to your instance's domain name.
|
||||||
|
|
||||||
|
## Creating a startup script for Pleroma
|
||||||
|
|
||||||
|
Pleroma will need to compile when it initially starts, which typically takes a longer
|
||||||
|
period of time. Therefore, it is good practice to initially run pleroma from the
|
||||||
|
command-line before utilizing the rc.d script. That is done as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
# su -l pleroma
|
||||||
|
$ cd $HOME/pleroma
|
||||||
|
$ MIX_ENV=prod mix phx.server
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the startup script to the correct location and make sure it's executable:
|
||||||
|
|
||||||
|
```
|
||||||
|
# cp /home/pleroma/pleroma/installation/freebsd/rc.d/pleroma /usr/local/etc/rc.d/pleroma
|
||||||
|
# chmod +x /usr/local/etc/rc.d/pleroma
|
||||||
|
```
|
||||||
|
|
||||||
|
Update the `/etc/rc.conf` and start pleroma with the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
# sysrc pleroma_enable=YES
|
||||||
|
# service pleroma start
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create your first user
|
||||||
|
|
||||||
|
If your instance is up and running, you can create your first user with administrative rights with the following task:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress> --admin
|
||||||
|
```
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Restart nginx with `# service nginx restart` and you should be up and running.
|
||||||
|
|
||||||
|
Make sure your time is in sync, or other instances will receive your posts with
|
||||||
|
incorrect timestamps. You should have ntpd running.
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
5
docs/installation/further_reading.include
Normal file
5
docs/installation/further_reading.include
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
* [How Federation Works/Why is my Federated Timeline empty?](https://blog.soykaf.com/post/how-federation-works/)
|
||||||
|
* [Backup your instance](../administration/backup.md)
|
||||||
|
* [Updating your instance](../administration/updating.md)
|
||||||
|
* [Hardening your instance](../configuration/hardening.md)
|
||||||
|
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
@ -28,6 +28,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i
|
||||||
* `dev-db/postgresql`
|
* `dev-db/postgresql`
|
||||||
* `dev-lang/elixir`
|
* `dev-lang/elixir`
|
||||||
* `dev-vcs/git`
|
* `dev-vcs/git`
|
||||||
|
* `dev-util/cmake`
|
||||||
* `sys-apps/file`
|
* `sys-apps/file`
|
||||||
|
|
||||||
#### Optional ebuilds used in this guide
|
#### Optional ebuilds used in this guide
|
||||||
|
@ -47,7 +48,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i
|
||||||
* Emerge all required the required and suggested software in one go:
|
* Emerge all required the required and suggested software in one go:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# emerge --ask dev-db/postgresql dev-lang/elixir dev-vcs/git www-servers/nginx app-crypt/certbot app-crypt/certbot-nginx sys-apps/file
|
# emerge --ask dev-db/postgresql dev-lang/elixir dev-vcs/git www-servers/nginx app-crypt/certbot app-crypt/certbot-nginx dev-util/cmake sys-apps/file
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
||||||
|
@ -284,10 +285,7 @@ If you opted to allow sudo for the `pleroma` user but would like to remove the a
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,13 @@ You will be running commands as root. If you aren't root already, please elevate
|
||||||
|
|
||||||
The system needs to have `curl` and `unzip` installed for downloading and unpacking release builds.
|
The system needs to have `curl` and `unzip` installed for downloading and unpacking release builds.
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```sh
|
||||||
apk add curl unzip
|
apk add curl unzip
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```sh
|
||||||
apt install curl unzip
|
apt install curl unzip
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -110,7 +112,8 @@ OTP releases have different service files than from-source installs so they need
|
||||||
|
|
||||||
**Warning:** The service files assume pleroma user's home directory is `/opt/pleroma`, please make sure all paths fit your installation.
|
**Warning:** The service files assume pleroma user's home directory is `/opt/pleroma`, please make sure all paths fit your installation.
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```sh
|
||||||
# Copy the service into a proper directory
|
# Copy the service into a proper directory
|
||||||
cp -f ~pleroma/installation/init.d/pleroma /etc/init.d/pleroma
|
cp -f ~pleroma/installation/init.d/pleroma /etc/init.d/pleroma
|
||||||
|
|
||||||
|
@ -118,7 +121,8 @@ cp -f ~pleroma/installation/init.d/pleroma /etc/init.d/pleroma
|
||||||
rc-service pleroma start
|
rc-service pleroma start
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```sh
|
||||||
# Copy the service into a proper directory
|
# Copy the service into a proper directory
|
||||||
cp ~pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service
|
cp ~pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ databases/postgresql11-client
|
||||||
databases/postgresql11-server
|
databases/postgresql11-server
|
||||||
devel/git-base
|
devel/git-base
|
||||||
devel/git-docs
|
devel/git-docs
|
||||||
|
devel/cmake
|
||||||
lang/elixir
|
lang/elixir
|
||||||
security/acmesh
|
security/acmesh
|
||||||
security/sudo
|
security/sudo
|
||||||
|
@ -196,3 +197,11 @@ incorrect timestamps. You should have ntpd running.
|
||||||
## Instances running NetBSD
|
## Instances running NetBSD
|
||||||
|
|
||||||
* <https://catgirl.science>
|
* <https://catgirl.science>
|
||||||
|
|
||||||
|
#### Further reading
|
||||||
|
|
||||||
|
{! backend/installation/further_reading.include !}
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
||||||
|
|
|
@ -14,11 +14,12 @@ The following packages need to be installed:
|
||||||
* git
|
* git
|
||||||
* postgresql-server
|
* postgresql-server
|
||||||
* postgresql-contrib
|
* postgresql-contrib
|
||||||
|
* cmake
|
||||||
|
|
||||||
To install them, run the following command (with doas or as root):
|
To install them, run the following command (with doas or as root):
|
||||||
|
|
||||||
```
|
```
|
||||||
pkg_add elixir gmake ImageMagick git postgresql-server postgresql-contrib
|
pkg_add elixir gmake ImageMagick git postgresql-server postgresql-contrib cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt.
|
Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt.
|
||||||
|
@ -242,3 +243,11 @@ If your instance is up and running, you can create your first user with administ
|
||||||
```
|
```
|
||||||
LC_ALL=en_US.UTF-8 MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress> --admin
|
LC_ALL=en_US.UTF-8 MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress> --admin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Further reading
|
||||||
|
|
||||||
|
{! backend/installation/further_reading.include !}
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
||||||
|
|
|
@ -16,7 +16,7 @@ Matrix-kanava #freenode_#pleroma:matrix.org ovat hyviä paikkoja löytää apua
|
||||||
|
|
||||||
Asenna tarvittava ohjelmisto:
|
Asenna tarvittava ohjelmisto:
|
||||||
|
|
||||||
`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3`
|
`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3 cmake`
|
||||||
|
|
||||||
Luo postgresql-tietokanta:
|
Luo postgresql-tietokanta:
|
||||||
|
|
||||||
|
|
|
@ -29,13 +29,15 @@ Other than things bundled in the OTP release Pleroma depends on:
|
||||||
* certbot (for Let's Encrypt certificates, could be swapped with another ACME client, but this guide covers only it)
|
* certbot (for Let's Encrypt certificates, could be swapped with another ACME client, but this guide covers only it)
|
||||||
* libmagic/file
|
* libmagic/file
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories
|
echo "http://nl.alpinelinux.org/alpine/latest-stable/community" >> /etc/apk/repositories
|
||||||
apk update
|
apk update
|
||||||
apk add curl unzip ncurses postgresql postgresql-contrib nginx certbot file-dev
|
apk add curl unzip ncurses postgresql postgresql-contrib nginx certbot file-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot libmagic-dev
|
apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot libmagic-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -48,7 +50,8 @@ apt install curl unzip libncurses5 postgresql postgresql-contrib nginx certbot l
|
||||||
|
|
||||||
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. You can read more about them on the [Configuration page](../configuration/cheatsheet.md#rum-indexing-for-full-text-search). They are completely optional and most of the time are not worth it, especially if you are running a single user instance (unless you absolutely need ordered search results).
|
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. You can read more about them on the [Configuration page](../configuration/cheatsheet.md#rum-indexing-for-full-text-search). They are completely optional and most of the time are not worth it, especially if you are running a single user instance (unless you absolutely need ordered search results).
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
apk add git build-base postgresql-dev
|
apk add git build-base postgresql-dev
|
||||||
git clone https://github.com/postgrespro/rum /tmp/rum
|
git clone https://github.com/postgrespro/rum /tmp/rum
|
||||||
cd /tmp/rum
|
cd /tmp/rum
|
||||||
|
@ -58,7 +61,8 @@ cd
|
||||||
rm -r /tmp/rum
|
rm -r /tmp/rum
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
# Available only on Buster/19.04
|
# Available only on Buster/19.04
|
||||||
apt install postgresql-11-rum
|
apt install postgresql-11-rum
|
||||||
```
|
```
|
||||||
|
@ -66,11 +70,13 @@ apt install postgresql-11-rum
|
||||||
#### (Optional) Performance configuration
|
#### (Optional) Performance configuration
|
||||||
It is encouraged to check [Optimizing your PostgreSQL performance](../configuration/postgresql.md) document, for tips on PostgreSQL tuning.
|
It is encouraged to check [Optimizing your PostgreSQL performance](../configuration/postgresql.md) document, for tips on PostgreSQL tuning.
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
rc-service postgresql restart
|
rc-service postgresql restart
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
systemctl restart postgresql
|
systemctl restart postgresql
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -152,11 +158,13 @@ certbot certonly --standalone --preferred-challenges http -d yourinstance.tld
|
||||||
|
|
||||||
The location of nginx configs is dependent on the distro
|
The location of nginx configs is dependent on the distro
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf
|
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf
|
cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/pleroma.conf
|
||||||
ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf
|
ln -s /etc/nginx/sites-available/pleroma.conf /etc/nginx/sites-enabled/pleroma.conf
|
||||||
```
|
```
|
||||||
|
@ -176,11 +184,13 @@ nginx -t
|
||||||
```
|
```
|
||||||
#### Start nginx
|
#### Start nginx
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
rc-service nginx start
|
rc-service nginx start
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
systemctl start nginx
|
systemctl start nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -188,7 +198,8 @@ At this point if you open your (sub)domain in a browser you should see a 502 err
|
||||||
|
|
||||||
### Setting up a system service
|
### Setting up a system service
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
# Copy the service into a proper directory
|
# Copy the service into a proper directory
|
||||||
cp /opt/pleroma/installation/init.d/pleroma /etc/init.d/pleroma
|
cp /opt/pleroma/installation/init.d/pleroma /etc/init.d/pleroma
|
||||||
|
|
||||||
|
@ -197,7 +208,8 @@ rc-service pleroma start
|
||||||
rc-update add pleroma
|
rc-update add pleroma
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
# Copy the service into a proper directory
|
# Copy the service into a proper directory
|
||||||
cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service
|
cp /opt/pleroma/installation/pleroma.service /etc/systemd/system/pleroma.service
|
||||||
|
|
||||||
|
@ -224,7 +236,8 @@ $EDITOR path-to-nginx-config
|
||||||
nginx -t
|
nginx -t
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Alpine"
|
=== "Alpine"
|
||||||
|
```
|
||||||
# Restart nginx
|
# Restart nginx
|
||||||
rc-service nginx restart
|
rc-service nginx restart
|
||||||
|
|
||||||
|
@ -245,7 +258,8 @@ chmod +x /etc/periodic/daily/renew-pleroma-cert
|
||||||
run-parts --test /etc/periodic/daily
|
run-parts --test /etc/periodic/daily
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh tab="Debian/Ubuntu"
|
=== "Debian/Ubuntu"
|
||||||
|
```
|
||||||
# Restart nginx
|
# Restart nginx
|
||||||
systemctl restart nginx
|
systemctl restart nginx
|
||||||
|
|
||||||
|
@ -271,10 +285,7 @@ This will create an account withe the username of 'joeuser' with the email addre
|
||||||
|
|
||||||
## Further reading
|
## Further reading
|
||||||
|
|
||||||
* [Backup your instance](../administration/backup.md)
|
{! backend/installation/further_reading.include !}
|
||||||
* [Hardening your instance](../configuration/hardening.md)
|
|
||||||
* [How to activate mediaproxy](../configuration/howto_mediaproxy.md)
|
|
||||||
* [Updating your instance](../administration/updating.md)
|
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
# Introduction to Pleroma
|
|
||||||
## What is Pleroma?
|
|
||||||
Pleroma is a federated social networking platform, compatible with GNU social, Mastodon and other OStatus and ActivityPub implementations. It is free software licensed under the AGPLv3.
|
|
||||||
It actually consists of two components: a backend, named simply Pleroma, and a user-facing frontend, named Pleroma-FE. It also includes the Mastodon frontend, if that's your thing.
|
|
||||||
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
|
|
||||||
One account on an instance is enough to talk to the entire fediverse!
|
|
||||||
|
|
||||||
## How can I use it?
|
|
||||||
|
|
||||||
Pleroma instances are already widely deployed, a list can be found at <http://distsn.org/pleroma-instances.html>. Information on all existing fediverse instances can be found at <https://fediverse.network/>.
|
|
||||||
|
|
||||||
If you don't feel like joining an existing instance, but instead prefer to deploy your own instance, that's easy too!
|
|
||||||
Installation instructions can be found in the installation section of these docs.
|
|
||||||
|
|
||||||
## I got an account, now what?
|
|
||||||
Great! Now you can explore the fediverse! Open the login page for your Pleroma instance (e.g. <https://pleroma.soykaf.com>) and login with your username and password. (If you don't have an account yet, click on Register)
|
|
||||||
|
|
||||||
At this point you will have two columns in front of you.
|
|
||||||
|
|
||||||
### Left column
|
|
||||||
|
|
||||||
- first block: here you can see your avatar, your nickname and statistics (Statuses, Following, Followers). Clicking your profile pic will open your profile.
|
|
||||||
Under that you have a text form which allows you to post new statuses. The number on the bottom of the text form is a character counter, every instance can have a different character limit (the default is 5000).
|
|
||||||
If you want to mention someone, type @ + name of the person. A drop-down menu will help you in finding the right person.
|
|
||||||
Under the text form there are also several visibility options and there is the option to use rich text.
|
|
||||||
Under that the icon on the left is for uploading media files and attach them to your post. There is also an emoji-picker and an option to post a poll.
|
|
||||||
To post your status, simply press Submit.
|
|
||||||
On the top right you will also see a wrench icon. This opens your personal settings.
|
|
||||||
|
|
||||||
- second block: Here you can switch between the different timelines:
|
|
||||||
- Timeline: all the people that you follow
|
|
||||||
- Interactions: here you can switch between different timelines where there was interaction with your account. There is Mentions, Repeats and Favorites, and New follows
|
|
||||||
- Direct Messages: these are the Direct Messages sent to you
|
|
||||||
- Public Timeline: all the statutes from the local instance
|
|
||||||
- The Whole Known Network: all public posts the instance knows about, both local and remote!
|
|
||||||
- About: This isn't a Timeline but shows relevant info about the instance. You can find a list of the moderators and admins, Terms of Service, MRF policies and enabled features.
|
|
||||||
- Optional third block: This is the Instance panel that can be activated, but is deactivated by default. It's fully customisable and by default has links to the pleroma-fe and Mastodon-fe.
|
|
||||||
- fourth block: This is the Notifications block, here you will get notified whenever somebody mentions you, follows you, repeats or favorites one of your statuses.
|
|
||||||
|
|
||||||
### Right column
|
|
||||||
This is where the interesting stuff happens!
|
|
||||||
Depending on the timeline you will see different statuses, but each status has a standard structure:
|
|
||||||
|
|
||||||
- Profile pic, name and link to profile. An optional left-arrow if it's a reply to another status (hovering will reveal the reply-to status). Clicking on the profile pic will uncollapse the user's profile.
|
|
||||||
- A `+` button on the right allows you to Expand/Collapse an entire discussion thread. It also updates in realtime!
|
|
||||||
- An arrow icon allows you to open the status on the instance where it's originating from.
|
|
||||||
- The text of the status, including mentions and attachements. If you click on a mention, it will automatically open the profile page of that person.
|
|
||||||
- Three buttons (left to right): Reply, Repeat, Favorite. There is also a forth button, this is a dropdown menu for simple moderation like muting the conversation or, if you have moderation rights, delete the status from the server.
|
|
||||||
|
|
||||||
### Top right
|
|
||||||
|
|
||||||
- The magnifier icon opens the search screen where you can search for statuses, people and hashtags. It's also possible to import statusses from remote servers by pasting the url to the post in the search field.
|
|
||||||
- The gear icon gives you general settings
|
|
||||||
- If you have admin rights, you'll see an icon that opens the admin interface
|
|
||||||
- The last icon is to log out
|
|
||||||
|
|
||||||
### Bottom right
|
|
||||||
On the bottom right you have a chatbox. Here you can communicate with people on the same instance in realtime. It is local-only, for now, but there are plans to make it extendable to the entire fediverse!
|
|
||||||
|
|
||||||
### Mastodon interface
|
|
||||||
If the Pleroma interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
|
|
||||||
Just add a "/web" after your instance url (e.g. <https://pleroma.soycaf.com/web>) and you'll end on the Mastodon web interface, but with a Pleroma backend! MAGIC!
|
|
||||||
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.
|
|
||||||
|
|
||||||
Remember, what you see is only the frontend part of Mastodon, the backend is still Pleroma.
|
|
|
@ -1,2 +1,2 @@
|
||||||
elixir_version=1.8.2
|
elixir_version=1.9.4
|
||||||
erlang_version=21.3.7
|
erlang_version=22.3.4.1
|
||||||
|
|
27
installation/freebsd/rc.d/pleroma
Executable file
27
installation/freebsd/rc.d/pleroma
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# $FreeBSD$
|
||||||
|
# PROVIDE: pleroma
|
||||||
|
# REQUIRE: DAEMON postgresql
|
||||||
|
# KEYWORD: shutdown
|
||||||
|
|
||||||
|
# sudo -u pleroma MIX_ENV=prod elixir --erl \"-detached\" -S mix phx.server
|
||||||
|
|
||||||
|
. /etc/rc.subr
|
||||||
|
|
||||||
|
name=pleroma
|
||||||
|
rcvar=pleroma_enable
|
||||||
|
|
||||||
|
desc="Pleroma Social Media Platform"
|
||||||
|
|
||||||
|
load_rc_config ${name}
|
||||||
|
|
||||||
|
: ${pleroma_user:=pleroma}
|
||||||
|
: ${pleroma_home:=$(getent passwd ${pleroma_user} | awk -F: '{print $6}')}
|
||||||
|
: ${pleroma_chdir:="${pleroma_home}/pleroma"}
|
||||||
|
: ${pleroma_env:="HOME=${pleroma_home} MIX_ENV=prod"}
|
||||||
|
|
||||||
|
command=/usr/local/bin/elixir
|
||||||
|
command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server"
|
||||||
|
procname="*beam.smp"
|
||||||
|
|
||||||
|
run_rc_command "$1"
|
|
@ -13,7 +13,7 @@ CACHE_DIRECTORY="/tmp/pleroma-media-cache"
|
||||||
## $3 - (optional) the number of parallel processes to run for grep.
|
## $3 - (optional) the number of parallel processes to run for grep.
|
||||||
get_cache_files() {
|
get_cache_files() {
|
||||||
local max_parallel=${3-16}
|
local max_parallel=${3-16}
|
||||||
find $2 -maxdepth 2 -type d | xargs -P $max_parallel -n 1 grep -E Rl "^KEY:.*$1" | sort -u
|
find $2 -maxdepth 2 -type d | xargs -P $max_parallel -n 1 grep -E -Rl "^KEY:.*$1" | sort -u
|
||||||
}
|
}
|
||||||
|
|
||||||
## Removes an item from the given cache zone.
|
## Removes an item from the given cache zone.
|
||||||
|
@ -37,4 +37,4 @@ purge() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
purge $1
|
purge $@
|
||||||
|
|
|
@ -3,15 +3,54 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Mix.Pleroma do
|
defmodule Mix.Pleroma do
|
||||||
|
@apps [
|
||||||
|
:restarter,
|
||||||
|
:ecto,
|
||||||
|
:ecto_sql,
|
||||||
|
:postgrex,
|
||||||
|
:db_connection,
|
||||||
|
:cachex,
|
||||||
|
:flake_id,
|
||||||
|
:swoosh,
|
||||||
|
:timex
|
||||||
|
]
|
||||||
|
@cachex_children ["object", "user", "scrubber"]
|
||||||
@doc "Common functions to be reused in mix tasks"
|
@doc "Common functions to be reused in mix tasks"
|
||||||
def start_pleroma do
|
def start_pleroma do
|
||||||
|
Pleroma.Config.Holder.save_default()
|
||||||
|
Pleroma.Config.Oban.warn()
|
||||||
Application.put_env(:phoenix, :serve_endpoints, false, persistent: true)
|
Application.put_env(:phoenix, :serve_endpoints, false, persistent: true)
|
||||||
|
|
||||||
if Pleroma.Config.get(:env) != :test do
|
if Pleroma.Config.get(:env) != :test do
|
||||||
Application.put_env(:logger, :console, level: :debug)
|
Application.put_env(:logger, :console, level: :debug)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, _} = Application.ensure_all_started(:pleroma)
|
adapter = Application.get_env(:tesla, :adapter)
|
||||||
|
|
||||||
|
apps =
|
||||||
|
if adapter == Tesla.Adapter.Gun do
|
||||||
|
[:gun | @apps]
|
||||||
|
else
|
||||||
|
[:hackney | @apps]
|
||||||
|
end
|
||||||
|
|
||||||
|
Enum.each(apps, &Application.ensure_all_started/1)
|
||||||
|
|
||||||
|
children =
|
||||||
|
[
|
||||||
|
Pleroma.Repo,
|
||||||
|
{Pleroma.Config.TransferTask, false},
|
||||||
|
Pleroma.Web.Endpoint,
|
||||||
|
{Oban, Pleroma.Config.get(Oban)}
|
||||||
|
] ++
|
||||||
|
http_children(adapter)
|
||||||
|
|
||||||
|
cachex_children = Enum.map(@cachex_children, &Pleroma.Application.build_cachex(&1, []))
|
||||||
|
|
||||||
|
Supervisor.start_link(children ++ cachex_children,
|
||||||
|
strategy: :one_for_one,
|
||||||
|
name: Pleroma.Supervisor
|
||||||
|
)
|
||||||
|
|
||||||
if Pleroma.Config.get(:env) not in [:test, :benchmark] do
|
if Pleroma.Config.get(:env) not in [:test, :benchmark] do
|
||||||
pleroma_rebooted?()
|
pleroma_rebooted?()
|
||||||
|
@ -82,4 +121,11 @@ def mix_shell?, do: :erlang.function_exported(Mix, :shell, 0)
|
||||||
def escape_sh_path(path) do
|
def escape_sh_path(path) do
|
||||||
~S(') <> String.replace(path, ~S('), ~S(\')) <> ~S(')
|
~S(') <> String.replace(path, ~S('), ~S(\')) <> ~S(')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp http_children(Tesla.Adapter.Gun) do
|
||||||
|
Pleroma.Gun.ConnectionPool.children() ++
|
||||||
|
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp http_children(_), do: []
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,20 +91,17 @@ def run(["adapters"]) do
|
||||||
"Without conn and without pool" => fn ->
|
"Without conn and without pool" => fn ->
|
||||||
{:ok, %Tesla.Env{}} =
|
{:ok, %Tesla.Env{}} =
|
||||||
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [],
|
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [],
|
||||||
adapter: [pool: :no_pool, receive_conn: false]
|
pool: :no_pool,
|
||||||
|
receive_conn: false
|
||||||
)
|
)
|
||||||
end,
|
end,
|
||||||
"Without conn and with pool" => fn ->
|
"Without conn and with pool" => fn ->
|
||||||
{:ok, %Tesla.Env{}} =
|
{:ok, %Tesla.Env{}} =
|
||||||
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [],
|
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], receive_conn: false)
|
||||||
adapter: [receive_conn: false]
|
|
||||||
)
|
|
||||||
end,
|
end,
|
||||||
"With reused conn and without pool" => fn ->
|
"With reused conn and without pool" => fn ->
|
||||||
{:ok, %Tesla.Env{}} =
|
{:ok, %Tesla.Env{}} =
|
||||||
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [],
|
Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500", [], pool: :no_pool)
|
||||||
adapter: [pool: :no_pool]
|
|
||||||
)
|
|
||||||
end,
|
end,
|
||||||
"With reused conn and with pool" => fn ->
|
"With reused conn and with pool" => fn ->
|
||||||
{:ok, %Tesla.Env{}} = Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500")
|
{:ok, %Tesla.Env{}} = Pleroma.HTTP.get("https://httpbin.org/stream-bytes/1500")
|
||||||
|
|
|
@ -52,6 +52,7 @@ def migrate_to_db(file_path \\ nil) do
|
||||||
|
|
||||||
defp do_migrate_to_db(config_file) do
|
defp do_migrate_to_db(config_file) do
|
||||||
if File.exists?(config_file) do
|
if File.exists?(config_file) do
|
||||||
|
shell_info("Migrating settings from file: #{Path.expand(config_file)}")
|
||||||
Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
|
Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
|
||||||
Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
|
Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
|
||||||
|
|
||||||
|
@ -72,8 +73,7 @@ defp create(group, settings) do
|
||||||
group
|
group
|
||||||
|> Pleroma.Config.Loader.filter_group(settings)
|
|> Pleroma.Config.Loader.filter_group(settings)
|
||||||
|> Enum.each(fn {key, value} ->
|
|> Enum.each(fn {key, value} ->
|
||||||
key = inspect(key)
|
{:ok, _} = ConfigDB.update_or_create(%{group: group, key: key, value: value})
|
||||||
{:ok, _} = ConfigDB.update_or_create(%{group: inspect(group), key: key, value: value})
|
|
||||||
|
|
||||||
shell_info("Settings for key #{key} migrated.")
|
shell_info("Settings for key #{key} migrated.")
|
||||||
end)
|
end)
|
||||||
|
@ -83,7 +83,7 @@ defp create(group, settings) do
|
||||||
|
|
||||||
defp migrate_from_db(opts) do
|
defp migrate_from_db(opts) do
|
||||||
if Pleroma.Config.get([:configurable_from_database]) do
|
if Pleroma.Config.get([:configurable_from_database]) do
|
||||||
env = opts[:env] || "prod"
|
env = opts[:env] || Pleroma.Config.get(:env)
|
||||||
|
|
||||||
config_path =
|
config_path =
|
||||||
if Pleroma.Config.get(:release) do
|
if Pleroma.Config.get(:release) do
|
||||||
|
@ -105,6 +105,10 @@ defp migrate_from_db(opts) do
|
||||||
|
|
||||||
:ok = File.close(file)
|
:ok = File.close(file)
|
||||||
System.cmd("mix", ["format", config_path])
|
System.cmd("mix", ["format", config_path])
|
||||||
|
|
||||||
|
shell_info(
|
||||||
|
"Database configuration settings have been exported to config/#{env}.exported_from_db.secret.exs"
|
||||||
|
)
|
||||||
else
|
else
|
||||||
migration_error()
|
migration_error()
|
||||||
end
|
end
|
||||||
|
@ -112,7 +116,7 @@ defp migrate_from_db(opts) do
|
||||||
|
|
||||||
defp migration_error do
|
defp migration_error do
|
||||||
shell_error(
|
shell_error(
|
||||||
"Migration is not allowed in config. You can change this behavior by setting `configurable_from_database` to true."
|
"Migration is not allowed in config. You can change this behavior by setting `config :pleroma, configurable_from_database: true`"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -131,12 +135,9 @@ defp write_and_delete(config, file, delete?) do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp write(config, file) do
|
defp write(config, file) do
|
||||||
value =
|
value = inspect(config.value, limit: :infinity)
|
||||||
config.value
|
|
||||||
|> ConfigDB.from_binary()
|
|
||||||
|> inspect(limit: :infinity)
|
|
||||||
|
|
||||||
IO.write(file, "config #{config.group}, #{config.key}, #{value}\r\n\r\n")
|
IO.write(file, "config #{inspect(config.group)}, #{inspect(config.key)}, #{value}\r\n\r\n")
|
||||||
|
|
||||||
config
|
config
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Mix.Tasks.Pleroma.Database do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
require Logger
|
require Logger
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
import Ecto.Query
|
||||||
import Mix.Pleroma
|
import Mix.Pleroma
|
||||||
use Mix.Task
|
use Mix.Task
|
||||||
|
|
||||||
|
@ -53,8 +54,6 @@ def run(["update_users_following_followers_counts"]) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(["prune_objects" | args]) do
|
def run(["prune_objects" | args]) do
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
{options, [], []} =
|
{options, [], []} =
|
||||||
OptionParser.parse(
|
OptionParser.parse(
|
||||||
args,
|
args,
|
||||||
|
@ -94,8 +93,6 @@ def run(["prune_objects" | args]) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(["fix_likes_collections"]) do
|
def run(["fix_likes_collections"]) do
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
|
||||||
from(object in Object,
|
from(object in Object,
|
||||||
|
@ -130,4 +127,38 @@ def run(["vacuum", args]) do
|
||||||
|
|
||||||
Maintenance.vacuum(args)
|
Maintenance.vacuum(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run(["ensure_expiration"]) do
|
||||||
|
start_pleroma()
|
||||||
|
days = Pleroma.Config.get([:mrf_activity_expiration, :days], 365)
|
||||||
|
|
||||||
|
Pleroma.Activity
|
||||||
|
|> join(:inner, [a], o in Object,
|
||||||
|
on:
|
||||||
|
fragment(
|
||||||
|
"(?->>'id') = COALESCE((?)->'object'->> 'id', (?)->>'object')",
|
||||||
|
o.data,
|
||||||
|
a.data,
|
||||||
|
a.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|> where(local: true)
|
||||||
|
|> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
|
||||||
|
|> where([_a, o], fragment("?->>'type' = 'Note'", o.data))
|
||||||
|
|> Pleroma.RepoStreamer.chunk_stream(100)
|
||||||
|
|> Stream.each(fn activities ->
|
||||||
|
Enum.each(activities, fn activity ->
|
||||||
|
expires_at =
|
||||||
|
activity.inserted_at
|
||||||
|
|> DateTime.from_naive!("Etc/UTC")
|
||||||
|
|> Timex.shift(days: days)
|
||||||
|
|
||||||
|
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||||
|
activity_id: activity.id,
|
||||||
|
expires_at: expires_at
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|> Stream.run()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,6 +41,10 @@ def run(args \\ []) do
|
||||||
load_pleroma()
|
load_pleroma()
|
||||||
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
||||||
|
|
||||||
|
if Application.get_env(:pleroma, Pleroma.Repo)[:ssl] do
|
||||||
|
Application.ensure_all_started(:ssl)
|
||||||
|
end
|
||||||
|
|
||||||
opts =
|
opts =
|
||||||
if opts[:to] || opts[:step] || opts[:all],
|
if opts[:to] || opts[:step] || opts[:all],
|
||||||
do: opts,
|
do: opts,
|
||||||
|
|
|
@ -40,6 +40,10 @@ def run(args \\ []) do
|
||||||
load_pleroma()
|
load_pleroma()
|
||||||
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
||||||
|
|
||||||
|
if Application.get_env(:pleroma, Pleroma.Repo)[:ssl] do
|
||||||
|
Application.ensure_all_started(:ssl)
|
||||||
|
end
|
||||||
|
|
||||||
opts =
|
opts =
|
||||||
if opts[:to] || opts[:step] || opts[:all],
|
if opts[:to] || opts[:step] || opts[:all],
|
||||||
do: opts,
|
do: opts,
|
||||||
|
|
|
@ -15,7 +15,7 @@ def run(["ls-packs" | args]) do
|
||||||
{options, [], []} = parse_global_opts(args)
|
{options, [], []} = parse_global_opts(args)
|
||||||
|
|
||||||
url_or_path = options[:manifest] || default_manifest()
|
url_or_path = options[:manifest] || default_manifest()
|
||||||
manifest = fetch_and_decode(url_or_path)
|
manifest = fetch_and_decode!(url_or_path)
|
||||||
|
|
||||||
Enum.each(manifest, fn {name, info} ->
|
Enum.each(manifest, fn {name, info} ->
|
||||||
to_print = [
|
to_print = [
|
||||||
|
@ -42,7 +42,7 @@ def run(["get-packs" | args]) do
|
||||||
|
|
||||||
url_or_path = options[:manifest] || default_manifest()
|
url_or_path = options[:manifest] || default_manifest()
|
||||||
|
|
||||||
manifest = fetch_and_decode(url_or_path)
|
manifest = fetch_and_decode!(url_or_path)
|
||||||
|
|
||||||
for pack_name <- pack_names do
|
for pack_name <- pack_names do
|
||||||
if Map.has_key?(manifest, pack_name) do
|
if Map.has_key?(manifest, pack_name) do
|
||||||
|
@ -92,7 +92,7 @@ def run(["get-packs" | args]) do
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
files = fetch_and_decode(files_loc)
|
files = fetch_and_decode!(files_loc)
|
||||||
|
|
||||||
IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
|
IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ def run(["gen-pack" | args]) do
|
||||||
|
|
||||||
IO.puts("Downloading the pack and generating SHA256")
|
IO.puts("Downloading the pack and generating SHA256")
|
||||||
|
|
||||||
binary_archive = Tesla.get!(client(), src).body
|
{:ok, %{body: binary_archive}} = Pleroma.HTTP.get(src)
|
||||||
archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
|
archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
|
||||||
|
|
||||||
IO.puts("SHA256 is #{archive_sha}")
|
IO.puts("SHA256 is #{archive_sha}")
|
||||||
|
@ -243,14 +243,16 @@ def run(["reload"]) do
|
||||||
IO.puts("Emoji packs have been reloaded.")
|
IO.puts("Emoji packs have been reloaded.")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch_and_decode(from) do
|
defp fetch_and_decode!(from) do
|
||||||
with {:ok, json} <- fetch(from) do
|
with {:ok, json} <- fetch(from) do
|
||||||
Jason.decode!(json)
|
Jason.decode!(json)
|
||||||
|
else
|
||||||
|
{:error, error} -> raise "#{from} cannot be fetched. Error: #{error} occur."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp fetch("http" <> _ = from) do
|
defp fetch("http" <> _ = from) do
|
||||||
with {:ok, %{body: body}} <- Tesla.get(client(), from) do
|
with {:ok, %{body: body}} <- Pleroma.HTTP.get(from) do
|
||||||
{:ok, body}
|
{:ok, body}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -269,13 +271,5 @@ defp parse_global_opts(args) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp client do
|
|
||||||
middleware = [
|
|
||||||
{Tesla.Middleware.FollowRedirects, [max_redirects: 3]}
|
|
||||||
]
|
|
||||||
|
|
||||||
Tesla.client(middleware)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp default_manifest, do: Pleroma.Config.get!([:emoji, :default_manifest])
|
defp default_manifest, do: Pleroma.Config.get!([:emoji, :default_manifest])
|
||||||
end
|
end
|
||||||
|
|
141
lib/mix/tasks/pleroma/frontend.ex
Normal file
141
lib/mix/tasks/pleroma/frontend.ex
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Mix.Tasks.Pleroma.Frontend do
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
import Mix.Pleroma
|
||||||
|
|
||||||
|
@shortdoc "Manages bundled Pleroma frontends"
|
||||||
|
|
||||||
|
@moduledoc File.read!("docs/administration/CLI_tasks/frontend.md")
|
||||||
|
|
||||||
|
def run(["install", "none" | _args]) do
|
||||||
|
shell_info("Skipping frontend installation because none was requested")
|
||||||
|
"none"
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(["install", frontend | args]) do
|
||||||
|
log_level = Logger.level()
|
||||||
|
Logger.configure(level: :warn)
|
||||||
|
start_pleroma()
|
||||||
|
|
||||||
|
{options, [], []} =
|
||||||
|
OptionParser.parse(
|
||||||
|
args,
|
||||||
|
strict: [
|
||||||
|
ref: :string,
|
||||||
|
static_dir: :string,
|
||||||
|
build_url: :string,
|
||||||
|
build_dir: :string,
|
||||||
|
file: :string
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
instance_static_dir =
|
||||||
|
with nil <- options[:static_dir] do
|
||||||
|
Pleroma.Config.get!([:instance, :static_dir])
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd_frontend_info = %{
|
||||||
|
"name" => frontend,
|
||||||
|
"ref" => options[:ref],
|
||||||
|
"build_url" => options[:build_url],
|
||||||
|
"build_dir" => options[:build_dir]
|
||||||
|
}
|
||||||
|
|
||||||
|
config_frontend_info = Pleroma.Config.get([:frontends, :available, frontend], %{})
|
||||||
|
|
||||||
|
frontend_info =
|
||||||
|
Map.merge(config_frontend_info, cmd_frontend_info, fn _key, config, cmd ->
|
||||||
|
# This only overrides things that are actually set
|
||||||
|
cmd || config
|
||||||
|
end)
|
||||||
|
|
||||||
|
ref = frontend_info["ref"]
|
||||||
|
|
||||||
|
unless ref do
|
||||||
|
raise "No ref given or configured"
|
||||||
|
end
|
||||||
|
|
||||||
|
dest =
|
||||||
|
Path.join([
|
||||||
|
instance_static_dir,
|
||||||
|
"frontends",
|
||||||
|
frontend,
|
||||||
|
ref
|
||||||
|
])
|
||||||
|
|
||||||
|
fe_label = "#{frontend} (#{ref})"
|
||||||
|
|
||||||
|
tmp_dir = Path.join([instance_static_dir, "frontends", "tmp"])
|
||||||
|
|
||||||
|
with {_, :ok} <-
|
||||||
|
{:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, options[:file])},
|
||||||
|
shell_info("Installing #{fe_label} to #{dest}"),
|
||||||
|
:ok <- install_frontend(frontend_info, tmp_dir, dest) do
|
||||||
|
File.rm_rf!(tmp_dir)
|
||||||
|
shell_info("Frontend #{fe_label} installed to #{dest}")
|
||||||
|
|
||||||
|
Logger.configure(level: log_level)
|
||||||
|
else
|
||||||
|
{:download_or_unzip, _} ->
|
||||||
|
shell_info("Could not download or unzip the frontend")
|
||||||
|
|
||||||
|
_e ->
|
||||||
|
shell_info("Could not install the frontend")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp download_or_unzip(frontend_info, temp_dir, file) do
|
||||||
|
if file do
|
||||||
|
with {:ok, zip} <- File.read(Path.expand(file)) do
|
||||||
|
unzip(zip, temp_dir)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
download_build(frontend_info, temp_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unzip(zip, dest) do
|
||||||
|
with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
|
||||||
|
File.rm_rf!(dest)
|
||||||
|
File.mkdir_p!(dest)
|
||||||
|
|
||||||
|
Enum.each(unzipped, fn {filename, data} ->
|
||||||
|
path = filename
|
||||||
|
|
||||||
|
new_file_path = Path.join(dest, path)
|
||||||
|
|
||||||
|
new_file_path
|
||||||
|
|> Path.dirname()
|
||||||
|
|> File.mkdir_p!()
|
||||||
|
|
||||||
|
File.write!(new_file_path, data)
|
||||||
|
end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp download_build(frontend_info, dest) do
|
||||||
|
shell_info("Downloading pre-built bundle for #{frontend_info["name"]}")
|
||||||
|
url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
|
||||||
|
|
||||||
|
with {:ok, %{status: 200, body: zip_body}} <-
|
||||||
|
Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
|
||||||
|
unzip(zip_body, dest)
|
||||||
|
else
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp install_frontend(frontend_info, source, dest) do
|
||||||
|
from = frontend_info["build_dir"] || "dist"
|
||||||
|
File.rm_rf!(dest)
|
||||||
|
File.mkdir_p!(dest)
|
||||||
|
File.cp_r!(Path.join([source, from]), dest)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
|
@ -145,7 +145,7 @@ def run(["gen" | rest]) do
|
||||||
options,
|
options,
|
||||||
:uploads_dir,
|
:uploads_dir,
|
||||||
"What directory should media uploads go in (when using the local uploader)?",
|
"What directory should media uploads go in (when using the local uploader)?",
|
||||||
Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads])
|
Config.get([Pleroma.Uploaders.Local, :uploads])
|
||||||
)
|
)
|
||||||
|> Path.expand()
|
|> Path.expand()
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ def run(["gen" | rest]) do
|
||||||
options,
|
options,
|
||||||
:static_dir,
|
:static_dir,
|
||||||
"What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
|
"What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
|
||||||
Pleroma.Config.get([:instance, :static_dir])
|
Config.get([:instance, :static_dir])
|
||||||
)
|
)
|
||||||
|> Path.expand()
|
|> Path.expand()
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ defmodule Mix.Tasks.Pleroma.NotificationSettings do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
> mix pleroma.notification_settings --privacy-option=false --nickname-users="parallel588" # set false only for parallel588 user
|
> mix pleroma.notification_settings --hide-notification-contents=false --nickname-users="parallel588" # set false only for parallel588 user
|
||||||
> mix pleroma.notification_settings --privacy-option=true # set true for all users
|
> mix pleroma.notification_settings --hide-notification-contents=true # set true for all users
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -19,16 +19,16 @@ def run(args) do
|
||||||
OptionParser.parse(
|
OptionParser.parse(
|
||||||
args,
|
args,
|
||||||
strict: [
|
strict: [
|
||||||
privacy_option: :boolean,
|
hide_notification_contents: :boolean,
|
||||||
email_users: :string,
|
email_users: :string,
|
||||||
nickname_users: :string
|
nickname_users: :string
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
privacy_option = Keyword.get(options, :privacy_option)
|
hide_notification_contents = Keyword.get(options, :hide_notification_contents)
|
||||||
|
|
||||||
if not is_nil(privacy_option) do
|
if not is_nil(hide_notification_contents) do
|
||||||
privacy_option
|
hide_notification_contents
|
||||||
|> build_query(options)
|
|> build_query(options)
|
||||||
|> Pleroma.Repo.update_all([])
|
|> Pleroma.Repo.update_all([])
|
||||||
end
|
end
|
||||||
|
@ -36,15 +36,15 @@ def run(args) do
|
||||||
shell_info("Done")
|
shell_info("Done")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_query(privacy_option, options) do
|
defp build_query(hide_notification_contents, options) do
|
||||||
query =
|
query =
|
||||||
from(u in Pleroma.User,
|
from(u in Pleroma.User,
|
||||||
update: [
|
update: [
|
||||||
set: [
|
set: [
|
||||||
notification_settings:
|
notification_settings:
|
||||||
fragment(
|
fragment(
|
||||||
"jsonb_set(notification_settings, '{privacy_option}', ?)",
|
"jsonb_set(notification_settings, '{hide_notification_contents}', ?)",
|
||||||
^privacy_option
|
^hide_notification_contents
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,30 +17,53 @@ defmodule Mix.Tasks.Pleroma.RefreshCounterCache do
|
||||||
def run([]) do
|
def run([]) do
|
||||||
Mix.Pleroma.start_pleroma()
|
Mix.Pleroma.start_pleroma()
|
||||||
|
|
||||||
["public", "unlisted", "private", "direct"]
|
instances =
|
||||||
|> Enum.each(fn visibility ->
|
Activity
|
||||||
count = status_visibility_count_query(visibility)
|
|> distinct([a], true)
|
||||||
name = "status_visibility_#{visibility}"
|
|> select([a], fragment("split_part(?, '/', 3)", a.actor))
|
||||||
CounterCache.set(name, count)
|
|> Repo.all()
|
||||||
Mix.Pleroma.shell_info("Set #{name} to #{count}")
|
|
||||||
|
instances
|
||||||
|
|> Enum.with_index(1)
|
||||||
|
|> Enum.each(fn {instance, i} ->
|
||||||
|
counters = instance_counters(instance)
|
||||||
|
CounterCache.set(instance, counters)
|
||||||
|
|
||||||
|
Mix.Pleroma.shell_info(
|
||||||
|
"[#{i}/#{length(instances)}] Setting #{instance} counters: #{inspect(counters)}"
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Mix.Pleroma.shell_info("Done")
|
Mix.Pleroma.shell_info("Done")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_visibility_count_query(visibility) do
|
defp instance_counters(instance) do
|
||||||
|
counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
|
||||||
|
|
||||||
Activity
|
Activity
|
||||||
|> where(
|
|> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
|
||||||
|
|> where([a], fragment("split_part(?, '/', 3) = ?", a.actor, ^instance))
|
||||||
|
|> select(
|
||||||
[a],
|
[a],
|
||||||
fragment(
|
{fragment(
|
||||||
"activity_visibility(?, ?, ?) = ?",
|
"activity_visibility(?, ?, ?)",
|
||||||
a.actor,
|
a.actor,
|
||||||
a.recipients,
|
a.recipients,
|
||||||
a.data,
|
a.data
|
||||||
^visibility
|
), count(a.id)}
|
||||||
|
)
|
||||||
|
|> group_by(
|
||||||
|
[a],
|
||||||
|
fragment(
|
||||||
|
"activity_visibility(?, ?, ?)",
|
||||||
|
a.actor,
|
||||||
|
a.recipients,
|
||||||
|
a.data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
|
|> Repo.all(timeout: :timer.minutes(30))
|
||||||
|> Repo.aggregate(:count, :id, timeout: :timer.minutes(30))
|
|> Enum.reduce(counters, fn {visibility, count}, acc ->
|
||||||
|
Map.put(acc, visibility, count)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,10 +35,16 @@ def run(["unfollow", target]) do
|
||||||
def run(["list"]) do
|
def run(["list"]) do
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
|
||||||
with {:ok, list} <- Relay.list(true) do
|
with {:ok, list} <- Relay.list() do
|
||||||
list |> Enum.each(&shell_info(&1))
|
Enum.each(list, &print_relay_url/1)
|
||||||
else
|
else
|
||||||
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
{:error, e} -> shell_error("Error while fetching relay subscription list: #{inspect(e)}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp print_relay_url(%{followed_back: false} = relay) do
|
||||||
|
shell_info("#{relay.actor} - no Accept received (relay didn't follow back)")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp print_relay_url(relay), do: shell_info(relay.actor)
|
||||||
end
|
end
|
||||||
|
|
|
@ -232,7 +232,7 @@ def run(["tag", nickname | tags]) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname) do
|
with %User{} = user <- User.get_cached_by_nickname(nickname) do
|
||||||
user = user |> User.tag(tags)
|
user = user |> User.tag(tags)
|
||||||
|
|
||||||
shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
|
shell_info("Tags of #{user.nickname}: #{inspect(user.tags)}")
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
shell_error("Could not change user tags for #{nickname}")
|
shell_error("Could not change user tags for #{nickname}")
|
||||||
|
@ -245,7 +245,7 @@ def run(["untag", nickname | tags]) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname) do
|
with %User{} = user <- User.get_cached_by_nickname(nickname) do
|
||||||
user = user |> User.untag(tags)
|
user = user |> User.untag(tags)
|
||||||
|
|
||||||
shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
|
shell_info("Tags of #{user.nickname}: #{inspect(user.tags)}")
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
shell_error("Could not change user tags for #{nickname}")
|
shell_error("Could not change user tags for #{nickname}")
|
||||||
|
|
|
@ -7,7 +7,6 @@ defmodule Pleroma.Activity do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Activity.Queries
|
alias Pleroma.Activity.Queries
|
||||||
alias Pleroma.ActivityExpiration
|
|
||||||
alias Pleroma.Bookmark
|
alias Pleroma.Bookmark
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
@ -60,8 +59,6 @@ defmodule Pleroma.Activity do
|
||||||
# typical case.
|
# typical case.
|
||||||
has_one(:object, Object, on_delete: :nothing, foreign_key: :id)
|
has_one(:object, Object, on_delete: :nothing, foreign_key: :id)
|
||||||
|
|
||||||
has_one(:expiration, ActivityExpiration, on_delete: :delete_all)
|
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -304,14 +301,14 @@ def all_by_actor_and_id(actor, status_ids) do
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do
|
def follow_requests_for_actor(%User{ap_id: ap_id}) do
|
||||||
ap_id
|
ap_id
|
||||||
|> Queries.by_object_id()
|
|> Queries.by_object_id()
|
||||||
|> Queries.by_type("Follow")
|
|> Queries.by_type("Follow")
|
||||||
|> where([a], fragment("? ->> 'state' = 'pending'", a.data))
|
|> where([a], fragment("? ->> 'state' = 'pending'", a.data))
|
||||||
end
|
end
|
||||||
|
|
||||||
def following_requests_for_actor(%Pleroma.User{ap_id: ap_id}) do
|
def following_requests_for_actor(%User{ap_id: ap_id}) do
|
||||||
Queries.by_type("Follow")
|
Queries.by_type("Follow")
|
||||||
|> where([a], fragment("?->>'state' = 'pending'", a.data))
|
|> where([a], fragment("?->>'state' = 'pending'", a.data))
|
||||||
|> where([a], a.actor == ^ap_id)
|
|> where([a], a.actor == ^ap_id)
|
||||||
|
@ -340,4 +337,10 @@ def direct_conversation_id(activity, for_user) do
|
||||||
_ -> nil
|
_ -> nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec pinned_by_actor?(Activity.t()) :: boolean()
|
||||||
|
def pinned_by_actor?(%Activity{} = activity) do
|
||||||
|
actor = user_actor(activity)
|
||||||
|
activity.id in actor.pinned_activities
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.ActivityExpiration do
|
|
||||||
use Ecto.Schema
|
|
||||||
|
|
||||||
alias Pleroma.Activity
|
|
||||||
alias Pleroma.ActivityExpiration
|
|
||||||
alias Pleroma.Repo
|
|
||||||
|
|
||||||
import Ecto.Changeset
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
@type t :: %__MODULE__{}
|
|
||||||
@min_activity_lifetime :timer.hours(1)
|
|
||||||
|
|
||||||
schema "activity_expirations" do
|
|
||||||
belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType)
|
|
||||||
field(:scheduled_at, :naive_datetime)
|
|
||||||
end
|
|
||||||
|
|
||||||
def changeset(%ActivityExpiration{} = expiration, attrs) do
|
|
||||||
expiration
|
|
||||||
|> cast(attrs, [:scheduled_at])
|
|
||||||
|> validate_required([:scheduled_at])
|
|
||||||
|> validate_scheduled_at()
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_by_activity_id(activity_id) do
|
|
||||||
ActivityExpiration
|
|
||||||
|> where([exp], exp.activity_id == ^activity_id)
|
|
||||||
|> Repo.one()
|
|
||||||
end
|
|
||||||
|
|
||||||
def create(%Activity{} = activity, scheduled_at) do
|
|
||||||
%ActivityExpiration{activity_id: activity.id}
|
|
||||||
|> changeset(%{scheduled_at: scheduled_at})
|
|
||||||
|> Repo.insert()
|
|
||||||
end
|
|
||||||
|
|
||||||
def due_expirations(offset \\ 0) do
|
|
||||||
naive_datetime =
|
|
||||||
NaiveDateTime.utc_now()
|
|
||||||
|> NaiveDateTime.add(offset, :millisecond)
|
|
||||||
|
|
||||||
ActivityExpiration
|
|
||||||
|> where([exp], exp.scheduled_at < ^naive_datetime)
|
|
||||||
|> Repo.all()
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_scheduled_at(changeset) do
|
|
||||||
validate_change(changeset, :scheduled_at, fn _, scheduled_at ->
|
|
||||||
if not expires_late_enough?(scheduled_at) do
|
|
||||||
[scheduled_at: "an ephemeral activity must live for at least one hour"]
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def expires_late_enough?(scheduled_at) do
|
|
||||||
now = NaiveDateTime.utc_now()
|
|
||||||
diff = NaiveDateTime.diff(scheduled_at, now, :millisecond)
|
|
||||||
diff > @min_activity_lifetime
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -22,6 +22,7 @@ def named_version, do: @name <> " " <> @version
|
||||||
def repository, do: @repository
|
def repository, do: @repository
|
||||||
|
|
||||||
def user_agent do
|
def user_agent do
|
||||||
|
if Process.whereis(Pleroma.Web.Endpoint) do
|
||||||
case Config.get([:http, :user_agent], :default) do
|
case Config.get([:http, :user_agent], :default) do
|
||||||
:default ->
|
:default ->
|
||||||
info = "#{Pleroma.Web.base_url()} <#{Config.get([:instance, :email], "")}>"
|
info = "#{Pleroma.Web.base_url()} <#{Config.get([:instance, :email], "")}>"
|
||||||
|
@ -30,18 +31,33 @@ def user_agent do
|
||||||
custom ->
|
custom ->
|
||||||
custom
|
custom
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
# fallback, if endpoint is not started yet
|
||||||
|
"Pleroma Data Loader"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# See http://elixir-lang.org/docs/stable/elixir/Application.html
|
# See http://elixir-lang.org/docs/stable/elixir/Application.html
|
||||||
# for more information on OTP Applications
|
# for more information on OTP Applications
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
Pleroma.Config.Holder.save_default()
|
# Scrubbers are compiled at runtime and therefore will cause a conflict
|
||||||
|
# every time the application is restarted, so we disable module
|
||||||
|
# conflicts at runtime
|
||||||
|
Code.compiler_options(ignore_module_conflict: true)
|
||||||
|
# Disable warnings_as_errors at runtime, it breaks Phoenix live reload
|
||||||
|
# due to protocol consolidation warnings
|
||||||
|
Code.compiler_options(warnings_as_errors: false)
|
||||||
|
Pleroma.Telemetry.Logger.attach()
|
||||||
|
Config.Holder.save_default()
|
||||||
Pleroma.HTML.compile_scrubbers()
|
Pleroma.HTML.compile_scrubbers()
|
||||||
|
Pleroma.Config.Oban.warn()
|
||||||
Config.DeprecationWarnings.warn()
|
Config.DeprecationWarnings.warn()
|
||||||
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
||||||
Pleroma.Repo.check_migrations_applied!()
|
Pleroma.ApplicationRequirements.verify!()
|
||||||
setup_instrumenters()
|
setup_instrumenters()
|
||||||
load_custom_modules()
|
load_custom_modules()
|
||||||
|
check_system_commands()
|
||||||
|
Pleroma.Docs.JSON.compile()
|
||||||
|
|
||||||
adapter = Application.get_env(:tesla, :adapter)
|
adapter = Application.get_env(:tesla, :adapter)
|
||||||
|
|
||||||
|
@ -149,7 +165,8 @@ defp cachex_children do
|
||||||
build_cachex("idempotency", expiration: idempotency_expiration(), limit: 2500),
|
build_cachex("idempotency", expiration: idempotency_expiration(), limit: 2500),
|
||||||
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("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -162,7 +179,8 @@ defp idempotency_expiration,
|
||||||
defp seconds_valid_interval,
|
defp seconds_valid_interval,
|
||||||
do: :timer.seconds(Config.get!([Pleroma.Captcha, :seconds_valid]))
|
do: :timer.seconds(Config.get!([Pleroma.Captcha, :seconds_valid]))
|
||||||
|
|
||||||
defp build_cachex(type, opts),
|
@spec build_cachex(String.t(), keyword()) :: map()
|
||||||
|
def build_cachex(type, opts),
|
||||||
do: %{
|
do: %{
|
||||||
id: String.to_atom("cachex_" <> type),
|
id: String.to_atom("cachex_" <> type),
|
||||||
start: {Cachex, :start_link, [String.to_atom(type <> "_cache"), opts]},
|
start: {Cachex, :start_link, [String.to_atom(type <> "_cache"), opts]},
|
||||||
|
@ -217,9 +235,7 @@ defp task_children(_) do
|
||||||
|
|
||||||
# start hackney and gun pools in tests
|
# start hackney and gun pools in tests
|
||||||
defp http_children(_, :test) do
|
defp http_children(_, :test) do
|
||||||
hackney_options = Config.get([:hackney_pools, :federation])
|
http_children(Tesla.Adapter.Hackney, nil) ++ http_children(Tesla.Adapter.Gun, nil)
|
||||||
hackney_pool = :hackney_pool.child_spec(:federation, hackney_options)
|
|
||||||
[hackney_pool, Pleroma.Pool.Supervisor]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp http_children(Tesla.Adapter.Hackney, _) do
|
defp http_children(Tesla.Adapter.Hackney, _) do
|
||||||
|
@ -238,7 +254,27 @@ defp http_children(Tesla.Adapter.Hackney, _) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp http_children(Tesla.Adapter.Gun, _), do: [Pleroma.Pool.Supervisor]
|
defp http_children(Tesla.Adapter.Gun, _) do
|
||||||
|
Pleroma.Gun.ConnectionPool.children() ++
|
||||||
|
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
|
||||||
|
end
|
||||||
|
|
||||||
defp http_children(_, _), do: []
|
defp http_children(_, _), do: []
|
||||||
|
|
||||||
|
defp check_system_commands do
|
||||||
|
filters = Config.get([Pleroma.Upload, :filters])
|
||||||
|
|
||||||
|
check_filter = fn filter, command_required ->
|
||||||
|
with true <- filter in filters,
|
||||||
|
false <- Pleroma.Utils.command_available?(command_required) do
|
||||||
|
Logger.error(
|
||||||
|
"#{filter} is specified in list of Pleroma.Upload filters, but the #{command_required} command is not found"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
check_filter.(Pleroma.Upload.Filters.Exiftool, "exiftool")
|
||||||
|
check_filter.(Pleroma.Upload.Filters.Mogrify, "mogrify")
|
||||||
|
check_filter.(Pleroma.Upload.Filters.Mogrifun, "mogrify")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
143
lib/pleroma/application_requirements.ex
Normal file
143
lib/pleroma/application_requirements.ex
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.ApplicationRequirements do
|
||||||
|
@moduledoc """
|
||||||
|
The module represents the collection of validations to runs before start server.
|
||||||
|
"""
|
||||||
|
|
||||||
|
defmodule VerifyError, do: defexception([:message])
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@spec verify!() :: :ok | VerifyError.t()
|
||||||
|
def verify! do
|
||||||
|
:ok
|
||||||
|
|> check_confirmation_accounts!
|
||||||
|
|> check_migrations_applied!()
|
||||||
|
|> check_welcome_message_config!()
|
||||||
|
|> check_rum!()
|
||||||
|
|> handle_result()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp handle_result(:ok), do: :ok
|
||||||
|
defp handle_result({:error, message}), do: raise(VerifyError, message: message)
|
||||||
|
|
||||||
|
defp check_welcome_message_config!(:ok) do
|
||||||
|
if Pleroma.Config.get([:welcome, :email, :enabled], false) and
|
||||||
|
not Pleroma.Emails.Mailer.enabled?() do
|
||||||
|
Logger.error("""
|
||||||
|
To send welcome email do you need to enable mail.
|
||||||
|
\nconfig :pleroma, Pleroma.Emails.Mailer, enabled: true
|
||||||
|
""")
|
||||||
|
|
||||||
|
{:error, "The mail disabled."}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_welcome_message_config!(result), do: result
|
||||||
|
|
||||||
|
# Checks account confirmation email
|
||||||
|
#
|
||||||
|
def check_confirmation_accounts!(:ok) do
|
||||||
|
if Pleroma.Config.get([:instance, :account_activation_required]) &&
|
||||||
|
not Pleroma.Config.get([Pleroma.Emails.Mailer, :enabled]) do
|
||||||
|
Logger.error(
|
||||||
|
"Account activation enabled, but no Mailer settings enabled.\nPlease set config :pleroma, :instance, account_activation_required: false\nOtherwise setup and enable Mailer."
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error,
|
||||||
|
"Account activation enabled, but Mailer is disabled. Cannot send confirmation emails."}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_confirmation_accounts!(result), do: result
|
||||||
|
|
||||||
|
# Checks for pending migrations.
|
||||||
|
#
|
||||||
|
def check_migrations_applied!(:ok) do
|
||||||
|
unless Pleroma.Config.get(
|
||||||
|
[:i_am_aware_this_may_cause_data_loss, :disable_migration_check],
|
||||||
|
false
|
||||||
|
) do
|
||||||
|
{_, res, _} =
|
||||||
|
Ecto.Migrator.with_repo(Pleroma.Repo, fn repo ->
|
||||||
|
down_migrations =
|
||||||
|
Ecto.Migrator.migrations(repo)
|
||||||
|
|> Enum.reject(fn
|
||||||
|
{:up, _, _} -> true
|
||||||
|
{:down, _, _} -> false
|
||||||
|
end)
|
||||||
|
|
||||||
|
if length(down_migrations) > 0 do
|
||||||
|
down_migrations_text =
|
||||||
|
Enum.map(down_migrations, fn {:down, id, name} -> "- #{name} (#{id})\n" end)
|
||||||
|
|
||||||
|
Logger.error(
|
||||||
|
"The following migrations were not applied:\n#{down_migrations_text}If you want to start Pleroma anyway, set\nconfig :pleroma, :i_am_aware_this_may_cause_data_loss, disable_migration_check: true"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, "Unapplied Migrations detected"}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
res
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_migrations_applied!(result), do: result
|
||||||
|
|
||||||
|
# Checks for settings of RUM indexes.
|
||||||
|
#
|
||||||
|
defp check_rum!(:ok) do
|
||||||
|
{_, res, _} =
|
||||||
|
Ecto.Migrator.with_repo(Pleroma.Repo, fn repo ->
|
||||||
|
migrate =
|
||||||
|
from(o in "columns",
|
||||||
|
where: o.table_name == "objects",
|
||||||
|
where: o.column_name == "fts_content"
|
||||||
|
)
|
||||||
|
|> repo.exists?(prefix: "information_schema")
|
||||||
|
|
||||||
|
setting = Pleroma.Config.get([:database, :rum_enabled], false)
|
||||||
|
|
||||||
|
do_check_rum!(setting, migrate)
|
||||||
|
end)
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_rum!(result), do: result
|
||||||
|
|
||||||
|
defp do_check_rum!(setting, migrate) do
|
||||||
|
case {setting, migrate} do
|
||||||
|
{true, false} ->
|
||||||
|
Logger.error(
|
||||||
|
"Use `RUM` index is enabled, but were not applied migrations for it.\nIf you want to start Pleroma anyway, set\nconfig :pleroma, :database, rum_enabled: false\nOtherwise apply the following migrations:\n`mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, "Unapplied RUM Migrations detected"}
|
||||||
|
|
||||||
|
{false, true} ->
|
||||||
|
Logger.error(
|
||||||
|
"Detected applied migrations to use `RUM` index, but `RUM` isn't enable in settings.\nIf you want to use `RUM`, set\nconfig :pleroma, :database, rum_enabled: true\nOtherwise roll `RUM` migrations back.\n`mix ecto.rollback --migrations-path priv/repo/optional_migrations/rum_indexing/`"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, "RUM Migrations detected"}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -21,7 +21,8 @@ def new do
|
||||||
type: :kocaptcha,
|
type: :kocaptcha,
|
||||||
token: json_resp["token"],
|
token: json_resp["token"],
|
||||||
url: endpoint <> json_resp["url"],
|
url: endpoint <> json_resp["url"],
|
||||||
answer_data: json_resp["md5"]
|
answer_data: json_resp["md5"],
|
||||||
|
seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,8 @@ def new do
|
||||||
type: :native,
|
type: :native,
|
||||||
token: token(),
|
token: token(),
|
||||||
url: "data:image/png;base64," <> Base.encode64(img_binary),
|
url: "data:image/png;base64," <> Base.encode64(img_binary),
|
||||||
answer_data: answer_data
|
answer_data: answer_data,
|
||||||
|
seconds_valid: Pleroma.Config.get([Pleroma.Captcha, :seconds_valid])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,12 +11,10 @@ def get(key), do: get(key, nil)
|
||||||
|
|
||||||
def get([key], default), do: get(key, default)
|
def get([key], default), do: get(key, default)
|
||||||
|
|
||||||
def get([parent_key | keys], default) do
|
def get([_ | _] = path, default) do
|
||||||
case :pleroma
|
case fetch(path) do
|
||||||
|> Application.get_env(parent_key)
|
{:ok, value} -> value
|
||||||
|> get_in(keys) do
|
:error -> default
|
||||||
nil -> default
|
|
||||||
any -> any
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,6 +32,24 @@ def get!(key) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch(key) when is_atom(key), do: fetch([key])
|
||||||
|
|
||||||
|
def fetch([root_key | keys]) do
|
||||||
|
Enum.reduce_while(keys, Application.fetch_env(:pleroma, root_key), fn
|
||||||
|
key, {:ok, config} when is_map(config) or is_list(config) ->
|
||||||
|
case Access.fetch(config, key) do
|
||||||
|
:error ->
|
||||||
|
{:halt, :error}
|
||||||
|
|
||||||
|
value ->
|
||||||
|
{:cont, value}
|
||||||
|
end
|
||||||
|
|
||||||
|
_key, _config ->
|
||||||
|
{:halt, :error}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
def put([key], value), do: put(key, value)
|
def put([key], value), do: put(key, value)
|
||||||
|
|
||||||
def put([parent_key | keys], value) do
|
def put([parent_key | keys], value) do
|
||||||
|
@ -50,18 +66,31 @@ def put(key, value) do
|
||||||
|
|
||||||
def delete([key]), do: delete(key)
|
def delete([key]), do: delete(key)
|
||||||
|
|
||||||
def delete([parent_key | keys]) do
|
def delete([parent_key | keys] = path) do
|
||||||
|
with {:ok, _} <- fetch(path) do
|
||||||
{_, parent} =
|
{_, parent} =
|
||||||
Application.get_env(:pleroma, parent_key)
|
parent_key
|
||||||
|
|> get()
|
||||||
|> get_and_update_in(keys, fn _ -> :pop end)
|
|> get_and_update_in(keys, fn _ -> :pop end)
|
||||||
|
|
||||||
Application.put_env(:pleroma, parent_key, parent)
|
Application.put_env(:pleroma, parent_key, parent)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def delete(key) do
|
def delete(key) do
|
||||||
Application.delete_env(:pleroma, key)
|
Application.delete_env(:pleroma, key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def restrict_unauthenticated_access?(resource, kind) do
|
||||||
|
setting = get([:restrict_unauthenticated, resource, kind])
|
||||||
|
|
||||||
|
if setting in [nil, :if_instance_is_private] do
|
||||||
|
!get!([:instance, :public])
|
||||||
|
else
|
||||||
|
setting
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def oauth_consumer_strategies, do: get([:auth, :oauth_consumer_strategies], [])
|
def oauth_consumer_strategies, do: get([:auth, :oauth_consumer_strategies], [])
|
||||||
|
|
||||||
def oauth_consumer_enabled?, do: oauth_consumer_strategies() != []
|
def oauth_consumer_enabled?, do: oauth_consumer_strategies() != []
|
||||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.ConfigDB do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
import Ecto.Query
|
import Ecto.Query, only: [select: 3]
|
||||||
import Pleroma.Web.Gettext
|
import Pleroma.Web.Gettext
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
@ -14,16 +14,6 @@ defmodule Pleroma.ConfigDB do
|
||||||
|
|
||||||
@type t :: %__MODULE__{}
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
@full_key_update [
|
|
||||||
{:pleroma, :ecto_repos},
|
|
||||||
{:quack, :meta},
|
|
||||||
{:mime, :types},
|
|
||||||
{:cors_plug, [:max_age, :methods, :expose, :headers]},
|
|
||||||
{:auto_linker, :opts},
|
|
||||||
{:swarm, :node_blacklist},
|
|
||||||
{:logger, :backends}
|
|
||||||
]
|
|
||||||
|
|
||||||
@full_subkey_update [
|
@full_subkey_update [
|
||||||
{:pleroma, :assets, :mascots},
|
{:pleroma, :assets, :mascots},
|
||||||
{:pleroma, :emoji, :groups},
|
{:pleroma, :emoji, :groups},
|
||||||
|
@ -32,14 +22,10 @@ defmodule Pleroma.ConfigDB do
|
||||||
{:pleroma, :mrf_keyword, :replace}
|
{:pleroma, :mrf_keyword, :replace}
|
||||||
]
|
]
|
||||||
|
|
||||||
@regex ~r/^~r(?'delimiter'[\/|"'([{<]{1})(?'pattern'.+)[\/|"')\]}>]{1}(?'modifier'[uismxfU]*)/u
|
|
||||||
|
|
||||||
@delimiters ["/", "|", "\"", "'", {"(", ")"}, {"[", "]"}, {"{", "}"}, {"<", ">"}]
|
|
||||||
|
|
||||||
schema "config" do
|
schema "config" do
|
||||||
field(:key, :string)
|
field(:key, Pleroma.EctoType.Config.Atom)
|
||||||
field(:group, :string)
|
field(:group, Pleroma.EctoType.Config.Atom)
|
||||||
field(:value, :binary)
|
field(:value, Pleroma.EctoType.Config.BinaryValue)
|
||||||
field(:db, {:array, :string}, virtual: true, default: [])
|
field(:db, {:array, :string}, virtual: true, default: [])
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
|
@ -51,10 +37,6 @@ def get_all_as_keyword do
|
||||||
|> select([c], {c.group, c.key, c.value})
|
|> select([c], {c.group, c.key, c.value})
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|> Enum.reduce([], fn {group, key, value}, acc ->
|
|> Enum.reduce([], fn {group, key, value}, acc ->
|
||||||
group = ConfigDB.from_string(group)
|
|
||||||
key = ConfigDB.from_string(key)
|
|
||||||
value = from_binary(value)
|
|
||||||
|
|
||||||
Keyword.update(acc, group, [{key, value}], &Keyword.merge(&1, [{key, value}]))
|
Keyword.update(acc, group, [{key, value}], &Keyword.merge(&1, [{key, value}]))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -64,50 +46,41 @@ def get_by_params(params), do: Repo.get_by(ConfigDB, params)
|
||||||
|
|
||||||
@spec changeset(ConfigDB.t(), map()) :: Changeset.t()
|
@spec changeset(ConfigDB.t(), map()) :: Changeset.t()
|
||||||
def changeset(config, params \\ %{}) do
|
def changeset(config, params \\ %{}) do
|
||||||
params = Map.put(params, :value, transform(params[:value]))
|
|
||||||
|
|
||||||
config
|
config
|
||||||
|> cast(params, [:key, :group, :value])
|
|> cast(params, [:key, :group, :value])
|
||||||
|> validate_required([:key, :group, :value])
|
|> validate_required([:key, :group, :value])
|
||||||
|> unique_constraint(:key, name: :config_group_key_index)
|
|> unique_constraint(:key, name: :config_group_key_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec create(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
defp create(params) do
|
||||||
def create(params) do
|
|
||||||
%ConfigDB{}
|
%ConfigDB{}
|
||||||
|> changeset(params)
|
|> changeset(params)
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec update(ConfigDB.t(), map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
defp update(%ConfigDB{} = config, %{value: value}) do
|
||||||
def update(%ConfigDB{} = config, %{value: value}) do
|
|
||||||
config
|
config
|
||||||
|> changeset(%{value: value})
|
|> changeset(%{value: value})
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_db_keys(ConfigDB.t()) :: [String.t()]
|
|
||||||
def get_db_keys(%ConfigDB{} = config) do
|
|
||||||
config.value
|
|
||||||
|> ConfigDB.from_binary()
|
|
||||||
|> get_db_keys(config.key)
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec get_db_keys(keyword(), any()) :: [String.t()]
|
@spec get_db_keys(keyword(), any()) :: [String.t()]
|
||||||
def get_db_keys(value, key) do
|
def get_db_keys(value, key) do
|
||||||
|
keys =
|
||||||
if Keyword.keyword?(value) do
|
if Keyword.keyword?(value) do
|
||||||
value |> Keyword.keys() |> Enum.map(&convert(&1))
|
Keyword.keys(value)
|
||||||
else
|
else
|
||||||
[convert(key)]
|
[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Enum.map(keys, &to_json_types(&1))
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec merge_group(atom(), atom(), keyword(), keyword()) :: keyword()
|
@spec merge_group(atom(), atom(), keyword(), keyword()) :: keyword()
|
||||||
def merge_group(group, key, old_value, new_value) do
|
def merge_group(group, key, old_value, new_value) do
|
||||||
new_keys = to_map_set(new_value)
|
new_keys = to_mapset(new_value)
|
||||||
|
|
||||||
intersect_keys =
|
intersect_keys = old_value |> to_mapset() |> MapSet.intersection(new_keys) |> MapSet.to_list()
|
||||||
old_value |> to_map_set() |> MapSet.intersection(new_keys) |> MapSet.to_list()
|
|
||||||
|
|
||||||
merged_value = ConfigDB.merge(old_value, new_value)
|
merged_value = ConfigDB.merge(old_value, new_value)
|
||||||
|
|
||||||
|
@ -120,12 +93,10 @@ def merge_group(group, key, old_value, new_value) do
|
||||||
[]
|
[]
|
||||||
end)
|
end)
|
||||||
|> List.flatten()
|
|> List.flatten()
|
||||||
|> Enum.reduce(merged_value, fn subkey, acc ->
|
|> Enum.reduce(merged_value, &Keyword.put(&2, &1, new_value[&1]))
|
||||||
Keyword.put(acc, subkey, new_value[subkey])
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp to_map_set(keyword) do
|
defp to_mapset(keyword) do
|
||||||
keyword
|
keyword
|
||||||
|> Keyword.keys()
|
|> Keyword.keys()
|
||||||
|> MapSet.new()
|
|> MapSet.new()
|
||||||
|
@ -159,57 +130,54 @@ defp deep_merge(_key, value1, value2) do
|
||||||
|
|
||||||
@spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
@spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
||||||
def update_or_create(params) do
|
def update_or_create(params) do
|
||||||
|
params = Map.put(params, :value, to_elixir_types(params[:value]))
|
||||||
search_opts = Map.take(params, [:group, :key])
|
search_opts = Map.take(params, [:group, :key])
|
||||||
|
|
||||||
with %ConfigDB{} = config <- ConfigDB.get_by_params(search_opts),
|
with %ConfigDB{} = config <- ConfigDB.get_by_params(search_opts),
|
||||||
{:partial_update, true, config} <-
|
{_, true, config} <- {:partial_update, can_be_partially_updated?(config), config},
|
||||||
{:partial_update, can_be_partially_updated?(config), config},
|
{_, true, config} <-
|
||||||
old_value <- from_binary(config.value),
|
{:can_be_merged, is_list(params[:value]) and is_list(config.value), config} do
|
||||||
transformed_value <- do_transform(params[:value]),
|
new_value = merge_group(config.group, config.key, config.value, params[:value])
|
||||||
{:can_be_merged, true, config} <- {:can_be_merged, is_list(transformed_value), config},
|
update(config, %{value: new_value})
|
||||||
new_value <-
|
|
||||||
merge_group(
|
|
||||||
ConfigDB.from_string(config.group),
|
|
||||||
ConfigDB.from_string(config.key),
|
|
||||||
old_value,
|
|
||||||
transformed_value
|
|
||||||
) do
|
|
||||||
ConfigDB.update(config, %{value: new_value})
|
|
||||||
else
|
else
|
||||||
{reason, false, config} when reason in [:partial_update, :can_be_merged] ->
|
{reason, false, config} when reason in [:partial_update, :can_be_merged] ->
|
||||||
ConfigDB.update(config, params)
|
update(config, params)
|
||||||
|
|
||||||
nil ->
|
nil ->
|
||||||
ConfigDB.create(params)
|
create(params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp can_be_partially_updated?(%ConfigDB{} = config), do: not only_full_update?(config)
|
defp can_be_partially_updated?(%ConfigDB{} = config), do: not only_full_update?(config)
|
||||||
|
|
||||||
defp only_full_update?(%ConfigDB{} = config) do
|
defp only_full_update?(%ConfigDB{group: group, key: key}) do
|
||||||
config_group = ConfigDB.from_string(config.group)
|
full_key_update = [
|
||||||
config_key = ConfigDB.from_string(config.key)
|
{:pleroma, :ecto_repos},
|
||||||
|
{:quack, :meta},
|
||||||
|
{:mime, :types},
|
||||||
|
{:cors_plug, [:max_age, :methods, :expose, :headers]},
|
||||||
|
{:swarm, :node_blacklist},
|
||||||
|
{:logger, :backends}
|
||||||
|
]
|
||||||
|
|
||||||
Enum.any?(@full_key_update, fn
|
Enum.any?(full_key_update, fn
|
||||||
{group, key} when is_list(key) ->
|
{s_group, s_key} ->
|
||||||
config_group == group and config_key in key
|
group == s_group and ((is_list(s_key) and key in s_key) or key == s_key)
|
||||||
|
|
||||||
{group, key} ->
|
|
||||||
config_group == group and config_key == key
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec delete(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
@spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()}
|
||||||
|
def delete(%ConfigDB{} = config), do: Repo.delete(config)
|
||||||
|
|
||||||
def delete(params) do
|
def delete(params) do
|
||||||
search_opts = Map.delete(params, :subkeys)
|
search_opts = Map.delete(params, :subkeys)
|
||||||
|
|
||||||
with %ConfigDB{} = config <- ConfigDB.get_by_params(search_opts),
|
with %ConfigDB{} = config <- ConfigDB.get_by_params(search_opts),
|
||||||
{config, sub_keys} when is_list(sub_keys) <- {config, params[:subkeys]},
|
{config, sub_keys} when is_list(sub_keys) <- {config, params[:subkeys]},
|
||||||
old_value <- from_binary(config.value),
|
keys <- Enum.map(sub_keys, &string_to_elixir_types(&1)),
|
||||||
keys <- Enum.map(sub_keys, &do_transform_string(&1)),
|
{_, config, new_value} when new_value != [] <-
|
||||||
{:partial_remove, config, new_value} when new_value != [] <-
|
{:partial_remove, config, Keyword.drop(config.value, keys)} do
|
||||||
{:partial_remove, config, Keyword.drop(old_value, keys)} do
|
update(config, %{value: new_value})
|
||||||
ConfigDB.update(config, %{value: new_value})
|
|
||||||
else
|
else
|
||||||
{:partial_remove, config, []} ->
|
{:partial_remove, config, []} ->
|
||||||
Repo.delete(config)
|
Repo.delete(config)
|
||||||
|
@ -225,37 +193,32 @@ def delete(params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec from_binary(binary()) :: term()
|
@spec to_json_types(term()) :: map() | list() | boolean() | String.t()
|
||||||
def from_binary(binary), do: :erlang.binary_to_term(binary)
|
def to_json_types(entity) when is_list(entity) do
|
||||||
|
Enum.map(entity, &to_json_types/1)
|
||||||
@spec from_binary_with_convert(binary()) :: any()
|
|
||||||
def from_binary_with_convert(binary) do
|
|
||||||
binary
|
|
||||||
|> from_binary()
|
|
||||||
|> do_convert()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec from_string(String.t()) :: atom() | no_return()
|
def to_json_types(%Regex{} = entity), do: inspect(entity)
|
||||||
def from_string(string), do: do_transform_string(string)
|
|
||||||
|
|
||||||
@spec convert(any()) :: any()
|
def to_json_types(entity) when is_map(entity) do
|
||||||
def convert(entity), do: do_convert(entity)
|
Map.new(entity, fn {k, v} -> {to_json_types(k), to_json_types(v)} end)
|
||||||
|
|
||||||
defp do_convert(entity) when is_list(entity) do
|
|
||||||
for v <- entity, into: [], do: do_convert(v)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert(%Regex{} = entity), do: inspect(entity)
|
def to_json_types({:args, args}) when is_list(args) do
|
||||||
|
arguments =
|
||||||
|
Enum.map(args, fn
|
||||||
|
arg when is_tuple(arg) -> inspect(arg)
|
||||||
|
arg -> to_json_types(arg)
|
||||||
|
end)
|
||||||
|
|
||||||
defp do_convert(entity) when is_map(entity) do
|
%{"tuple" => [":args", arguments]}
|
||||||
for {k, v} <- entity, into: %{}, do: {do_convert(k), do_convert(v)}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert({:proxy_url, {type, :localhost, port}}) do
|
def to_json_types({:proxy_url, {type, :localhost, port}}) do
|
||||||
%{"tuple" => [":proxy_url", %{"tuple" => [do_convert(type), "localhost", port]}]}
|
%{"tuple" => [":proxy_url", %{"tuple" => [to_json_types(type), "localhost", port]}]}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert({:proxy_url, {type, host, port}}) when is_tuple(host) do
|
def to_json_types({:proxy_url, {type, host, port}}) when is_tuple(host) do
|
||||||
ip =
|
ip =
|
||||||
host
|
host
|
||||||
|> :inet_parse.ntoa()
|
|> :inet_parse.ntoa()
|
||||||
|
@ -264,66 +227,64 @@ defp do_convert({:proxy_url, {type, host, port}}) when is_tuple(host) do
|
||||||
%{
|
%{
|
||||||
"tuple" => [
|
"tuple" => [
|
||||||
":proxy_url",
|
":proxy_url",
|
||||||
%{"tuple" => [do_convert(type), ip, port]}
|
%{"tuple" => [to_json_types(type), ip, port]}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert({:proxy_url, {type, host, port}}) do
|
def to_json_types({:proxy_url, {type, host, port}}) do
|
||||||
%{
|
%{
|
||||||
"tuple" => [
|
"tuple" => [
|
||||||
":proxy_url",
|
":proxy_url",
|
||||||
%{"tuple" => [do_convert(type), to_string(host), port]}
|
%{"tuple" => [to_json_types(type), to_string(host), port]}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert({:partial_chain, entity}), do: %{"tuple" => [":partial_chain", inspect(entity)]}
|
def to_json_types({:partial_chain, entity}),
|
||||||
|
do: %{"tuple" => [":partial_chain", inspect(entity)]}
|
||||||
|
|
||||||
defp do_convert(entity) when is_tuple(entity) do
|
def to_json_types(entity) when is_tuple(entity) do
|
||||||
value =
|
value =
|
||||||
entity
|
entity
|
||||||
|> Tuple.to_list()
|
|> Tuple.to_list()
|
||||||
|> do_convert()
|
|> to_json_types()
|
||||||
|
|
||||||
%{"tuple" => value}
|
%{"tuple" => value}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert(entity) when is_boolean(entity) or is_number(entity) or is_nil(entity) do
|
def to_json_types(entity) when is_binary(entity), do: entity
|
||||||
|
|
||||||
|
def to_json_types(entity) when is_boolean(entity) or is_number(entity) or is_nil(entity) do
|
||||||
entity
|
entity
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert(entity)
|
def to_json_types(entity) when entity in [:"tlsv1.1", :"tlsv1.2", :"tlsv1.3"] do
|
||||||
when is_atom(entity) and entity in [:"tlsv1.1", :"tlsv1.2", :"tlsv1.3"] do
|
|
||||||
":#{entity}"
|
":#{entity}"
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_convert(entity) when is_atom(entity), do: inspect(entity)
|
def to_json_types(entity) when is_atom(entity), do: inspect(entity)
|
||||||
|
|
||||||
defp do_convert(entity) when is_binary(entity), do: entity
|
@spec to_elixir_types(boolean() | String.t() | map() | list()) :: term()
|
||||||
|
def to_elixir_types(%{"tuple" => [":args", args]}) when is_list(args) do
|
||||||
|
arguments =
|
||||||
|
Enum.map(args, fn arg ->
|
||||||
|
if String.contains?(arg, ["{", "}"]) do
|
||||||
|
{elem, []} = Code.eval_string(arg)
|
||||||
|
elem
|
||||||
|
else
|
||||||
|
to_elixir_types(arg)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
@spec transform(any()) :: binary() | no_return()
|
{:args, arguments}
|
||||||
def transform(entity) when is_binary(entity) or is_map(entity) or is_list(entity) do
|
|
||||||
entity
|
|
||||||
|> do_transform()
|
|
||||||
|> to_binary()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def transform(entity), do: to_binary(entity)
|
def to_elixir_types(%{"tuple" => [":proxy_url", %{"tuple" => [type, host, port]}]}) do
|
||||||
|
{:proxy_url, {string_to_elixir_types(type), parse_host(host), port}}
|
||||||
@spec transform_with_out_binary(any()) :: any()
|
|
||||||
def transform_with_out_binary(entity), do: do_transform(entity)
|
|
||||||
|
|
||||||
@spec to_binary(any()) :: binary()
|
|
||||||
def to_binary(entity), do: :erlang.term_to_binary(entity)
|
|
||||||
|
|
||||||
defp do_transform(%Regex{} = entity), do: entity
|
|
||||||
|
|
||||||
defp do_transform(%{"tuple" => [":proxy_url", %{"tuple" => [type, host, port]}]}) do
|
|
||||||
{:proxy_url, {do_transform_string(type), parse_host(host), port}}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(%{"tuple" => [":partial_chain", entity]}) do
|
def to_elixir_types(%{"tuple" => [":partial_chain", entity]}) do
|
||||||
{partial_chain, []} =
|
{partial_chain, []} =
|
||||||
entity
|
entity
|
||||||
|> String.replace(~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "")
|
|> String.replace(~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "")
|
||||||
|
@ -332,25 +293,51 @@ defp do_transform(%{"tuple" => [":partial_chain", entity]}) do
|
||||||
{:partial_chain, partial_chain}
|
{:partial_chain, partial_chain}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(%{"tuple" => entity}) do
|
def to_elixir_types(%{"tuple" => entity}) do
|
||||||
Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end)
|
Enum.reduce(entity, {}, &Tuple.append(&2, to_elixir_types(&1)))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(entity) when is_map(entity) do
|
def to_elixir_types(entity) when is_map(entity) do
|
||||||
for {k, v} <- entity, into: %{}, do: {do_transform(k), do_transform(v)}
|
Map.new(entity, fn {k, v} -> {to_elixir_types(k), to_elixir_types(v)} end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(entity) when is_list(entity) do
|
def to_elixir_types(entity) when is_list(entity) do
|
||||||
for v <- entity, into: [], do: do_transform(v)
|
Enum.map(entity, &to_elixir_types/1)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(entity) when is_binary(entity) do
|
def to_elixir_types(entity) when is_binary(entity) do
|
||||||
entity
|
entity
|
||||||
|> String.trim()
|
|> String.trim()
|
||||||
|> do_transform_string()
|
|> string_to_elixir_types()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform(entity), do: entity
|
def to_elixir_types(entity), do: entity
|
||||||
|
|
||||||
|
@spec string_to_elixir_types(String.t()) ::
|
||||||
|
atom() | Regex.t() | module() | String.t() | no_return()
|
||||||
|
def string_to_elixir_types("~r" <> _pattern = regex) do
|
||||||
|
pattern =
|
||||||
|
~r/^~r(?'delimiter'[\/|"'([{<]{1})(?'pattern'.+)[\/|"')\]}>]{1}(?'modifier'[uismxfU]*)/u
|
||||||
|
|
||||||
|
delimiters = ["/", "|", "\"", "'", {"(", ")"}, {"[", "]"}, {"{", "}"}, {"<", ">"}]
|
||||||
|
|
||||||
|
with %{"modifier" => modifier, "pattern" => pattern, "delimiter" => regex_delimiter} <-
|
||||||
|
Regex.named_captures(pattern, regex),
|
||||||
|
{:ok, {leading, closing}} <- find_valid_delimiter(delimiters, pattern, regex_delimiter),
|
||||||
|
{result, _} <- Code.eval_string("~r#{leading}#{pattern}#{closing}#{modifier}") do
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def string_to_elixir_types(":" <> atom), do: String.to_atom(atom)
|
||||||
|
|
||||||
|
def string_to_elixir_types(value) do
|
||||||
|
if module_name?(value) do
|
||||||
|
String.to_existing_atom("Elixir." <> value)
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp parse_host("localhost"), do: :localhost
|
defp parse_host("localhost"), do: :localhost
|
||||||
|
|
||||||
|
@ -387,27 +374,8 @@ defp find_valid_delimiter([delimiter | others], pattern, regex_delimiter) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_transform_string("~r" <> _pattern = regex) do
|
@spec module_name?(String.t()) :: boolean()
|
||||||
with %{"modifier" => modifier, "pattern" => pattern, "delimiter" => regex_delimiter} <-
|
def module_name?(string) do
|
||||||
Regex.named_captures(@regex, regex),
|
|
||||||
{:ok, {leading, closing}} <- find_valid_delimiter(@delimiters, pattern, regex_delimiter),
|
|
||||||
{result, _} <- Code.eval_string("~r#{leading}#{pattern}#{closing}#{modifier}") do
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp do_transform_string(":" <> atom), do: String.to_atom(atom)
|
|
||||||
|
|
||||||
defp do_transform_string(value) do
|
|
||||||
if is_module_name?(value) do
|
|
||||||
String.to_existing_atom("Elixir." <> value)
|
|
||||||
else
|
|
||||||
value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec is_module_name?(String.t()) :: boolean()
|
|
||||||
def is_module_name?(string) do
|
|
||||||
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Quack|Ueberauth|Swoosh)\./, string) or
|
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Quack|Ueberauth|Swoosh)\./, string) or
|
||||||
string in ["Oban", "Ueberauth", "ExSyslogger"]
|
string in ["Oban", "Ueberauth", "ExSyslogger"]
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,23 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Config.DeprecationWarnings do
|
defmodule Pleroma.Config.DeprecationWarnings do
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
|
|
||||||
|
@type config_namespace() :: atom() | [atom()]
|
||||||
|
@type config_map() :: {config_namespace(), config_namespace(), String.t()}
|
||||||
|
|
||||||
|
@mrf_config_map [
|
||||||
|
{[:instance, :rewrite_policy], [:mrf, :policies],
|
||||||
|
"\n* `config :pleroma, :instance, rewrite_policy` is now `config :pleroma, :mrf, policies`"},
|
||||||
|
{[:instance, :mrf_transparency], [:mrf, :transparency],
|
||||||
|
"\n* `config :pleroma, :instance, mrf_transparency` is now `config :pleroma, :mrf, transparency`"},
|
||||||
|
{[:instance, :mrf_transparency_exclusions], [:mrf, :transparency_exclusions],
|
||||||
|
"\n* `config :pleroma, :instance, mrf_transparency_exclusions` is now `config :pleroma, :mrf, transparency_exclusions`"}
|
||||||
|
]
|
||||||
|
|
||||||
def check_hellthread_threshold do
|
def check_hellthread_threshold do
|
||||||
if Config.get([:mrf_hellthread, :threshold]) do
|
if Config.get([:mrf_hellthread, :threshold]) do
|
||||||
Logger.warn("""
|
Logger.warn("""
|
||||||
|
@ -39,5 +53,126 @@ def mrf_user_allowlist do
|
||||||
def warn do
|
def warn do
|
||||||
check_hellthread_threshold()
|
check_hellthread_threshold()
|
||||||
mrf_user_allowlist()
|
mrf_user_allowlist()
|
||||||
|
check_old_mrf_config()
|
||||||
|
check_media_proxy_whitelist_config()
|
||||||
|
check_welcome_message_config()
|
||||||
|
check_gun_pool_options()
|
||||||
|
check_activity_expiration_config()
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_welcome_message_config do
|
||||||
|
instance_config = Pleroma.Config.get([:instance])
|
||||||
|
|
||||||
|
use_old_config =
|
||||||
|
Keyword.has_key?(instance_config, :welcome_user_nickname) or
|
||||||
|
Keyword.has_key?(instance_config, :welcome_message)
|
||||||
|
|
||||||
|
if use_old_config do
|
||||||
|
Logger.error("""
|
||||||
|
!!!DEPRECATION WARNING!!!
|
||||||
|
Your config is using the old namespace for Welcome messages configuration. You need to change to the new namespace:
|
||||||
|
\n* `config :pleroma, :instance, welcome_user_nickname` is now `config :pleroma, :welcome, :direct_message, :sender_nickname`
|
||||||
|
\n* `config :pleroma, :instance, welcome_message` is now `config :pleroma, :welcome, :direct_message, :message`
|
||||||
|
""")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_old_mrf_config do
|
||||||
|
warning_preface = """
|
||||||
|
!!!DEPRECATION WARNING!!!
|
||||||
|
Your config is using old namespaces for MRF configuration. They should work for now, but you are advised to change to new namespaces to prevent possible issues later:
|
||||||
|
"""
|
||||||
|
|
||||||
|
move_namespace_and_warn(@mrf_config_map, warning_preface)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec move_namespace_and_warn([config_map()], String.t()) :: :ok | nil
|
||||||
|
def move_namespace_and_warn(config_map, warning_preface) do
|
||||||
|
warning =
|
||||||
|
Enum.reduce(config_map, "", fn
|
||||||
|
{old, new, err_msg}, acc ->
|
||||||
|
old_config = Config.get(old)
|
||||||
|
|
||||||
|
if old_config do
|
||||||
|
Config.put(new, old_config)
|
||||||
|
acc <> err_msg
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if warning != "" do
|
||||||
|
Logger.warn(warning_preface <> warning)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec check_media_proxy_whitelist_config() :: :ok | nil
|
||||||
|
def check_media_proxy_whitelist_config do
|
||||||
|
whitelist = Config.get([:media_proxy, :whitelist])
|
||||||
|
|
||||||
|
if Enum.any?(whitelist, &(not String.starts_with?(&1, "http"))) do
|
||||||
|
Logger.warn("""
|
||||||
|
!!!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.
|
||||||
|
""")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_gun_pool_options do
|
||||||
|
pool_config = Config.get(:connections_pool)
|
||||||
|
|
||||||
|
if timeout = pool_config[:await_up_timeout] do
|
||||||
|
Logger.warn("""
|
||||||
|
!!!DEPRECATION WARNING!!!
|
||||||
|
Your config is using old setting name `await_up_timeout` instead of `connect_timeout`. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later.
|
||||||
|
""")
|
||||||
|
|
||||||
|
Config.put(:connections_pool, Keyword.put_new(pool_config, :connect_timeout, timeout))
|
||||||
|
end
|
||||||
|
|
||||||
|
pools_configs = Config.get(:pools)
|
||||||
|
|
||||||
|
warning_preface = """
|
||||||
|
!!!DEPRECATION WARNING!!!
|
||||||
|
Your config is using old setting name `timeout` instead of `recv_timeout` in pool settings. Setting should work for now, but you are advised to change format to scheme with port to prevent possible issues later.
|
||||||
|
"""
|
||||||
|
|
||||||
|
updated_config =
|
||||||
|
Enum.reduce(pools_configs, [], fn {pool_name, config}, acc ->
|
||||||
|
if timeout = config[:timeout] do
|
||||||
|
Keyword.put(acc, pool_name, Keyword.put_new(config, :recv_timeout, timeout))
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if updated_config != [] do
|
||||||
|
pool_warnings =
|
||||||
|
updated_config
|
||||||
|
|> Keyword.keys()
|
||||||
|
|> Enum.map(fn pool_name ->
|
||||||
|
"\n* `:timeout` options in #{pool_name} pool is now `:recv_timeout`"
|
||||||
|
end)
|
||||||
|
|
||||||
|
Logger.warn(Enum.join([warning_preface | pool_warnings]))
|
||||||
|
|
||||||
|
Config.put(:pools, updated_config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec check_activity_expiration_config() :: :ok | nil
|
||||||
|
def check_activity_expiration_config do
|
||||||
|
warning_preface = """
|
||||||
|
!!!DEPRECATION WARNING!!!
|
||||||
|
Your config is using old namespace for activity expiration configuration. Setting should work for now, but you are advised to change to new namespace to prevent possible issues later:
|
||||||
|
"""
|
||||||
|
|
||||||
|
move_namespace_and_warn(
|
||||||
|
[
|
||||||
|
{Pleroma.ActivityExpiration, Pleroma.Workers.PurgeExpiredActivity,
|
||||||
|
"\n* `config :pleroma, Pleroma.ActivityExpiration` is now `config :pleroma, Pleroma.Workers.PurgeExpiredActivity`"}
|
||||||
|
],
|
||||||
|
warning_preface
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
17
lib/pleroma/config/helpers.ex
Normal file
17
lib/pleroma/config/helpers.ex
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Config.Helpers do
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
|
def instance_name, do: Config.get([:instance, :name])
|
||||||
|
|
||||||
|
defp instance_notify_email do
|
||||||
|
Config.get([:instance, :notify_email]) || Config.get([:instance, :email])
|
||||||
|
end
|
||||||
|
|
||||||
|
def sender do
|
||||||
|
{instance_name(), instance_notify_email()}
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,6 +12,11 @@ defmodule Pleroma.Config.Loader do
|
||||||
:swarm
|
:swarm
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@reject_groups [
|
||||||
|
:postgrex,
|
||||||
|
:tesla
|
||||||
|
]
|
||||||
|
|
||||||
if Code.ensure_loaded?(Config.Reader) do
|
if Code.ensure_loaded?(Config.Reader) do
|
||||||
@reader Config.Reader
|
@reader Config.Reader
|
||||||
|
|
||||||
|
@ -47,7 +52,8 @@ defp filter(configs) do
|
||||||
@spec filter_group(atom(), keyword()) :: keyword()
|
@spec filter_group(atom(), keyword()) :: keyword()
|
||||||
def filter_group(group, configs) do
|
def filter_group(group, configs) do
|
||||||
Enum.reject(configs[group], fn {key, _v} ->
|
Enum.reject(configs[group], fn {key, _v} ->
|
||||||
key in @reject_keys or (group == :phoenix and key == :serve_endpoints) or group == :postgrex
|
key in @reject_keys or group in @reject_groups or
|
||||||
|
(group == :phoenix and key == :serve_endpoints)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
34
lib/pleroma/config/oban.ex
Normal file
34
lib/pleroma/config/oban.ex
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
defmodule Pleroma.Config.Oban do
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def warn do
|
||||||
|
oban_config = Pleroma.Config.get(Oban)
|
||||||
|
|
||||||
|
crontab =
|
||||||
|
[
|
||||||
|
Pleroma.Workers.Cron.StatsWorker,
|
||||||
|
Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker,
|
||||||
|
Pleroma.Workers.Cron.ClearOauthTokenWorker
|
||||||
|
]
|
||||||
|
|> Enum.reduce(oban_config[:crontab], fn removed_worker, acc ->
|
||||||
|
with acc when is_list(acc) <- acc,
|
||||||
|
setting when is_tuple(setting) <-
|
||||||
|
Enum.find(acc, fn {_, worker} -> worker == removed_worker end) do
|
||||||
|
"""
|
||||||
|
!!!OBAN CONFIG WARNING!!!
|
||||||
|
You are using old workers in Oban crontab settings, which were removed.
|
||||||
|
Please, remove setting from crontab in your config file (prod.secret.exs): #{
|
||||||
|
inspect(setting)
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|> Logger.warn()
|
||||||
|
|
||||||
|
List.delete(acc, setting)
|
||||||
|
else
|
||||||
|
_ -> acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
Pleroma.Config.put(Oban, Keyword.put(oban_config, :crontab, crontab))
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,15 +28,11 @@ defmodule Pleroma.Config.TransferTask do
|
||||||
{:pleroma, Pleroma.Captcha, [:seconds_valid]},
|
{:pleroma, Pleroma.Captcha, [:seconds_valid]},
|
||||||
{:pleroma, Pleroma.Upload, [:proxy_remote]},
|
{:pleroma, Pleroma.Upload, [:proxy_remote]},
|
||||||
{:pleroma, :instance, [:upload_limit]},
|
{:pleroma, :instance, [:upload_limit]},
|
||||||
{:pleroma, :email_notifications, [:digest]},
|
|
||||||
{:pleroma, :oauth2, [:clean_expired_tokens]},
|
|
||||||
{:pleroma, Pleroma.ActivityExpiration, [:enabled]},
|
|
||||||
{:pleroma, Pleroma.ScheduledActivity, [:enabled]},
|
|
||||||
{:pleroma, :gopher, [:enabled]}
|
{:pleroma, :gopher, [:enabled]}
|
||||||
]
|
]
|
||||||
|
|
||||||
def start_link(_) do
|
def start_link(restart_pleroma? \\ true) do
|
||||||
load_and_update_env()
|
load_and_update_env([], restart_pleroma?)
|
||||||
if Config.get(:env) == :test, do: Ecto.Adapters.SQL.Sandbox.checkin(Repo)
|
if Config.get(:env) == :test, do: Ecto.Adapters.SQL.Sandbox.checkin(Repo)
|
||||||
:ignore
|
:ignore
|
||||||
end
|
end
|
||||||
|
@ -48,7 +44,7 @@ def load_and_update_env(deleted_settings \\ [], restart_pleroma? \\ true) do
|
||||||
|
|
||||||
{logger, other} =
|
{logger, other} =
|
||||||
(Repo.all(ConfigDB) ++ deleted_settings)
|
(Repo.all(ConfigDB) ++ deleted_settings)
|
||||||
|> Enum.map(&transform_and_merge/1)
|
|> Enum.map(&merge_with_default/1)
|
||||||
|> Enum.split_with(fn {group, _, _, _} -> group in [:logger, :quack] end)
|
|> Enum.split_with(fn {group, _, _, _} -> group in [:logger, :quack] end)
|
||||||
|
|
||||||
logger
|
logger
|
||||||
|
@ -92,11 +88,7 @@ defp maybe_set_pleroma_last(apps) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp transform_and_merge(%{group: group, key: key, value: value} = setting) do
|
defp merge_with_default(%{group: group, key: key, value: value} = setting) do
|
||||||
group = ConfigDB.from_string(group)
|
|
||||||
key = ConfigDB.from_string(key)
|
|
||||||
value = ConfigDB.from_binary(value)
|
|
||||||
|
|
||||||
default = Config.Holder.default_config(group, key)
|
default = Config.Holder.default_config(group, key)
|
||||||
|
|
||||||
merged =
|
merged =
|
||||||
|
|
|
@ -162,10 +162,13 @@ def for_user_with_last_activity_id(user, params \\ %{}) do
|
||||||
for_user(user, params)
|
for_user(user, params)
|
||||||
|> Enum.map(fn participation ->
|
|> Enum.map(fn participation ->
|
||||||
activity_id =
|
activity_id =
|
||||||
ActivityPub.fetch_latest_activity_id_for_context(participation.conversation.ap_id, %{
|
ActivityPub.fetch_latest_direct_activity_id_for_context(
|
||||||
|
participation.conversation.ap_id,
|
||||||
|
%{
|
||||||
user: user,
|
user: user,
|
||||||
blocking_user: user
|
blocking_user: user
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
participation
|
participation
|
||||||
|
|
|
@ -10,32 +10,70 @@ defmodule Pleroma.CounterCache do
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
schema "counter_cache" do
|
schema "counter_cache" do
|
||||||
field(:name, :string)
|
field(:instance, :string)
|
||||||
field(:count, :integer)
|
field(:public, :integer)
|
||||||
|
field(:unlisted, :integer)
|
||||||
|
field(:private, :integer)
|
||||||
|
field(:direct, :integer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def changeset(struct, params) do
|
def changeset(struct, params) do
|
||||||
struct
|
struct
|
||||||
|> cast(params, [:name, :count])
|
|> cast(params, [:instance, :public, :unlisted, :private, :direct])
|
||||||
|> validate_required([:name])
|
|> validate_required([:instance])
|
||||||
|> unique_constraint(:name)
|
|> unique_constraint(:instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_as_map(names) when is_list(names) do
|
def get_by_instance(instance) do
|
||||||
CounterCache
|
CounterCache
|
||||||
|> where([cc], cc.name in ^names)
|
|> select([c], %{
|
||||||
|> Repo.all()
|
"public" => c.public,
|
||||||
|> Enum.group_by(& &1.name, & &1.count)
|
"unlisted" => c.unlisted,
|
||||||
|> Map.new(fn {k, v} -> {k, hd(v)} end)
|
"private" => c.private,
|
||||||
|
"direct" => c.direct
|
||||||
|
})
|
||||||
|
|> where([c], c.instance == ^instance)
|
||||||
|
|> Repo.one()
|
||||||
|
|> case do
|
||||||
|
nil -> %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
|
||||||
|
val -> val
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set(name, count) do
|
def get_sum do
|
||||||
|
CounterCache
|
||||||
|
|> select([c], %{
|
||||||
|
"public" => type(sum(c.public), :integer),
|
||||||
|
"unlisted" => type(sum(c.unlisted), :integer),
|
||||||
|
"private" => type(sum(c.private), :integer),
|
||||||
|
"direct" => type(sum(c.direct), :integer)
|
||||||
|
})
|
||||||
|
|> Repo.one()
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(instance, values) do
|
||||||
|
params =
|
||||||
|
Enum.reduce(
|
||||||
|
["public", "private", "unlisted", "direct"],
|
||||||
|
%{"instance" => instance},
|
||||||
|
fn param, acc ->
|
||||||
|
Map.put_new(acc, param, Map.get(values, param, 0))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
%CounterCache{}
|
%CounterCache{}
|
||||||
|> changeset(%{"name" => name, "count" => count})
|
|> changeset(params)
|
||||||
|> Repo.insert(
|
|> Repo.insert(
|
||||||
on_conflict: [set: [count: count]],
|
on_conflict: [
|
||||||
|
set: [
|
||||||
|
public: params["public"],
|
||||||
|
private: params["private"],
|
||||||
|
unlisted: params["unlisted"],
|
||||||
|
direct: params["direct"]
|
||||||
|
]
|
||||||
|
],
|
||||||
returning: true,
|
returning: true,
|
||||||
conflict_target: :name
|
conflict_target: :instance
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,16 +6,21 @@ def process(implementation, descriptions) do
|
||||||
implementation.process(descriptions)
|
implementation.process(descriptions)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec list_modules_in_dir(String.t(), String.t()) :: [module()]
|
@spec list_behaviour_implementations(behaviour :: module()) :: [module()]
|
||||||
def list_modules_in_dir(dir, start) do
|
def list_behaviour_implementations(behaviour) do
|
||||||
with {:ok, files} <- File.ls(dir) do
|
:code.all_loaded()
|
||||||
files
|
|> Enum.filter(fn {module, _} ->
|
||||||
|> Enum.filter(&String.ends_with?(&1, ".ex"))
|
# This shouldn't be needed as all modules are expected to have module_info/1,
|
||||||
|> Enum.map(fn filename ->
|
# but in test enviroments some transient modules `:elixir_compiler_XX`
|
||||||
module = filename |> String.trim_trailing(".ex") |> Macro.camelize()
|
# are loaded for some reason (where XX is a random integer).
|
||||||
String.to_atom(start <> module)
|
if function_exported?(module, :module_info, 1) do
|
||||||
end)
|
module.module_info(:attributes)
|
||||||
|
|> Keyword.get_values(:behaviour)
|
||||||
|
|> List.flatten()
|
||||||
|
|> Enum.member?(behaviour)
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
|> Enum.map(fn {module, _} -> module end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -87,6 +92,12 @@ defp humanize(entity) do
|
||||||
else: string
|
else: string
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp format_suggestions({:list_behaviour_implementations, behaviour}) do
|
||||||
|
behaviour
|
||||||
|
|> list_behaviour_implementations()
|
||||||
|
|> format_suggestions()
|
||||||
|
end
|
||||||
|
|
||||||
defp format_suggestions([]), do: []
|
defp format_suggestions([]), do: []
|
||||||
|
|
||||||
defp format_suggestions([suggestion | tail]) do
|
defp format_suggestions([suggestion | tail]) do
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
defmodule Pleroma.Docs.JSON do
|
defmodule Pleroma.Docs.JSON do
|
||||||
@behaviour Pleroma.Docs.Generator
|
@behaviour Pleroma.Docs.Generator
|
||||||
|
@external_resource "config/description.exs"
|
||||||
|
@raw_config Pleroma.Config.Loader.read("config/description.exs")
|
||||||
|
@raw_descriptions @raw_config[:pleroma][:config_description]
|
||||||
|
@term __MODULE__.Compiled
|
||||||
|
|
||||||
|
@spec compile :: :ok
|
||||||
|
def compile do
|
||||||
|
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(@raw_descriptions))
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec compiled_descriptions :: Map.t()
|
||||||
|
def compiled_descriptions do
|
||||||
|
:persistent_term.get(@term)
|
||||||
|
end
|
||||||
|
|
||||||
@spec process(keyword()) :: {:ok, String.t()}
|
@spec process(keyword()) :: {:ok, String.t()}
|
||||||
def process(descriptions) do
|
def process(descriptions) do
|
||||||
|
@ -13,11 +27,4 @@ def process(descriptions) do
|
||||||
{:ok, path}
|
{:ok, path}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile do
|
|
||||||
with config <- Pleroma.Config.Loader.read("config/description.exs") do
|
|
||||||
config[:pleroma][:config_description]
|
|
||||||
|> Pleroma.Docs.Generator.convert_to_strings()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -68,6 +68,11 @@ defp print_suggestion(file, suggestion, as_list \\ false) do
|
||||||
IO.write(file, " #{list_mark}`#{inspect(suggestion)}`\n")
|
IO.write(file, " #{list_mark}`#{inspect(suggestion)}`\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp print_suggestions(file, {:list_behaviour_implementations, behaviour}) do
|
||||||
|
suggestions = Pleroma.Docs.Generator.list_behaviour_implementations(behaviour)
|
||||||
|
print_suggestions(file, suggestions)
|
||||||
|
end
|
||||||
|
|
||||||
defp print_suggestions(_file, nil), do: nil
|
defp print_suggestions(_file, nil), do: nil
|
||||||
|
|
||||||
defp print_suggestions(_file, ""), do: nil
|
defp print_suggestions(_file, ""), do: nil
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.DateTime do
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
The AP standard defines the date fields in AP as xsd:DateTime. Elixir's
|
The AP standard defines the date fields in AP as xsd:DateTime. Elixir's
|
||||||
DateTime can't parse this, but it can parse the related iso8601. This
|
DateTime can't parse this, but it can parse the related iso8601. This
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.Emoji do
|
||||||
|
use Ecto.Type
|
||||||
|
|
||||||
|
def type, do: :map
|
||||||
|
|
||||||
|
def cast(data) when is_map(data) do
|
||||||
|
has_invalid_emoji? =
|
||||||
|
Enum.find(data, fn
|
||||||
|
{name, uri} when is_binary(name) and is_binary(uri) ->
|
||||||
|
# based on ObjectValidators.Uri.cast()
|
||||||
|
case URI.parse(uri) do
|
||||||
|
%URI{host: nil} -> true
|
||||||
|
%URI{host: ""} -> true
|
||||||
|
%URI{scheme: scheme} when scheme in ["https", "http"] -> false
|
||||||
|
_ -> true
|
||||||
|
end
|
||||||
|
|
||||||
|
{_name, _uri} ->
|
||||||
|
true
|
||||||
|
end)
|
||||||
|
|
||||||
|
if has_invalid_emoji?, do: :error, else: {:ok, data}
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast(_data), do: :error
|
||||||
|
|
||||||
|
def dump(data), do: {:ok, data}
|
||||||
|
|
||||||
|
def load(data), do: {:ok, data}
|
||||||
|
end
|
|
@ -1,4 +1,8 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID do
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID do
|
||||||
use Ecto.Type
|
use Ecto.Type
|
||||||
|
|
||||||
def type, do: :string
|
def type, do: :string
|
|
@ -1,7 +1,11 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.Recipients do
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients do
|
||||||
use Ecto.Type
|
use Ecto.Type
|
||||||
|
|
||||||
alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID
|
alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID
|
||||||
|
|
||||||
def type, do: {:array, ObjectID}
|
def type, do: {:array, ObjectID}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeText do
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText do
|
||||||
use Ecto.Type
|
use Ecto.Type
|
||||||
|
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
|
@ -1,4 +1,8 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ObjectValidators.Types.Uri do
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.Uri do
|
||||||
use Ecto.Type
|
use Ecto.Type
|
||||||
|
|
||||||
def type, do: :string
|
def type, do: :string
|
26
lib/pleroma/ecto_type/config/atom.ex
Normal file
26
lib/pleroma/ecto_type/config/atom.ex
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.Config.Atom do
|
||||||
|
use Ecto.Type
|
||||||
|
|
||||||
|
def type, do: :atom
|
||||||
|
|
||||||
|
def cast(key) when is_atom(key) do
|
||||||
|
{:ok, key}
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast(key) when is_binary(key) do
|
||||||
|
{:ok, Pleroma.ConfigDB.string_to_elixir_types(key)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast(_), do: :error
|
||||||
|
|
||||||
|
def load(key) do
|
||||||
|
{:ok, Pleroma.ConfigDB.string_to_elixir_types(key)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def dump(key) when is_atom(key), do: {:ok, inspect(key)}
|
||||||
|
def dump(_), do: :error
|
||||||
|
end
|
27
lib/pleroma/ecto_type/config/binary_value.ex
Normal file
27
lib/pleroma/ecto_type/config/binary_value.ex
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.EctoType.Config.BinaryValue do
|
||||||
|
use Ecto.Type
|
||||||
|
|
||||||
|
def type, do: :term
|
||||||
|
|
||||||
|
def cast(value) when is_binary(value) do
|
||||||
|
if String.valid?(value) do
|
||||||
|
{:ok, value}
|
||||||
|
else
|
||||||
|
{:ok, :erlang.binary_to_term(value)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast(value), do: {:ok, value}
|
||||||
|
|
||||||
|
def load(value) when is_binary(value) do
|
||||||
|
{:ok, :erlang.binary_to_term(value)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def dump(value) do
|
||||||
|
{:ok, :erlang.term_to_binary(value)}
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,9 +8,10 @@ defmodule Pleroma.Emails.AdminEmail do
|
||||||
import Swoosh.Email
|
import Swoosh.Email
|
||||||
|
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Web.Router.Helpers
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
defp instance_config, do: Pleroma.Config.get(:instance)
|
defp instance_config, do: Config.get(:instance)
|
||||||
defp instance_name, do: instance_config()[:name]
|
defp instance_name, do: instance_config()[:name]
|
||||||
|
|
||||||
defp instance_notify_email do
|
defp instance_notify_email do
|
||||||
|
@ -72,6 +73,8 @@ def report(to, reporter, account, statuses, comment) do
|
||||||
<p>Reported Account: <a href="#{user_url(account)}">#{account.nickname}</a></p>
|
<p>Reported Account: <a href="#{user_url(account)}">#{account.nickname}</a></p>
|
||||||
#{comment_html}
|
#{comment_html}
|
||||||
#{statuses_html}
|
#{statuses_html}
|
||||||
|
<p>
|
||||||
|
<a href="#{Pleroma.Web.base_url()}/pleroma/admin/#/reports/index">View Reports in AdminFE</a>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
new()
|
new()
|
||||||
|
@ -80,4 +83,18 @@ def report(to, reporter, account, statuses, comment) do
|
||||||
|> subject("#{instance_name()} Report")
|
|> subject("#{instance_name()} Report")
|
||||||
|> html_body(html_body)
|
|> html_body(html_body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new_unapproved_registration(to, account) do
|
||||||
|
html_body = """
|
||||||
|
<p>New account for review: <a href="#{user_url(account)}">@#{account.nickname}</a></p>
|
||||||
|
<blockquote>#{HTML.strip_tags(account.registration_reason)}</blockquote>
|
||||||
|
<a href="#{Pleroma.Web.base_url()}/pleroma/admin">Visit AdminFE</a>
|
||||||
|
"""
|
||||||
|
|
||||||
|
new()
|
||||||
|
|> to({to.name, to.email})
|
||||||
|
|> from({instance_name(), instance_notify_email()})
|
||||||
|
|> subject("New account up for review on #{instance_name()} (@#{account.nickname})")
|
||||||
|
|> html_body(html_body)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,17 +12,22 @@ defmodule Pleroma.Emails.UserEmail do
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
alias Pleroma.Web.Router
|
alias Pleroma.Web.Router
|
||||||
|
|
||||||
defp instance_name, do: Config.get([:instance, :name])
|
import Pleroma.Config.Helpers, only: [instance_name: 0, sender: 0]
|
||||||
|
|
||||||
defp sender do
|
|
||||||
email = Config.get([:instance, :notify_email]) || Config.get([:instance, :email])
|
|
||||||
{instance_name(), email}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp recipient(email, nil), do: email
|
defp recipient(email, nil), do: email
|
||||||
defp recipient(email, name), do: {name, email}
|
defp recipient(email, name), do: {name, email}
|
||||||
defp recipient(%User{} = user), do: recipient(user.email, user.name)
|
defp recipient(%User{} = user), do: recipient(user.email, user.name)
|
||||||
|
|
||||||
|
@spec welcome(User.t(), map()) :: Swoosh.Email.t()
|
||||||
|
def welcome(user, opts \\ %{}) do
|
||||||
|
new()
|
||||||
|
|> to(recipient(user))
|
||||||
|
|> from(Map.get(opts, :sender, sender()))
|
||||||
|
|> subject(Map.get(opts, :subject, "Welcome to #{instance_name()}!"))
|
||||||
|
|> html_body(Map.get(opts, :html, "Welcome to #{instance_name()}!"))
|
||||||
|
|> text_body(Map.get(opts, :text, "Welcome to #{instance_name()}!"))
|
||||||
|
end
|
||||||
|
|
||||||
def password_reset_email(user, token) when is_binary(token) do
|
def password_reset_email(user, token) when is_binary(token) do
|
||||||
password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token)
|
password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token)
|
||||||
|
|
||||||
|
@ -102,6 +107,8 @@ def digest_email(user) do
|
||||||
|> Enum.filter(&(&1.activity.data["type"] == "Create"))
|
|> Enum.filter(&(&1.activity.data["type"] == "Create"))
|
||||||
|> Enum.map(fn notification ->
|
|> Enum.map(fn notification ->
|
||||||
object = Pleroma.Object.normalize(notification.activity)
|
object = Pleroma.Object.normalize(notification.activity)
|
||||||
|
|
||||||
|
if not is_nil(object) do
|
||||||
object = update_in(object.data["content"], &format_links/1)
|
object = update_in(object.data["content"], &format_links/1)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -109,18 +116,25 @@ def digest_email(user) do
|
||||||
object: object,
|
object: object,
|
||||||
from: User.get_by_ap_id(notification.activity.actor)
|
from: User.get_by_ap_id(notification.activity.actor)
|
||||||
}
|
}
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|
||||||
followers =
|
followers =
|
||||||
notifications
|
notifications
|
||||||
|> Enum.filter(&(&1.activity.data["type"] == "Follow"))
|
|> Enum.filter(&(&1.activity.data["type"] == "Follow"))
|
||||||
|> Enum.map(fn notification ->
|
|> Enum.map(fn notification ->
|
||||||
|
from = User.get_by_ap_id(notification.activity.actor)
|
||||||
|
|
||||||
|
if not is_nil(from) do
|
||||||
%{
|
%{
|
||||||
data: notification,
|
data: notification,
|
||||||
object: Pleroma.Object.normalize(notification.activity),
|
object: Pleroma.Object.normalize(notification.activity),
|
||||||
from: User.get_by_ap_id(notification.activity.actor)
|
from: User.get_by_ap_id(notification.activity.actor)
|
||||||
}
|
}
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|
||||||
unless Enum.empty?(mentions) do
|
unless Enum.empty?(mentions) do
|
||||||
styling = Config.get([__MODULE__, :styling])
|
styling = Config.get([__MODULE__, :styling])
|
||||||
|
|
|
@ -108,7 +108,7 @@ defp load_pack(pack_dir, emoji_groups) do
|
||||||
if File.exists?(emoji_txt) do
|
if File.exists?(emoji_txt) do
|
||||||
load_from_file(emoji_txt, emoji_groups)
|
load_from_file(emoji_txt, emoji_groups)
|
||||||
else
|
else
|
||||||
extensions = Pleroma.Config.get([:emoji, :pack_extensions])
|
extensions = Config.get([:emoji, :pack_extensions])
|
||||||
|
|
||||||
Logger.info(
|
Logger.info(
|
||||||
"No emoji.txt found for pack \"#{pack_name}\", assuming all #{
|
"No emoji.txt found for pack \"#{pack_name}\", assuming all #{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule Pleroma.Emoji.Pack do
|
defmodule Pleroma.Emoji.Pack do
|
||||||
@derive {Jason.Encoder, only: [:files, :pack]}
|
@derive {Jason.Encoder, only: [:files, :pack, :files_count]}
|
||||||
defstruct files: %{},
|
defstruct files: %{},
|
||||||
|
files_count: 0,
|
||||||
pack_file: nil,
|
pack_file: nil,
|
||||||
path: nil,
|
path: nil,
|
||||||
pack: %{},
|
pack: %{},
|
||||||
|
@ -8,6 +9,7 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
|
|
||||||
@type t() :: %__MODULE__{
|
@type t() :: %__MODULE__{
|
||||||
files: %{String.t() => Path.t()},
|
files: %{String.t() => Path.t()},
|
||||||
|
files_count: non_neg_integer(),
|
||||||
pack_file: Path.t(),
|
pack_file: Path.t(),
|
||||||
path: Path.t(),
|
path: Path.t(),
|
||||||
pack: map(),
|
pack: map(),
|
||||||
|
@ -16,7 +18,7 @@ defmodule Pleroma.Emoji.Pack do
|
||||||
|
|
||||||
alias Pleroma.Emoji
|
alias Pleroma.Emoji
|
||||||
|
|
||||||
@spec create(String.t()) :: :ok | {:error, File.posix()} | {:error, :empty_values}
|
@spec create(String.t()) :: {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}
|
||||||
def create(name) do
|
def create(name) do
|
||||||
with :ok <- validate_not_empty([name]),
|
with :ok <- validate_not_empty([name]),
|
||||||
dir <- Path.join(emoji_path(), name),
|
dir <- Path.join(emoji_path(), name),
|
||||||
|
@ -26,10 +28,28 @@ def create(name) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec show(String.t()) :: {:ok, t()} | {:error, atom()}
|
defp paginate(entities, 1, page_size), do: Enum.take(entities, page_size)
|
||||||
def show(name) do
|
|
||||||
|
defp paginate(entities, page, page_size) do
|
||||||
|
entities
|
||||||
|
|> Enum.chunk_every(page_size)
|
||||||
|
|> Enum.at(page - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec show(keyword()) :: {:ok, t()} | {:error, atom()}
|
||||||
|
def show(opts) do
|
||||||
|
name = opts[:name]
|
||||||
|
|
||||||
with :ok <- validate_not_empty([name]),
|
with :ok <- validate_not_empty([name]),
|
||||||
{:ok, pack} <- load_pack(name) do
|
{:ok, pack} <- load_pack(name) do
|
||||||
|
shortcodes =
|
||||||
|
pack.files
|
||||||
|
|> Map.keys()
|
||||||
|
|> Enum.sort()
|
||||||
|
|> paginate(opts[:page], opts[:page_size])
|
||||||
|
|
||||||
|
pack = Map.put(pack, :files, Map.take(pack.files, shortcodes))
|
||||||
|
|
||||||
{:ok, validate_pack(pack)}
|
{:ok, validate_pack(pack)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -120,10 +140,10 @@ def list_remote(url) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec list_local() :: {:ok, map()}
|
@spec list_local(keyword()) :: {:ok, map(), non_neg_integer()}
|
||||||
def list_local do
|
def list_local(opts) do
|
||||||
with {:ok, results} <- list_packs_dir() do
|
with {:ok, results} <- list_packs_dir() do
|
||||||
packs =
|
all_packs =
|
||||||
results
|
results
|
||||||
|> Enum.map(fn name ->
|
|> Enum.map(fn name ->
|
||||||
case load_pack(name) do
|
case load_pack(name) do
|
||||||
|
@ -132,9 +152,13 @@ def list_local do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|
||||||
|
packs =
|
||||||
|
all_packs
|
||||||
|
|> paginate(opts[:page], opts[:page_size])
|
||||||
|> Map.new(fn pack -> {pack.name, validate_pack(pack)} end)
|
|> Map.new(fn pack -> {pack.name, validate_pack(pack)} end)
|
||||||
|
|
||||||
{:ok, packs}
|
{:ok, packs, length(all_packs)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -146,7 +170,7 @@ def get_archive(name) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec download(String.t(), String.t(), String.t()) :: :ok | {:error, atom()}
|
@spec download(String.t(), String.t(), String.t()) :: {:ok, t()} | {:error, atom()}
|
||||||
def download(name, url, as) do
|
def download(name, url, as) do
|
||||||
uri = url |> String.trim() |> URI.parse()
|
uri = url |> String.trim() |> URI.parse()
|
||||||
|
|
||||||
|
@ -197,7 +221,12 @@ def load_pack(name) do
|
||||||
|> Map.put(:path, Path.dirname(pack_file))
|
|> Map.put(:path, Path.dirname(pack_file))
|
||||||
|> Map.put(:name, name)
|
|> Map.put(:name, name)
|
||||||
|
|
||||||
{:ok, pack}
|
files_count =
|
||||||
|
pack.files
|
||||||
|
|> Map.keys()
|
||||||
|
|> length()
|
||||||
|
|
||||||
|
{:ok, Map.put(pack, :files_count, files_count)}
|
||||||
else
|
else
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
end
|
end
|
||||||
|
@ -296,7 +325,9 @@ defp downloadable?(pack) do
|
||||||
# Otherwise, they'd have to download it from external-src
|
# Otherwise, they'd have to download it from external-src
|
||||||
pack.pack["share-files"] &&
|
pack.pack["share-files"] &&
|
||||||
Enum.all?(pack.files, fn {_, file} ->
|
Enum.all?(pack.files, fn {_, file} ->
|
||||||
File.exists?(Path.join(pack.path, file))
|
pack.path
|
||||||
|
|> Path.join(file)
|
||||||
|
|> File.exists?()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -440,7 +471,7 @@ defp list_packs_dir do
|
||||||
# with the API so it should be sufficient
|
# with the API so it should be sufficient
|
||||||
with {:create_dir, :ok} <- {:create_dir, File.mkdir_p(emoji_path)},
|
with {:create_dir, :ok} <- {:create_dir, File.mkdir_p(emoji_path)},
|
||||||
{:ls, {:ok, results}} <- {:ls, File.ls(emoji_path)} do
|
{:ls, {:ok, results}} <- {:ls, File.ls(emoji_path)} do
|
||||||
{:ok, results}
|
{:ok, Enum.sort(results)}
|
||||||
else
|
else
|
||||||
{:create_dir, {:error, e}} -> {:error, :create_dir, e}
|
{:create_dir, {:error, e}} -> {:error, :create_dir, e}
|
||||||
{:ls, {:error, e}} -> {:error, :ls, e}
|
{:ls, {:error, e}} -> {:error, :ls, e}
|
||||||
|
|
|
@ -34,10 +34,18 @@ def get(id, %{id: user_id} = _user) do
|
||||||
Repo.one(query)
|
Repo.one(query)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_filters(%User{id: user_id} = _user) do
|
def get_active(query) do
|
||||||
|
from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now())
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_irreversible(query) do
|
||||||
|
from(f in query, where: f.hide)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_filters(query \\ __MODULE__, %User{id: user_id}) do
|
||||||
query =
|
query =
|
||||||
from(
|
from(
|
||||||
f in Pleroma.Filter,
|
f in query,
|
||||||
where: f.user_id == ^user_id,
|
where: f.user_id == ^user_id,
|
||||||
order_by: [desc: :id]
|
order_by: [desc: :id]
|
||||||
)
|
)
|
||||||
|
@ -95,4 +103,34 @@ def update(%Pleroma.Filter{} = filter, params) do
|
||||||
|> validate_required([:phrase, :context])
|
|> validate_required([:phrase, :context])
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def compose_regex(user_or_filters, format \\ :postgres)
|
||||||
|
|
||||||
|
def compose_regex(%User{} = user, format) do
|
||||||
|
__MODULE__
|
||||||
|
|> get_active()
|
||||||
|
|> get_irreversible()
|
||||||
|
|> get_filters(user)
|
||||||
|
|> compose_regex(format)
|
||||||
|
end
|
||||||
|
|
||||||
|
def compose_regex([_ | _] = filters, format) do
|
||||||
|
phrases =
|
||||||
|
filters
|
||||||
|
|> Enum.map(& &1.phrase)
|
||||||
|
|> Enum.join("|")
|
||||||
|
|
||||||
|
case format do
|
||||||
|
:postgres ->
|
||||||
|
"\\y(#{phrases})\\y"
|
||||||
|
|
||||||
|
:re ->
|
||||||
|
~r/\b#{phrases}\b/i
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def compose_regex(_, _), do: nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -95,7 +95,11 @@ def followers_query(%User{} = user) do
|
||||||
|> where([r], r.state == ^:follow_accept)
|
|> where([r], r.state == ^:follow_accept)
|
||||||
end
|
end
|
||||||
|
|
||||||
def followers_ap_ids(%User{} = user, from_ap_ids \\ nil) do
|
def followers_ap_ids(user, from_ap_ids \\ nil)
|
||||||
|
|
||||||
|
def followers_ap_ids(_, []), do: []
|
||||||
|
|
||||||
|
def followers_ap_ids(%User{} = user, from_ap_ids) do
|
||||||
query =
|
query =
|
||||||
user
|
user
|
||||||
|> followers_query()
|
|> followers_query()
|
||||||
|
@ -124,6 +128,7 @@ def get_follow_requests(%User{id: id}) do
|
||||||
|> join(:inner, [r], f in assoc(r, :follower))
|
|> join(:inner, [r], f in assoc(r, :follower))
|
||||||
|> where([r], r.state == ^:follow_pending)
|
|> where([r], r.state == ^:follow_pending)
|
||||||
|> where([r], r.following_id == ^id)
|
|> where([r], r.following_id == ^id)
|
||||||
|
|> where([r, f], f.deactivated != true)
|
||||||
|> select([r, f], f)
|
|> select([r, f], f)
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
@ -259,4 +264,12 @@ defp validate_following_id_follower_id_inequality(%Changeset{} = changeset) do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec following_ap_ids(User.t()) :: [String.t()]
|
||||||
|
def following_ap_ids(%User{} = user) do
|
||||||
|
user
|
||||||
|
|> following_query()
|
||||||
|
|> select([r, u], u.ap_id)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue