Compare commits

..

2 commits

Author SHA1 Message Date
sadposter
eeafafb06d add a little loggie 2023-06-08 14:59:34 +01:00
sadposter
67beb1404b add mix task for instance deletion 2023-06-08 14:59:34 +01:00
453 changed files with 8513 additions and 125427 deletions

View file

@ -1,14 +1,3 @@
[
import_deps: [:ecto, :ecto_sql, :phoenix],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: [
"mix.exs",
"*.{heex,ex,exs}",
"{config,lib,test}/**/*.{heex,ex,exs}",
"priv/*/seeds.exs",
"priv/repo/migrations/*.exs",
"priv/repo/optional_migrations/**/*.exs",
"priv/scrubbers/*.ex"
]
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/migrations/*.exs", "priv/repo/optional_migrations/**/*.exs", "priv/scrubbers/*.ex"]
]

View file

@ -1,8 +1,3 @@
platform: linux/amd64
depends_on:
- test
variables:
- &scw-secrets
- SCW_ACCESS_KEY
@ -17,6 +12,8 @@ variables:
branch:
- develop
- stable
- refs/tags/v*
- refs/tags/stable-*
- &on-stable
when:
event:
@ -24,6 +21,14 @@ variables:
- tag
branch:
- stable
- refs/tags/stable-*
- &on-point-release
when:
event:
- push
branch:
- develop
- stable
- &on-pr-open
when:
event:
@ -34,10 +39,63 @@ variables:
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean"
services:
postgres:
image: postgres:15
when:
event:
- pull_request
environment:
POSTGRES_DB: pleroma_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
pipeline:
lint:
<<: *on-pr-open
image: akkoma/ci-base:1.14
commands:
- mix local.hex --force
- mix local.rebar --force
- mix format --check-formatted
build:
image: akkoma/ci-base:1.14
<<: *on-pr-open
environment:
MIX_ENV: test
POSTGRES_DB: pleroma_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DB_HOST: postgres
commands:
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix compile
test:
image: akkoma/ci-base:1.14
<<: *on-pr-open
environment:
MIX_ENV: test
POSTGRES_DB: pleroma_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DB_HOST: postgres
commands:
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix compile
- mix ecto.drop -f -q
- mix ecto.create
- mix ecto.migrate
- mix test --preload-modules --exclude erratic --exclude federated --max-cases 4
# Canonical amd64
debian-bookworm:
image: hexpm/elixir:1.15.4-erlang-26.0.2-debian-bookworm-20230612
ubuntu22:
image: hexpm/elixir:1.14.3-erlang-25.2.2-ubuntu-jammy-20221130
<<: *on-release
environment:
MIX_ENV: prod
@ -50,51 +108,51 @@ pipeline:
- *tag-build
- mix deps.get --only prod
- mix release --path release
- zip akkoma-ubuntu-jammy.zip -r release
release-ubuntu22:
image: akkoma/releaser
<<: *on-release
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-ubuntu-jammy.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-ubuntu-jammy.zip
- /bin/sh /entrypoint.sh
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-ubuntu-jammy.zip
- /bin/sh /entrypoint.sh
debian-bullseye:
image: hexpm/elixir:1.14.3-erlang-25.2.2-debian-bullseye-20230109
<<: *on-release
environment:
MIX_ENV: prod
DEBIAN_FRONTEND: noninteractive
commands:
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential gcc make g++ wget
- *clean
- echo "import Config" > config/prod.secret.exs
- *setup-hex
- *tag-build
- *mix-clean
- mix deps.get --only prod
- mix release --path release
- zip akkoma-amd64.zip -r release
release-debian-bookworm:
release-debian:
image: akkoma/releaser
<<: *on-release
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-amd64.zip
# AMD64
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
- /bin/sh /entrypoint.sh
# Ubuntu jammy (currently compatible)
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-ubuntu-jammy.zip
- /bin/sh /entrypoint.sh
debian-bullseye:
image: hexpm/elixir:1.15.4-erlang-26.0.2-debian-bullseye-20230612
<<: *on-release
environment:
MIX_ENV: prod
DEBIAN_FRONTEND: noninteractive
commands:
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
- *clean
- echo "import Config" > config/prod.secret.exs
- *setup-hex
- *tag-build
- mix deps.get --only prod
- mix release --path release
- zip akkoma-amd64-debian-bullseye.zip -r release
release-debian-bullseye:
image: akkoma/releaser
<<: *on-release
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-amd64-debian-bullseye.zip
# AMD64
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-debian-bullseye.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-debian-stable.zip
- /bin/sh /entrypoint.sh
# Canonical amd64-musl
musl:
image: hexpm/elixir:1.15.4-erlang-26.0.2-alpine-3.18.2
<<: *on-stable
image: hexpm/elixir:1.14.3-erlang-25.2.2-alpine-3.15.6
<<: *on-release
environment:
MIX_ENV: prod
commands:
@ -109,9 +167,31 @@ pipeline:
release-musl:
image: akkoma/releaser
<<: *on-stable
<<: *on-release
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-amd64-musl.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip
- /bin/sh /entrypoint.sh
docs:
<<: *on-point-release
secrets:
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
environment:
CI: "true"
image: python:3.10-slim
commands:
- apt-get update && apt-get install -y rclone wget git zip
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- chmod +x scaleway-cli
- ./scaleway-cli object config install type=rclone
- cd docs
- pip install -r requirements.txt
- mkdocs build
- zip -r docs.zip site/*
- cd site
- rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/

View file

@ -1,89 +0,0 @@
platform: linux/arm64
depends_on:
- test
variables:
- &scw-secrets
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
- &setup-hex "mix local.hex --force && mix local.rebar --force"
- &on-release
when:
event:
- push
- tag
branch:
- stable
- develop
- &on-stable
when:
event:
- push
- tag
branch:
- stable
- &on-pr-open
when:
event:
- pull_request
- &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean"
pipeline:
# Canonical arm64
debian-bookworm:
image: hexpm/elixir:1.15.4-erlang-26.0.2-debian-bookworm-20230612
<<: *on-release
environment:
MIX_ENV: prod
DEBIAN_FRONTEND: noninteractive
commands:
- apt-get update && apt-get install -y cmake libmagic-dev rclone zip imagemagick libmagic-dev git build-essential g++ wget
- *clean
- echo "import Config" > config/prod.secret.exs
- *setup-hex
- *tag-build
- mix deps.get --only prod
- mix release --path release
- zip akkoma-arm64.zip -r release
release-debian-bookworm:
image: akkoma/releaser:arm64
<<: *on-release
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-arm64.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64-ubuntu-jammy.zip
- /bin/sh /entrypoint.sh
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64.zip
- /bin/sh /entrypoint.sh
# Canonical arm64-musl
musl:
image: hexpm/elixir:1.15.4-erlang-26.0.2-alpine-3.18.2
<<: *on-stable
environment:
MIX_ENV: prod
commands:
- apk add git gcc g++ musl-dev make cmake file-dev rclone wget zip imagemagick
- *clean
- *setup-hex
- *mix-clean
- *tag-build
- mix deps.get --only prod
- mix release --path release
- zip akkoma-arm64-musl.zip -r release
release-musl:
image: akkoma/releaser:arm64
<<: *on-stable
secrets: *scw-secrets
commands:
- export SOURCE=akkoma-arm64-musl.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-arm64-musl.zip
- /bin/sh /entrypoint.sh

View file

@ -1,69 +0,0 @@
platform: linux/amd64
depends_on:
- test
- build-amd64
variables:
- &scw-secrets
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
- &setup-hex "mix local.hex --force && mix local.rebar --force"
- &on-release
when:
event:
- push
- tag
branch:
- develop
- stable
- refs/tags/v*
- refs/tags/stable-*
- &on-stable
when:
event:
- push
- tag
branch:
- stable
- refs/tags/stable-*
- &on-point-release
when:
event:
- push
branch:
- develop
- stable
- &on-pr-open
when:
event:
- pull_request
- &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean"
pipeline:
docs:
<<: *on-point-release
secrets:
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
environment:
CI: "true"
image: python:3.10-slim
commands:
- apt-get update && apt-get install -y rclone wget git zip
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- chmod +x scaleway-cli
- ./scaleway-cli object config install type=rclone
- cd docs
- pip install -r requirements.txt
- mkdocs build
- zip -r docs.zip site/*
- cd site
- rclone copy . scaleway:akkoma-docs/$CI_COMMIT_BRANCH/

View file

@ -1,55 +0,0 @@
platform: linux/amd64
variables:
- &scw-secrets
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
- &setup-hex "mix local.hex --force && mix local.rebar --force"
- &on-release
when:
event:
- push
- tag
branch:
- develop
- stable
- refs/tags/v*
- refs/tags/stable-*
- &on-stable
when:
event:
- push
- tag
branch:
- stable
- refs/tags/stable-*
- &on-point-release
when:
event:
- push
branch:
- develop
- stable
- &on-pr-open
when:
event:
- pull_request
- &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean"
pipeline:
lint:
image: akkoma/ci-base:1.15-otp26
<<: *on-pr-open
environment:
MIX_ENV: test
commands:
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix compile
- mix format --check-formatted

View file

@ -1,93 +0,0 @@
platform: linux/amd64
depends_on:
- lint
matrix:
ELIXIR_VERSION:
- 1.14
- 1.15
OTP_VERSION:
- 25
- 26
include:
- ELIXIR_VERSION: 1.14
OTP_VERSION: 25
- ELIXIR_VERSION: 1.15
OTP_VERSION: 25
- ELIXIR_VERSION: 1.15
OTP_VERSION: 26
variables:
- &scw-secrets
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
- &setup-hex "mix local.hex --force && mix local.rebar --force"
- &on-release
when:
event:
- push
- tag
branch:
- develop
- stable
- refs/tags/v*
- refs/tags/stable-*
- &on-stable
when:
event:
- push
- tag
branch:
- stable
- refs/tags/stable-*
- &on-point-release
when:
event:
- push
branch:
- develop
- stable
- &on-pr-open
when:
event:
- pull_request
- &tag-build "export BUILD_TAG=$${CI_COMMIT_TAG:-\"$CI_COMMIT_BRANCH\"} && export PLEROMA_BUILD_BRANCH=$BUILD_TAG"
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean"
services:
postgres:
image: postgres:15
when:
event:
- pull_request
environment:
POSTGRES_DB: pleroma_test_${ELIXIR_VERSION}_${OTP_VERSION}
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
pipeline:
test:
image: akkoma/ci-base:${ELIXIR_VERSION}-otp${OTP_VERSION}
<<: *on-pr-open
environment:
MIX_ENV: test
POSTGRES_DB: pleroma_test_${ELIXIR_VERSION}_${OTP_VERSION}
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DB_HOST: postgres
commands:
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix compile
- mix ecto.drop -f -q
- mix ecto.create
- mix ecto.migrate
- mkdir -p test/tmp
- mix test --preload-modules --exclude erratic --exclude federated --exclude mocked
- mix test --preload-modules --only mocked

View file

@ -4,65 +4,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased
## Added
- Full compatibility with Erlang OTP26
- handling of GET /api/v1/preferences
## Changed
- OTP builds are now built on erlang OTP26
- The base Phoenix framework is now updated to 1.7
## Fixed
- Documentation issue in which a non-existing nginx file was referenced
- Issue where a bad inbox URL could break federation
- Issue where hashtag rel values would be scrubbed
## 2023.08
## Added
- Added a new configuration option to the MediaProxy feature that allows the blocking of specific domains from using the media proxy or being explicitly allowed by the Content-Security-Policy.
- Please make sure instances you wanted to block media from are not in the MediaProxy `whitelist`, and instead use `blocklist`.
- `OnlyMedia` Upload Filter to simplify restricting uploads to audio, image, and video types
- ARM64 OTP builds
- Ubuntu22 builds are available for develop and stable
- other distributions are stable only
- Support for Elixir 1.15
- 1.14 is still supported
- OTP26 is currently "unsupported". It will probably work, but due to the way
it handles map ordering, the test suite will not pass for it as yet.
## Changed
- Alpine OTP builds are now from alpine 3.18, which is OpenSSLv3 compatible.
If you use alpine OTP builds you will have to update your local system.
- Debian OTP builds are now from a base of bookworm, which is OpenSSLv3 compatible.
If you use debian OTP builds you will have to update your local system to
bookworm (currently: stable).
- Ubuntu and debian builds are compatible again! (for now...)
- Blocks/Mutes now return from max ID to min ID, in line with mastodon.
- The AnonymizeFilename filter is now enabled by default.
## Fixed
- Deactivated users can no longer show up in the emoji reaction list
- Embedded posts can no longer bypass `:restrict\_unauthenticated`
- GET/HEAD requests will now work when requesting AWS-based instances.
## Security
- Add `no_new_privs` hardening to OpenRC and systemd service files
- XML parsers cannot load any entities (thanks @Mae@is.badat.dev!)
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
## Removed
- Builds for debian oldstable (bullseye)
- If you are on oldstable you should NOT attempt to update OTP builds without
first updating your machine.
## 2023.05
## Added
@ -145,6 +86,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Rich media will now hard-exit after 5 seconds, to prevent timeline hangs
- HTTP Content Security Policy is now far more strict to prevent any potential XSS/CSS leakages
- Follow requests are now paginated, matches mastodon API spec, so use the Link header to paginate.
- `internal.fetch` and `relay` actors are now represented with the actor type `Application`
### Fixed
- /api/v1/accounts/lookup will now respect restrict\_unauthenticated

View file

@ -1,4 +1,4 @@
FROM hexpm/elixir:1.15.4-erlang-26.0.2-alpine-3.18.2
FROM hexpm/elixir:1.14.3-erlang-25.3-alpine-3.17.2
ENV MIX_ENV=prod
ENV ERL_EPMD_ADDRESS=127.0.0.1

View file

@ -14,7 +14,7 @@
method: Pleroma.Captcha.Mock
# Print only warnings and errors during test
config :logger, level: :warning
config :logger, level: :warn
config :pleroma, :auth, oauth_consumer_strategies: []

View file

@ -110,6 +110,17 @@
"xmpp"
]
websocket_config = [
path: "/websocket",
serializer: [
{Phoenix.Socket.V1.JSONSerializer, "~> 1.0.0"},
{Phoenix.Socket.V2.JSONSerializer, "~> 2.0.0"}
],
timeout: 60_000,
transport_log: false,
compress: false
]
# Configures the endpoint
config :pleroma, Pleroma.Web.Endpoint,
url: [host: "localhost"],
@ -119,7 +130,10 @@
{:_,
[
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
{:_, Plug.Cowboy.Handler, {Pleroma.Web.Endpoint, []}}
{"/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}},
{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
]}
]
],
@ -156,10 +170,6 @@
"application/ld+json" => ["activity+json"]
}
config :mime, :extensions, %{
"activity+json" => "application/activity+json"
}
config :tesla, :adapter, {Tesla.Adapter.Finch, name: MyFinch}
# Configures http settings, upstream proxy etc.
@ -433,8 +443,7 @@
# Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1
max_read_duration: 30_000
],
whitelist: [],
blocklist: []
whitelist: []
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
method: :purge,

View file

@ -1081,7 +1081,7 @@
key: :level,
type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warning, :error]
suggestions: [:debug, :info, :warn, :error]
},
%{
key: :ident,
@ -1114,7 +1114,7 @@
key: :level,
type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warning, :error]
suggestions: [:debug, :info, :warn, :error]
},
%{
key: :format,
@ -1558,21 +1558,7 @@
%{
key: :whitelist,
type: {:list, :string},
description: """
List of hosts with scheme to bypass the MediaProxy.\n
The media will be fetched by the client, directly from the remote server.\n
To allow this, it will Content-Security-Policy exceptions for each instance listed.\n
This is to be used for instances you trust and do not want to cache media for.
""",
suggestions: ["http://example.com"]
},
%{
key: :blocklist,
type: {:list, :string},
description: """
List of hosts with scheme which will not go through the MediaProxy, and will not be explicitly allowed by the Content-Security-Policy.
This is to be used for instances where you do not want their media to go through your server or to be accessed by clients.
""",
description: "List of hosts with scheme to bypass the MediaProxy",
suggestions: ["http://example.com"]
}
]
@ -1858,7 +1844,7 @@
key: :log,
type: {:dropdown, :atom},
description: "Logs verbose mode",
suggestions: [false, :error, :warning, :info, :debug]
suggestions: [false, :error, :warn, :info, :debug]
},
%{
key: :queues,

View file

@ -16,7 +16,7 @@
# Print only warnings and errors during test
config :logger, :console,
level: :warning,
level: :warn,
format: "\n[$level] $message\n"
config :pleroma, :auth, oauth_consumer_strategies: []
@ -81,7 +81,10 @@
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
config :pleroma, Oban, testing: :manual
config :pleroma, Oban,
queues: false,
crontab: false,
plugins: false
config :pleroma, Pleroma.ScheduledActivity,
daily_user_limit: 2,

View file

@ -1,4 +1,4 @@
#!/bin/sh
docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db
docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db

View file

@ -1,3 +1,3 @@
#!/bin/sh
docker compose run --rm akkoma $@
docker-compose run --rm akkoma $@

View file

@ -42,7 +42,7 @@ For a frontend configured under the `available` key, it's enough to install it b
This will download the latest build for the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
You can override any of the details. To install an Akkoma-FE build from a different URL, you could do this:
You can override any of the details. To install a Pleroma-FE build from a different URL, you could do this:
=== "OTP"

View file

@ -62,6 +62,6 @@ mix ecto.migrate
# Start akkoma (replace with your system service manager's equivalent if different)
sudo systemctl start akkoma
# Update Akkoma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
# Update Pleroma-FE frontend to latest stable. For other Frontends see Frontend Configuration doc for more information.
mix pleroma.frontend install pleroma-fe --ref stable
```

View file

@ -2,14 +2,6 @@
Note: Additional clients may work, but these are known to work with Akkoma.
Apps listed here might not support all of Akkoma's features.
## Multiplatform
### Kaiteki
- Homepage: <https://kaiteki.app/>
- Source Code: <https://github.com/Kaiteki-Fedi/Kaiteki>
- Contact: [@kaiteki@fedi.software](https://fedi.software/@Kaiteki)
- Platforms: Web, Windows, Linux, Android
- Features: MastoAPI, Supports multiple backends
## Desktop
### Whalebird
- Homepage: <https://whalebird.social/>

View file

@ -246,11 +246,11 @@ Notes:
### :frontend_configurations
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Akkoma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Pleroma-FE configuration and customization for instance administrators](https://docs-fe.akkoma.dev/stable/CONFIGURATION/#options).
Frontends can access these settings at `/api/v1/pleroma/frontend_configurations`
To add your own configuration for Akkoma-FE, use it like this:
To add your own configuration for Pleroma-FE, use it like this:
```elixir
config :pleroma, :frontend_configurations,
@ -615,12 +615,6 @@ This filter only strips the GPS and location metadata with Exiftool leaving colo
No specific configuration.
#### Pleroma.Upload.Filter.OnlyMedia
This filter rejects uploads that are not identified with Content-Type matching audio/\*, image/\*, or video/\*
No specific configuration.
#### Pleroma.Upload.Filter.Mogrify
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.

View file

@ -26,7 +26,7 @@ config :pleroma, :frontends,
}
```
This would serve the frontend from the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit.
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.
Refer to [the frontend CLI task](../../administration/CLI_tasks/frontend) for how to install the frontend's files

View file

@ -6,7 +6,7 @@ To add a custom theme to your instance, you'll first need to get a custom theme,
### Create your own theme
* You can create your own theme using the Akkoma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
* You can create your own theme using the Pleroma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
* To download your theme, you can do Save preset
* If you want to upload a theme to customise it further, you can upload it using Load preset

View file

@ -25,7 +25,6 @@ Home, public, hashtag & list timelines accept these parameters:
## Statuses
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
- `emoji_reactions`: additional field since Akkoma 3.2.0; identical to `pleroma/emoji_reactions`
Has these additional fields under the `pleroma` object:
@ -37,9 +36,7 @@ Has these additional fields under the `pleroma` object:
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being its mimetype. Currently, the only alternate representation supported is `text/plain`
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
- `thread_muted`: true if the thread the post belongs to is muted
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 2, me: true, account_ids: ["UserID1", "UserID2"]}`.
The `account_ids` property was added in Akkoma 3.2.0.
Further info about all reacting users at once, can be found using the `/statuses/:id/reactions` endpoint.
- `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.
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
@ -217,11 +214,6 @@ Returns: array of Status.
The maximum number of statuses is limited to 100 per request.
## PUT `/api/v1/statuses/:id/emoji_reactions/:emoji`
This endpoint is an extension of the Fedibird Mastodon fork.
It behaves identical to PUT `/api/v1/pleroma/statuses/:id/reactions/:emoji`.
## PATCH `/api/v1/accounts/update_credentials`
Additional parameters can be added to the JSON body/Form data:

View file

@ -3,7 +3,7 @@
# Introduction to Akkoma
## What is Akkoma?
Akkoma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named Akkoma-FE. It also includes the Mastodon frontend, if that's your thing.
It actually consists of two components: a backend, named simply Akkoma, and a user-facing frontend, named 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!
@ -31,11 +31,11 @@ Installation instructions can be found in the installation section of these docs
## I got an account, now what?
Great! Now you can explore the fediverse! Open the login page for your Akkoma instance (e.g. <https://otp.akkoma.dev>) and login with your username and password. (If you don't have an account yet, click on Register)
### Akkoma-FE
The default front-end used by Akkoma is Akkoma-FE. You can find more information on what it is and how to use it in the [Introduction to Akkoma-FE](https://docs-fe.akkoma.dev/stable/).
### Pleroma-FE
The default front-end used by Akkoma is Pleroma-FE. You can find more information on what it is and how to use it in the [Introduction to Pleroma-FE](https://docs-fe.akkoma.dev/stable/).
### Mastodon interface
If the Akkoma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
If the Pleroma-FE interface isn't your thing, or you're just trying something new but you want to keep using the familiar Mastodon interface, we got that too!
Just add a "/web" after your instance url (e.g. <https://otp.akkoma.dev/web>) and you'll end on the Mastodon web interface, but with a Akkoma backend! MAGIC!
The Mastodon interface is from the Glitch-soc fork. For more information on the Mastodon interface you can check the [Mastodon](https://docs.joinmastodon.org/) and [Glitch-soc](https://glitch-soc.github.io/docs/) documentation.

View file

@ -4,7 +4,7 @@
## Installation
This guide will assume you are on Debian 12 (“bookworm”) or later. This guide should also work with Ubuntu 22.04 (“Jammy Jellyfish”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu akkoma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
This guide will assume you are on Debian 11 (“bullseye”) or later. This guide should also work with Ubuntu 18.04 (“Bionic Beaver”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu akkoma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
{! installation/generic_dependencies.include !}
@ -23,67 +23,15 @@ sudo apt full-upgrade
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev
```
### Create the akkoma user
* Add a new system user for the Akkoma service:
```shell
sudo useradd -r -s /bin/false -m -d /var/lib/akkoma -U akkoma
```
**Note**: To execute a single command as the Akkoma system user, use `sudo -Hu akkoma command`. You can also switch to a shell by using `sudo -Hu akkoma $SHELL`. If you dont have and want `sudo` on your system, you can use `su` as root user (UID 0) for a single command by using `su -l akkoma -s $SHELL -c 'command'` and `su -l akkoma -s $SHELL` for starting a shell.
### Install Elixir and Erlang
If your distribution packages a recent enough version of Elixir, you can install it directly from the distro repositories and skip to the next section of the guide:
* Install Elixir and Erlang (you might need to use backports or [asdf](https://github.com/asdf-vm/asdf) on old systems):
```shell
sudo apt update
sudo apt install elixir erlang-dev erlang-nox
```
Otherwise use [asdf](https://github.com/asdf-vm/asdf) to install the latest versions of Elixir and Erlang.
First, install some dependencies needed to build Elixir and Erlang:
```shell
sudo apt install curl unzip build-essential autoconf m4 libncurses5-dev libssh-dev unixodbc-dev xsltproc libxml2-utils libncurses-dev
```
Then login to the `akkoma` user and install asdf:
```shell
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3
```
Add the following lines to `~/.bashrc`:
```shell
. "$HOME/.asdf/asdf.sh"
# asdf completions
. "$HOME/.asdf/completions/asdf.bash"
```
Restart the shell:
```shell
exec $SHELL
```
Next install Erlang:
```shell
asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
export KERL_CONFIGURE_OPTIONS="--disable-debug --without-javac"
asdf install erlang 25.3.2.5
asdf global erlang 25.3.2.5
```
Now install Elixir:
```shell
asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
asdf install elixir 1.15.4-otp-25
asdf global elixir 1.15.4-otp-25
```
Confirm that Elixir is installed correctly by checking the version:
```shell
elixir --version
```
### Optional packages: [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md)
@ -93,7 +41,15 @@ sudo apt install imagemagick ffmpeg libimage-exiftool-perl
### Install AkkomaBE
* Log into the `akkoma` user and clone the AkkomaBE repository from the stable branch and make the Akkoma user the owner of the directory:
* Add a new system user for the Akkoma service:
```shell
sudo useradd -r -s /bin/false -m -d /var/lib/akkoma -U akkoma
```
**Note**: To execute a single command as the Akkoma system user, use `sudo -Hu akkoma command`. You can also switch to a shell by using `sudo -Hu akkoma $SHELL`. If you dont have and want `sudo` on your system, you can use `su` as root user (UID 0) for a single command by using `su -l akkoma -s $SHELL -c 'command'` and `su -l akkoma -s $SHELL` for starting a shell.
* Git clone the AkkomaBE repository from stable-branch and make the Akkoma user the owner of the directory:
```shell
sudo mkdir -p /opt/akkoma

View file

@ -10,7 +10,7 @@ If you want to migrate from or OTP to docker, check out [the migration guide](./
### Prepare the system
* Install docker and docker compose
* Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
@ -26,7 +26,7 @@ echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
variables for the docker compose file.
variables for the docker-compose file.
### Building the container
@ -65,9 +65,9 @@ cp config/generated_config.exs config/prod.secret.exs
We need to run a few commands on the database container, this isn't too bad
```bash
docker compose run --rm --user akkoma -d db
docker-compose run --rm --user akkoma -d db
# Note down the name it gives here, it will be something like akkoma_db_run
docker compose run --rm akkoma psql -h db -U akkoma -f config/setup_db.psql
docker-compose run --rm akkoma psql -h db -U akkoma -f config/setup_db.psql
docker stop akkoma_db_run # Replace with the name you noted down
```
@ -84,17 +84,17 @@ We're going to run it in the foreground on the first run, just to make sure
everything start up.
```bash
docker compose up
docker-compose up
```
If everything went well, you should be able to access your instance at http://localhost:4000
You can `ctrl-c` out of the docker compose now to shutdown the server.
You can `ctrl-c` out of the docker-compose now to shutdown the server.
### Running in the background
```bash
docker compose up -d
docker-compose up -d
```
### Create your first user
@ -125,8 +125,8 @@ cp docker-resources/Caddyfile.example docker-resources/Caddyfile
Then edit the TLD in your caddyfile to the domain you're serving on.
Uncomment the `caddy` section in the docker compose file,
then run `docker compose up -d` again.
Uncomment the `caddy` section in the docker-compose file,
then run `docker-compose up -d` again.
#### Running a reverse proxy on the host
@ -152,7 +152,7 @@ git pull
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix ecto.migrate
docker compose restart akkoma db
docker-compose restart akkoma db
```
#### Further reading

View file

@ -2,7 +2,7 @@
* PostgreSQL 9.6+
* Elixir 1.14+
* Erlang OTP 25+
* Erlang OTP 24+
* git
* file / libmagic
* gcc (clang might also work)

View file

@ -40,7 +40,7 @@ If you are on pleroma develop, and have updated since 2022-08, you may have issu
Please roll back the given migrations:
```bash
MIX_ENV=prod mix ecto.rollback --migrations-path priv/repo/optional_migrations/pleroma_develop_rollbacks -n5
MIX_ENV=prod mix ecto.rollback --migrations-path priv/repo/optional_migrations/pleroma_develop_rollbacks -n3
```
Then compile, migrate and restart as usual.
@ -118,15 +118,3 @@ To fix this, run:
```
which will remove the config from the database. Things should work now.
## Migrating back to Pleroma
Akkoma is a hard fork of Pleroma. As such, migrating back is not guaranteed to always work. But if you want to migrate back to Pleroma, you can always try. Just note that you may run into unexpected issues and you're basically on your own. The following are some tips that may help, but note that these are barely tested, so proceed at your own risk.
First you will need to roll back the database migrations. The latest migration both Akkoma and Pleroma still have in common should be 20210416051708, so roll back to that. If you run from source, that should be
```sh
MIX_ENV=prod mix ecto.rollback --to 20210416051708
```
Then switch back to Pleroma for updates (similar to how was done to migrate to Akkoma), and remove the front-ends. The front-ends are installed in the `frontends` folder in the [static directory](../configuration/static_dir.md). Once you are back to Pleroma, you will need to run the database migrations again. See the Pleroma documentation for this.

View file

@ -10,7 +10,7 @@ You probably should, in the first instance.
### Prepare the system
* Install docker and docker compose
* Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
@ -46,7 +46,7 @@ For *most* from-source installs it'll already be there.
And the same with `uploads`, make sure your uploads (if you have them on disk) are
located at `uploads/` in the akkoma source directory.
If you have them on a different disk, you will need to mount that disk into the docker compose file,
If you have them on a different disk, you will need to mount that disk into the docker-compose file,
with an entry that looks like this:
```yaml
@ -66,7 +66,7 @@ echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
variables for the docker compose file.
variables for the docker-compose file.
=== "From source"
@ -126,21 +126,21 @@ mkdir pgdata
Now we can import our database to the container.
```bash
docker compose run --rm --user akkoma -d db
docker compose run --rm akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
docker-compose run --rm --user akkoma -d db
docker-compose run --rm akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
```
### Reverse proxies
If you're just reusing your old proxy, you may have to uncomment the line in
the docker compose file under `ports`. You'll find it.
the docker-compose file under `ports`. You'll find it.
Otherwise, you can use the same setup as the [docker installation guide](./docker_en.md#reverse-proxies).
### Let's go
```bash
docker compose up -d
docker-compose up -d
```
You should now be at the same point as you were before, but with a docker install.

View file

@ -1,19 +1,19 @@
# Optional software packages needed for specific functionality
For specific Akkoma functionality (which is disabled by default) some or all of the below packages are required:
* `ImageMagick`
For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
* `ImageMagic`
* `ffmpeg`
* `exiftool`
Please refer to documentation in `docs/installation` on how to install them on specific OS.
Note: the packages are not required with the current default settings of Akkoma.
Note: the packages are not required with the current default settings of Pleroma.
## `ImageMagick`
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
It is required for the following Akkoma features:
It is required for the following Pleroma features:
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
@ -21,12 +21,12 @@ It is required for the following Akkoma features:
`ffmpeg` is software to record, convert and stream audio and video.
It is required for the following Akkoma features:
It is required for the following Pleroma features:
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `exiftool`
`exiftool` is media files metadata reader/writer.
It is required for the following Akkoma features:
It is required for the following Pleroma features:
* `Pleroma.Upload.Filters.Exiftool` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)

View file

@ -5,7 +5,7 @@
This guide covers a installation using an OTP release. To install Akkoma from source, please check out the corresponding guide for your distro.
## Pre-requisites
* A machine running Linux with GNU (e.g. Debian, Ubuntu) or musl (e.g. Alpine) libc and an `x86_64` or `arm64` CPU you have root access to. If you are not sure if it's compatible see [Detecting flavour section](#detecting-flavour) below
* A machine running Linux with GNU (e.g. Debian, Ubuntu) or musl (e.g. Alpine) libc and an `x86_64` CPU you have root access to. If you are not sure if it's compatible see [Detecting flavour section](#detecting-flavour) below
* For installing OTP releases on RedHat-based distros like Fedora and Centos Stream, please follow [this guide](./otp_redhat_en.md) instead.
* A (sub)domain pointed to the machine
@ -15,16 +15,16 @@ While in theory OTP releases are possbile to install on any compatible machine,
### Detecting flavour
This is a little more complex than it used to be (thanks ubuntu)
Use the following mapping to figure out your flavour:
| distribution | architecture | flavour | available branches |
| --------------- | ------------------ | ------------------- | ------------------- |
| debian bookworm | amd64 | amd64 | develop, stable |
| debian bookworm | arm64 | arm64 | stable |
| ubuntu jammy | amd64 | amd64 | develop, stable |
| ubuntu jammy | arm64 | arm64 | develop, stable |
| alpine | amd64 | amd64-musl | stable |
| alpine | arm64 | arm64-musl | stable |
| distribution | flavour | available branches |
| ------------- | ------------------ | ------------------- |
| debian stable | amd64 | develop, stable |
| ubuntu focal | amd64 | develop, stable |
| ubuntu jammy | amd64-ubuntu-jammy | develop, stable |
| alpine | amd64-musl | stable |
Other similar distributions will _probably_ work, but if it is not listed above, there is no official
support.
@ -118,12 +118,8 @@ Restart PostgreSQL to apply configuration changes:
adduser --system --shell /bin/false --home /opt/akkoma akkoma
# Set the flavour environment variable to the string you got in Detecting flavour section.
# For example if the flavour is `amd64-musl` the command will be
# export FLAVOUR="amd64-musl"
export FLAVOUR="<replace-this-with-the-correct-flavour-string>"
# Make sure the SHELL variable is set
export SHELL="${SHELL:-/bin/sh}"
# For example if the flavour is `amd64` the command will be
export FLAVOUR="amd64"
# Clone the release build into a temporary directory and unpack it
su akkoma -s $SHELL -lc "
@ -187,18 +183,18 @@ The location of nginx configs is dependent on the distro
=== "Alpine"
```
cp /opt/akkoma/installation/akkoma.nginx /etc/nginx/conf.d/akkoma.conf
cp /opt/akkoma/installation/nginx/akkoma.nginx /etc/nginx/conf.d/akkoma.conf
```
=== "Debian/Ubuntu"
```
cp /opt/akkoma/installation/akkoma.nginx /etc/nginx/sites-available/akkoma.conf
cp /opt/akkoma/installation/nginx/akkoma.nginx /etc/nginx/sites-available/akkoma.conf
ln -s /etc/nginx/sites-available/akkoma.conf /etc/nginx/sites-enabled/akkoma.conf
```
If your distro does not have either of those you can append `include /etc/nginx/akkoma.conf` to the end of the http section in /etc/nginx/nginx.conf and
```sh
cp /opt/akkoma/installation/akkoma.nginx /etc/nginx/akkoma.conf
cp /opt/akkoma/installation/nginx/akkoma.nginx /etc/nginx/akkoma.conf
```
#### Edit the nginx config

View file

@ -178,7 +178,7 @@ certbot certonly --standalone --preferred-challenges http -d yourinstance.tld
#### Copy Akkoma nginx configuration to the nginx folder
```shell
cp /opt/akkoma/installation/akkoma.nginx /etc/nginx/conf.d/akkoma.conf
cp /opt/akkoma/installation/nginx/akkoma.nginx /etc/nginx/conf.d/akkoma.conf
```
#### Edit the nginx config

View file

@ -38,11 +38,11 @@
{% endif %}
{% if page and page.url.startswith('backend') %}
{% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma" %}
{% set repo_name = "AkkomaGang/akkoma" %}
{% set repo_url = "https://git.pleroma.social/pleroma/pleroma" %}
{% set repo_name = "pleroma/pleroma" %}
{% elif page and page.url.startswith('frontend') %}
{% set repo_url = "https://akkoma.dev/AkkomaGang/akkoma-fe" %}
{% set repo_name = "AkkomaGang/akkoma-fe" %}
{% set repo_url = "https://git.pleroma.social/pleroma/pleroma-fe" %}
{% set repo_name = "pleroma/pleroma-fe" %}
{% else %}
{% set repo_url = config.repo_url %}
{% set repo_name = config.repo_name %}

View file

@ -8,8 +8,6 @@ Restart=on-failure
; Uncomment this if you're on Arch Linux
; Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl"
; Uncomment if using asdf to manage Elixir and Erlang
; Environment="PATH=/var/lib/akkoma/.asdf/shims:/var/lib/akkoma/.asdf/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
; Name of the user that runs the Akkoma service.
User=akkoma
@ -26,8 +24,6 @@ Environment="HOME=/var/lib/akkoma"
WorkingDirectory=/opt/akkoma
; Path to the Mix binary.
ExecStart=/usr/bin/mix phx.server
; If using asdf comment the above line and uncomment the one below instead
; ExecStart=/var/lib/akkoma/.asdf/shims/mix phx.server
; Some security directives.
; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops.
@ -38,8 +34,6 @@ ProtectHome=true
ProtectSystem=full
; Sets up a new /dev mount for the process and only adds API pseudo devices like /dev/null, /dev/zero or /dev/random but not physical devices. Disabled by default because it may not work on devices like the Raspberry Pi.
PrivateDevices=false
; Ensures that the service process and all its children can never gain new privileges through execve().
NoNewPrivileges=true
; Drops the sysadmin capability from the daemon.
CapabilityBoundingSet=~CAP_SYS_ADMIN

View file

@ -4,9 +4,6 @@
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
# 2. Copy this section into your Caddyfile and restart Caddy.
# If you are able to, it's highly recommended to have your media served via a separate subdomain for improved security.
# Uncomment the relevant sectons here and modify the base_url setting for Pleroma.Upload and :media_proxy accordingly.
example.tld {
log {
output file /var/log/caddy/akkoma.log
@ -17,21 +14,4 @@ example.tld {
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
# and `localhost.` resolves to [::0] on some systems: see issue #930
reverse_proxy 127.0.0.1:4000
# Uncomment if using a separate media subdomain
#@mediaproxy path /media/* /proxy/*
#handle @mediaproxy {
# redir https://media.example.tld{uri} permanent
#}
}
# Uncomment if using a separate media subdomain
#media.example.tld {
# @mediaproxy path /media/* /proxy/*
# reverse_proxy @mediaproxy 127.0.0.1:4000 {
# transport http {
# response_header_timeout 10s
# read_timeout 15s
# }
# }
#}

View file

@ -8,7 +8,6 @@ pidfile="/var/run/akkoma.pid"
directory=/opt/akkoma
healthcheck_delay=60
healthcheck_timer=30
no_new_privs="yes"
: ${akkoma_port:-4000}

View file

@ -359,7 +359,7 @@ def run(["set_text_search_config", tsconfig]) do
)
end
shell_info(~c"Done.")
shell_info('Done.')
end
end

View file

@ -130,7 +130,6 @@ def run(["get-packs" | args]) do
}
File.write!(Path.join(pack_path, "pack.json"), Jason.encode!(pack_json, pretty: true))
Pleroma.Emoji.reload()
else
IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
end
@ -236,8 +235,6 @@ def run(["gen-pack" | args]) do
IO.puts("#{pack_file} has been created with the #{name} pack")
end
Pleroma.Emoji.reload()
end
def run(["reload"]) do

View file

@ -247,22 +247,16 @@ def run(["gen" | rest]) do
config_dir = Path.dirname(config_path)
psql_dir = Path.dirname(psql_path)
# Note: Distros requiring group read (0o750) on those directories should
# pre-create the directories.
to_create =
[config_dir, psql_dir, static_dir, uploads_dir]
|> Enum.reject(&File.exists?/1)
for dir <- to_create do
File.mkdir_p!(dir)
File.chmod!(dir, 0o700)
end
shell_info("Writing config to #{config_path}.")
# Sadly no fchmod(2) equivalent in Elixir…
File.touch!(config_path)
File.chmod!(config_path, 0o640)
File.write(config_path, result_config)
shell_info("Writing the postgres script to #{psql_path}.")
File.write(psql_path, result_psql)
@ -281,7 +275,8 @@ def run(["gen" | rest]) do
else
shell_error(
"The task would have overwritten the following files:\n" <>
Enum.map_join(will_overwrite, &"- #{&1}\n") <> "Rerun with `--force` to overwrite them."
(Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>
"Rerun with `--force` to overwrite them."
)
end
end

View file

@ -0,0 +1,13 @@
defmodule Mix.Tasks.Pleroma.Moderation do
use Mix.Task
import Mix.Pleroma
@shortdoc "Does moderation"
def run(["rm-instance", domain | _rest]) do
start_pleroma()
IO.puts("Deleting #{domain}")
Pleroma.Instances.Instance.perform(:delete_instance, domain)
|> IO.inspect()
end
end

View file

@ -30,12 +30,12 @@ def run(["index"]) do
meili_put(
"/indexes/objects/settings/ranking-rules",
[
"published:desc",
"words",
"exactness",
"proximity",
"typo",
"exactness",
"attribute",
"published:desc",
"sort"
]
)

View file

@ -11,7 +11,6 @@ defmodule Mix.Tasks.Pleroma.User do
alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline
use Pleroma.Web, :verified_routes
@shortdoc "Manages Pleroma users"
@moduledoc File.read!("docs/docs/administration/CLI_tasks/user.md")
@ -114,7 +113,11 @@ def run(["reset_password", nickname]) do
{:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
shell_info("Generated password reset token for #{user.nickname}")
IO.puts("URL: #{~p[/api/v1/pleroma/password_reset/#{token.token}]}")
IO.puts(
"URL: #{Pleroma.Web.Router.Helpers.reset_password_url(Pleroma.Web.Endpoint,
:reset,
token.token)}"
)
else
_ ->
shell_error("No local user #{nickname}")
@ -300,7 +303,13 @@ def run(["invite" | rest]) do
{:ok, invite} <- UserInviteToken.create_invite(options) do
shell_info("Generated user invite token " <> String.replace(invite.invite_type, "_", " "))
url = url(~p[/registration/#{invite.token}])
url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:registration_page,
invite.token
)
IO.puts(url)
else
error ->

View file

@ -26,6 +26,7 @@ def init(%Plug.Conn{method: "GET"} = conn, {endpoint, handler, transport}) do
conn
|> fetch_query_params
|> Transport.transport_log(opts[:transport_log])
|> Transport.force_ssl(handler, endpoint, opts)
|> Transport.check_origin(handler, endpoint, opts)
case conn do

View file

@ -390,8 +390,7 @@ def restrict_deactivated_users(query) do
active in fragment(
"SELECT is_active from users WHERE ap_id = ? AND is_active = TRUE",
activity.actor
),
on: true
)
)
end

View file

@ -21,7 +21,7 @@ defp generate_topics(object, activity) do
["user", "list"] ++ visibility_tags(object, activity)
end
defp visibility_tags(object, %{data: %{"type" => type}} = activity) when type != "Announce" do
defp visibility_tags(object, activity) do
case Visibility.get_visibility(activity) do
"public" ->
if activity.local do
@ -31,10 +31,6 @@ defp visibility_tags(object, %{data: %{"type" => type}} = activity) when type !=
end
|> item_creation_tags(object, activity)
"local" ->
["public:local"]
|> item_creation_tags(object, activity)
"direct" ->
["direct"]
@ -43,10 +39,6 @@ defp visibility_tags(object, %{data: %{"type" => type}} = activity) when type !=
end
end
defp visibility_tags(_object, _activity) do
[]
end
defp item_creation_tags(tags, object, %{data: %{"type" => "Create"}} = activity) do
tags ++
remote_topics(activity) ++ hashtags_to_topics(object) ++ attachment_topics(object, activity)
@ -71,18 +63,7 @@ defp remote_topics(_), do: []
defp attachment_topics(%{data: %{"attachment" => []}}, _act), do: []
defp attachment_topics(_object, %{local: true} = activity) do
case Visibility.get_visibility(activity) do
"public" ->
["public:media", "public:local:media"]
"local" ->
["public:local:media"]
_ ->
[]
end
end
defp attachment_topics(_object, %{local: true}), do: ["public:media", "public:local:media"]
defp attachment_topics(_object, %{actor: actor}) when is_binary(actor),
do: ["public:media", "public:remote:media:" <> URI.parse(actor).host]

View file

@ -53,7 +53,6 @@ def start(_type, _args) do
Config.DeprecationWarnings.warn()
Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled()
Pleroma.ApplicationRequirements.verify!()
load_all_pleroma_modules()
load_custom_modules()
Pleroma.Docs.JSON.compile()
limiters_setup()
@ -88,7 +87,7 @@ def start(_type, _args) do
# Go for the default 3 unless we're in test
max_restarts =
if @mix_env == :test do
1000
100
else
3
end
@ -113,7 +112,7 @@ defp set_postgres_server_version do
num
else
e ->
Logger.warning(
Logger.warn(
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6"
)
@ -145,24 +144,6 @@ def load_custom_modules do
end
end
def load_all_pleroma_modules do
:code.all_available()
|> Enum.filter(fn {mod, _, _} ->
mod
|> to_string()
|> String.starts_with?("Elixir.Pleroma.")
end)
|> Enum.map(fn {mod, _, _} ->
mod
|> to_string()
|> String.to_existing_atom()
|> Code.ensure_loaded!()
end)
# Use this when 1.15 is standard
# |> Code.ensure_all_loaded!()
end
defp cachex_children do
[
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
@ -281,8 +262,6 @@ defp http_children do
proxy = Pleroma.HTTP.AdapterHelper.format_proxy(proxy_url)
pool_size = Config.get([:http, :pool_size])
:public_key.cacerts_load()
config =
[:http, :adapter]
|> Config.get([])

View file

@ -34,7 +34,7 @@ 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.warning("""
Logger.warn("""
To send welcome emails, you need to enable the mailer.
Welcome emails will NOT be sent with the current config.
@ -53,7 +53,7 @@ defp check_welcome_message_config!(result), do: result
def check_confirmation_accounts!(:ok) do
if Pleroma.Config.get([:instance, :account_activation_required]) &&
not Pleroma.Emails.Mailer.enabled?() do
Logger.warning("""
Logger.warn("""
Account activation is required, but the mailer is disabled.
Users will NOT be able to confirm their accounts with this config.
Either disable account activation or enable the mailer.

View file

@ -28,7 +28,7 @@ def check_simple_policy_tuples do
|> Enum.any?(fn {_, v} -> is_list(v) and Enum.any?(v, &is_binary/1) end)
if has_strings do
Logger.warning("""
Logger.warn("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the SimplePolicy configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@ -87,7 +87,7 @@ def check_quarantined_instances_tuples do
has_strings = Config.get([:instance, :quarantined_instances], []) |> Enum.any?(&is_binary/1)
if has_strings do
Logger.warning("""
Logger.warn("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the quarantined_instances configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@ -124,7 +124,7 @@ def check_transparency_exclusions_tuples do
has_strings = Config.get([:mrf, :transparency_exclusions]) |> Enum.any?(&is_binary/1)
if has_strings do
Logger.warning("""
Logger.warn("""
!!!DEPRECATION WARNING!!!
Your config is using strings in the transparency_exclusions configuration instead of tuples. They should work for now, but you are advised to change to the new configuration to prevent possible issues later:
@ -159,7 +159,7 @@ def check_transparency_exclusions_tuples do
def check_hellthread_threshold do
if Config.get([:mrf_hellthread, :threshold]) do
Logger.warning("""
Logger.warn("""
!!!DEPRECATION WARNING!!!
You are using the old configuration mechanism for the hellthread filter. Please check config.md.
""")
@ -264,7 +264,7 @@ def move_namespace_and_warn(config_map, warning_preface) do
if warning == "" do
:ok
else
Logger.warning(warning_preface <> warning)
Logger.warn(warning_preface <> warning)
:error
end
end
@ -274,7 +274,7 @@ 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.warning("""
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.
""")

View file

@ -23,7 +23,7 @@ def warn do
You are using old workers in Oban crontab settings, which were removed.
Please, remove setting from crontab in your config file (prod.secret.exs): #{inspect(setting)}
"""
|> Logger.warning()
|> Logger.warn()
List.delete(acc, setting)
else

View file

@ -22,20 +22,6 @@ def load(config, opts) do
with_runtime_config =
if File.exists?(config_path) do
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
%File.Stat{mode: mode} = File.lstat!(config_path)
if Bitwise.band(mode, 0o007) > 0 do
raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"
end
if Bitwise.band(mode, 0o020) > 0 do
raise "Configuration at #{config_path} has group-wise write permissions, execute the following: chmod g-w #{config_path}"
end
# Note: Elixir doesn't provides a getuid(2)
# so cannot forbid group-read only when config is owned by us
runtime_config = Config.Reader.read!(config_path)
with_defaults

View file

@ -110,7 +110,7 @@ defp merge_with_default(%{group: group, key: key, value: value} = setting) do
defp configure({_, :backends, _, merged}) do
# removing current backends
Enum.each(Application.get_env(:logger, :backends, []), &Logger.remove_backend/1)
Enum.each(Application.get_env(:logger, :backends), &Logger.remove_backend/1)
Enum.each(merged, &Logger.add_backend/1)
@ -149,7 +149,7 @@ defp update({group, key, value, merged}) do
error_msg =
"updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}"
Logger.warning(error_msg)
Logger.warn(error_msg)
nil
end
@ -183,12 +183,12 @@ defp restart(started_applications, app, _) do
:ok = Application.start(app)
else
nil ->
Logger.warning("#{app} is not started.")
Logger.warn("#{app} is not started.")
error ->
error
|> inspect()
|> Logger.warning()
|> Logger.warn()
end
end

View file

@ -25,7 +25,7 @@ defmodule Pleroma.Constants do
const(static_only_files,
do:
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance embed sw.js sw-pleroma.js favicon.png schemas doc)
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css)
)
const(status_updatable_fields,

View file

@ -6,13 +6,10 @@ defmodule Pleroma.Emails.AdminEmail do
@moduledoc "Admin emails"
import Swoosh.Email
use Pleroma.Web, :mailer
alias Pleroma.Config
alias Pleroma.HTML
use Phoenix.VerifiedRoutes,
endpoint: Pleroma.Web.Endpoint,
router: Pleroma.Web.Router
alias Pleroma.Web.Router.Helpers
defp instance_config, do: Config.get(:instance)
defp instance_name, do: instance_config()[:name]
@ -48,7 +45,7 @@ def report(to, reporter, account, statuses, comment) do
statuses
|> Enum.map(fn
%{id: id} ->
status_url = url(~p[/notice/#{id}])
status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, id)
"<li><a href=\"#{status_url}\">#{status_url}</li>"
%{"id" => id} when is_binary(id) ->

View file

@ -6,11 +6,12 @@ defmodule Pleroma.Emails.UserEmail do
@moduledoc "User emails"
require Pleroma.Web.Gettext
use Pleroma.Web, :mailer
alias Pleroma.Config
alias Pleroma.User
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Gettext
alias Pleroma.Web.Router
import Swoosh.Email
import Phoenix.Swoosh, except: [render_body: 3]
@ -74,7 +75,7 @@ def welcome(user, opts \\ %{}) do
def password_reset_email(user, token) when is_binary(token) do
Gettext.with_locale_or_default user.language do
password_reset_url = ~p[/api/v1/pleroma/password_reset/#{token}]
password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token)
html_body =
Gettext.dpgettext(
@ -107,7 +108,12 @@ def user_invitation_email(
to_name \\ nil
) do
Gettext.with_locale_or_default user.language do
registration_url = ~p[/registration/#{user_invite_token.token}]
registration_url =
Router.Helpers.redirect_url(
Endpoint,
:registration_page,
user_invite_token.token
)
html_body =
Gettext.dpgettext(
@ -140,7 +146,13 @@ def user_invitation_email(
def account_confirmation_email(user) do
Gettext.with_locale_or_default user.language do
confirmation_url = ~p[/api/account/confirm_email/#{user.id}/#{user.confirmation_token}]
confirmation_url =
Router.Helpers.confirm_email_url(
Endpoint,
:confirm_email,
user.id,
to_string(user.confirmation_token)
)
html_body =
Gettext.dpgettext(
@ -330,7 +342,7 @@ def unsubscribe_url(user, notifications_type) do
|> Pleroma.JWT.generate_and_sign!()
|> Base.encode64()
~p[/mailer/unsubscribe/#{token}]
Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
end
def backup_is_ready_email(backup, admin_user_id \\ nil) do

View file

@ -59,7 +59,7 @@ def load do
Logger.info("Found emoji packs: #{Enum.join(packs, ", ")}")
if not Enum.empty?(files) do
Logger.warning(
Logger.warn(
"Found files in the emoji folder. These will be ignored, please move them to a subdirectory\nFound files: #{Enum.join(files, ", ")}"
)
end

View file

@ -287,7 +287,6 @@ def update_metadata(name, data) do
@spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()}
def load_pack(name) do
name = Path.basename(name)
pack_file = Path.join([emoji_path(), name, "pack.json"])
with {:ok, _} <- File.stat(pack_file),
@ -412,10 +411,10 @@ defp downloadable?(pack) do
end
defp create_archive_and_cache(pack, hash) do
files = [~c"pack.json" | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
files = ['pack.json' | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
{:ok, {_, result}} =
:zip.zip(~c"#{pack.name}.zip", files, [:memory, cwd: to_charlist(pack.path)])
:zip.zip('#{pack.name}.zip', files, [:memory, cwd: to_charlist(pack.path)])
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
@ -582,7 +581,7 @@ defp unzip(archive, pack_info, remote_pack, local_pack) do
with :ok <- File.mkdir_p!(local_pack.path) do
files = Enum.map(remote_pack["files"], fn {_, path} -> to_charlist(path) end)
# Fallback cannot contain a pack.json file
files = if pack_info[:fallback], do: files, else: [~c"pack.json" | files]
files = if pack_info[:fallback], do: files, else: ['pack.json' | files]
:zip.unzip(archive, cwd: to_charlist(local_pack.path), file_list: files)
end

View file

@ -27,10 +27,10 @@ defmodule Pleroma.HTTP do
nil | {:ok, Env.t()} | {:error, any()}
def get(url, headers \\ [], options \\ [])
def get(nil, _, _), do: nil
def get(url, headers, options), do: request(:get, url, nil, headers, options)
def get(url, headers, options), do: request(:get, url, "", headers, options)
@spec head(Request.url(), Request.headers(), keyword()) :: {:ok, Env.t()} | {:error, any()}
def head(url, headers \\ [], options \\ []), do: request(:head, url, nil, headers, options)
def head(url, headers \\ [], options \\ []), do: request(:head, url, "", headers, options)
@doc """
Performs POST request.
@ -62,13 +62,6 @@ def request(method, url, body, headers, options) when is_binary(url) do
uri = URI.parse(url)
adapter_opts = AdapterHelper.options(uri, options || [])
adapter_opts =
if uri.scheme == :https do
AdapterHelper.maybe_add_cacerts(adapter_opts, :public_key.cacerts_get())
else
adapter_opts
end
options = put_in(options[:adapter], adapter_opts)
params = options[:params] || []
request = build_request(method, headers, options, url, body, params)

View file

@ -47,17 +47,6 @@ def maybe_add_proxy_pool(opts, proxy) do
|> put_in([:pools, :default, :conn_opts, :proxy], proxy)
end
def maybe_add_cacerts(opts, nil), do: opts
def maybe_add_cacerts(opts, cacerts) do
opts
|> maybe_add_pools()
|> maybe_add_default_pool()
|> maybe_add_conn_opts()
|> maybe_add_transport_opts()
|> put_in([:pools, :default, :conn_opts, :transport_opts, :cacerts], cacerts)
end
def add_pool_size(opts, pool_size) do
opts
|> maybe_add_pools()
@ -93,16 +82,6 @@ defp maybe_add_conn_opts(opts) do
end
end
defp maybe_add_transport_opts(opts) do
transport_opts = get_in(opts, [:pools, :default, :conn_opts, :transport_opts])
unless is_nil(transport_opts) do
opts
else
put_in(opts, [:pools, :default, :conn_opts, :transport_opts], [])
end
end
@doc """
Merge default connection & adapter options with received ones.
"""
@ -131,7 +110,7 @@ def parse_proxy(proxy) when is_binary(proxy) do
{:ok, type, uri.host, uri.port}
else
e ->
Logger.warning("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}")
Logger.warn("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}")
{:error, :invalid_proxy}
end
end
@ -141,7 +120,7 @@ def parse_proxy(proxy) when is_tuple(proxy) do
{:ok, type, host, port}
else
_ ->
Logger.warning("Parsing proxy failed #{inspect(proxy)}")
Logger.warn("Parsing proxy failed #{inspect(proxy)}")
{:error, :invalid_proxy}
end
end

View file

@ -20,7 +20,7 @@ def vacuum(args) do
"full" ->
Logger.info("Running VACUUM FULL.")
Logger.warning(
Logger.warn(
"Re-packing your entire database may take a while and will consume extra disk space during the process."
)

View file

@ -73,7 +73,7 @@ def handle_continue(:init_state, _state) do
data_migration.state == :manual or data_migration.name in manual_migrations ->
message = "Data migration is in manual execution or manual fix mode."
update_status(:manual, message)
Logger.warning("#{__MODULE__}: #{message}")
Logger.warn("#{__MODULE__}: #{message}")
data_migration.state == :complete ->
on_complete(data_migration)
@ -109,7 +109,7 @@ def handle_info(:perform, state) do
Putting data migration to manual fix mode. Try running `#{__MODULE__}.retry_failed/0`.
"""
Logger.warning("#{__MODULE__}: #{message}")
Logger.warn("#{__MODULE__}: #{message}")
update_status(:manual, message)
on_complete(data_migration())
@ -125,7 +125,7 @@ def handle_info(:perform, state) do
defp on_complete(data_migration) do
if data_migration.feature_lock || feature_state() == :disabled do
Logger.warning(
Logger.warn(
"#{__MODULE__}: migration complete but feature is locked; consider enabling."
)

View file

@ -195,7 +195,6 @@ defp exclude_filtered(query, user) do
from([_n, a, o] in query,
where:
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
fragment("?->>'content' is null", o.data) or
fragment("?->>'actor' = ?", o.data, ^user.ap_id)
)
end
@ -696,7 +695,7 @@ def skip?(
cond do
opts[:type] == "poll" -> false
user.ap_id == actor -> false
!User.following?(user, follower) -> true
!User.following?(follower, user) -> true
true -> false
end
end

View file

@ -117,8 +117,6 @@ def refetch_object(%Object{data: %{"id" => id}} = object) do
# Note: will create a Create activity, which we need internally at the moment.
def fetch_object_from_id(id, options \\ []) do
with %URI{} = uri <- URI.parse(id),
# let's check the URI is even vaguely valid first
{:scheme, true} <- {:scheme, uri.scheme == "http" or uri.scheme == "https"},
# If we have instance restrictions, apply them here to prevent fetching from unwanted instances
{:ok, nil} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_reject(uri),
{:ok, _} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_accept(uri),
@ -137,9 +135,6 @@ def fetch_object_from_id(id, options \\ []) do
{:allowed_depth, false} ->
{:error, "Max thread distance exceeded."}
{:scheme, false} ->
{:error, "URI Scheme Invalid"}
{:containment, _} ->
{:error, "Object containment failed."}

View file

@ -129,10 +129,7 @@ def make_update_object_data(original_data, new_data, date) do
else
%{updated_object: updated_data} =
updated_data
|> maybe_update_history(original_data,
updated: updated,
use_history_in_new_object?: false
)
|> maybe_update_history(original_data, updated: updated, use_history_in_new_object?: false)
updated_data
|> Map.put("updated", date)

View file

@ -76,6 +76,6 @@ def sign(%User{keys: keys} = user, headers) do
def signed_date, do: signed_date(NaiveDateTime.utc_now())
def signed_date(%NaiveDateTime{} = date) do
Timex.lformat!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT", "en")
Timex.format!(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT")
end
end

View file

@ -63,9 +63,6 @@ defmodule Pleroma.Upload do
blurhash: String.t(),
path: String.t()
}
@always_enabled_filters [Pleroma.Upload.Filter.AnonymizeFilename]
defstruct [:id, :name, :tempfile, :content_type, :width, :height, :blurhash, :path]
@spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()}
@ -135,11 +132,7 @@ defp get_opts(opts) do
activity_type: Keyword.get(opts, :activity_type, activity_type),
size_limit: Keyword.get(opts, :size_limit, size_limit),
uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
filters:
Enum.uniq(
Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])) ++
@always_enabled_filters
),
filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
description: Keyword.get(opts, :description),
base_url: base_url()
}

View file

@ -38,9 +38,9 @@ def filter([filter | rest], upload) do
{:ok, :noop} ->
filter(rest, upload)
{:error, e} ->
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(e)}")
{:error, e}
error ->
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(error)}")
error
end
end
end

View file

@ -28,7 +28,7 @@ def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload)
{:ok, :filtered, upload}
rescue
e in ErlangError ->
Logger.warning("#{__MODULE__}: #{inspect(e)}")
Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end
@ -45,7 +45,7 @@ def filter(%Pleroma.Upload{tempfile: file, content_type: "video" <> _} = upload)
{:ok, :filtered, upload}
rescue
e in ErlangError ->
Logger.warning("#{__MODULE__}: #{inspect(e)}")
Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop}
end
end

View file

@ -1,20 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.OnlyMedia do
@behaviour Pleroma.Upload.Filter
alias Pleroma.Upload
def filter(%Upload{content_type: content_type}) do
[type, _subtype] = String.split(content_type, "/")
if type in ["image", "video", "audio"] do
{:ok, :noop}
else
{:error, "Disallowed content-type: #{content_type}"}
end
end
def filter(_), do: {:ok, :noop}
end

View file

@ -44,8 +44,6 @@ defmodule Pleroma.User do
alias Pleroma.Web.RelMe
alias Pleroma.Workers.BackgroundWorker
use Pleroma.Web, :verified_routes
require Logger
@type t :: %__MODULE__{}
@ -878,7 +876,7 @@ def post_register_action(%User{is_approved: true, is_confirmed: true} = user) do
end
end
defp send_user_approval_email(%User{email: email} = user) when is_binary(email) do
defp send_user_approval_email(user) do
user
|> Pleroma.Emails.UserEmail.approval_pending_email()
|> Pleroma.Emails.Mailer.deliver_async()
@ -886,10 +884,6 @@ defp send_user_approval_email(%User{email: email} = user) when is_binary(email)
{:ok, :enqueued}
end
defp send_user_approval_email(_user) do
{:ok, :skipped}
end
defp send_admin_approval_emails(user) do
all_superusers()
|> Enum.filter(fn user -> not is_nil(user.email) end)
@ -1495,7 +1489,7 @@ def unmute(muter_id, mutee_id) do
unmute(muter, mutee)
else
{who, result} = error ->
Logger.warning(
Logger.warn(
"User.unmute/2 failed. #{who}: #{result}, muter_id: #{muter_id}, mutee_id: #{mutee_id}"
)
@ -1605,13 +1599,9 @@ def blocks_user?(%User{} = user, %User{} = target) do
def blocks_user?(_, _), do: false
def blocks_domain?(%User{} = user, %User{} = target) do
domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks)
%{host: host} = URI.parse(target.ap_id)
Enum.member?(user.domain_blocks, host)
# TODO: functionality should probably be changed such that subdomains block as well,
# but as it stands, this just hecks up the relationships endpoint
# domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks)
# %{host: host} = URI.parse(target.ap_id)
# Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host)
Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host)
end
def blocks_domain?(_, _), do: false
@ -2016,6 +2006,7 @@ defp create_service_actor(uri, nickname) do
%User{
invisible: true,
local: true,
actor_type: "Application",
ap_id: uri,
nickname: nickname,
follower_address: uri <> "/followers"
@ -2453,7 +2444,12 @@ defp validate_rel_me_field(changeset, fields, raw_fields, %User{
end
if is_url(raw_value) do
frontend_url = url(~p[/#{nickname}])
frontend_url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:redirector_with_meta,
nickname
)
possible_urls = [ap_id, frontend_url]

View file

@ -119,7 +119,7 @@ def process(%__MODULE__{} = backup) do
end
end
@files [~c"actor.json", ~c"outbox.json", ~c"likes.json", ~c"bookmarks.json"]
@files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json']
def export(%__MODULE__{} = backup) do
backup = Repo.preload(backup, :user)
name = String.trim_trailing(backup.file_name, ".zip")

View file

@ -27,7 +27,6 @@ defmodule Pleroma.Web do
alias Pleroma.Web.Plugs.ExpectPublicOrAuthenticatedCheckPlug
alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.PlugHelper
require Pleroma.Constants
def controller do
quote do
@ -38,7 +37,7 @@ def controller do
import Pleroma.Web.Gettext
import Pleroma.Web.TranslationHelpers
unquote(verified_routes())
alias Pleroma.Web.Router.Helpers, as: Routes
plug(:set_put_layout)
@ -185,10 +184,7 @@ def view do
# Import convenience functions from controllers
import Phoenix.Controller,
only: [view_module: 1, view_template: 1]
import Phoenix.Flash
alias Phoenix.Flash
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
@ -222,7 +218,7 @@ def component do
def router do
quote do
use Phoenix.Router, helpers: false
use Phoenix.Router
import Plug.Conn
import Phoenix.Controller
@ -250,24 +246,7 @@ defp view_helpers do
import Pleroma.Web.ErrorHelpers
import Pleroma.Web.Gettext
unquote(verified_routes())
end
end
def static_paths, do: Pleroma.Constants.static_only_files()
def verified_routes do
quote do
use Phoenix.VerifiedRoutes,
endpoint: Pleroma.Web.Endpoint,
router: Pleroma.Web.Router,
statics: Pleroma.Web.static_paths()
end
end
def mailer do
quote do
unquote(verified_routes())
alias Pleroma.Web.Router.Helpers, as: Routes
end
end

View file

@ -1792,11 +1792,6 @@ def pin_data_from_featured_collection(
end)
end
def pin_data_from_featured_collection(obj) do
Logger.error("Could not parse featured collection #{inspect(obj)}")
%{}
end
def fetch_and_prepare_featured_from_ap_id(nil) do
{:ok, %{}}
end

View file

@ -454,7 +454,7 @@ def update_outbox(
|> json(message)
e ->
Logger.warning(fn -> "AP C2S: #{inspect(e)}" end)
Logger.warn(fn -> "AP C2S: #{inspect(e)}" end)
conn
|> put_status(:bad_request)

View file

@ -18,8 +18,6 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.CommonAPI.ActivityDraft
alias Pleroma.Web.Endpoint
use Pleroma.Web, :verified_routes
require Pleroma.Constants
def accept_or_reject(actor, activity, type) do
@ -404,6 +402,6 @@ def unpin(%User{} = user, object) do
end
defp pinned_url(nickname) when is_binary(nickname) do
url(~p[/users/#{nickname}/collections/featured])
Pleroma.Web.Router.Helpers.activity_pub_url(Pleroma.Web.Endpoint, :pinned, nickname)
end
end

View file

@ -70,8 +70,6 @@ def filter_one(policy, %{"type" => type} = message)
end
def filter_one(policy, message) do
Code.ensure_loaded!(policy)
should_plug_history? =
if function_exported?(policy, :history_awareness, 0) do
policy.history_awareness()
@ -241,7 +239,7 @@ def config_descriptions(policies) do
if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
[description | acc]
else
Logger.warning(
Logger.warn(
"#{policy} config description doesn't have one or all required keys #{inspect(@required_description_keys)}"
)

View file

@ -41,7 +41,7 @@ defp steal_emoji({shortcode, url}, emoji_dir_path) do
shortcode
e ->
Logger.warning("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
Logger.warn("MRF.StealEmojiPolicy: Failed to write to #{file_path}: #{inspect(e)}")
nil
end
else
@ -53,7 +53,7 @@ defp steal_emoji({shortcode, url}, emoji_dir_path) do
end
else
e ->
Logger.warning("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
nil
end
end

View file

@ -14,7 +14,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
import Ecto.Changeset
require Logger
require Pleroma.Web.ActivityPub.Transmogrifier
@primary_key false
@derive Jason.Encoder

View file

@ -22,10 +22,7 @@ def cast_and_filter_recipients(message, field, follower_collection, field_fallba
end
def fix_object_defaults(data) do
context =
Utils.maybe_create_context(
data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]
)
context = Utils.maybe_create_context(data["context"] || data["conversation"])
%User{follower_address: follower_collection} = User.get_cached_by_ap_id(data["attributedTo"])

View file

@ -115,18 +115,13 @@ defp allowed_instances do
def should_federate?(url) do
%{host: host} = URI.parse(url)
with {nil, false} <- {nil, is_nil(host)},
allowed <- allowed_instances(),
with allowed <- allowed_instances(),
false <- Enum.empty?(allowed) do
allowed
|> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples()
|> Pleroma.Web.ActivityPub.MRF.subdomains_regex()
|> Pleroma.Web.ActivityPub.MRF.subdomain_match?(host)
else
# oi!
{nil, true} ->
false
_ ->
quarantined_instances =
blocked_instances()

View file

@ -136,7 +136,7 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
|> Map.drop(["conversation", "inReplyToAtomUri"])
else
e ->
Logger.warning("Couldn't fetch reply@#{inspect(in_reply_to_id)}, error: #{inspect(e)}")
Logger.warn("Couldn't fetch reply@#{inspect(in_reply_to_id)}, error: #{inspect(e)}")
object
end
else
@ -159,7 +159,7 @@ def fix_quote_url(%{"quoteUri" => quote_url} = object, options)
|> Map.put("quoteUri", quoted_object.data["id"])
else
e ->
Logger.warning("Couldn't fetch quote@#{inspect(quote_url)}, error: #{inspect(e)}")
Logger.warn("Couldn't fetch quote@#{inspect(quote_url)}, error: #{inspect(e)}")
object
end
else
@ -920,13 +920,8 @@ def add_attributed_to(object) do
def prepare_attachments(object) do
attachments =
case Map.get(object, "attachment", []) do
[_ | _] = list -> list
_ -> []
end
attachments =
attachments
object
|> Map.get("attachment", [])
|> Enum.map(fn data ->
[%{"mediaType" => media_type, "href" => href} = url | _] = data["url"]

View file

@ -16,11 +16,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers
import Ecto.Query
use Pleroma.Web, :verified_routes
require Logger
require Pleroma.Constants
@ -125,15 +124,19 @@ def make_date do
end
def generate_activity_id do
url(~p[/activities/#{UUID.generate()}])
generate_id("activities")
end
def generate_context_id do
url(~p[/contexts/#{UUID.generate()}])
generate_id("contexts")
end
def generate_object_id do
url(~p[/objects/#{UUID.generate()}])
Helpers.o_status_url(Endpoint, :object, UUID.generate())
end
def generate_id(type) do
"#{Endpoint.url()}/#{type}/#{UUID.generate()}"
end
def get_notified_from_object(%{"type" => type} = object) when type in @supported_object_types do
@ -151,7 +154,7 @@ def get_notified_from_object(object) do
Notification.get_notified_from_activity(%Activity{data: object}, false)
end
def maybe_create_context(context), do: context || generate_context_id()
def maybe_create_context(context), do: context || generate_id("contexts")
@doc """
Enqueues an activity for federation if it's local

View file

@ -12,22 +12,22 @@ defmodule Pleroma.Web.ActivityPub.UserView do
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
require Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers
import Ecto.Query
def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do
%{"sharedInbox" => url(~p"/inbox")}
%{"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)}
end
def render("endpoints.json", %{user: %User{local: true} = _user}) do
%{
"oauthAuthorizationEndpoint" => url(~p"/oauth/authorize"),
"oauthRegistrationEndpoint" => url(~p"/api/v1/apps"),
"oauthTokenEndpoint" => url(~p"/oauth/token"),
"sharedInbox" => url(~p"/inbox"),
"uploadMedia" => url(~p"/api/ap/upload_media")
"oauthAuthorizationEndpoint" => Helpers.o_auth_url(Endpoint, :authorize),
"oauthRegistrationEndpoint" => Helpers.app_url(Endpoint, :create),
"oauthTokenEndpoint" => Helpers.o_auth_url(Endpoint, :token_exchange),
"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox),
"uploadMedia" => Helpers.activity_pub_url(Endpoint, :upload_media)
}
end

View file

@ -17,7 +17,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.AdminAPI.ModerationLogView
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Router
@users_page_size 50
@ -254,7 +256,7 @@ def get_password_reset(conn, %{"nickname" => nickname}) do
conn
|> json(%{
token: token.token,
link: url(~p[/api/v1/pleroma/password_reset/#{token.token}])
link: Router.Helpers.reset_password_url(Endpoint, :reset, token.token)
})
end

View file

@ -410,7 +410,7 @@ def blocks_operation do
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
parameters: [with_relationships_param() | pagination_params()],
parameters: pagination_params(),
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
@ -451,20 +451,6 @@ def endorsements_operation do
}
end
def preferences_operation do
%Operation{
tags: ["Account Preferences"],
description: "Preferences defined by the user in their account settings.",
summary: "Preferred common behaviors to be shared across clients.",
operationId: "AccountController.preferences",
security: [%{"oAuth" => ["read:accounts"]}],
responses: %{
200 => Operation.response("Preferences", "application/json", Account),
401 => Operation.response("Error", "application/json", ApiError)
}
}
end
def identity_proofs_operation do
%Operation{
tags: ["Retrieve account information"],

View file

@ -143,7 +143,7 @@ def admin_account do
}
},
tags: %Schema{type: :string},
is_confirmed: %Schema{type: :boolean}
is_confirmed: %Schema{type: :string}
}
}
end

View file

@ -232,7 +232,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
source: %Schema{
nullable: true,
oneOf: [
%Schema{type: :string, example: ~c"plaintext content"},
%Schema{type: :string, example: 'plaintext content'},
%Schema{
type: :object,
properties: %{

View file

@ -110,7 +110,7 @@ defp register_user(connection, base, uid, name) do
}
params =
case List.keyfind(attributes, ~c"mail", 0) do
case List.keyfind(attributes, 'mail', 0) do
{_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
_ -> params
end

View file

@ -88,7 +88,7 @@ def reject_follow_request(follower, followed) do
def delete(activity_id, user) do
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
{:find_activity, Activity.get_by_id(activity_id, filter: [])},
{:find_activity, Activity.get_by_id(activity_id)},
{_, %Object{} = object, _} <-
{:find_object, Object.normalize(activity, fetch: false), activity},
true <- User.superuser?(user) || user.ap_id == object.data["actor"],
@ -467,7 +467,7 @@ def remove_mute(user_id, activity_id) do
remove_mute(user, activity)
else
{what, result} = error ->
Logger.warning(
Logger.warn(
"CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{activity_id}"
)

View file

@ -144,8 +144,6 @@ def make_poll_data(%{poll: %{options: options, expires_in: expires_in}} = data)
when is_list(options) do
limits = Config.get([:instance, :poll_limits])
options = options |> Enum.uniq()
with :ok <- validate_poll_expiration(expires_in, limits),
:ok <- validate_poll_options_amount(options, limits),
:ok <- validate_poll_options_length(options, limits) do
@ -181,15 +179,10 @@ def make_poll_data(_data) do
end
defp validate_poll_options_amount(options, %{max_options: max_options}) do
cond do
Enum.count(options) < 2 ->
{:error, "Poll must contain at least 2 options"}
Enum.count(options) > max_options ->
{:error, "Poll can't contain more than #{max_options} options"}
true ->
:ok
if Enum.count(options) > max_options do
{:error, "Poll can't contain more than #{max_options} options"}
else
:ok
end
end
@ -324,13 +317,13 @@ def date_to_asctime(date) when is_binary(date) do
format_asctime(date)
else
_e ->
Logger.warning("Date #{date} in wrong format, must be ISO 8601")
Logger.warn("Date #{date} in wrong format, must be ISO 8601")
""
end
end
def date_to_asctime(date) do
Logger.warning("Date #{date} in wrong format, must be ISO 8601")
Logger.warn("Date #{date} in wrong format, must be ISO 8601")
""
end

View file

@ -11,31 +11,22 @@ defmodule Pleroma.Web.EmbedController do
alias Pleroma.Web.ActivityPub.Visibility
plug(:put_layout, :embed)
def show(conn, %{"id" => id}) do
with {:activity, %Activity{} = activity} <-
{:activity, Activity.get_by_id_with_object(id)},
{:local, true} <- {:local, activity.local},
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, nil)} do
with %Activity{local: true} = activity <-
Activity.get_by_id_with_object(id),
true <- Visibility.is_public?(activity.object) do
{:ok, author} = User.get_or_fetch(activity.object.data["actor"])
conn
|> delete_resp_header("x-frame-options")
|> delete_resp_header("content-security-policy")
|> put_view(Pleroma.Web.EmbedView)
|> render("show.html",
activity: activity,
author: User.sanitize_html(author),
counts: get_counts(activity)
)
else
{:activity, _} ->
render_error(conn, :not_found, "Post not found")
{:local, false} ->
render_error(conn, :unauthorized, "Federated posts cannot be embedded")
{:visible, false} ->
render_error(conn, :unauthorized, "Not authorized to view this post")
end
end

View file

@ -97,7 +97,7 @@ defmodule Pleroma.Web.Endpoint do
Plug.Static,
at: "/",
from: :pleroma,
only: Pleroma.Web.static_paths(),
only: Pleroma.Constants.static_only_files(),
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
gzip: true,
cache_control_for_etags: @static_cache_control,

View file

@ -30,7 +30,7 @@ def feed_redirect(%{assigns: %{format: format}} = conn, _params)
def feed_redirect(conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
redirect(conn, external: "#{url(~p"/users/#{user.nickname}/feed")}.atom")
redirect(conn, external: "#{Routes.user_feed_url(conn, :feed, user.nickname)}.atom")
end
end

View file

@ -34,9 +34,9 @@ def index(conn, _params) do
index =
if flavour == "fedibird-fe" do
"fedibird.html"
"fedibird.index.html"
else
"glitchsoc.html"
"glitchsoc.index.html"
end
conn

View file

@ -51,7 +51,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(
OAuthScopesPlug,
%{scopes: ["read:accounts"]}
when action in [:verify_credentials, :endorsements, :identity_proofs, :preferences]
when action in [:verify_credentials, :endorsements, :identity_proofs]
)
plug(
@ -497,7 +497,7 @@ def mutes(%{assigns: %{user: user}} = conn, params) do
users =
user
|> User.muted_users_relation(_restrict_deactivated = true)
|> Pleroma.Pagination.fetch_paginated(params)
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
conn
|> add_link_headers(users)
@ -514,16 +514,11 @@ def blocks(%{assigns: %{user: user}} = conn, params) do
users =
user
|> User.blocked_users_relation(_restrict_deactivated = true)
|> Pleroma.Pagination.fetch_paginated(params)
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
conn
|> add_link_headers(users)
|> render("index.json",
users: users,
for: user,
as: :user,
embed_relationships: embed_relationships?(params)
)
|> render("index.json", users: users, for: user, as: :user)
end
@doc "GET /api/v1/accounts/lookup"
@ -544,9 +539,4 @@ def endorsements(conn, params), do: MastodonAPIController.empty_array(conn, para
@doc "GET /api/v1/identity_proofs"
def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
@doc "GET /api/v1/preferences"
def preferences(%{assigns: %{user: user}} = conn, _params) do
render(conn, "preferences.json", user: user)
end
end

View file

@ -54,7 +54,12 @@ def login(conn, params) do
defp redirect_to_oauth_form(conn, _params) do
with {:ok, app} <- local_mastofe_app() do
path =
~p[/oauth/authorize?#{[response_type: "code", client_id: app.client_id, redirect_uri: ".", scope: Enum.join(app.scopes, " ")]}]
Routes.o_auth_path(conn, :authorize,
response_type: "code",
client_id: app.client_id,
redirect_uri: ".",
scope: Enum.join(app.scopes, " ")
)
redirect(conn, to: path)
end
@ -86,7 +91,7 @@ def password_reset(conn, params) do
defp local_mastodon_post_login_path(conn) do
case get_session(conn, :return_to) do
nil ->
~p"/web/getting-started"
Routes.masto_fe_path(conn, :index, ["getting-started"])
return_to ->
delete_session(conn, :return_to)

View file

@ -190,17 +190,6 @@ def render("instance.json", %{instance: %Pleroma.Instances.Instance{} = instance
def render("instance.json", _), do: nil
def render("preferences.json", %{user: user} = _opts) do
# TODO: Do we expose more settings that make sense to plug in here?
%{
"posting:default:visibility": user.default_scope,
"posting:default:sensitive": false,
"posting:default:language": nil,
"reading:expand:media": "default",
"reading:expand:spoilers": false
}
end
defp do_render("show.json", %{user: user} = opts) do
user = User.sanitize_html(user, User.html_filter_policy(opts[:for]))
display_name = user.name || user.nickname

View file

@ -322,7 +322,7 @@ def render("show.json", %{activity: %{id: id, data: %{"object" => _object}} = ac
url =
if user.local do
url(~p[/notice/#{activity}])
Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity)
else
object.data["url"] || object.data["external_url"] || object.data["id"]
end

View file

@ -1,6 +1,7 @@
defmodule Pleroma.Web.MastodonAPI.TagView do
use Pleroma.Web, :view
alias Pleroma.User
alias Pleroma.Web.Router.Helpers
def render("index.json", %{tags: tags, for_user: user}) do
render_many(tags, __MODULE__, "show.json", %{for_user: user})
@ -16,7 +17,7 @@ def render("show.json", %{tag: tag, for_user: user}) do
%{
name: tag.name,
url: url(~p[/tags/#{tag.name}]),
url: Helpers.tag_feed_url(Pleroma.Web.Endpoint, :feed, tag.name),
history: [],
following: following
}

View file

@ -52,7 +52,7 @@ def url(url) do
@spec url_proxiable?(String.t()) :: boolean()
def url_proxiable?(url) do
not local?(url) and not whitelisted?(url) and not blocked?(url)
not local?(url) and not whitelisted?(url)
end
def preview_url(url, preview_params \\ []) do
@ -76,23 +76,13 @@ def whitelisted?(url) do
mediaproxy_whitelist_domains =
[:media_proxy, :whitelist]
|> Config.get([])
|> Config.get()
|> Kernel.++(["#{Upload.base_url()}"])
|> Enum.map(&maybe_get_domain_from_url/1)
domain in mediaproxy_whitelist_domains
end
def blocked?(url) do
%{scheme: scheme, host: domain} = URI.parse(url)
# Block either the bare domain or the scheme-domain combo
scheme_domain = "#{scheme}://#{domain}"
blocklist = Config.get([:media_proxy, :blocklist])
Enum.member?(blocklist, domain) ||
Enum.member?(blocklist, scheme_domain)
end
defp maybe_get_domain_from_url("http" <> _ = url) do
URI.parse(url).host
end

View file

@ -3,9 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Metadata.Providers.Feed do
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Metadata.Providers.Provider
use Pleroma.Web, :verified_routes
alias Pleroma.Web.Router.Helpers
@behaviour Provider
@ -16,7 +16,7 @@ def build_tags(%{user: user}) do
[
rel: "alternate",
type: "application/atom+xml",
href: ~p[/users/#{user.nickname}/feed.atom]
href: Helpers.user_feed_path(Endpoint, :feed, user.nickname) <> ".atom"
], []}
]
end

View file

@ -8,20 +8,12 @@ defmodule Pleroma.Web.Metadata.Providers.RelMe do
@impl Provider
def build_tags(%{user: user}) do
profile_tree =
user.bio
|> append_fields_tag(user.fields)
|> Floki.parse_fragment!()
bio_tree = Floki.parse_fragment!(user.bio)
(Floki.attribute(profile_tree, "link[rel~=me]", "href") ++
Floki.attribute(profile_tree, "a[rel~=me]", "href"))
(Floki.attribute(bio_tree, "link[rel~=me]", "href") ++
Floki.attribute(bio_tree, "a[rel~=me]", "href"))
|> Enum.map(fn link ->
{:link, [rel: "me", href: link], []}
end)
end
defp append_fields_tag(bio, fields) do
fields
|> Enum.reduce(bio, fn %{"value" => v}, res -> res <> v end)
end
end

View file

@ -10,8 +10,6 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
alias Pleroma.Web.Metadata.Providers.Provider
alias Pleroma.Web.Metadata.Utils
use Pleroma.Web, :verified_routes
@behaviour Provider
@media_types ["image", "audio", "video"]
@ -22,12 +20,12 @@ def build_tags(%{activity_id: id, object: object, user: user}) do
[
title_tag(user),
{:meta, [name: "twitter:description", content: scrubbed_content], []}
{:meta, [property: "twitter:description", content: scrubbed_content], []}
] ++
if attachments == [] or Metadata.activity_nsfw?(object) do
[
image_tag(user),
{:meta, [name: "twitter:card", content: "summary"], []}
{:meta, [property: "twitter:card", content: "summary"], []}
]
else
attachments
@ -39,19 +37,20 @@ def build_tags(%{user: user}) do
with truncated_bio = Utils.scrub_html_and_truncate(user.bio) do
[
title_tag(user),
{:meta, [name: "twitter:description", content: truncated_bio], []},
{:meta, [property: "twitter:description", content: truncated_bio], []},
image_tag(user),
{:meta, [name: "twitter:card", content: "summary"], []}
{:meta, [property: "twitter:card", content: "summary"], []}
]
end
end
defp title_tag(user) do
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []}
{:meta, [property: "twitter:title", content: Utils.user_name_string(user)], []}
end
def image_tag(user) do
{:meta, [name: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))], []}
{:meta, [property: "twitter:image", content: MediaProxy.preview_url(User.avatar_url(user))],
[]}
end
defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
@ -61,10 +60,10 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
case Utils.fetch_media_type(@media_types, url["mediaType"]) do
"audio" ->
[
{:meta, [name: "twitter:card", content: "player"], []},
{:meta, [name: "twitter:player:width", content: "480"], []},
{:meta, [name: "twitter:player:height", content: "80"], []},
{:meta, [name: "twitter:player", content: player_url(id)], []}
{:meta, [property: "twitter:card", content: "player"], []},
{:meta, [property: "twitter:player:width", content: "480"], []},
{:meta, [property: "twitter:player:height", content: "80"], []},
{:meta, [property: "twitter:player", content: player_url(id)], []}
| acc
]
@ -75,10 +74,10 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
# workaround.
"image" ->
[
{:meta, [name: "twitter:card", content: "summary_large_image"], []},
{:meta, [property: "twitter:card", content: "summary_large_image"], []},
{:meta,
[
name: "twitter:player",
property: "twitter:player",
content: MediaProxy.url(url["href"])
], []}
| acc
@ -91,14 +90,14 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
width = url["width"] || 480
[
{:meta, [name: "twitter:card", content: "player"], []},
{:meta, [name: "twitter:player", content: player_url(id)], []},
{:meta, [name: "twitter:player:width", content: "#{width}"], []},
{:meta, [name: "twitter:player:height", content: "#{height}"], []},
{:meta, [name: "twitter:player:stream", content: MediaProxy.url(url["href"])],
{:meta, [property: "twitter:card", content: "player"], []},
{:meta, [property: "twitter:player", content: player_url(id)], []},
{:meta, [property: "twitter:player:width", content: "#{width}"], []},
{:meta, [property: "twitter:player:height", content: "#{height}"], []},
{:meta, [property: "twitter:player:stream", content: MediaProxy.url(url["href"])],
[]},
{:meta, [name: "twitter:player:stream:content_type", content: url["mediaType"]],
[]}
{:meta,
[property: "twitter:player:stream:content_type", content: url["mediaType"]], []}
| acc
]
@ -114,7 +113,7 @@ defp build_attachments(id, %{data: %{"attachment" => attachments}}) do
defp build_attachments(_id, _object), do: []
defp player_url(id) do
url(~p[/notice/#{id}/embed_player])
Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice_player, id)
end
# Videos have problems without dimensions, but we used to not provide WxH for images.
@ -124,8 +123,8 @@ defp maybe_add_dimensions(metadata, url) do
!is_nil(url["height"]) && !is_nil(url["width"]) ->
metadata ++
[
{:meta, [name: "twitter:player:width", content: "#{url["width"]}"], []},
{:meta, [name: "twitter:player:height", content: "#{url["height"]}"], []}
{:meta, [property: "twitter:player:width", content: "#{url["width"]}"], []},
{:meta, [property: "twitter:player:height", content: "#{url["height"]}"], []}
]
true ->

Some files were not shown because too many files have changed in this diff Show more