mirror of
https://code.eliotberriot.com/funkwhale/funkwhale.git
synced 2025-10-06 05:09:56 +02:00
Merge branch 'develop'
This commit is contained in:
commit
f29daefa76
436 changed files with 64250 additions and 26142 deletions
|
@ -1,5 +1,5 @@
|
|||
FROM python:3.6
|
||||
|
||||
RUN apt-get update && apt-get install -y graphviz
|
||||
RUN pip install sphinx livereload
|
||||
RUN pip install sphinx livereload sphinx_rtd_theme
|
||||
WORKDIR /app/docs
|
||||
|
|
|
@ -42,9 +42,17 @@ Replace the ``location /_protected/media`` block with the following::
|
|||
|
||||
location ~ /_protected/media/(.+) {
|
||||
internal;
|
||||
# Needed to ensure DSub auth isn't forwarded to S3/Minio, see #932
|
||||
proxy_set_header Authorization "";
|
||||
proxy_pass $1;
|
||||
}
|
||||
|
||||
Add your S3 store URL to the ``img-src`` and ``media-src`` headers
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
add_header Content-Security-Policy "...img-src 'self' https://<your-s3-URL> data:;...media-src https://<your-s3-URL> 'self' data:";
|
||||
|
||||
Then restart Funkwhale and nginx.
|
||||
|
||||
From now on, media files will be stored on the S3 bucket you configured. If you already
|
||||
|
@ -71,9 +79,9 @@ This URL is actually be visible by the client, but contains a signature valid on
|
|||
no one can reuse this URL or share it publicly to distribute unauthorized content.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
If you are using Amazon S3, you will need to set your ``AWS_S3_REGION_NAME`` in the ``.env`` file to
|
||||
use this feature.
|
||||
use this feature.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -136,8 +144,41 @@ in your ``funkwhale.template`` under the ``location ~/_protected/media/(.+)`` se
|
|||
.. code-block:: shell
|
||||
|
||||
location ~ /_protected/media/(.+) {
|
||||
resolver 1.1.1.1;
|
||||
internal;
|
||||
proxy_pass $1;
|
||||
resolver 1.1.1.1;
|
||||
internal;
|
||||
proxy_set_header Authorization "";
|
||||
proxy_pass $1;
|
||||
}
|
||||
|
||||
No Images or Media Loading
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are serving media from an S3-compatible store, you may experience an issue where
|
||||
nothing loads in the front end. The error logs in your browser may show something like
|
||||
the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Content Security Policy: The page's settings blocked the loading of a resource at https://<your-s3-url> ("img-src")
|
||||
Content Security Policy: The page's settings blocked the loading of a resource at https://<your-s3-url> ("media-src")
|
||||
|
||||
This happens when your S3 store isn't defined in the ``Content-Security-Policy`` headers
|
||||
in your Nginx files. To resolve the issue, add the base URL of your S3 store to the ``img-src``
|
||||
and ``media-src`` headers and reload nginx.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
add_header Content-Security-Policy "...img-src 'self' https://<your-s3-URL> data:;...media-src https://<your-s3-URL> 'self' data:";
|
||||
|
||||
Broken Images in Audio Player On Page Reload
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are serving media directly from an S3-compatible store, you may find that images
|
||||
in the queue and the player won't load after the page is refreshed. This happens if the
|
||||
generated URL has expired and the authorization is no longer valid. You can extend the expiry time
|
||||
using the following setting in your ``.env`` file:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# The default value is 3600 (60 mins). The maximum is 604800 (7 days)
|
||||
AWS_QUERYSTRING_EXPIRE=604800
|
||||
|
|
|
@ -25,6 +25,13 @@ to the ``/music`` directory on the container:
|
|||
export LIBRARY_ID="<your_libary_id>"
|
||||
docker-compose run --rm api python manage.py import_files $LIBRARY_ID "/music/**/*.ogg" --recursive --noinput
|
||||
|
||||
When you installed Funkwhale via ansible, you need to call a script instead of Python, and the folder path must be adapted accordingly:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
export LIBRARY_ID="<your_libary_id>"
|
||||
/srv/funkwhale/manage import_files $LIBRARY_ID "/srv/funkwhale/data/music/**/**/*.ogg" --recursive --noinput
|
||||
|
||||
.. note::
|
||||
You'll have to create a library in the Web UI before to get your library ID. Simply visit
|
||||
https://yourdomain/content/libraries/ to create one.
|
||||
|
|
|
@ -26,6 +26,7 @@ Administration
|
|||
commands
|
||||
url
|
||||
upgrading
|
||||
mrf
|
||||
|
||||
Troubleshooting Issues
|
||||
----------------------
|
||||
|
|
117
docs/admin/mrf.rst
Normal file
117
docs/admin/mrf.rst
Normal file
|
@ -0,0 +1,117 @@
|
|||
Message Rewrite Facility (MRF)
|
||||
==============================
|
||||
|
||||
Funkwhale includes a feature that mimics `Pleroma's Message Rewrite Facility <https://docs-develop.pleroma.social/mrf.html>`_.
|
||||
Using the MRF, instance admins can write and configure custom and automated moderation rules
|
||||
that couldn't be implemented otherwise using :doc:`our other built-in moderation tools <../moderator/index>`.
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The MRF is a pluggable system that will process messages and forward those to the list
|
||||
of registered policies, in turn. Each policy can mutate the message, leave it as is, or discard it entirely.
|
||||
|
||||
Some of our built-in moderation tools are actually implemented as a MRF policy, e.g:
|
||||
|
||||
- Allow-list, when checking incoming messages (`code <https://dev.funkwhale.audio/funkwhale/funkwhale/blob/develop/api/funkwhale_api/moderation/mrf_policies.py>`_)
|
||||
- Domain and user blocking, when checking incoming messages (`code <https://dev.funkwhale.audio/funkwhale/funkwhale/blob/develop/api/funkwhale_api/federation/mrf_policies.py>`_)
|
||||
|
||||
.. note::
|
||||
|
||||
While Pleroma MRF policies can also affect outgoing messages, this is not supported yet in Funkwhale.
|
||||
|
||||
|
||||
Disclaimer
|
||||
----------
|
||||
|
||||
Writing custom MRF can impact negatively the performance and stability of your pod, as well as message
|
||||
delivery. Your policy will be called everytime a message is delivered, so ensure you don't execute
|
||||
any slow operation here.
|
||||
|
||||
Please note that the Funkwhale developers consider custom MRF policy modules to fall under the purview of the AGPL. As such, you are obligated to release the sources to your custom MRF policy modules upon request.
|
||||
|
||||
Writing your first MRF policy
|
||||
-----------------------------
|
||||
|
||||
MRF Policies are written as Python 3 functions that take at least one ``payload`` parameter.
|
||||
This payload is the raw ActivityPub message, received via HTTP, after the HTTP signature check.
|
||||
|
||||
In the example below we write a policy that discards all Follow requests from listed domains:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import urllib.parse
|
||||
from funkwhale_api.moderation import mrf
|
||||
|
||||
BLOCKED_FOLLOW_DOMAINS = ['domain1.com', 'botdomain.org']
|
||||
|
||||
# registering the policy is required to have it applied
|
||||
# the name can be anything you want, it will appear in the mrf logs
|
||||
@mrf.inbox.register(name='blocked_follow_domains')
|
||||
def blocked_follow_domains_policy(payload, **kwargs):
|
||||
actor_id = payload.get('actor')
|
||||
domain = urllib.parse.urlparse(actor_id).hostname
|
||||
if domain not in BLOCKED_FOLLOW_DOMAINS:
|
||||
# raising mrf.Skip isn't strictly necessary but it provides
|
||||
# for info in the debug logs. Otherwise, you can simply return
|
||||
raise mrf.Skip("This domain isn't blocked")
|
||||
|
||||
activity_type = payload.get('type')
|
||||
object_type = payload.get('object', {}).get('type')
|
||||
|
||||
if object_type == 'Follow' and activity_type == 'Create':
|
||||
raise mrf.Discard('Follow from blocked domain')
|
||||
|
||||
|
||||
This code must be stored in a Funkwhale plugin. To create one, just execute the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# plugin name must contain only ASCII letters, numbers and undercores
|
||||
export PLUGIN_NAME="myplugin"
|
||||
# this is the default path where Funkwhale will look for plugins
|
||||
# if you want to use another path, update this path and ensure
|
||||
# your PLUGINS_PATH is also included in your .env
|
||||
export PLUGINS_PATH="/srv/funkwhale/plugins/"
|
||||
mkdir -p $PLUGINS_PATH/$PLUGIN_NAME
|
||||
cd $PLUGINS_PATH/$PLUGIN_NAME
|
||||
|
||||
touch __init__.py # required to make the plugin a valid Python package
|
||||
# create the required apps.py file to register our plugin in Funkwhale
|
||||
cat > apps.py <<EOF
|
||||
from django.apps import AppConfig
|
||||
|
||||
class Plugin(AppConfig):
|
||||
name = "$PLUGIN_NAME"
|
||||
|
||||
EOF
|
||||
|
||||
Once you have a Funkwhale plugin, simply put your MRF policy code inside a ``mrf_policies.py``
|
||||
file whithin the plugin directory. Then enable the plugin in your ``.env`` by
|
||||
adding its name to the coma-separated list of ``FUNKWHALE_PLUGINS`` (add the variable if it's not there).
|
||||
|
||||
|
||||
Testing a MRF policy
|
||||
--------------------
|
||||
|
||||
To make the job of writing and debugging MRF policies easier, we provide a management
|
||||
command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python manage.py mrf_check --help
|
||||
# list registered MRF policies
|
||||
python manage.py mrf_check --list
|
||||
|
||||
# check how our MRF would handle a legit follow
|
||||
export MRF_MESSAGE='{"actor": "https://normal.domain/@alice", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | python manage.py mrf_check inbox - -p blocked_follow_domains
|
||||
|
||||
# check how our MRF would handle a problematic follow
|
||||
export MRF_MESSAGE='{"actor": "https://botdomain.org/@bob", "type": "Create", "object": {"type": "Follow"}}'
|
||||
echo $MRF_MESSAGE | python manage.py mrf_check inbox - -p blocked_follow_domains
|
||||
|
||||
# check against an activity already present in the database
|
||||
# you can get the UUID of activities by visiting /api/admin/federation/activity
|
||||
export ACTIVITY_UUID="06208aea-c687-4e8b-aefd-22f1c3f76039"
|
||||
echo $MRF_MESSAGE | python manage.py mrf_check inbox $ACTIVITY_UUID -p blocked_follow_domains
|
|
@ -136,6 +136,10 @@ keeping a backup of the old version in ``./postgres-old``:
|
|||
Non-docker setup
|
||||
----------------
|
||||
|
||||
If you installed Funkwhale using the install script, upgrading is done using ``sh -c "$(curl -sSL https://get.funkwhale.audio/upgrade.sh)"``. Make sure to run this command with root permissions.
|
||||
|
||||
If you manually installed Funkwhale, please use the following instructions.
|
||||
|
||||
Upgrade the static files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
17
docs/conf.py
17
docs/conf.py
|
@ -89,13 +89,24 @@ todo_include_todos = False
|
|||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "alabaster"
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
html_theme_options = {
|
||||
'gitlab_url': 'https://dev.funkwhale.audio/funkwhale/funkwhale'
|
||||
}
|
||||
html_context = {
|
||||
'display_gitlab': True,
|
||||
'gitlab_host': 'dev.funkwhale.audio',
|
||||
'gitlab_repo': 'funkwhale',
|
||||
'gitlab_user': 'funkwhale',
|
||||
'gitlab_version': 'master',
|
||||
'conf_py_path': '/docs/',
|
||||
}
|
||||
html_logo = 'logo.svg'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
|
@ -166,7 +177,7 @@ redirect_files = [
|
|||
('importing-music.html', 'admin/importing-music.html'),
|
||||
('architecture.html', 'developers/architecture.html'),
|
||||
('troubleshooting.html', 'admin/troubleshooting.html'),
|
||||
('configuration.html', 'admin/configuration.html'),
|
||||
('configuration.html', 'admin/configuration.html'),
|
||||
('upgrading/index.html', '../admin/upgrading.html'),
|
||||
('upgrading/0.17.html', '../admin/0.17.html'),
|
||||
('users/django.html', '../admin/django.html'),
|
||||
|
|
2
docs/get-releases-json.py
Normal file → Executable file
2
docs/get-releases-json.py
Normal file → Executable file
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
|
|
|
@ -24,7 +24,7 @@ On Debian-like systems, you can install them using:
|
|||
# Install dependencies
|
||||
sudo apt-get install curl python3-pip python3-venv git unzip libldap2-dev libsasl2-dev
|
||||
# Funkwhale dependencies
|
||||
sudo apt install build-essential ffmpeg libjpeg-dev libmagic-dev libpq-dev postgresql-client python3-dev
|
||||
sudo apt install build-essential ffmpeg libjpeg-dev libmagic-dev libpq-dev postgresql-client python3-dev make
|
||||
|
||||
On Arch Linux and its derivatives:
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@ Create the user and the directory:
|
|||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo useradd -r -s /usr/bin/nologin -d /srv/funkwhale -m funkwhale
|
||||
sudo adduser funkwhale docker
|
||||
sudo useradd -r -s /usr/bin/nologin -m -d /srv/funkwhale -U -G docker funkwhale
|
||||
cd /srv/funkwhale
|
||||
|
||||
Log in as the newly created user from now on:
|
||||
|
@ -39,7 +38,7 @@ Log in as the newly created user from now on:
|
|||
|
||||
sudo -u funkwhale -H bash
|
||||
|
||||
Export the version you want to deploy:
|
||||
Export the `version you want <https://hub.docker.com/r/funkwhale/all-in-one/tags>`_ to deploy (e.g., ``0.19.1``):
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
@ -50,16 +49,24 @@ Create an env file to store a few important configuration options:
|
|||
.. code-block:: shell
|
||||
|
||||
touch .env
|
||||
echo "FUNKWHALE_HOSTNAME=yourdomain.funkwhale" >> .env
|
||||
echo "FUNKWHALE_PROTOCOL=https" >> .env # or http
|
||||
echo "NGINX_MAX_BODY_SIZE=100M" >> .env
|
||||
echo "FUNKWHALE_API_IP=127.0.0.1" >> .env
|
||||
echo "FUNKWHALE_API_PORT=5000" >> .env # or the container port you want to expose on the host
|
||||
echo "DJANGO_SECRET_KEY=$(openssl rand -hex 45)" >> .env # generate and store a secure secret key for your instance
|
||||
# Remove this if you expose the container directly on ports 80/443
|
||||
echo "NESTED_PROXY=1" >> .env
|
||||
|
||||
chmod 600 .env # reduce permissions on the .env file since it contains sensitive data
|
||||
cat > .env <<EOD
|
||||
# Replace 'your.funkwhale.example' with your actual domain
|
||||
FUNKWHALE_HOSTNAME=your.funkwhale.example
|
||||
# Protocol may also be: http
|
||||
FUNKWHALE_PROTOCOL=https
|
||||
# This limits the upload size
|
||||
NGINX_MAX_BODY_SIZE=100M
|
||||
# Bind to localhost
|
||||
FUNKWHALE_API_IP=127.0.0.1
|
||||
# Container port you want to expose on the host
|
||||
FUNKWHALE_API_PORT=5000
|
||||
# Generate and store a secure secret key for your instance
|
||||
DJANGO_SECRET_KEY=$(openssl rand -hex 45)
|
||||
# Remove this if you expose the container directly on ports 80/443
|
||||
NESTED_PROXY=1
|
||||
EOD
|
||||
|
||||
|
||||
Then start the container:
|
||||
|
||||
|
@ -143,6 +150,11 @@ Useful commands:
|
|||
ports:
|
||||
- "5000:80"
|
||||
|
||||
Then start the container:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker-compose up -d
|
||||
|
||||
.. _docker-multi-container:
|
||||
|
||||
|
@ -151,7 +163,7 @@ Multi-container installation
|
|||
|
||||
First, ensure you have `Docker <https://docs.docker.com/engine/installation/>`_ and `docker-compose <https://docs.docker.com/compose/install/>`_ installed.
|
||||
|
||||
Export the version you want to deploy:
|
||||
Export the `version you want <https://hub.docker.com/r/funkwhale/all-in-one/tags>`_ to deploy (e.g., ``0.19.1``):
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
@ -164,9 +176,9 @@ Download the sample docker-compose file:
|
|||
mkdir /srv/funkwhale
|
||||
cd /srv/funkwhale
|
||||
mkdir nginx
|
||||
curl -L -o nginx/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/deploy/docker.nginx.template"
|
||||
curl -L -o nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/deploy/docker.funkwhale_proxy.conf"
|
||||
curl -L -o docker-compose.yml "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/deploy/docker-compose.yml"
|
||||
curl -L -o nginx/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/docker.nginx.template"
|
||||
curl -L -o nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/docker.funkwhale_proxy.conf"
|
||||
curl -L -o docker-compose.yml "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/docker-compose.yml"
|
||||
|
||||
At this point, the architecture of ``/srv/funkwhale`` should look like that:
|
||||
|
||||
|
@ -182,7 +194,7 @@ Create your env file:
|
|||
|
||||
.. parsed-literal::
|
||||
|
||||
curl -L -o .env "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/|version|/deploy/env.prod.sample"
|
||||
curl -L -o .env "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/${FUNKWHALE_VERSION}/deploy/env.prod.sample"
|
||||
sed -i "s/FUNKWHALE_VERSION=latest/FUNKWHALE_VERSION=$FUNKWHALE_VERSION/" .env
|
||||
chmod 600 .env # reduce permissions on the .env file since it contains sensitive data
|
||||
sudo nano .env
|
||||
|
|
|
@ -305,6 +305,22 @@ installation guide.
|
|||
Check the configuration is valid with ``apache2ctl configtest``, and once you're
|
||||
done, load the new configuration with ``service apache2 restart``.
|
||||
|
||||
Caddy
|
||||
^^^^^
|
||||
|
||||
If you're using Caddy as a reverse proxy in front of your docker containers (either mono or multi-container setup),
|
||||
you can use the following configuration::
|
||||
|
||||
yourdomain.funkwhale {
|
||||
proxy / 127.0.0.1:5000 {
|
||||
transparent
|
||||
websocket
|
||||
header_upstream X-Forwarded-Host {host}:{server_port}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
About internal locations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
30
docs/logo.svg
Normal file
30
docs/logo.svg
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 256 256" style="enable-background:new 0 0 256 256;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill:#009FE3;}
|
||||
.st2{fill:#3C3C3B;}
|
||||
</style>
|
||||
<circle class="st0" cx="128" cy="128" r="128"/>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M128,157.1c17.7,0,32.1-14.4,32.1-32.1c0-0.9-0.8-1.7-1.7-1.7h-12.1c-0.9,0-1.7,0.8-1.7,1.7
|
||||
c0,9.1-7.4,16.6-16.6,16.6c-9.1,0-16.6-7.4-16.6-16.6c0-0.9-0.8-1.7-1.7-1.7H97.6c-0.9,0-1.7,0.8-1.7,1.7
|
||||
C95.9,142.8,110.3,157.1,128,157.1z"/>
|
||||
<path class="st1" d="M128,187.4c34.3,0,62.3-28,62.3-62.3c0-0.9-0.8-1.7-1.7-1.7h-12.1c-0.9,0-1.7,0.8-1.7,1.7
|
||||
c0,25.9-21,46.9-46.9,46.9s-46.9-21-46.9-46.9c0-0.9-0.8-1.7-1.7-1.7H67.4c-0.9,0-1.7,0.8-1.7,1.7
|
||||
C65.5,159.4,93.5,187.4,128,187.4z"/>
|
||||
<path class="st1" d="M219,123.4h-12.1c-0.9,0-1.7,0.8-1.7,1.7c0,42.6-34.8,77.3-77.3,77.3c-42.6,0-77.3-34.6-77.3-77.3
|
||||
c0-0.9-0.8-1.7-1.7-1.7H37c-0.9,0-1.7,0.8-1.7,1.7c0,51.1,41.6,92.7,92.7,92.7s92.7-41.6,92.7-92.7
|
||||
C220.7,124.2,219.9,123.4,219,123.4z"/>
|
||||
</g>
|
||||
<path class="st2" d="M86.3,83.3c6.2,3.2,12.9,3.8,18.9,7.3c3.9,2.3,6.4,4.8,8.8,8.6c3.8,5.7,3.6,12.9,3.6,12.9l0.5,7.9
|
||||
c0,0,3,7.9,9.7,7.9c7.1,0,9.7-7.9,9.7-7.9l0.5-7.9c0,0-0.2-7.1,3.6-12.9c2.4-3.8,4.8-6.5,8.8-8.6c6-3.5,12.7-4.1,18.9-7.3
|
||||
c6.2-3.2,12.2-7.3,16.3-13s6-13.3,3.8-20c-11.8-0.6-25.4,0.8-35.8,6.4c-14.5,7.7-23.3,5-25.9,16.5h-0.2
|
||||
c-2.6-11.6-11.3-8.8-25.9-16.5c-10.4-5.6-24-7-35.8-6.4c-2.3,6.7-0.3,14.2,3.8,20C74,76.1,80.1,80.2,86.3,83.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -2,7 +2,7 @@ Moderator Documentation
|
|||
=========================
|
||||
|
||||
This documentation is targeted at instance moderators. Moderators have enhanced permissions
|
||||
which allow them to moderate federated accounts and domains.
|
||||
which allow them to handle reports and moderate federated accounts and domains.
|
||||
|
||||
Moderation Guides
|
||||
-----------------
|
||||
|
@ -10,5 +10,7 @@ Moderation Guides
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
reports
|
||||
domains
|
||||
users
|
||||
users
|
||||
listing
|
||||
|
|
94
docs/moderator/listing.rst
Normal file
94
docs/moderator/listing.rst
Normal file
|
@ -0,0 +1,94 @@
|
|||
Allow-Listing
|
||||
=============
|
||||
|
||||
The Allow-Listing feature grants pod moderators
|
||||
and administrators greater control over federation
|
||||
by allowing you to create a pod-wide allow-list.
|
||||
|
||||
When allow-listing is enabled, your pod's users will only
|
||||
be able to interact with pods included in the allow-list.
|
||||
Any messages, activity, uploads, or modifications to
|
||||
libraries and playlists will only be shared with pods
|
||||
on the allow-list. Pods which are not included in the
|
||||
allow-list will not have access to your pod's content
|
||||
or messages and will not be able to send anything to
|
||||
your pod.
|
||||
|
||||
Enabling Allow-Listing
|
||||
----------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
If your pod is already federating proceed with caution.
|
||||
Enabling the Allow-Listing feature will initially block
|
||||
all activity from external domains as the list will be
|
||||
empty
|
||||
|
||||
To enable allow-listing:
|
||||
|
||||
- Navigate to the "Settings" menu
|
||||
- Go to the "Moderation" section
|
||||
- Toggle the "Enable allow-listing" radio button
|
||||
- Click "Save" to commit the change
|
||||
|
||||
Once enabled, you can start adding domains to your
|
||||
allow-list.
|
||||
|
||||
Adding/Removing Domains
|
||||
-----------------------
|
||||
|
||||
Add a New Domain
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
- Navigate to the "Moderation" menu. Any domains currently
|
||||
in the allow-list will be visible here with a green check
|
||||
mark next to their name. Other pods with which you have previously
|
||||
interacted will also be visible here
|
||||
- Type the domain name of the pod you wish to allow into
|
||||
the "Add a Domain" input box in the top-right of the screen
|
||||
- Tick the "Add to allow-list" tickbox
|
||||
- Click "Add" to add the domain
|
||||
|
||||
Add a Known Domain
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Navigate to the "Moderation" menu. Any domains currently
|
||||
in the allow-list will be visible here with a green check
|
||||
mark next to their name. Other pods with which you have previously
|
||||
interacted will also be visible here
|
||||
- Click on the tickbox next to the domain(s) you wish to add to
|
||||
the allow-list
|
||||
- Select "Add to allow-list" from the drop-down menu titled "Actions"
|
||||
and click "Go" to add the domain(s)
|
||||
|
||||
Remove a Domain
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
To remove a domain from the allow-list:
|
||||
|
||||
- Navigate to the "Moderation" menu. Any domains currently
|
||||
in the allow-list will be visible here with a green check
|
||||
mark next to their name. Other pods with which you have previously
|
||||
interacted will also be visible here
|
||||
- Click on the tickbox next to the domain(s) you wish to remove
|
||||
from the allow-list
|
||||
- Select "Remove from allow-list" from the drop-down menu titled
|
||||
"Actions" and click "Go" to remove the domain(s)
|
||||
|
||||
Purging Existing Content
|
||||
------------------------
|
||||
|
||||
Moderators can add and remove domains at any time, and removing
|
||||
a domain from the allow-list will effectively block all future
|
||||
content from being received on your pod. Previously received
|
||||
messages and content from pods not on the allow-list will remain
|
||||
until you purge it from your pod. To do this:
|
||||
|
||||
- Navigate to the "Moderation" menu. Any domains currently
|
||||
in the allow-list will be visible here with a green check
|
||||
mark next to their name. Other pods with which you have
|
||||
previously interacted will also be visible here
|
||||
- Click on the tickbox next to the domain(s) you wish to purge
|
||||
received messages from
|
||||
- Select "Purge" from the drop-down menu titled "Actions"
|
||||
and click "Go" to purge the messages
|
44
docs/moderator/reports.rst
Normal file
44
docs/moderator/reports.rst
Normal file
|
@ -0,0 +1,44 @@
|
|||
Handling user reports
|
||||
=====================
|
||||
|
||||
:doc:`Users can submit reports </users/reports>` in various places. When they do so,
|
||||
their report ends up in a moderation queue until it is reviewed and resolved by a moderator.
|
||||
|
||||
View unresolved reports
|
||||
-----------------------
|
||||
|
||||
Assuming you have the moderation permission, you'll find a "Moderation" link in the sidebar.
|
||||
|
||||
Clicking on this link will bring you to the list of unresolved reports. For convenience,
|
||||
the number of unresolved reports (if any) is also displayed directly next to this link, and updated in real time
|
||||
when new reports are submitted.
|
||||
|
||||
Email notifications
|
||||
-------------------
|
||||
|
||||
In addition to the web UI, all moderators will receive a notification email whenever a report is
|
||||
submitted or resolved providing your pod has a valid email sending configuration.
|
||||
This notification will include a link to review and handle the report, as well as additional
|
||||
information about the report itself.
|
||||
|
||||
Handling reports
|
||||
----------------
|
||||
|
||||
When viewing the moderation queue, you will be presented with the list of unresolved reports.
|
||||
|
||||
Each report in the queue should include all the information you need to handle it, in particular:
|
||||
|
||||
- Who submitted the report (or the email adress of the submitter if it's an accountless report)
|
||||
- The report content
|
||||
- A link to the reported object, and a copy of this object data at the time the report was submitted
|
||||
|
||||
When you mark a report as resolved, the report will simply be removed from the queue, and you can proceed to the next one.
|
||||
|
||||
Doing so will also assign the report to you, so other moderators can see who handled a given report.
|
||||
|
||||
Internal Notes
|
||||
--------------
|
||||
|
||||
Whenever you need to perform an action because of a report, you can use the included form to leave a note to other moderators, or even yourself, for reference.
|
||||
|
||||
These notes are viewable by instance admins and moderators only.
|
174
docs/swagger.yml
174
docs/swagger.yml
|
@ -33,6 +33,79 @@ info:
|
|||
If you keep the default server (https://demo.funkwhale.audio), the default username and password
|
||||
couple is "demo" and "demo".
|
||||
|
||||
Rate limiting
|
||||
-------------
|
||||
|
||||
Depending on server configuration, pods running Funkwhale 0.20 and higher may rate-limit incoming
|
||||
requests to prevent abuse and improve the stability of service. Requests that are dropped because of rate-limiting
|
||||
receive a 429 HTTP response.
|
||||
|
||||
The limits themselves vary depending on:
|
||||
|
||||
- The client: anonymous requests are subject to lower limits than authenticated requests
|
||||
- The operation being performed: Write and delete operations, as performed with DELETE, POST, PUT and PATCH HTTP methods are subject to lower limits
|
||||
|
||||
Those conditions are used to determine the scope of the request, which in turns determine the limit that is applied.
|
||||
For instance, authenticated POST requests are bound to the `authenticated-create` scope, with a default limit of
|
||||
1000 requests/hour, but anonymous POST requests are bound to the `anonymous-create` scope, with a lower limit of 1000 requests/day.
|
||||
|
||||
A full list of scopes with their corresponding description, and the current usage data for the client performing the request
|
||||
is available via the `/api/v1/rate-limit` endpoint.
|
||||
|
||||
Additionally, we include HTTP headers on all API response to ensure API clients can understand:
|
||||
|
||||
- what scope was bound to a given request
|
||||
- what is the corresponding limit
|
||||
- how much similar requests can be sent before being limited
|
||||
- and how much time they should wait if they have been limited
|
||||
|
||||
<table>
|
||||
<caption>Rate limiting headers</caption>
|
||||
<thead>
|
||||
<th>Header</th>
|
||||
<th>Example value</th>
|
||||
<th>Description value</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-Limit</code></td>
|
||||
<td>50</td>
|
||||
<td>The number of allowed requests whithin a given period</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-Duration</code></td>
|
||||
<td>3600</td>
|
||||
<td>The time window, in seconds, during which those requests are accounted for.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-Scope</code></td>
|
||||
<td>login</td>
|
||||
<td>The name of the scope as computed for the request</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-Remaining</code></td>
|
||||
<td>42</td>
|
||||
<td>How many requests can be sent with the same scope before the limit applies</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Retry-After</code> (if <code>X-RateLimit-Remaining</code> is 0)</td>
|
||||
<td>3543</td>
|
||||
<td>How many seconds to wait before a retry</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-Reset</code></td>
|
||||
<td>1568126089</td>
|
||||
<td>A timestamp indicating when <code>X-RateLimit-Remaining</code> will return to its higher possible value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>X-RateLimit-ResetSeconds</code></td>
|
||||
<td>3599</td>
|
||||
<td>How many seconds to wait before <code>X-RateLimit-Remaining</code> returns to its higher possible value</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
|
@ -103,7 +176,7 @@ security:
|
|||
|
||||
tags:
|
||||
- name: Auth and security
|
||||
description: Login, logout and authorization endpoints
|
||||
description: Login, logout, rate-limit and authorization endpoints
|
||||
- name: Library and metadata
|
||||
description: Information and metadata about musical and audio entities (albums, tracks, artists, etc.)
|
||||
- name: Uploads and audio content
|
||||
|
@ -117,7 +190,7 @@ paths:
|
|||
/api/v1/oauth/apps/:
|
||||
post:
|
||||
tags:
|
||||
- "auth"
|
||||
- "Auth and security"
|
||||
description:
|
||||
Register an OAuth application
|
||||
security: []
|
||||
|
@ -247,6 +320,19 @@ paths:
|
|||
schema:
|
||||
$ref: "#/definitions/Me"
|
||||
|
||||
/api/v1/rate-limit/:
|
||||
get:
|
||||
summary: Retrive rate-limit information and current usage status
|
||||
tags:
|
||||
- "Auth and security"
|
||||
|
||||
responses:
|
||||
200:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/definitions/RateLimitStatus"
|
||||
|
||||
/api/v1/artists/:
|
||||
get:
|
||||
summary: List artists
|
||||
|
@ -296,6 +382,7 @@ paths:
|
|||
summary: Retrieve a single artist
|
||||
parameters:
|
||||
- $ref: "#/parameters/ObjectId"
|
||||
- $ref: "#/parameters/Refresh"
|
||||
security:
|
||||
- oauth2:
|
||||
- "read:libraries"
|
||||
|
@ -395,6 +482,7 @@ paths:
|
|||
summary: Retrieve a single album
|
||||
parameters:
|
||||
- $ref: "#/parameters/ObjectId"
|
||||
- $ref: "#/parameters/Refresh"
|
||||
|
||||
security:
|
||||
- oauth2:
|
||||
|
@ -518,6 +606,7 @@ paths:
|
|||
get:
|
||||
parameters:
|
||||
- $ref: "#/parameters/ObjectId"
|
||||
- $ref: "#/parameters/Refresh"
|
||||
summary: Retrieve a single track
|
||||
|
||||
security:
|
||||
|
@ -974,6 +1063,14 @@ parameters:
|
|||
schema:
|
||||
required: false
|
||||
type: "boolean"
|
||||
Refresh:
|
||||
name: "refresh"
|
||||
in: "query"
|
||||
default: false
|
||||
description: "Trigger an ActivityPub fetch to refresh local data"
|
||||
schema:
|
||||
required: false
|
||||
type: "boolean"
|
||||
|
||||
responses:
|
||||
200:
|
||||
|
@ -1179,6 +1276,10 @@ definitions:
|
|||
- $ref: "#/definitions/BaseArtist"
|
||||
- type: "object"
|
||||
properties:
|
||||
tracks_count:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 42
|
||||
albums:
|
||||
type: "array"
|
||||
items:
|
||||
|
@ -1631,6 +1732,75 @@ definitions:
|
|||
type: "boolean"
|
||||
example: false
|
||||
description: A boolean indicating if the user can manage instance settings and users
|
||||
RateLimitStatus:
|
||||
type: "object"
|
||||
properties:
|
||||
enabled:
|
||||
type: "boolean"
|
||||
example: true
|
||||
description: A boolean indicating if rate-limiting is enabled on the server
|
||||
ident:
|
||||
type: "object"
|
||||
description: Client-related data
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
example: "anonymous"
|
||||
enum:
|
||||
- "authenticated"
|
||||
- "anonymous"
|
||||
id:
|
||||
type: string
|
||||
example: "92.143.42"
|
||||
description: An address IP or user ID identifying the client
|
||||
scopes:
|
||||
type: "array"
|
||||
items:
|
||||
type: "object"
|
||||
description: Rate-limit scope configuration and usage
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: "password-reset"
|
||||
description:
|
||||
type: string
|
||||
example: "Password reset request"
|
||||
rate:
|
||||
type: string
|
||||
example: "30/day"
|
||||
limit:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 30
|
||||
duration:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 86400
|
||||
remaining:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 28
|
||||
description: How many requests can be sent with the same scope before the limit applies
|
||||
reset:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 1568126189
|
||||
description: A timestamp indicating when <code>remaining</code> will return to its higher possible value
|
||||
reset_seconds:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 86267
|
||||
description: How many seconds to wait before <code>remaining</code> returns to its higher possible value
|
||||
available:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 1568126089
|
||||
description: A timestamp indicating when the client can retry
|
||||
available_seconds:
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 54
|
||||
description: How many seconds to wait before a retry
|
||||
|
||||
ResourceNotFound:
|
||||
type: "object"
|
||||
|
|
14
docs/users/account.rst
Normal file
14
docs/users/account.rst
Normal file
|
@ -0,0 +1,14 @@
|
|||
Manage your account
|
||||
===================
|
||||
|
||||
Delete your account
|
||||
-------------------
|
||||
|
||||
You can delete your Funkwhale account by visiting your settings. The deletion form is found at the bottom of the page. You will need to input your password to confirm the deletion.
|
||||
|
||||
Once the deletion request is submitted, your account and associated data will be removed from the server within a few minutes. This includes, but isn't limited to your avatar, email address, music, favorites, radios, followers and playlists.
|
||||
|
||||
Your server will also broadcast a message to other server on the federation to inform them about the deletion.
|
||||
|
||||
Please note that while these servers are supposed to comply and delete any local copy of your data, this isn't a strong guarantee and some data may remain available, especially on servers
|
||||
that are offline or unreachable when the deletion message is broadcasted.
|
|
@ -21,6 +21,7 @@ Using Funkwhale
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
account
|
||||
queue
|
||||
managing
|
||||
playlists
|
||||
|
@ -28,6 +29,7 @@ Using Funkwhale
|
|||
radios
|
||||
follow
|
||||
apps
|
||||
reports
|
||||
../cli/index
|
||||
|
||||
Troubleshooting Issues
|
||||
|
|
54
docs/users/reports.rst
Normal file
54
docs/users/reports.rst
Normal file
|
@ -0,0 +1,54 @@
|
|||
Reporting content and accounts
|
||||
==============================
|
||||
|
||||
Funkwhale includes a report feature you can use to contact your pod's moderators.
|
||||
|
||||
If you think some action, such as removal, should be taken toward an account or specific content (like an artist or a library), we encourage you to use
|
||||
this feature. This is especially recommended if you find illegal or abusive content, or anything that could be an infraction of your pod's rules.
|
||||
|
||||
After submission, your pod moderators will be notified and will be able to :doc:`act on your report </moderator/reports>`.
|
||||
|
||||
Submit a report
|
||||
---------------
|
||||
|
||||
You can submit those reports from various places in the app, depending on what you are reporting (see below).
|
||||
|
||||
You'll need to pick a category for your report. Available categories are:
|
||||
|
||||
- **Takedown request**: to request removal of copyrighted material
|
||||
- **Illegal content**: to report an account, track, album, artist, library, playlist or account that features illegal content
|
||||
- **Offensive content**: to report an account, track, album, artist, library, playlist or account that features offensive or abusive content
|
||||
- **Invalid metadata**: to report a track, album or artist with invalid or incomplete metadata
|
||||
- **Other**: to report anything else that doesn't fit into one of these categories
|
||||
|
||||
You can also include with your report an additional explanation to ensure moderators can understand and act on the issue.
|
||||
|
||||
Accountless reports
|
||||
-------------------
|
||||
|
||||
If this feature is enabled on the pod you are browsing, you'll be able to submit reports without an account.
|
||||
|
||||
This works exactly the same, but the report form will have an extra "email" field where you should include a working
|
||||
email address, in the event moderators need to contact you.
|
||||
|
||||
Reporting an account
|
||||
--------------------
|
||||
|
||||
Accounts can be reported in two ways.
|
||||
|
||||
- When viewing user activity, such as favorites or listening history, the dropdown menu next to the corresponding activity will include an option to report the account
|
||||
- When viewing a library the dropdown menu in the top right corner will include an option to report the corresponding account
|
||||
|
||||
Reporting an artist, playlist, album or track
|
||||
---------------------------------------------
|
||||
|
||||
Anything you can play can typically be reported using the dropdown menu on the "Play" button.
|
||||
|
||||
Additionally, when viewing the detail page of an artist, playlist, album or track, you can find the
|
||||
report option under the dropdown menu on the "More…" button.
|
||||
|
||||
|
||||
Reporting a library
|
||||
-------------------
|
||||
|
||||
When viewing a library the dropdown menu in the top right corner will include an option to report the library.
|
|
@ -74,16 +74,19 @@ However, Funkwhale can understand and use additional tags to enhance user experi
|
|||
| ``Title`` (required) | ``Letting you`` | The track title |
|
||||
| | | |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Album`` (required) | ``The Slip`` | The album title |
|
||||
| | | |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Artist`` (required) | ``Nine Inch Nails`` | The artist name |
|
||||
| | | |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Album`` | ``The Slip`` | The album title. If none is provided, an [Unknown Album] |
|
||||
| | | entry will be created |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Album artist`` | ``Trent Reznor`` | The album artist name (can be different than the track |
|
||||
| | | artist) |
|
||||
| | | |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Genre`` | ``Industrial, Metal`` | A comma separated list of tags to associate with the track |
|
||||
| | | Other supported separators: ``;`` and ``/`` |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
| ``Track number`` | ``4`` | The position of the track in the album/release |
|
||||
| | | |
|
||||
+----------------------------------+--------------------------------------------+---------------------------------------------------------------+
|
||||
|
@ -173,7 +176,7 @@ and reupload it.
|
|||
|
||||
.. _unknown_error:
|
||||
|
||||
Unkwown error
|
||||
Unknown error
|
||||
:::::::::::::
|
||||
|
||||
This error can happen for multiple reasons and likely indicates an issue with the Funkwhale
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue