Adds IP blocklist views

This commit is contained in:
Mouse Reeve 2021-09-17 12:59:16 -07:00
parent 8a5004d947
commit 6022e7b232
13 changed files with 173 additions and 5 deletions

View file

@ -311,6 +311,12 @@ class EmailBlocklistForm(CustomForm):
fields = ["domain"] fields = ["domain"]
class IPBlocklistForm(CustomForm):
class Meta:
model = models.IPBlocklist
fields = ["address"]
class ServerForm(CustomForm): class ServerForm(CustomForm):
class Meta: class Meta:
model = models.FederatedServer model = models.FederatedServer

View file

@ -11,6 +11,6 @@ class IPBlocklistMiddleware:
def __call__(self, request): def __call__(self, request):
address = request.META.get("REMOTE_ADDR") address = request.META.get("REMOTE_ADDR")
if models.IPBlockList.objects.filter(address=address).exists(): if models.IPBlocklist.objects.filter(address=address).exists():
raise Http404() raise Http404()
return self.get_response(request) return self.get_response(request)

View file

@ -378,6 +378,13 @@ input[type=file]::file-selector-button:hover {
right: 1em; right: 1em;
} }
/** Tooltips
******************************************************************************/
.tooltip {
width: 100%;
}
/** States /** States
******************************************************************************/ ******************************************************************************/

View file

@ -3,7 +3,7 @@
{% trans "Help" as button_text %} {% trans "Help" as button_text %}
{% include 'snippets/toggle/open_button.html' with text=button_text class="ml-3 is-rounded is-small is-white p-0 pb-1" icon="question-circle is-size-6" controls_text=controls_text controls_uid=controls_uid %} {% include 'snippets/toggle/open_button.html' with text=button_text class="ml-3 is-rounded is-small is-white p-0 pb-1" icon="question-circle is-size-6" controls_text=controls_text controls_uid=controls_uid %}
<aside class="notification is-hidden transition-y is-pulled-left mb-2" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}"> <aside class="tooltip notification is-hidden transition-y is-pulled-left mb-2" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}">
{% trans "Close" as button_text %} {% trans "Close" as button_text %}
{% include 'snippets/toggle/close_button.html' with label=button_text class="delete" nonbutton=True controls_text=controls_text controls_uid=controls_uid %} {% include 'snippets/toggle/close_button.html' with label=button_text class="delete" nonbutton=True controls_text=controls_text controls_uid=controls_uid %}

View file

@ -8,7 +8,7 @@
{% block form %} {% block form %}
<form name="add-domain" method="post" action="{% url 'settings-email-blocks' %}"> <form name="add-domain" method="post" action="{% url 'settings-email-blocks' %}">
{% csrf_token %} {% csrf_token %}
<label class="label" for="id_event_date">{% trans "Domain:" %}</label> <label class="label" for="id_domain">{% trans "Domain:" %}</label>
<div class="field has-addons"> <div class="field has-addons">
<div class="control"> <div class="control">
<div class="button is-disabled">@</div> <div class="button is-disabled">@</div>

View file

@ -0,0 +1,36 @@
{% extends 'components/inline_form.html' %}
{% load i18n %}
{% block header %}
{% trans "Add IP address" %}
{% endblock %}
{% block form %}
<form name="add-address" method="post" action="{% url 'settings-ip-blocks' %}">
<div class="block">
{% trans "Use IP address blocks with caution, and consider using blocks only temporarily, as IP addresses are often shared or change hands. If you block your own IP, you will not be able to access this page." %}
</div>
{% csrf_token %}
<div class="field">
<label class="label" for="id_address">
{% trans "IP Address:" %}
</label>
</div>
<div class="field">
<input type="text" name="address" maxlength="255" class="input" required="" id="id_address" placeholder="190.0.2.0/24">
</div>
{% for error in form.address.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
<div class="field">
<div class="control">
<button type="submit" class="button is-primary">{% trans "Add" %}</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,47 @@
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% block title %}{% trans "IP Address Blocklist" %}{% endblock %}
{% block header %}{% trans "IP Address Blocklist" %}{% endblock %}
{% block edit-button %}
{% trans "Add IP address" as button_text %}
{% include 'snippets/toggle/open_button.html' with controls_text="add_address" icon_with_text="plus" text=button_text focus="add_address_header" %}
{% endblock %}
{% block panel %}
{% include 'settings/ip_address_form.html' with controls_text="add_address" class="block" %}
<p class="notification block">
{% trans "Any traffic from this IP address will get a 404 response when trying to access any part of the application." %}
</p>
<table class="table is-striped is-fullwidth">
<tr>
<th>
{% trans "Address" %}
</th>
<th>
{% trans "Options" %}
</th>
</tr>
{% for address in addresses %}
<tr>
<td>{{ address.address }}</td>
<td>
<form name="remove-{{ address.id }}" action="{% url 'settings-ip-blocks-delete' address.id %}" method="post">
{% csrf_token %}
{% trans "Delete" as button_text %}
<button class="button" type="submit">
<span class="icon icon-x" title="{{ button_text }}" aria-hidden="true"></span>
<span class="is-hidden-mobile">{{ button_text }}</span>
</button>
</form>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View file

