Allow admins to upload domain blocklists

Fixes #804
This commit is contained in:
Mouse Reeve 2021-04-12 14:23:51 -07:00
parent 1bc8526710
commit 901e7f69d4
8 changed files with 128 additions and 6 deletions

View file

@ -26,7 +26,7 @@
</select>
</div>
<div class="field">
<label class="label" for="id_csv_field">{% trans "Data file:" %}</label>
<label class="label" for="id_csv_file">{% trans "Data file:" %}</label>
{{ import_form.csv_file }}
</div>
</div>

View file

@ -9,6 +9,19 @@
{% block panel %}
<div class="tabs">
<ul>
{% url 'settings-import-blocklist' as url %}
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Import block list" %}</a>
</li>
{% url 'settings-add-federated-server' as url %}
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Add server" %}</a>
</li>
</ul>
</div>
<form method="POST" action="{% url 'settings-add-federated-server' %}">
{% csrf_token %}
<div class="columns">
@ -24,8 +37,8 @@
<label class="label" for="id_status">{% trans "Status:" %}</label>
<div class="select">
<select name="status" class="" id="id_status">
<option value="federated" {% if form.status.value == "federated" or not form.status.value %}selected=""{% endif %}>{% trans "Federated" %}</option>
<option value="blocked" {% if form.status.value == "blocked" %}selected{% endif %}>{% trans "Blocked" %}</option>
<option value="federated" {% if form.status.value == "federated" %}selected=""{% endif %}>{% trans "Federated" %}</option>
<option value="blocked" {% if form.status.value == "blocked" or not form.status.value %}selected{% endif %}>{% trans "Blocked" %}</option>
</select>
</div>
</div>

View file

@ -1,6 +1,7 @@
{% extends 'settings/admin_layout.html' %}
{% block title %}{{ server.server_name }}{% endblock %}
{% load i18n %}
{% load bookwyrm_tags %}
{% block header %}
{{ server.server_name }}
@ -81,7 +82,7 @@
</div>
</header>
{% if server.notes %}
<p id="hide-edit-notes">{{ server.notes }}</p>
<p id="hide-edit-notes">{{ server.notes|to_markdown|safe }}</p>
{% endif %}
<form class="box is-hidden" method="POST" action="{% url 'settings-federated-server' server.id %}" id="edit-notes">
{% csrf_token %}

View file

@ -5,7 +5,7 @@
{% block header %}{% trans "Federated Servers" %}{% endblock %}
{% block edit-button %}
<a href="{% url 'settings-add-federated-server' %}">
<a href="{% url 'settings-import-blocklist' %}">
<span class="icon icon-plus" title="{% trans 'Add server' %}">
<span class="is-sr-only">{% trans "Add server" %}</span>
</span>

View file

@ -0,0 +1,67 @@
{% extends 'settings/admin_layout.html' %}
{% load i18n %}
{% block title %}{% trans "Add server" %}{% endblock %}
{% block header %}
{% trans "Import Blocklist" %}
<a href="{% url 'settings-federation' %}" class="has-text-weight-normal help">{% trans "Back to server list" %}</a>
{% endblock %}
{% block panel %}
<div class="tabs">
<ul>
{% url 'settings-import-blocklist' as url %}
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Import block list" %}</a>
</li>
{% url 'settings-add-federated-server' as url %}
<li {% if url in request.path %}class="is-active" aria-current="page"{% endif %}>
<a href="{{ url }}">{% trans "Add server" %}</a>
</li>
</ul>
</div>
{% if succeeded and not failed %}
<p class="notification is-primary">{% trans "Success!" %}</p>
{% elif succeeded or failed %}
<div class="block content">
{% if succeeded %}
<p>{% trans "Successfully blocked:" %} {{ succeeded }}</p>
{% endif %}
<p>{% trans "Failed:" %}</p>
<ul>
{% for item in failed %}
<li>
<pre>
{{ item }}
</pre>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form method="POST" action="{% url 'settings-import-blocklist' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="field">
<label class="label" for="id_file">JSON data:</label>
<aside class="help">
Expects a json file in the format provided by <a href="https://fediblock.org/" target="_blank" rel=”noopener”>FediBlock</a>, with a list of entries that have <code>instance</code> and <code>url</code> fields. For example:
<pre>
[
{
"instance": "example.server.com",
"url": "https://link.to.more/info"
},
...
]
</pre>
</aside>
<input type="file" name="json_file" required="" id="id_file">
</div>
<button type="submit" class="button is-primary">{% trans "Import" %}</button>
</form>
{% endblock %}

View file

@ -83,6 +83,11 @@ urlpatterns = [
views.AddFederatedServer.as_view(),
name="settings-add-federated-server",
),
re_path(
r"^settings/federation/import/?$",
views.ImportServerBlocklist.as_view(),
name="settings-import-blocklist",
),
re_path(
r"^settings/invites/?$", views.ManageInvites.as_view(), name="settings-invites"
),

View file

@ -5,7 +5,8 @@ from .block import Block, unblock
from .books import Book, EditBook, ConfirmEditBook, Editions
from .books import upload_cover, add_description, switch_edition, resolve_book
from .directory import Directory
from .federation import Federation, FederatedServer, AddFederatedServer
from .federation import Federation, FederatedServer
from .federation import AddFederatedServer, ImportServerBlocklist
from .federation import block_server, unblock_server
from .feed import DirectMessage, Feed, Replies, Status
from .follow import follow, unfollow

View file

@ -1,6 +1,8 @@
""" manage federated servers """
import json
from django.contrib.auth.decorators import login_required, permission_required
from django.core.paginator import Paginator
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
@ -63,6 +65,39 @@ class AddFederatedServer(View):
return redirect("settings-federated-server", server.id)
class ImportServerBlocklist(View):
""" manually add a server """
def get(self, request):
""" add server form """
return TemplateResponse(request, "settings/server_blocklist.html")
def post(self, request):
""" add a server from the admin panel """
json_data = json.load(
request.FILES["json_file"]
)
failed = []
success_count = 0
for item in json_data:
server_name = item.get("instance")
if not server_name:
failed.append(item)
continue
info_link = item.get("url")
with transaction.atomic():
server, _ = models.FederatedServer.objects.get_or_create(
server_name=server_name,
)
server.notes = info_link
server.save()
server.block()
success_count += 1
data = {"failed": failed, "succeeded": success_count}
return TemplateResponse(request, "settings/server_blocklist.html", data)
@method_decorator(login_required, name="dispatch")
@method_decorator(
permission_required("bookwyrm.control_federation", raise_exception=True),