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
451 changed files with 8489 additions and 125391 deletions

View file

@ -1,14 +1,3 @@
[ [
import_deps: [:ecto, :ecto_sql, :phoenix], inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/migrations/*.exs", "priv/repo/optional_migrations/**/*.exs", "priv/scrubbers/*.ex"]
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"
]
] ]

View file

@ -1,8 +1,3 @@
platform: linux/amd64
depends_on:
- test
variables: variables:
- &scw-secrets - &scw-secrets
- SCW_ACCESS_KEY - SCW_ACCESS_KEY
@ -17,6 +12,8 @@ variables:
branch: branch:
- develop - develop
- stable - stable
- refs/tags/v*
- refs/tags/stable-*
- &on-stable - &on-stable
when: when:
event: event:
@ -24,6 +21,14 @@ variables:
- tag - tag
branch: branch:
- stable - stable
- refs/tags/stable-*
- &on-point-release
when:
event:
- push
branch:
- develop
- stable
- &on-pr-open - &on-pr-open
when: when:
event: event:
@ -34,10 +39,63 @@ variables:
- &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)" - &clean "(rm -rf release || true) && (rm -rf _build || true) && (rm -rf /root/.mix)"
- &mix-clean "mix deps.clean --all && mix clean" - &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: 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 # Canonical amd64
debian-bookworm: ubuntu22:
image: hexpm/elixir:1.15.4-erlang-26.0.2-debian-bookworm-20230612 image: hexpm/elixir:1.14.3-erlang-25.2.2-ubuntu-jammy-20221130
<<: *on-release <<: *on-release
environment: environment:
MIX_ENV: prod MIX_ENV: prod
@ -50,51 +108,51 @@ pipeline:
- *tag-build - *tag-build
- mix deps.get --only prod - mix deps.get --only prod
- mix release --path release - 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 - zip akkoma-amd64.zip -r release
release-debian-bookworm: release-debian:
image: akkoma/releaser image: akkoma/releaser
<<: *on-release <<: *on-release
secrets: *scw-secrets secrets: *scw-secrets
commands: commands:
- export SOURCE=akkoma-amd64.zip - export SOURCE=akkoma-amd64.zip
# AMD64
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64.zip
- /bin/sh /entrypoint.sh - /bin/sh /entrypoint.sh
# Ubuntu jammy (currently compatible) - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-debian-stable.zip
- 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
- /bin/sh /entrypoint.sh - /bin/sh /entrypoint.sh
# Canonical amd64-musl # Canonical amd64-musl
musl: musl:
image: hexpm/elixir:1.15.4-erlang-26.0.2-alpine-3.18.2 image: hexpm/elixir:1.14.3-erlang-25.2.2-alpine-3.15.6
<<: *on-stable <<: *on-release
environment: environment:
MIX_ENV: prod MIX_ENV: prod
commands: commands:
@ -109,9 +167,31 @@ pipeline:
release-musl: release-musl:
image: akkoma/releaser image: akkoma/releaser
<<: *on-stable <<: *on-release
secrets: *scw-secrets secrets: *scw-secrets
commands: commands:
- export SOURCE=akkoma-amd64-musl.zip - export SOURCE=akkoma-amd64-musl.zip
- export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip - export DEST=scaleway:akkoma-updates/$${CI_COMMIT_TAG:-"$CI_COMMIT_BRANCH"}/akkoma-amd64-musl.zip
- /bin/sh /entrypoint.sh - /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,64 +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/). 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
## 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 ## 2023.05
## Added ## Added
@ -144,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 - 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 - 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. - 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 ### Fixed
- /api/v1/accounts/lookup will now respect restrict\_unauthenticated - /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 MIX_ENV=prod
ENV ERL_EPMD_ADDRESS=127.0.0.1 ENV ERL_EPMD_ADDRESS=127.0.0.1

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,6 @@ services:
db: db:
image: akkoma-db:latest image: akkoma-db:latest
build: ./docker-resources/database build: ./docker-resources/database
shm_size: 4gb
restart: unless-stopped restart: unless-stopped
user: ${DOCKER_USER} user: ${DOCKER_USER}
environment: { environment: {

View file

@ -1,4 +1,4 @@
#!/bin/sh #!/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) 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) db

View file

@ -1,3 +1,3 @@
#!/bin/sh #!/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`). 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" === "OTP"

View file

@ -62,6 +62,6 @@ mix ecto.migrate
# Start akkoma (replace with your system service manager's equivalent if different) # Start akkoma (replace with your system service manager's equivalent if different)
sudo systemctl start akkoma 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 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. Note: Additional clients may work, but these are known to work with Akkoma.
Apps listed here might not support all of Akkoma's features. 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 ## Desktop
### Whalebird ### Whalebird
- Homepage: <https://whalebird.social/> - Homepage: <https://whalebird.social/>

View file

@ -246,11 +246,11 @@ Notes:
### :frontend_configurations ### :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` 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 ```elixir
config :pleroma, :frontend_configurations, config :pleroma, :frontend_configurations,
@ -615,12 +615,6 @@ This filter only strips the GPS and location metadata with Exiftool leaving colo
No specific configuration. 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 #### Pleroma.Upload.Filter.Mogrify
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`. * `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 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 ### 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 * 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 * If you want to upload a theme to customise it further, you can upload it using Load preset
@ -70,4 +70,4 @@ config :pleroma, :frontend_configurations,
} }
``` ```
If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes. If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes.

View file

@ -25,7 +25,6 @@ Home, public, hashtag & list timelines accept these parameters:
## Statuses ## Statuses
- `visibility`: has additional possible values `list` and `local` (for local-only 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: 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` - `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 - `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
- `thread_muted`: true if the thread the post belongs to is muted - `thread_muted`: true if the thread the post belongs to is muted
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 2, me: true, account_ids: ["UserID1", "UserID2"]}`. - `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.
The `account_ids` property was added in Akkoma 3.2.0.
Further info about all reacting users at once, can be found using the `/statuses/:id/reactions` endpoint.
- `parent_visible`: If the parent of this post is visible to the user or not. - `parent_visible`: If the parent of this post is visible to the user or not.
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise. - `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
@ -217,11 +214,6 @@ Returns: array of Status.
The maximum number of statuses is limited to 100 per request. The maximum number of statuses is limited to 100 per request.
## 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` ## PATCH `/api/v1/accounts/update_credentials`
Additional parameters can be added to the JSON body/Form data: Additional parameters can be added to the JSON body/Form data:

View file

@ -3,7 +3,7 @@
# Introduction to Akkoma # Introduction to Akkoma
## What is 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. 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. 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! 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? ## 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) 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 ### Pleroma-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/). 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 ### 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! 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. 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 ## 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 !} {! installation/generic_dependencies.include !}
@ -23,67 +23,15 @@ sudo apt full-upgrade
sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev 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 ### 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 ```shell
sudo apt update
sudo apt install elixir erlang-dev erlang-nox 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) ### 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 ### 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 ```shell
sudo mkdir -p /opt/akkoma 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 ### Prepare the system
* Install docker and docker compose * Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/) * [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/) * [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation. * 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 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 ### 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 We need to run a few commands on the database container, this isn't too bad
```bash ```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 # 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 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. everything start up.
```bash ```bash
docker compose up docker-compose up
``` ```
If everything went well, you should be able to access your instance at http://localhost:4000 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 ### Running in the background
```bash ```bash
docker compose up -d docker-compose up -d
``` ```
### Create your first user ### 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. Then edit the TLD in your caddyfile to the domain you're serving on.
Uncomment the `caddy` section in the docker compose file, Uncomment the `caddy` section in the docker-compose file,
then run `docker compose up -d` again. then run `docker-compose up -d` again.
#### Running a reverse proxy on the host #### 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 deps.get
./docker-resources/manage.sh mix compile ./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix ecto.migrate ./docker-resources/manage.sh mix ecto.migrate
docker compose restart akkoma db docker-compose restart akkoma db
``` ```
#### Further reading #### Further reading

View file

@ -2,7 +2,7 @@
* PostgreSQL 9.6+ * PostgreSQL 9.6+
* Elixir 1.14+ * Elixir 1.14+
* Erlang OTP 25+ * Erlang OTP 24+
* git * git
* file / libmagic * file / libmagic
* gcc (clang might also work) * 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: Please roll back the given migrations:
```bash ```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. Then compile, migrate and restart as usual.
@ -117,16 +117,4 @@ To fix this, run:
mix pleroma.config delete pleroma frontends mix pleroma.config delete pleroma frontends
``` ```
which will remove the config from the database. Things should work now. 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 ### Prepare the system
* Install docker and docker compose * Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/) * [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/) * [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation. * 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 And the same with `uploads`, make sure your uploads (if you have them on disk) are
located at `uploads/` in the akkoma source directory. 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: with an entry that looks like this:
```yaml ```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 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" === "From source"
@ -126,21 +126,21 @@ mkdir pgdata
Now we can import our database to the container. Now we can import our database to the container.
```bash ```bash
docker compose run --rm --user akkoma -d db 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 akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
``` ```
### Reverse proxies ### Reverse proxies
If you're just reusing your old proxy, you may have to uncomment the line in 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). Otherwise, you can use the same setup as the [docker installation guide](./docker_en.md#reverse-proxies).
### Let's go ### Let's go
```bash ```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. 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 # 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: For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
* `ImageMagick` * `ImageMagic`
* `ffmpeg` * `ffmpeg`
* `exiftool` * `exiftool`
Please refer to documentation in `docs/installation` on how to install them on specific OS. 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`
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images. `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`) * `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`) * 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. `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`) * Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `exiftool` ## `exiftool`
`exiftool` is media files metadata reader/writer. `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`) * `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. 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 ## 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. * 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 * 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 ### Detecting flavour
This is a little more complex than it used to be (thanks ubuntu)
Use the following mapping to figure out your flavour: Use the following mapping to figure out your flavour:
| distribution | architecture | flavour | available branches | | distribution | flavour | available branches |
| --------------- | ------------------ | ------------------- | ------------------- | | ------------- | ------------------ | ------------------- |
| debian bookworm | amd64 | amd64 | develop, stable | | debian stable | amd64 | develop, stable |
| debian bookworm | arm64 | arm64 | stable | | ubuntu focal | amd64 | develop, stable |
| ubuntu jammy | amd64 | amd64 | develop, stable | | ubuntu jammy | amd64-ubuntu-jammy | develop, stable |
| ubuntu jammy | arm64 | arm64 | develop, stable | | alpine | amd64-musl | stable |
| alpine | amd64 | amd64-musl | stable |
| alpine | arm64 | arm64-musl | stable |
Other similar distributions will _probably_ work, but if it is not listed above, there is no official Other similar distributions will _probably_ work, but if it is not listed above, there is no official
support. support.
@ -118,12 +118,8 @@ Restart PostgreSQL to apply configuration changes:
adduser --system --shell /bin/false --home /opt/akkoma akkoma adduser --system --shell /bin/false --home /opt/akkoma akkoma
# Set the flavour environment variable to the string you got in Detecting flavour section. # 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 # For example if the flavour is `amd64` the command will be
# export FLAVOUR="amd64-musl" export FLAVOUR="amd64"
export FLAVOUR="<replace-this-with-the-correct-flavour-string>"
# Make sure the SHELL variable is set
export SHELL="${SHELL:-/bin/sh}"
# Clone the release build into a temporary directory and unpack it # Clone the release build into a temporary directory and unpack it
su akkoma -s $SHELL -lc " su akkoma -s $SHELL -lc "
@ -187,18 +183,18 @@ The location of nginx configs is dependent on the distro
=== "Alpine" === "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" === "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 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 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 ```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 #### 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 #### Copy Akkoma nginx configuration to the nginx folder
```shell ```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 #### Edit the nginx config

View file

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

View file

@ -8,8 +8,6 @@ Restart=on-failure
; Uncomment this if you're on Arch Linux ; 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" ; 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. ; Name of the user that runs the Akkoma service.
User=akkoma User=akkoma
@ -26,8 +24,6 @@ Environment="HOME=/var/lib/akkoma"
WorkingDirectory=/opt/akkoma WorkingDirectory=/opt/akkoma
; Path to the Mix binary. ; Path to the Mix binary.
ExecStart=/usr/bin/mix phx.server 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. ; Some security directives.
; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops. ; 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 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. ; 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 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. ; Drops the sysadmin capability from the daemon.
CapabilityBoundingSet=~CAP_SYS_ADMIN CapabilityBoundingSet=~CAP_SYS_ADMIN

View file

@ -4,9 +4,6 @@
# 1. Replace 'example.tld' with your instance's domain wherever it appears. # 1. Replace 'example.tld' with your instance's domain wherever it appears.
# 2. Copy this section into your Caddyfile and restart Caddy. # 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 { example.tld {
log { log {
output file /var/log/caddy/akkoma.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 # this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
# and `localhost.` resolves to [::0] on some systems: see issue #930 # and `localhost.` resolves to [::0] on some systems: see issue #930
reverse_proxy 127.0.0.1:4000 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 directory=/opt/akkoma
healthcheck_delay=60 healthcheck_delay=60
healthcheck_timer=30 healthcheck_timer=30
no_new_privs="yes"
: ${akkoma_port:-4000} : ${akkoma_port:-4000}

View file

@ -359,7 +359,7 @@ def run(["set_text_search_config", tsconfig]) do
) )
end end
shell_info(~c"Done.") shell_info('Done.')
end end
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)) File.write!(Path.join(pack_path, "pack.json"), Jason.encode!(pack_json, pretty: true))
Pleroma.Emoji.reload()
else else
IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"])) IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
end end
@ -236,8 +235,6 @@ def run(["gen-pack" | args]) do
IO.puts("#{pack_file} has been created with the #{name} pack") IO.puts("#{pack_file} has been created with the #{name} pack")
end end
Pleroma.Emoji.reload()
end end
def run(["reload"]) do def run(["reload"]) do

View file

@ -247,22 +247,16 @@ def run(["gen" | rest]) do
config_dir = Path.dirname(config_path) config_dir = Path.dirname(config_path)
psql_dir = Path.dirname(psql_path) psql_dir = Path.dirname(psql_path)
# Note: Distros requiring group read (0o750) on those directories should
# pre-create the directories.
to_create = to_create =
[config_dir, psql_dir, static_dir, uploads_dir] [config_dir, psql_dir, static_dir, uploads_dir]
|> Enum.reject(&File.exists?/1) |> Enum.reject(&File.exists?/1)
for dir <- to_create do for dir <- to_create do
File.mkdir_p!(dir) File.mkdir_p!(dir)
File.chmod!(dir, 0o700)
end end
shell_info("Writing config to #{config_path}.") 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) File.write(config_path, result_config)
shell_info("Writing the postgres script to #{psql_path}.") shell_info("Writing the postgres script to #{psql_path}.")
File.write(psql_path, result_psql) File.write(psql_path, result_psql)
@ -281,7 +275,8 @@ def run(["gen" | rest]) do
else else
shell_error( shell_error(
"The task would have overwritten the following files:\n" <> "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
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( meili_put(
"/indexes/objects/settings/ranking-rules", "/indexes/objects/settings/ranking-rules",
[ [
"published:desc",
"words", "words",
"exactness",
"proximity", "proximity",
"typo", "typo",
"exactness",
"attribute", "attribute",
"published:desc",
"sort" "sort"
] ]
) )

View file

@ -11,7 +11,6 @@ defmodule Mix.Tasks.Pleroma.User do
alias Pleroma.UserInviteToken alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.Pipeline
use Pleroma.Web, :verified_routes
@shortdoc "Manages Pleroma users" @shortdoc "Manages Pleroma users"
@moduledoc File.read!("docs/docs/administration/CLI_tasks/user.md") @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 {:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
shell_info("Generated password reset token for #{user.nickname}") 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 else
_ -> _ ->
shell_error("No local user #{nickname}") shell_error("No local user #{nickname}")
@ -300,7 +303,13 @@ def run(["invite" | rest]) do
{:ok, invite} <- UserInviteToken.create_invite(options) do {:ok, invite} <- UserInviteToken.create_invite(options) do
shell_info("Generated user invite token " <> String.replace(invite.invite_type, "_", " ")) 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) IO.puts(url)
else else
error -> error ->

View file

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

View file

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

View file

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

View file

@ -53,7 +53,6 @@ def start(_type, _args) do
Config.DeprecationWarnings.warn() Config.DeprecationWarnings.warn()
Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled() Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled()
Pleroma.ApplicationRequirements.verify!() Pleroma.ApplicationRequirements.verify!()
load_all_pleroma_modules()
load_custom_modules() load_custom_modules()
Pleroma.Docs.JSON.compile() Pleroma.Docs.JSON.compile()
limiters_setup() limiters_setup()
@ -88,7 +87,7 @@ def start(_type, _args) do
# Go for the default 3 unless we're in test # Go for the default 3 unless we're in test
max_restarts = max_restarts =
if @mix_env == :test do if @mix_env == :test do
1000 100
else else
3 3
end end
@ -113,7 +112,7 @@ defp set_postgres_server_version do
num num
else else
e -> e ->
Logger.warning( Logger.warn(
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6" "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
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 defp cachex_children do
[ [
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()), 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) proxy = Pleroma.HTTP.AdapterHelper.format_proxy(proxy_url)
pool_size = Config.get([:http, :pool_size]) pool_size = Config.get([:http, :pool_size])
:public_key.cacerts_load()
config = config =
[:http, :adapter] [:http, :adapter]
|> Config.get([]) |> 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 defp check_welcome_message_config!(:ok) do
if Pleroma.Config.get([:welcome, :email, :enabled], false) and if Pleroma.Config.get([:welcome, :email, :enabled], false) and
not Pleroma.Emails.Mailer.enabled?() do not Pleroma.Emails.Mailer.enabled?() do
Logger.warning(""" Logger.warn("""
To send welcome emails, you need to enable the mailer. To send welcome emails, you need to enable the mailer.
Welcome emails will NOT be sent with the current config. Welcome emails will NOT be sent with the current config.
@ -53,7 +53,7 @@ defp check_welcome_message_config!(result), do: result
def check_confirmation_accounts!(:ok) do def check_confirmation_accounts!(:ok) do
if Pleroma.Config.get([:instance, :account_activation_required]) && if Pleroma.Config.get([:instance, :account_activation_required]) &&
not Pleroma.Emails.Mailer.enabled?() do not Pleroma.Emails.Mailer.enabled?() do
Logger.warning(""" Logger.warn("""
Account activation is required, but the mailer is disabled. Account activation is required, but the mailer is disabled.
Users will NOT be able to confirm their accounts with this config. Users will NOT be able to confirm their accounts with this config.
Either disable account activation or enable the mailer. Either disable account activation or enable the mailer.

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

View file

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

View file

@ -22,20 +22,6 @@ def load(config, opts) do
with_runtime_config = with_runtime_config =
if File.exists?(config_path) do if File.exists?(config_path) do
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
%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) runtime_config = Config.Reader.read!(config_path)
with_defaults 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 defp configure({_, :backends, _, merged}) do
# removing current backends # 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) Enum.each(merged, &Logger.add_backend/1)
@ -149,7 +149,7 @@ defp update({group, key, value, merged}) do
error_msg = error_msg =
"updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}" "updating env causes error, group: #{inspect(group)}, key: #{inspect(key)}, value: #{inspect(value)} error: #{inspect(error)}"
Logger.warning(error_msg) Logger.warn(error_msg)
nil nil
end end
@ -183,12 +183,12 @@ defp restart(started_applications, app, _) do
:ok = Application.start(app) :ok = Application.start(app)
else else
nil -> nil ->
Logger.warning("#{app} is not started.") Logger.warn("#{app} is not started.")
error -> error ->
error error
|> inspect() |> inspect()
|> Logger.warning() |> Logger.warn()
end end
end end

View file

@ -25,7 +25,7 @@ defmodule Pleroma.Constants do
const(static_only_files, const(static_only_files,
do: 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, const(status_updatable_fields,

View file

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

View file

@ -6,11 +6,12 @@ defmodule Pleroma.Emails.UserEmail do
@moduledoc "User emails" @moduledoc "User emails"
require Pleroma.Web.Gettext require Pleroma.Web.Gettext
use Pleroma.Web, :mailer
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Gettext alias Pleroma.Web.Gettext
alias Pleroma.Web.Router
import Swoosh.Email import Swoosh.Email
import Phoenix.Swoosh, except: [render_body: 3] 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 def password_reset_email(user, token) when is_binary(token) do
Gettext.with_locale_or_default user.language 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 = html_body =
Gettext.dpgettext( Gettext.dpgettext(
@ -107,7 +108,12 @@ def user_invitation_email(
to_name \\ nil to_name \\ nil
) do ) do
Gettext.with_locale_or_default user.language 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 = html_body =
Gettext.dpgettext( Gettext.dpgettext(
@ -140,7 +146,13 @@ def user_invitation_email(
def account_confirmation_email(user) do def account_confirmation_email(user) do
Gettext.with_locale_or_default user.language 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 = html_body =
Gettext.dpgettext( Gettext.dpgettext(
@ -330,7 +342,7 @@ def unsubscribe_url(user, notifications_type) do
|> Pleroma.JWT.generate_and_sign!() |> Pleroma.JWT.generate_and_sign!()
|> Base.encode64() |> Base.encode64()
~p[/mailer/unsubscribe/#{token}] Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
end end
def backup_is_ready_email(backup, admin_user_id \\ nil) do def backup_is_ready_email(backup, admin_user_id \\ nil) do

View file

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

View file

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

View file

@ -27,10 +27,10 @@ defmodule Pleroma.HTTP do
nil | {:ok, Env.t()} | {:error, any()} nil | {:ok, Env.t()} | {:error, any()}
def get(url, headers \\ [], options \\ []) def get(url, headers \\ [], options \\ [])
def get(nil, _, _), do: nil 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()} @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 """ @doc """
Performs POST request. Performs POST request.
@ -62,13 +62,6 @@ def request(method, url, body, headers, options) when is_binary(url) do
uri = URI.parse(url) uri = URI.parse(url)
adapter_opts = AdapterHelper.options(uri, options || []) 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) options = put_in(options[:adapter], adapter_opts)
params = options[:params] || [] params = options[:params] || []
request = build_request(method, headers, options, url, body, 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) |> put_in([:pools, :default, :conn_opts, :proxy], proxy)
end 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 def add_pool_size(opts, pool_size) do
opts opts
|> maybe_add_pools() |> maybe_add_pools()
@ -93,16 +82,6 @@ defp maybe_add_conn_opts(opts) do
end end
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 """ @doc """
Merge default connection & adapter options with received ones. 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} {:ok, type, uri.host, uri.port}
else else
e -> e ->
Logger.warning("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}") Logger.warn("Parsing proxy failed #{inspect(proxy)}, #{inspect(e)}")
{:error, :invalid_proxy} {:error, :invalid_proxy}
end end
end end
@ -141,7 +120,7 @@ def parse_proxy(proxy) when is_tuple(proxy) do
{:ok, type, host, port} {:ok, type, host, port}
else else
_ -> _ ->
Logger.warning("Parsing proxy failed #{inspect(proxy)}") Logger.warn("Parsing proxy failed #{inspect(proxy)}")
{:error, :invalid_proxy} {:error, :invalid_proxy}
end end
end end

View file

@ -20,7 +20,7 @@ def vacuum(args) do
"full" -> "full" ->
Logger.info("Running VACUUM 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." "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 -> data_migration.state == :manual or data_migration.name in manual_migrations ->
message = "Data migration is in manual execution or manual fix mode." message = "Data migration is in manual execution or manual fix mode."
update_status(:manual, message) update_status(:manual, message)
Logger.warning("#{__MODULE__}: #{message}") Logger.warn("#{__MODULE__}: #{message}")
data_migration.state == :complete -> data_migration.state == :complete ->
on_complete(data_migration) 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`. 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) update_status(:manual, message)
on_complete(data_migration()) on_complete(data_migration())
@ -125,7 +125,7 @@ def handle_info(:perform, state) do
defp on_complete(data_migration) do defp on_complete(data_migration) do
if data_migration.feature_lock || feature_state() == :disabled do if data_migration.feature_lock || feature_state() == :disabled do
Logger.warning( Logger.warn(
"#{__MODULE__}: migration complete but feature is locked; consider enabling." "#{__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, from([_n, a, o] in query,
where: where:
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
fragment("?->>'content' is null", o.data) or
fragment("?->>'actor' = ?", o.data, ^user.ap_id) fragment("?->>'actor' = ?", o.data, ^user.ap_id)
) )
end end
@ -696,7 +695,7 @@ def skip?(
cond do cond do
opts[:type] == "poll" -> false opts[:type] == "poll" -> false
user.ap_id == actor -> false user.ap_id == actor -> false
!User.following?(user, follower) -> true !User.following?(follower, user) -> true
true -> false true -> false
end end
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. # Note: will create a Create activity, which we need internally at the moment.
def fetch_object_from_id(id, options \\ []) do def fetch_object_from_id(id, options \\ []) do
with %URI{} = uri <- URI.parse(id), 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 # 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, nil} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_reject(uri),
{:ok, _} <- Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_accept(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} -> {:allowed_depth, false} ->
{:error, "Max thread distance exceeded."} {:error, "Max thread distance exceeded."}
{:scheme, false} ->
{:error, "URI Scheme Invalid"}
{:containment, _} -> {:containment, _} ->
{:error, "Object containment failed."} {:error, "Object containment failed."}

View file

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

View file

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

View file

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

View file

@ -28,7 +28,7 @@ def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload)
{:ok, :filtered, upload} {:ok, :filtered, upload}
rescue rescue
e in ErlangError -> e in ErlangError ->
Logger.warning("#{__MODULE__}: #{inspect(e)}") Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop} {:ok, :noop}
end end
end end
@ -45,7 +45,7 @@ def filter(%Pleroma.Upload{tempfile: file, content_type: "video" <> _} = upload)
{:ok, :filtered, upload} {:ok, :filtered, upload}
rescue rescue
e in ErlangError -> e in ErlangError ->
Logger.warning("#{__MODULE__}: #{inspect(e)}") Logger.warn("#{__MODULE__}: #{inspect(e)}")
{:ok, :noop} {:ok, :noop}
end end
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.Web.RelMe
alias Pleroma.Workers.BackgroundWorker alias Pleroma.Workers.BackgroundWorker
use Pleroma.Web, :verified_routes
require Logger require Logger
@type t :: %__MODULE__{} @type t :: %__MODULE__{}
@ -878,7 +876,7 @@ def post_register_action(%User{is_approved: true, is_confirmed: true} = user) do
end end
end end
defp send_user_approval_email(%User{email: email} = user) when is_binary(email) do defp send_user_approval_email(user) do
user user
|> Pleroma.Emails.UserEmail.approval_pending_email() |> Pleroma.Emails.UserEmail.approval_pending_email()
|> Pleroma.Emails.Mailer.deliver_async() |> Pleroma.Emails.Mailer.deliver_async()
@ -886,10 +884,6 @@ defp send_user_approval_email(%User{email: email} = user) when is_binary(email)
{:ok, :enqueued} {:ok, :enqueued}
end end
defp send_user_approval_email(_user) do
{:ok, :skipped}
end
defp send_admin_approval_emails(user) do defp send_admin_approval_emails(user) do
all_superusers() all_superusers()
|> Enum.filter(fn user -> not is_nil(user.email) end) |> Enum.filter(fn user -> not is_nil(user.email) end)
@ -1495,7 +1489,7 @@ def unmute(muter_id, mutee_id) do
unmute(muter, mutee) unmute(muter, mutee)
else else
{who, result} = error -> {who, result} = error ->
Logger.warning( Logger.warn(
"User.unmute/2 failed. #{who}: #{result}, muter_id: #{muter_id}, mutee_id: #{mutee_id}" "User.unmute/2 failed. #{who}: #{result}, muter_id: #{muter_id}, mutee_id: #{mutee_id}"
) )
@ -2012,6 +2006,7 @@ defp create_service_actor(uri, nickname) do
%User{ %User{
invisible: true, invisible: true,
local: true, local: true,
actor_type: "Application",
ap_id: uri, ap_id: uri,
nickname: nickname, nickname: nickname,
follower_address: uri <> "/followers" follower_address: uri <> "/followers"
@ -2449,7 +2444,12 @@ defp validate_rel_me_field(changeset, fields, raw_fields, %User{
end end
if is_url(raw_value) do 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] possible_urls = [ap_id, frontend_url]

View file

@ -119,7 +119,7 @@ def process(%__MODULE__{} = backup) do
end end
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 def export(%__MODULE__{} = backup) do
backup = Repo.preload(backup, :user) backup = Repo.preload(backup, :user)
name = String.trim_trailing(backup.file_name, ".zip") 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.ExpectPublicOrAuthenticatedCheckPlug
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.PlugHelper alias Pleroma.Web.Plugs.PlugHelper
require Pleroma.Constants
def controller do def controller do
quote do quote do
@ -38,7 +37,7 @@ def controller do
import Pleroma.Web.Gettext import Pleroma.Web.Gettext
import Pleroma.Web.TranslationHelpers import Pleroma.Web.TranslationHelpers
unquote(verified_routes()) alias Pleroma.Web.Router.Helpers, as: Routes
plug(:set_put_layout) plug(:set_put_layout)
@ -185,10 +184,7 @@ def view do
# Import convenience functions from controllers # Import convenience functions from controllers
import Phoenix.Controller, import Phoenix.Controller,
only: [view_module: 1, view_template: 1] only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
import Phoenix.Flash
alias Phoenix.Flash
# Include shared imports and aliases for views # Include shared imports and aliases for views
unquote(view_helpers()) unquote(view_helpers())
@ -222,7 +218,7 @@ def component do
def router do def router do
quote do quote do
use Phoenix.Router, helpers: false use Phoenix.Router
import Plug.Conn import Plug.Conn
import Phoenix.Controller import Phoenix.Controller
@ -250,24 +246,7 @@ defp view_helpers do
import Pleroma.Web.ErrorHelpers import Pleroma.Web.ErrorHelpers
import Pleroma.Web.Gettext import Pleroma.Web.Gettext
unquote(verified_routes()) alias Pleroma.Web.Router.Helpers, as: 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())
end end
end end

View file

@ -1792,11 +1792,6 @@ def pin_data_from_featured_collection(
end) end)
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 def fetch_and_prepare_featured_from_ap_id(nil) do
{:ok, %{}} {:ok, %{}}
end end

View file

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

View file

@ -18,8 +18,6 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.CommonAPI.ActivityDraft alias Pleroma.Web.CommonAPI.ActivityDraft
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
use Pleroma.Web, :verified_routes
require Pleroma.Constants require Pleroma.Constants
def accept_or_reject(actor, activity, type) do def accept_or_reject(actor, activity, type) do
@ -404,6 +402,6 @@ def unpin(%User{} = user, object) do
end end
defp pinned_url(nickname) when is_binary(nickname) do 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
end end

View file

@ -70,8 +70,6 @@ def filter_one(policy, %{"type" => type} = message)
end end
def filter_one(policy, message) do def filter_one(policy, message) do
Code.ensure_loaded!(policy)
should_plug_history? = should_plug_history? =
if function_exported?(policy, :history_awareness, 0) do if function_exported?(policy, :history_awareness, 0) do
policy.history_awareness() policy.history_awareness()
@ -241,7 +239,7 @@ def config_descriptions(policies) do
if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do if Enum.all?(@required_description_keys, &Map.has_key?(description, &1)) do
[description | acc] [description | acc]
else else
Logger.warning( Logger.warn(
"#{policy} config description doesn't have one or all required keys #{inspect(@required_description_keys)}" "#{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 shortcode
e -> 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 nil
end end
else else
@ -53,7 +53,7 @@ defp steal_emoji({shortcode, url}, emoji_dir_path) do
end end
else else
e -> e ->
Logger.warning("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}") Logger.warn("MRF.StealEmojiPolicy: Failed to fetch #{url}: #{inspect(e)}")
nil nil
end end
end end

View file

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

View file

@ -22,10 +22,7 @@ def cast_and_filter_recipients(message, field, follower_collection, field_fallba
end end
def fix_object_defaults(data) do def fix_object_defaults(data) do
context = context = Utils.maybe_create_context(data["context"] || data["conversation"])
Utils.maybe_create_context(
data["context"] || data["conversation"] || data["inReplyTo"] || data["id"]
)
%User{follower_address: follower_collection} = User.get_cached_by_ap_id(data["attributedTo"]) %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 def should_federate?(url) do
%{host: host} = URI.parse(url) %{host: host} = URI.parse(url)
with {nil, false} <- {nil, is_nil(host)}, with allowed <- allowed_instances(),
allowed <- allowed_instances(),
false <- Enum.empty?(allowed) do false <- Enum.empty?(allowed) do
allowed allowed
|> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples() |> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples()
|> Pleroma.Web.ActivityPub.MRF.subdomains_regex() |> Pleroma.Web.ActivityPub.MRF.subdomains_regex()
|> Pleroma.Web.ActivityPub.MRF.subdomain_match?(host) |> Pleroma.Web.ActivityPub.MRF.subdomain_match?(host)
else else
# oi!
{nil, true} ->
false
_ -> _ ->
quarantined_instances = quarantined_instances =
blocked_instances() blocked_instances()

View file

@ -136,7 +136,7 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
|> Map.drop(["conversation", "inReplyToAtomUri"]) |> Map.drop(["conversation", "inReplyToAtomUri"])
else else
e -> 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 object
end end
else else
@ -159,7 +159,7 @@ def fix_quote_url(%{"quoteUri" => quote_url} = object, options)
|> Map.put("quoteUri", quoted_object.data["id"]) |> Map.put("quoteUri", quoted_object.data["id"])
else else
e -> 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 object
end end
else else
@ -920,13 +920,8 @@ def add_attributed_to(object) do
def prepare_attachments(object) do def prepare_attachments(object) do
attachments = attachments =
case Map.get(object, "attachment", []) do object
[_ | _] = list -> list |> Map.get("attachment", [])
_ -> []
end
attachments =
attachments
|> Enum.map(fn data -> |> Enum.map(fn data ->
[%{"mediaType" => media_type, "href" => href} = url | _] = data["url"] [%{"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.ActivityPub.Visibility
alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint
alias Pleroma.Web.Router.Helpers
import Ecto.Query import Ecto.Query
use Pleroma.Web, :verified_routes
require Logger require Logger
require Pleroma.Constants require Pleroma.Constants
@ -125,15 +124,19 @@ def make_date do
end end
def generate_activity_id do def generate_activity_id do
url(~p[/activities/#{UUID.generate()}]) generate_id("activities")
end end
def generate_context_id do def generate_context_id do
url(~p[/contexts/#{UUID.generate()}]) generate_id("contexts")
end end
def generate_object_id do 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 end
def get_notified_from_object(%{"type" => type} = object) when type in @supported_object_types do 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) Notification.get_notified_from_activity(%Activity{data: object}, false)
end end
def maybe_create_context(context), do: context || generate_context_id() def maybe_create_context(context), do: context || generate_id("contexts")
@doc """ @doc """
Enqueues an activity for federation if it's local 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.ObjectView
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Endpoint
require Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.Router.Helpers
import Ecto.Query import Ecto.Query
def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do
%{"sharedInbox" => url(~p"/inbox")} %{"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)}
end end
def render("endpoints.json", %{user: %User{local: true} = _user}) do def render("endpoints.json", %{user: %User{local: true} = _user}) do
%{ %{
"oauthAuthorizationEndpoint" => url(~p"/oauth/authorize"), "oauthAuthorizationEndpoint" => Helpers.o_auth_url(Endpoint, :authorize),
"oauthRegistrationEndpoint" => url(~p"/api/v1/apps"), "oauthRegistrationEndpoint" => Helpers.app_url(Endpoint, :create),
"oauthTokenEndpoint" => url(~p"/oauth/token"), "oauthTokenEndpoint" => Helpers.o_auth_url(Endpoint, :token_exchange),
"sharedInbox" => url(~p"/inbox"), "sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox),
"uploadMedia" => url(~p"/api/ap/upload_media") "uploadMedia" => Helpers.activity_pub_url(Endpoint, :upload_media)
} }
end end

View file

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

View file

@ -410,7 +410,7 @@ def blocks_operation do
operationId: "AccountController.blocks", operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}", description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}], security: [%{"oAuth" => ["read:blocks"]}],
parameters: [with_relationships_param() | pagination_params()], parameters: pagination_params(),
responses: %{ responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts()) 200 => Operation.response("Accounts", "application/json", array_of_accounts())
} }
@ -451,20 +451,6 @@ def endorsements_operation do
} }
end 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 def identity_proofs_operation do
%Operation{ %Operation{
tags: ["Retrieve account information"], tags: ["Retrieve account information"],

View file

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

View file

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

View file

@ -110,7 +110,7 @@ defp register_user(connection, base, uid, name) do
} }
params = 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)) {_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
_ -> params _ -> params
end end

View file

@ -88,7 +88,7 @@ def reject_follow_request(follower, followed) do
def delete(activity_id, user) do def delete(activity_id, user) do
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <- 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, _} <- {_, %Object{} = object, _} <-
{:find_object, Object.normalize(activity, fetch: false), activity}, {:find_object, Object.normalize(activity, fetch: false), activity},
true <- User.superuser?(user) || user.ap_id == object.data["actor"], 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) remove_mute(user, activity)
else else
{what, result} = error -> {what, result} = error ->
Logger.warning( Logger.warn(
"CommonAPI.remove_mute/2 failed. #{what}: #{result}, user_id: #{user_id}, activity_id: #{activity_id}" "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 when is_list(options) do
limits = Config.get([:instance, :poll_limits]) limits = Config.get([:instance, :poll_limits])
options = options |> Enum.uniq()
with :ok <- validate_poll_expiration(expires_in, limits), with :ok <- validate_poll_expiration(expires_in, limits),
:ok <- validate_poll_options_amount(options, limits), :ok <- validate_poll_options_amount(options, limits),
:ok <- validate_poll_options_length(options, limits) do :ok <- validate_poll_options_length(options, limits) do
@ -181,15 +179,10 @@ def make_poll_data(_data) do
end end
defp validate_poll_options_amount(options, %{max_options: max_options}) do defp validate_poll_options_amount(options, %{max_options: max_options}) do
cond do if Enum.count(options) > max_options do
Enum.count(options) < 2 -> {:error, "Poll can't contain more than #{max_options} options"}
{:error, "Poll must contain at least 2 options"} else
:ok
Enum.count(options) > max_options ->
{:error, "Poll can't contain more than #{max_options} options"}
true ->
:ok
end end
end end
@ -324,13 +317,13 @@ def date_to_asctime(date) when is_binary(date) do
format_asctime(date) format_asctime(date)
else else
_e -> _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
end end
def date_to_asctime(date) do 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 end

View file

@ -11,31 +11,22 @@ defmodule Pleroma.Web.EmbedController do
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
plug(:put_layout, :embed)
def show(conn, %{"id" => id}) do def show(conn, %{"id" => id}) do
with {:activity, %Activity{} = activity} <- with %Activity{local: true} = activity <-
{:activity, Activity.get_by_id_with_object(id)}, Activity.get_by_id_with_object(id),
{:local, true} <- {:local, activity.local}, true <- Visibility.is_public?(activity.object) do
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, nil)} do
{:ok, author} = User.get_or_fetch(activity.object.data["actor"]) {:ok, author} = User.get_or_fetch(activity.object.data["actor"])
conn conn
|> delete_resp_header("x-frame-options") |> delete_resp_header("x-frame-options")
|> delete_resp_header("content-security-policy") |> delete_resp_header("content-security-policy")
|> put_view(Pleroma.Web.EmbedView)
|> render("show.html", |> render("show.html",
activity: activity, activity: activity,
author: User.sanitize_html(author), author: User.sanitize_html(author),
counts: get_counts(activity) 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
end end

View file

@ -97,7 +97,7 @@ defmodule Pleroma.Web.Endpoint do
Plug.Static, Plug.Static,
at: "/", at: "/",
from: :pleroma, from: :pleroma,
only: Pleroma.Web.static_paths(), only: Pleroma.Constants.static_only_files(),
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
gzip: true, gzip: true,
cache_control_for_etags: @static_cache_control, 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 def feed_redirect(conn, %{"nickname" => nickname}) do
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_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
end end

View file

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

View file

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

View file

@ -54,7 +54,12 @@ def login(conn, params) do
defp redirect_to_oauth_form(conn, _params) do defp redirect_to_oauth_form(conn, _params) do
with {:ok, app} <- local_mastofe_app() do with {:ok, app} <- local_mastofe_app() do
path = 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) redirect(conn, to: path)
end end
@ -86,7 +91,7 @@ def password_reset(conn, params) do
defp local_mastodon_post_login_path(conn) do defp local_mastodon_post_login_path(conn) do
case get_session(conn, :return_to) do case get_session(conn, :return_to) do
nil -> nil ->
~p"/web/getting-started" Routes.masto_fe_path(conn, :index, ["getting-started"])
return_to -> return_to ->
delete_session(conn, :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("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 defp do_render("show.json", %{user: user} = opts) do
user = User.sanitize_html(user, User.html_filter_policy(opts[:for])) user = User.sanitize_html(user, User.html_filter_policy(opts[:for]))
display_name = user.name || user.nickname display_name = user.name || user.nickname

View file

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

View file

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

View file

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

View file

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

View file

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

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