@ -0,0 +1,8 @@
{% extends 'components/tooltip.html' %}
{% load i18n %}
{% block tooltip_content %}
{% trans "You can block IP ranges using CIDR syntax." %}
{% endblock %}

View file

@ -58,6 +58,10 @@
{% url 'settings-email-blocks' as url %} {% url 'settings-email-blocks' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Email Blocklist" %}</a> <a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "Email Blocklist" %}</a>
</li> </li>
<li>
{% url 'settings-ip-blocks' as url %}
<a href="{{ url }}"{% if url in request.path %} class="is-active" aria-selected="true"{% endif %}>{% trans "IP Address Blocklist" %}</a>
</li>
</ul> </ul>
{% endif %} {% endif %}
{% if perms.bookwyrm.edit_instance_settings %} {% if perms.bookwyrm.edit_instance_settings %}

View file

@ -154,6 +154,16 @@ urlpatterns = [
views.EmailBlocklist.as_view(), views.EmailBlocklist.as_view(),
name="settings-email-blocks-delete", name="settings-email-blocks-delete",
), ),
re_path(
r"^settings/ip-blocklist/?$",
views.IPBlocklist.as_view(),
name="settings-ip-blocks",
),
re_path(
r"^settings/ip-blocks/(?P<block_id>\d+)/delete/?$",
views.IPBlocklist.as_view(),
name="settings-ip-blocks-delete",
),
# moderation # moderation
re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"), re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"),
re_path( re_path(

View file

@ -5,6 +5,7 @@ from .admin.federation import Federation, FederatedServer
from .admin.federation import AddFederatedServer, ImportServerBlocklist from .admin.federation import AddFederatedServer, ImportServerBlocklist
from .admin.federation import block_server, unblock_server from .admin.federation import block_server, unblock_server
from .admin.email_blocklist import EmailBlocklist from .admin.email_blocklist import EmailBlocklist
from .admin.ip_blocklist import IPBlocklist
from .admin.invite import ManageInvites, Invite, InviteRequest from .admin.invite import ManageInvites, Invite, InviteRequest
from .admin.invite import ManageInviteRequests, ignore_invite_request from .admin.invite import ManageInviteRequests, ignore_invite_request
from .admin.reports import ( from .admin.reports import (

View file

@ -1,4 +1,4 @@
""" moderation via flagged posts and users """ """ Manage email blocklist"""
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
@ -14,7 +14,7 @@ from bookwyrm import forms, models
name="dispatch", name="dispatch",
) )
class EmailBlocklist(View): class EmailBlocklist(View):
"""Block users by email address""" """Block registration by email address"""
def get(self, request): def get(self, request):
"""view and compose blocks""" """view and compose blocks"""

View file

@ -0,0 +1,49 @@
""" Manage IP blocklist """
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View
from bookwyrm import forms, models
# pylint: disable=no-self-use
@method_decorator(login_required, name="dispatch")
@method_decorator(
permission_required("bookwyrm.moderate_user", raise_exception=True),
name="dispatch",
)
class IPBlocklist(View):
"""Block registration by ip address"""
def get(self, request):
"""view and compose blocks"""
data = {
"addresses": models.IPBlocklist.objects.all(),
"form": forms.IPBlocklistForm(),
}
return TemplateResponse(request, "settings/ip_blocklist.html", data)
def post(self, request, block_id=None):
"""create a new ip address block"""
if block_id:
return self.delete(request, block_id)
form = forms.IPBlocklistForm(request.POST)
data = {
"addresses": models.IPBlocklist.objects.all(),
"form": form,
}
if not form.is_valid():
return TemplateResponse(request, "settings/ip_blocklist.html", data)
form.save()
data["form"] = forms.IPBlocklistForm()
return TemplateResponse(request, "settings/ip_blocklist.html", data)
# pylint: disable=unused-argument
def delete(self, request, domain_id):
"""remove a domain block"""
domain = get_object_or_404(models.IPBlocklist, id=domain_id)
domain.delete()
return redirect("settings-ip-blocks")