forked from AkkomaGang/akkoma
Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
af90a4e51b | |||
5e7be063c7 | |||
a1317bf541 | |||
a0dd670e68 | |||
11d29d27b8 | |||
44da806a77 | |||
d7c805b0bb | |||
c52982e9c5 | |||
2e433e106f | |||
bfbe4e8dce |
37 changed files with 133 additions and 723 deletions
|
@ -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
10
.gitignore
vendored
|
@ -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
|
||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -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
|
||||
|
|
51
Dockerfile
51
Dockerfile
|
@ -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"]
|
||||
|
|
|
@ -185,7 +185,7 @@
|
|||
adapter: []
|
||||
|
||||
config :pleroma, :instance,
|
||||
name: "Akkoma",
|
||||
name: "Pleroma",
|
||||
email: "example@example.com",
|
||||
notify_email: "noreply@example.com",
|
||||
description: "Akkoma: The cooler fediverse server",
|
||||
|
|
|
@ -1389,12 +1389,6 @@
|
|||
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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
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 @@
|
|||
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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
MIX_ENV=prod
|
||||
DB_NAME=akkoma
|
||||
DB_USER=akkoma
|
||||
DB_PASS=akkoma
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
docker-compose run --rm akkoma $@
|
|
@ -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).
|
||||
|
|
|
@ -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 !}
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 !}
|
||||
|
|
@ -67,9 +67,8 @@ def create(relationship_type, %User{} = source, %User{} = target) 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
|
||||
|
||||
|
|
|
@ -334,22 +334,6 @@ def unblock_operation 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"],
|
||||
|
|
|
@ -102,7 +102,7 @@ defp register_user(connection, base, uid, name) 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,
|
||||
|
|
|
@ -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 @@ def note(
|
|||
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
|
||||
|
|
|
@ -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 @@ def format_body(
|
|||
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 @@ def format_title(%{type: type}, mastodon_type) 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
|
||||
|
|
|
@ -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 |
|
@ -61,12 +61,6 @@ def handle_cast(:refresh, _state) 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 @@ def handle_cast({:restart, _, delay}, state) 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}
|
||||
|
|
|
@ -13,8 +13,7 @@ def project do
|
|||
|
||||
def application do
|
||||
[
|
||||
mod: {Restarter, []},
|
||||
extra_applications: [:logger]
|
||||
mod: {Restarter, []}
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -119,87 +119,44 @@ test "transfer config values with full subkey update" 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
|
||||
|
|
|
@ -122,11 +122,11 @@ test "recreating an existing participations sets it to unread" 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
|
||||
|
|
|
@ -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 @@ test "creates user relationship record if it doesn't exist", %{users: [user1, us
|
|||
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
|
||||
|
|
|
@ -311,7 +311,7 @@ test "local users do not automatically follow local locked accounts" 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 @@ test "updates the counters normally on following/getting a follow when disabled"
|
|||
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 @@ test "synchronizes the counters with the remote instance for the followed when e
|
|||
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)
|
||||
|
|
|
@ -1632,7 +1632,7 @@ test "fetches only public posts for other users" 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,
|
||||
|
|
|
@ -1921,48 +1921,4 @@ test "create a note on a user" 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
|
||||
|
|
|
@ -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 @@ test "a filter with expires_in", %{conn: conn, user: user} 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 @@ test "with adding expires_at", %{conn: conn, user: user} 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)
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ test "creates a new user after successful LDAP authorization" 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)
|
||||
|
|
|
@ -48,42 +48,38 @@ test "it is enabled if remote_ip_found flag doesn't exist" 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 @@ test "doesn't crash due to a race condition when multiple requests are made at t
|
|||
|
||||
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
|
||||
|
|
|
@ -200,21 +200,6 @@ test "renders title and body for pleroma:emoji_reaction activity" 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")
|
||||
|
||||
|
|
Loading…
Reference in a new issue