Compare commits

..

10 commits

40 changed files with 137 additions and 727 deletions

View file

@ -6,12 +6,12 @@ COPYING
*file
elixir_buildpack.config
test/
instance/
_build
deps
test
benchmarks
docs/site
docker-db
uploads
instance
# Required to get version
!.git

10
.gitignore vendored
View file

@ -17,13 +17,6 @@ secret
/instance
/priv/ssh_keys
vm.args
.cache/
.hex/
.mix/
.psql_history
docker-resources/Dockerfile
docker-resources/Caddyfile
pgdata
# Prevent committing custom emojis
/priv/static/emoji/custom/*
@ -72,6 +65,3 @@ pleroma.iml
# Generated documentation
docs/site
# docker stuff
docker-db

View file

@ -6,17 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased
## Added
- Officially supported docker release
- Ability to remove followers unilaterally without a block
## Changes
- Follows no longer override domain blocks, a domain block is final
- Deletes are now the lowest priority to publish and will be handled after creates
## Fixed
- Registrations via ldap are now compatible with the latest OTP24
## 2022.10
### Added
@ -62,6 +55,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2022.08
### Removed
- Non-finch HTTP adapters. `:tesla, :adapter` is now highly recommended to be set to the default.
## 2022.08
### Added
- extended runtime module support, see config cheatsheet
- quote posting; quotes are limited to public posts

View file

@ -1,8 +1,21 @@
FROM hexpm/elixir:1.13.4-erlang-24.3.4.5-alpine-3.15.6
FROM elixir:1.13.4-alpine as build
COPY . .
ENV MIX_ENV=prod
ARG HOME=/opt/akkoma
RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
echo "import Config" > config/prod.secret.exs &&\
mix local.hex --force &&\
mix local.rebar --force &&\
mix deps.get --only prod &&\
mkdir release &&\
mix release --path release
FROM alpine:3.16
ARG BUILD_DATE
ARG VCS_REF
LABEL org.opencontainers.image.title="akkoma" \
org.opencontainers.image.description="Akkoma for Docker" \
@ -13,21 +26,25 @@ LABEL org.opencontainers.image.title="akkoma" \
org.opencontainers.image.revision=$VCS_REF \
org.opencontainers.image.created=$BUILD_DATE
RUN apk add git gcc g++ musl-dev make cmake file-dev exiftool ffmpeg imagemagick libmagic ncurses postgresql-client
ARG HOME=/opt/akkoma
ARG DATA=/var/lib/akkoma
RUN apk update &&\
apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\
adduser --system --shell /bin/false --home ${HOME} akkoma &&\
mkdir -p ${DATA}/uploads &&\
mkdir -p ${DATA}/static &&\
chown -R akkoma ${DATA} &&\
mkdir -p /etc/akkoma &&\
chown -R akkoma /etc/akkoma
USER akkoma
COPY --from=build --chown=akkoma:0 /release ${HOME}
COPY ./config/docker.exs /etc/akkoma/config.exs
COPY ./docker-entrypoint.sh ${HOME}
EXPOSE 4000
ARG UID=1000
ARG GID=1000
ARG UNAME=akkoma
RUN addgroup -g $GID $UNAME
RUN adduser -u $UID -G $UNAME -D -h $HOME $UNAME
WORKDIR /opt/akkoma
USER $UNAME
RUN mix local.hex --force &&\
mix local.rebar --force
CMD ["/opt/akkoma/docker-entrypoint.sh"]
ENTRYPOINT ["/opt/akkoma/docker-entrypoint.sh"]

View file

@ -185,7 +185,7 @@ config :pleroma, :http,
adapter: []
config :pleroma, :instance,
name: "Akkoma",
name: "Pleroma",
email: "example@example.com",
notify_email: "noreply@example.com",
description: "Akkoma: The cooler fediverse server",

View file

@ -1389,12 +1389,6 @@ config :pleroma, :config_description, [
label: "Render misskey markdown",
type: :boolean,
description: "Whether to render Misskey-flavoured markdown"
},
%{
key: :stopGifs,
label: "Stop Gifs",
type: :boolean,
description: "Whether to pause animated images until they're hovered on"
}
]
},

View file

@ -24,11 +24,11 @@ config :pleroma, Pleroma.Repo,
config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}"
config :pleroma, :database, rum_enabled: false
config :pleroma, :instance, static_dir: "/var/lib/akkoma/static"
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/akkoma/uploads"
config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
# We can't store the secrets in this file, since this is baked into the docker image
if not File.exists?("/var/lib/akkoma/secret.exs") do
if not File.exists?("/var/lib/pleroma/secret.exs") do
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
@ -52,16 +52,16 @@ if not File.exists?("/var/lib/akkoma/secret.exs") do
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false)
)
File.write("/var/lib/akkoma/secret.exs", secret_file)
File.write("/var/lib/pleroma/secret.exs", secret_file)
end
import_config("/var/lib/akkoma/secret.exs")
import_config("/var/lib/pleroma/secret.exs")
# For additional user config
if File.exists?("/var/lib/akkoma/config.exs"),
do: import_config("/var/lib/akkoma/config.exs"),
if File.exists?("/var/lib/pleroma/config.exs"),
do: import_config("/var/lib/pleroma/config.exs"),
else:
File.write("/var/lib/akkoma/config.exs", """
File.write("/var/lib/pleroma/config.exs", """
import Config
# For additional configuration outside of environmental variables

View file

@ -1,61 +0,0 @@
version: "3.7"
services:
db:
image: akkoma-db:latest
build: ./docker-resources/database
restart: unless-stopped
user: ${DOCKER_USER}
environment: {
# This might seem insecure but is usually not a problem.
# You should leave this at the "akkoma" default.
# The DB is only reachable by containers in the same docker network,
# and is not exposed to the open internet.
#
# If you do change this, remember to update "config.exs".
POSTGRES_DB: akkoma,
POSTGRES_USER: akkoma,
POSTGRES_PASSWORD: akkoma,
}
env_file:
- .env
volumes:
- type: bind
source: ./pgdata
target: /var/lib/postgresql/data
akkoma:
image: akkoma:latest
build: .
restart: unless-stopped
env_file:
- .env
links:
- db
ports: [
# Uncomment/Change port mappings below as needed.
# The left side is your host machine, the right one is the akkoma container.
# You can prefix the left side with an ip.
# Webserver (for reverse-proxies outside of docker)
# If you use a dockerized proxy, you can leave this commented
# and use a container link instead.
"127.0.0.1:4000:4000",
]
volumes:
- .:/opt/akkoma
# Uncomment the following if you want to use a reverse proxy
#proxy:
# image: caddy:2-alpine
# restart: unless-stopped
# links:
# - akkoma
# ports: [
# "443:443",
# "80:80"
# ]
# volumes:
# - ./docker-resources/Caddyfile:/etc/caddy/Caddyfile
# - ./caddy-data:/data
# - ./caddy-config:/config

View file

@ -8,7 +8,7 @@ while ! pg_isready -U ${DB_USER:-pleroma} -d postgres://${DB_HOST:-db}:5432/${DB
done
echo "-- Running migrations..."
mix ecto.migrate
$HOME/bin/pleroma_ctl migrate
echo "-- Starting!"
mix phx.server
exec $HOME/bin/pleroma start

View file

@ -1,14 +0,0 @@
# default docker Caddyfile config for Akkoma
#
# Simple installation instructions:
# 1. Replace 'example.tld' with your instance's domain wherever it appears.
example.tld {
log {
output file /var/log/caddy/akkoma.log
}
encode gzip
reverse_proxy akkoma:4000
}

View file

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

View file

@ -1,10 +0,0 @@
FROM postgres:14-alpine
ARG UID=1000
ARG GID=1000
ARG UNAME=akkoma
RUN addgroup -g $GID $UNAME
RUN adduser -u $UID -G $UNAME -D -h $HOME $UNAME
USER akkoma

View file

@ -1,4 +0,0 @@
MIX_ENV=prod
DB_NAME=akkoma
DB_USER=akkoma
DB_PASS=akkoma

View file

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

View file

@ -59,7 +59,6 @@ To add configuration to your config file, you can copy it from the base config.
* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
* `show_reactions`: Let favourites and emoji reactions be viewed through the API (default: `true`).
* `password_reset_token_validity`: The time after which reset tokens aren't accepted anymore, in seconds (default: one day).
* `local_bubble`: Array of domains representing instances closely related to yours. Used to populate the `bubble` timeline. e.g `['example.com']`, (default: `[]`)
## :database
* `improved_hashtag_timeline`: Setting to force toggle / force disable improved hashtags timeline. `:enabled` forces hashtags to be fetched from `hashtags` table for hashtags timeline. `:disabled` forces object-embedded hashtags to be used (slower). Keep it `:auto` for automatic behaviour (it is auto-set to `:enabled` [unless overridden] when HashtagsTableMigrator completes).

View file

@ -1,161 +0,0 @@
# Installing in Docker
## Installation
This guide will show you how to get akkoma working in a docker container,
if you want isolation, or if you run a distribution not supported by the OTP
releases.
If you want to migrate from or OTP to docker, check out [the migration guide](./migrating_to_docker_en.md).
### Prepare the system
* Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
* Clone the akkoma repository
* `git clone https://akkoma.dev/AkkomaGang/akkoma.git -b stable`
* `cd akkoma`
### Set up basic configuration
```bash
cp docker-resources/env.example .env
echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
variables for the docker-compose file.
### Building the container
The container provided is a thin wrapper around akkoma's dependencies,
it does not contain the code itself. This is to allow for easy updates
and debugging if required.
```bash
./docker-resources/build.sh
```
This will generate a container called `akkoma` which we can use
in our compose environment.
### Generating your instance
```bash
mkdir pgdata
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix pleroma.instance gen
```
This will ask you a few questions - the defaults are fine for most things,
the database hostname is `db`, and you will want to set the ip to `0.0.0.0`.
Now we'll want to copy over the config it just created
```bash
cp config/generated_config.exs config/prod.secret.exs
```
### Setting up the database
We need to run a few commands on the database container, this isn't too bad
```bash
docker-compose run --rm --user akkoma -d db
# 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 stop akkoma_db_run # Replace with the name you noted down
```
Now we can actually run our migrations
```bash
./docker-resources/manage.sh mix ecto.migrate
# this will recompile your files at the same time, since we changed the config
```
### Start the server
We're going to run it in the foreground on the first run, just to make sure
everything start up.
```bash
docker-compose up
```
If everything went well, you should be able to access your instance at http://localhost:4000
You can `ctrl-c` out of the docker-compose now to shutdown the server.
### Running in the background
```bash
docker-compose up -d
```
### Create your first user
If your instance is up and running, you can create your first user with administrative rights with the following task:
```shell
./docker-resources/manage.sh mix pleroma.user new MY_USERNAME MY_EMAIL@SOMEWHERE --admin
```
And follow the prompts
### Reverse proxies
This is a tad more complex in docker than on the host itself. It
You've got two options.
#### Running caddy in a container
This is by far the easiest option. It'll handle HTTPS and all that for you.
```bash
mkdir caddy-data
mkdir caddy-config
cp docker-resources/Caddyfile.example docker-resources/Caddyfile
```
Then edit the TLD in your caddyfile to the domain you're serving on.
Uncomment the `caddy` section in the docker-compose file,
then run `docker-compose up -d` again.
#### Running a reverse proxy on the host
If you want, you can also run the reverse proxy on the host. This is a bit more complex, but it's also more flexible.
Follow the guides for source install for your distribution of choice, or adapt
as needed. Your standard setup can be found in the [Debian Guide](../debian_based_en/#nginx)
### You're done!
All that's left is to set up your frontends.
The standard from-source commands will apply to you, just make sure you
prefix them with `./docker-resources/manage.sh`!
{! installation/frontends.include !}
### Updating Docker Installs
```bash
git pull
./docker-resources/build.sh
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix ecto.migrate
docker-compose restart akkoma db
```
#### Further reading
{! installation/further_reading.include !}
{! support.include !}

View file

@ -21,11 +21,5 @@ For most installations, the following will suffice:
mix pleroma.frontend install admin-fe --ref stable
```
=== "Docker"
```sh
./docker-resources/manage.sh mix pleroma.frontend install pleroma-fe --ref stable
./docker-resources/manage.sh mix pleroma.frontend install admin-fe --ref stable
```
For more customised installations, refer to [Frontend Management](../../configuration/frontend_management)

View file

@ -1,158 +0,0 @@
# Migrating to a Docker Installation
If you for any reason wish to migrate a source or OTP install to a docker one,
this guide is for you.
You have a few options - your major one will be whether you want to keep your
reverse-proxy setup from before.
You probably should, in the first instance.
### Prepare the system
* Install docker and docker-compose
* [Docker](https://docs.docker.com/engine/install/)
* [Docker-compose](https://docs.docker.com/compose/install/)
* This will usually just be a repository installation and a package manager invocation.
=== "Source"
```bash
git pull
```
=== "OTP"
Clone the akkoma repository
```bash
git clone https://akkoma.dev/AkkomaGang/akkoma.git -b stable
cd akkoma
```
### Back up your old database
Change the database name as needed
```bash
pg_dump -d akkoma_prod --format c > akkoma_backup.sql
```
### Getting your static files in the right place
This will vary by every installation. Copy your `instance` directory to `instance/` in
the akkoma source directory - this is where the docker container will look for it.
For *most* from-source installs it'll already be there.
And the same with `uploads`, make sure your uploads (if you have them on disk) are
located at `uploads/` in the akkoma source directory.
If you have them on a different disk, you will need to mount that disk into the docker-compose file,
with an entry that looks like this:
```yaml
akkoma:
volumes:
- .:/opt/akkoma # This should already be there
- type: bind
source: /path/to/your/uploads
target: /opt/akkoma/uploads
```
### Set up basic configuration
```bash
cp docker-resources/env.example .env
echo "DOCKER_USER=$(id -u):$(id -g)" >> .env
```
This probably won't need to be changed, it's only there to set basic environment
variables for the docker-compose file.
=== "From source"
You probably won't need to change your config. Provided your `config/prod.secret.exs` file
is still there, you're all good.
=== "OTP"
```bash
cp /etc/akkoma/config.exs config/prod.secret.exs
```
**BOTH**
Set the following config in `config/prod.secret.exs`:
```elixir
config :pleroma, Pleroma.Web.Endpoint,
...,
http: [ip: {0, 0, 0, 0}, port: 4000]
config :pleroma, Pleroma.Repo,
...,
username: "akkoma",
password: "akkoma",
database: "akkoma",
hostname: "db"
```
### Building the container
The container provided is a thin wrapper around akkoma's dependencies,
it does not contain the code itself. This is to allow for easy updates
and debugging if required.
```bash
./docker-resources/build.sh
```
This will generate a container called `akkoma` which we can use
in our compose environment.
### Setting up the docker resources
```bash
# These won't exist if you're migrating from OTP
rm -rf deps
rm -rf _build
```
```bash
mkdir pgdata
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
```
### Setting up the database
Now we can import our database to the container.
```bash
docker-compose run --rm --user akkoma -d db
docker-compose run --rm akkoma pg_restore -v -U akkoma -j $(grep -c ^processor /proc/cpuinfo) -d akkoma -h db akkoma_backup.sql
```
### Reverse proxies
If you're just reusing your old proxy, you may have to uncomment the line in
the docker-compose file under `ports`. You'll find it.
Otherwise, you can use the same setup as the [docker installation guide](./docker_en.md#reverse-proxies).
### Let's go
```bash
docker-compose up -d
```
You should now be at the same point as you were before, but with a docker install.
{! installation/frontends.include !}
See the [docker installation guide](./docker_en.md) for more information on how to
update.
#### Further reading
{! installation/further_reading.include !}
{! support.include !}

View file

@ -67,9 +67,8 @@ defmodule Pleroma.UserRelationship do
target_id: target.id
})
|> Repo.insert(
on_conflict: {:replace_all_except, [:id, :inserted_at]},
conflict_target: [:source_id, :relationship_type, :target_id],
returning: true
on_conflict: {:replace_all_except, [:id]},
conflict_target: [:source_id, :relationship_type, :target_id]
)
end

View file

@ -334,22 +334,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
def remove_from_followers_operation do
%Operation{
tags: ["Account actions"],
summary: "Remove from followers",
operationId: "AccountController.remove_from_followers",
security: [%{"oAuth" => ["follow", "write:follows"]}],
description: "Remove the given account from followers",
parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
end
def note_operation do
%Operation{
tags: ["Account actions"],

View file

@ -102,7 +102,7 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
{:scope, :eldap.wholeSubtree()},
{:timeout, @search_timeout}
]) do
{:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _, _}} ->
{:ok, {:eldap_search_result, [{:eldap_entry, _, attributes}], _}} ->
params = %{
name: name,
nickname: name,

View file

@ -76,16 +76,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
plug(
OAuthScopesPlug,
%{scopes: ["follow", "write:follows"]}
when action in [:follow_by_uri, :follow, :unfollow, :remove_from_followers]
%{scopes: ["follow", "write:follows"]} when action in [:follow_by_uri, :follow, :unfollow]
)
plug(OAuthScopesPlug, %{scopes: ["follow", "read:mutes"]} when action == :mutes)
plug(OAuthScopesPlug, %{scopes: ["follow", "write:mutes"]} when action in [:mute, :unmute])
@relationship_actions [:follow, :unfollow, :remove_from_followers]
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock note remove_from_followers)a
@relationship_actions [:follow, :unfollow]
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock note)a
plug(
RateLimiter,
@ -448,20 +447,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
end
end
@doc "POST /api/v1/accounts/:id/remove_from_followers"
def remove_from_followers(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
{:error, "Can not unfollow yourself"}
end
def remove_from_followers(%{assigns: %{user: followed, account: follower}} = conn, _params) do
with {:ok, follower} <- CommonAPI.reject_follow_request(follower, followed) do
render(conn, "relationship.json", user: followed, target: follower)
else
nil ->
render_error(conn, :not_found, "Record not found")
end
end
@doc "POST /api/v1/follows"
def follow_by_uri(%{body_params: %{uri: uri}} = conn, _) do
case User.get_cached_by_nickname(uri) do

View file

@ -68,7 +68,7 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlug do
]
}
[{"report-to", Jason.encode!(report_group)} | headers]
[{"reply-to", Jason.encode!(report_group)} | headers]
else
headers
end

View file

@ -16,7 +16,7 @@ defmodule Pleroma.Web.Push.Impl do
require Logger
import Ecto.Query
@types ["Create", "Follow", "Announce", "Like", "Move", "EmojiReact", "Update"]
@types ["Create", "Follow", "Announce", "Like", "Move", "EmojiReact"]
@doc "Performs sending notifications for user subscriptions"
@spec perform(Notification.t()) :: list(any) | :error | {:error, :unknown_type}
@ -167,15 +167,6 @@ defmodule Pleroma.Web.Push.Impl do
end
end
def format_body(
%{activity: %{data: %{"type" => "Update"}}},
actor,
_object,
_mastodon_type
) do
"@#{actor.nickname} edited a status"
end
def format_title(activity, mastodon_type \\ nil)
def format_title(%{activity: %{data: %{"directMessage" => true}}}, _mastodon_type) do
@ -189,7 +180,6 @@ defmodule Pleroma.Web.Push.Impl do
"follow_request" -> "New Follow Request"
"reblog" -> "New Repeat"
"favourite" -> "New Favorite"
"update" -> "New Update"
"pleroma:emoji_reaction" -> "New Reaction"
type -> "New #{String.capitalize(type || "event")}"
end

View file

@ -509,7 +509,6 @@ defmodule Pleroma.Web.Router do
post("/accounts/:id/mute", AccountController, :mute)
post("/accounts/:id/unmute", AccountController, :unmute)
post("/accounts/:id/note", AccountController, :note)
post("/accounts/:id/remove_from_followers", AccountController, :remove_from_followers)
get("/conversations", ConversationController, :index)
post("/conversations/:id/read", ConversationController, :mark_as_read)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

View file

@ -61,12 +61,6 @@ defmodule Restarter.Pleroma do
{:noreply, @init_state}
end
# Don't actually restart during tests.
# We just check if the correct call has been done.
# If we actually restart, we get errors during the tests like
# (RuntimeError) could not lookup Ecto repo Pleroma.Repo because it was not started or
# it does not exist
# See tests in Pleroma.Config.TransferTaskTest
def handle_cast({:restart, :test, _}, state) do
Logger.debug("pleroma manually restarted")
{:noreply, Map.put(state, :need_reboot, false)}
@ -80,12 +74,6 @@ defmodule Restarter.Pleroma do
def handle_cast({:after_boot, _}, %{after_boot: true} = state), do: {:noreply, state}
# Don't actually restart during tests.
# We just check if the correct call has been done.
# If we actually restart, we get errors during the tests like
# (RuntimeError) could not lookup Ecto repo Pleroma.Repo because it was not started or
# it does not exist
# See tests in Pleroma.Config.TransferTaskTest
def handle_cast({:after_boot, :test}, state) do
Logger.debug("pleroma restarted after boot")
state = %{state | after_boot: true, rebooted: true}

View file

@ -13,8 +13,7 @@ defmodule Restarter.MixProject do
def application do
[
mod: {Restarter, []},
extra_applications: [:logger]
mod: {Restarter, []}
]
end

View file

@ -119,87 +119,44 @@ defmodule Pleroma.Config.TransferTaskTest do
describe "pleroma restart" do
setup do
on_exit(fn ->
Restarter.Pleroma.refresh()
# Restarter.Pleroma.refresh/0 is an asynchronous call.
# A GenServer will first finish the previous call before starting a new one.
# Here we do a synchronous call.
# That way we are sure that the previous call has finished before we continue.
# See https://stackoverflow.com/questions/51361856/how-to-use-task-await-with-genserver
Restarter.Pleroma.rebooted?()
end)
on_exit(fn -> Restarter.Pleroma.refresh() end)
end
@tag :erratic
test "don't restart if no reboot time settings were changed" do
clear_config(:emoji)
insert(:config, key: :emoji, value: [groups: [a: 1, b: 2]])
refute String.contains?(
capture_log(fn ->
TransferTask.start_link([])
# TransferTask.start_link/1 is an asynchronous call.
# A GenServer will first finish the previous call before starting a new one.
# Here we do a synchronous call.
# That way we are sure that the previous call has finished before we continue.
Restarter.Pleroma.rebooted?()
end),
capture_log(fn -> TransferTask.start_link([]) end),
"pleroma restarted"
)
end
@tag :erratic
test "on reboot time key" do
clear_config(:rate_limit)
insert(:config, key: :rate_limit, value: [enabled: false])
# Note that we don't actually restart Pleroma.
# See module Restarter.Pleroma
assert capture_log(fn ->
TransferTask.start_link([])
# TransferTask.start_link/1 is an asynchronous call.
# A GenServer will first finish the previous call before starting a new one.
# Here we do a synchronous call.
# That way we are sure that the previous call has finished before we continue.
Restarter.Pleroma.rebooted?()
end) =~ "pleroma restarted"
clear_config([:pleroma, :rate_limit])
insert(:config, key: {:pleroma, :rate_limit}, value: [enabled: false])
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
@tag :erratic
test "on reboot time subkey" do
clear_config(Pleroma.Captcha)
insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
# Note that we don't actually restart Pleroma.
# See module Restarter.Pleroma
assert capture_log(fn ->
TransferTask.start_link([])
# TransferTask.start_link/1 is an asynchronous call.
# A GenServer will first finish the previous call before starting a new one.
# Here we do a synchronous call.
# That way we are sure that the previous call has finished before we continue.
Restarter.Pleroma.rebooted?()
end) =~ "pleroma restarted"
assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
end
@tag :erratic
test "don't restart pleroma on reboot time key and subkey if there is false flag" do
clear_config(:rate_limit)
clear_config([:pleroma, :rate_limit])
clear_config(Pleroma.Captcha)
insert(:config, key: :rate_limit, value: [enabled: false])
insert(:config, key: {:pleroma, :rate_limit}, value: [enabled: false])
insert(:config, key: Pleroma.Captcha, value: [seconds_valid: 60])
refute String.contains?(
capture_log(fn ->
TransferTask.load_and_update_env([], false)
# TransferTask.start_link/1 is an asynchronous call.
# A GenServer will first finish the previous call before starting a new one.
# Here we do a synchronous call.
# That way we are sure that the previous call has finished before we continue.
Restarter.Pleroma.rebooted?()
end),
capture_log(fn -> TransferTask.load_and_update_env([], false) end),
"pleroma restarted"
)
end

View file

@ -122,11 +122,11 @@ defmodule Pleroma.Conversation.ParticipationTest do
end
test "it marks a participation as read" do
participation = insert(:participation, %{updated_at: ~N[2017-07-17 17:09:58], read: false})
participation = insert(:participation, %{read: false})
{:ok, updated_participation} = Participation.mark_as_read(participation)
assert updated_participation.read
assert :gt = NaiveDateTime.compare(updated_participation.updated_at, participation.updated_at)
assert updated_participation.updated_at == participation.updated_at
end
test "it marks a participation as unread" do

View file

@ -27,7 +27,7 @@ defmodule Pleroma.Emails.UserEmailTest do
token = %Pleroma.UserInviteToken{token: "test-token"}
email = UserEmail.user_invitation_email(user, token, "test@test.com", "Jonh")
assert email.from == {config[:name], config[:notify_email]}
assert email.subject == "Invitation to Akkoma"
assert email.subject == "Invitation to Pleroma"
assert email.to == [{"Jonh", "test@test.com"}]
assert email.html_body =~

View file

@ -5,9 +5,8 @@
defmodule Pleroma.UserRelationshipTest do
alias Pleroma.UserRelationship
use Pleroma.DataCase, async: false
use Pleroma.DataCase, async: true
import Mock
import Pleroma.Factory
describe "*_exists?/2" do
@ -80,12 +79,7 @@ defmodule Pleroma.UserRelationshipTest do
end
test "if record already exists, returns it", %{users: [user1, user2]} do
user_block =
with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
{:ok, %{inserted_at: ~N[2017-03-17 17:09:58]}} =
UserRelationship.create_block(user1, user2)
end
user_block = UserRelationship.create_block(user1, user2)
assert user_block == UserRelationship.create_block(user1, user2)
end
end

View file

@ -311,7 +311,7 @@ defmodule Pleroma.UserTest do
describe "unfollow/2" do
setup do: clear_config([:instance, :external_user_synchronization])
test "unfollow with synchronizes external user" do
test "unfollow with syncronizes external user" do
clear_config([:instance, :external_user_synchronization], true)
followed =
@ -2260,7 +2260,7 @@ defmodule Pleroma.UserTest do
assert other_user.follower_count == 1
end
test "synchronizes the counters with the remote instance for the followed when enabled" do
test "syncronizes the counters with the remote instance for the followed when enabled" do
clear_config([:instance, :external_user_synchronization], false)
user = insert(:user)
@ -2282,7 +2282,7 @@ defmodule Pleroma.UserTest do
assert other_user.follower_count == 437
end
test "synchronizes the counters with the remote instance for the follower when enabled" do
test "syncronizes the counters with the remote instance for the follower when enabled" do
clear_config([:instance, :external_user_synchronization], false)
user = insert(:user)

View file

@ -1632,7 +1632,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
describe "fetch_follow_information_for_user" do
test "synchronizes following/followers counters" do
test "syncronizes following/followers counters" do
user =
insert(:user,
local: false,

View file

@ -1921,48 +1921,4 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/accounts/relationships?id=#{other_user.id}")
|> json_response_and_validate_schema(200)
end
describe "remove from followers" do
setup do: oauth_access(["follow"])
test "removing user from followers", %{conn: conn, user: user} do
%{id: other_user_id} = other_user = insert(:user)
CommonAPI.follow(other_user, user)
assert %{"id" => ^other_user_id, "followed_by" => false} =
conn
|> post("/api/v1/accounts/#{other_user_id}/remove_from_followers")
|> json_response_and_validate_schema(200)
refute User.following?(other_user, user)
end
test "removing remote user from followers", %{conn: conn, user: user} do
%{id: other_user_id} = other_user = insert(:user, local: false)
CommonAPI.follow(other_user, user)
assert User.following?(other_user, user)
assert %{"id" => ^other_user_id, "followed_by" => false} =
conn
|> post("/api/v1/accounts/#{other_user_id}/remove_from_followers")
|> json_response_and_validate_schema(200)
refute User.following?(other_user, user)
end
test "removing user from followers errors", %{user: user, conn: conn} do
# self remove
conn_res = post(conn, "/api/v1/accounts/#{user.id}/remove_from_followers")
assert %{"error" => "Can not unfollow yourself"} =
json_response_and_validate_schema(conn_res, 400)
# remove non existing user
conn_res = post(conn, "/api/v1/accounts/doesntexist/remove_from_followers")
assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
end
end
end

View file

@ -3,10 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
use Pleroma.Web.ConnCase, async: false
use Pleroma.Web.ConnCase, async: true
use Oban.Testing, repo: Pleroma.Repo
import Mock
import Pleroma.Factory
alias Pleroma.Filter
@ -54,20 +53,25 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
in_seconds = 600
response =
with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/filters", %{
"phrase" => "knights",
context: ["home"],
expires_in: in_seconds
})
|> json_response_and_validate_schema(200)
end
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/filters", %{
"phrase" => "knights",
context: ["home"],
expires_in: in_seconds
})
|> json_response_and_validate_schema(200)
assert response["irreversible"] == false
assert response["expires_at"] == "2017-03-17T17:19:58.000Z"
expires_at =
NaiveDateTime.utc_now()
|> NaiveDateTime.add(in_seconds)
assert NaiveDateTime.diff(
NaiveDateTime.from_iso8601!(response["expires_at"]),
expires_at
) < 5
filter = Filter.get(response["id"], user)
@ -179,21 +183,26 @@ defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
in_seconds = 600
response =
with_mock NaiveDateTime, [:passthrough], utc_now: fn -> ~N[2017-03-17 17:09:58] end do
conn
|> put_req_header("content-type", "application/json")
|> put("/api/v1/filters/#{filter.filter_id}", %{
phrase: "nii",
context: ["public"],
expires_in: in_seconds,
irreversible: true
})
|> json_response_and_validate_schema(200)
end
conn
|> put_req_header("content-type", "application/json")
|> put("/api/v1/filters/#{filter.filter_id}", %{
phrase: "nii",
context: ["public"],
expires_in: in_seconds,
irreversible: true
})
|> json_response_and_validate_schema(200)
assert response["irreversible"] == true
assert response["expires_at"] == "2017-03-17T17:19:58.000Z"
expected_time =
NaiveDateTime.utc_now()
|> NaiveDateTime.add(in_seconds)
assert NaiveDateTime.diff(
NaiveDateTime.from_iso8601!(response["expires_at"]),
expected_time
) < 5
filter = Filter.get(response["id"], user)

View file

@ -71,7 +71,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do
equalityMatch: fn _type, _value -> :ok end,
wholeSubtree: fn -> :ok end,
search: fn _connection, _options ->
{:ok, {:eldap_search_result, [{:eldap_entry, '', []}], [], []}}
{:ok, {:eldap_search_result, [{:eldap_entry, '', []}], []}}
end,
close: fn _connection ->
send(self(), :close_connection)

View file

@ -59,9 +59,9 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do
assert csp =~ ~r|report-uri https://endpoint.com;report-to csp-endpoint;|
[report_to] = Conn.get_resp_header(conn, "report-to")
[reply_to] = Conn.get_resp_header(conn, "reply-to")
assert report_to ==
assert reply_to ==
"{\"endpoints\":[{\"url\":\"https://endpoint.com\"}],\"group\":\"csp-endpoint\",\"max-age\":10886400}"
end

View file

@ -48,42 +48,38 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
refute RateLimiter.disabled?(build_conn())
end
@tag :erratic
test "it restricts based on config values" do
limiter_name = :test_plug_opts
scale = 80
limit = 5
clear_config([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1})
clear_config([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
clear_config([:rate_limit, limiter_name], {scale, limit})
plug_opts = RateLimiter.init(name: limiter_name)
conn = build_conn(:get, "/")
for _ <- 1..5 do
conn_limited = RateLimiter.call(conn, plug_opts)
refute conn_limited.status == Conn.Status.code(:too_many_requests)
refute conn_limited.resp_body
refute conn_limited.halted
for i <- 1..5 do
conn = RateLimiter.call(conn, plug_opts)
assert {^i, _} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
Process.sleep(10)
end
conn_limited = RateLimiter.call(conn, plug_opts)
assert %{"error" => "Throttled"} = ConnTest.json_response(conn_limited, :too_many_requests)
assert conn_limited.halted
conn = RateLimiter.call(conn, plug_opts)
assert %{"error" => "Throttled"} = ConnTest.json_response(conn, :too_many_requests)
assert conn.halted
expire_ttl(conn, limiter_name)
Process.sleep(50)
for _ <- 1..5 do
conn_limited = RateLimiter.call(conn, plug_opts)
conn = build_conn(:get, "/")
refute conn_limited.status == Conn.Status.code(:too_many_requests)
refute conn_limited.resp_body
refute conn_limited.halted
end
conn = RateLimiter.call(conn, plug_opts)
assert {1, 4} = RateLimiter.inspect_bucket(conn, limiter_name, plug_opts)
conn_limited = RateLimiter.call(conn, plug_opts)
assert %{"error" => "Throttled"} = ConnTest.json_response(conn_limited, :too_many_requests)
assert conn_limited.halted
refute conn.status == Conn.Status.code(:too_many_requests)
refute conn.resp_body
refute conn.halted
end
describe "options" do
@ -267,12 +263,4 @@ defmodule Pleroma.Web.Plugs.RateLimiterTest do
refute {:err, :not_found} == RateLimiter.inspect_bucket(conn, limiter_name, opts)
end
def expire_ttl(%{remote_ip: remote_ip} = _conn, bucket_name_root) do
bucket_name = "anon:#{bucket_name_root}" |> String.to_atom()
key_name = "ip::#{remote_ip |> Tuple.to_list() |> Enum.join(".")}"
{:ok, bucket_value} = Cachex.get(bucket_name, key_name)
Cachex.put(bucket_name, key_name, bucket_value, ttl: -1)
end
end

View file

@ -200,21 +200,6 @@ defmodule Pleroma.Web.Push.ImplTest do
"New Reaction"
end
test "renders title and body for update activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "lorem ipsum"})
{:ok, activity} = CommonAPI.update(user, activity, %{status: "edited status"})
object = Object.normalize(activity, fetch: false)
assert Impl.format_body(%{activity: activity, type: "update"}, user, object) ==
"@#{user.nickname} edited a status"
assert Impl.format_title(%{activity: activity, type: "update"}) ==
"New Update"
end
test "renders title for create activity with direct visibility" do
user = insert(:user, nickname: "Bob")