Rename CreatePostView -> CreateView, add utils.is_banned

The artist formerly known as CreatePostView is a little more generic now
and outsources its ban check to a new util method, is_banned.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-06-24 16:50:46 -07:00
parent 36f73a2d31
commit a3bf5098ba
2 changed files with 37 additions and 27 deletions

View File

@@ -1,6 +1,13 @@
from board.models import Ban, RangeBan from typing import TYPE_CHECKING
from django.utils import timezone
import ipaddress import ipaddress
from board.models import Ban, RangeBan
if TYPE_CHECKING:
from board.models import Board
def get_client_ip(request): def get_client_ip(request):
"Get the IP address of a client-side request. Shamelessly copy/pasted from StackOverflow." "Get the IP address of a client-side request. Shamelessly copy/pasted from StackOverflow."
@@ -24,3 +31,17 @@ def get_ip_bans(ip: str) -> list:
if start <= ip_addr <= end: # type: ignore if start <= ip_addr <= end: # type: ignore
bans += [rangeban] bans += [rangeban]
return bans return bans
def is_banned(ip: str, board: "Board" | None) -> bool:
now = timezone.now()
bans = [ban for ban in get_ip_bans(ip) if ban.board == board or not ban.board]
if bans:
active = [ban for ban in bans if ban.expires > now]
expired = [ban for ban in bans if ban.expires <= now]
# Delete expired bans
for ban in expired:
ban.delete()
return bool(active)
else:
return False

View File

@@ -1,16 +1,17 @@
from typing import Any, Dict from typing import Any, Dict
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Q from django.db.models import Q
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView from django.views.generic import edit
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils import timezone from django.utils import timezone
from board.forms import BanForm, PostForm, ReplyForm, ReportForm from board.forms import BanForm, PostForm, ReplyForm, ReportForm
from board.models import Ban, BanTemplate, Board, Post, Report from board.models import Ban, BanTemplate, Board, Post, Report
from board.utils import get_client_ip, get_ip_bans from board.utils import *
__all__ = ( __all__ = (
"BanCreateView", "BanCreateView",
@@ -40,16 +41,17 @@ class BannedView(TemplateView):
return context return context
class CreatePostView(CreateView): class CreateView(edit.CreateView):
""" """
Helper class that sets a few variables for posts. This should not be used by itself. Helper class that sets a few variables for posts and check against bans.
This should not be used by itself.
This class sets the following variables on GET and POST: This class sets the following variables on GET and POST:
* self.board * self.board
""" """
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super(CreatePostView, self).get_form_kwargs() kwargs = super(CreateView, self).get_form_kwargs()
kwargs["board"] = self.board kwargs["board"] = self.board
kwargs["ip"] = get_client_ip(self.request) kwargs["ip"] = get_client_ip(self.request)
return kwargs return kwargs
@@ -58,28 +60,15 @@ class CreatePostView(CreateView):
# Set the board on this object # Set the board on this object
self.board = get_object_or_404(Board, url=kwargs["url"]) self.board = get_object_or_404(Board, url=kwargs["url"])
# Check for bans
ip = get_client_ip(request) ip = get_client_ip(request)
# Filter bans by board first if request.method == "POST" and is_banned(ip, self.board):
bans = [ return HttpResponseRedirect(reverse("board:banned"))
ban for ban in get_ip_bans(ip) if ban.board == self.board or not ban.board else:
] return super(CreateView, self).dispatch(request, *args, **kwargs)
if bans:
# Check if any bans are expired
now = timezone.now()
active = [ban for ban in bans if ban.expires > now]
expired = [ban for ban in bans if ban.expires <= now]
# Delete expired bans
for ban in expired:
ban.delete()
# If there are any active bans, and someone is trying to create
# something with a POST request, stop and redirect
if request.method == "POST" and active:
return HttpResponseRedirect(reverse("board:banned"))
return super(CreatePostView, self).dispatch(request, *args, **kwargs)
class BoardView(CreatePostView): class BoardView(CreateView):
model = Post model = Post
form_class = PostForm form_class = PostForm
slug_field = "url" slug_field = "url"
@@ -116,7 +105,7 @@ class BoardView(CreatePostView):
return super(BoardView, self).get_context_data(**kwargs) return super(BoardView, self).get_context_data(**kwargs)
class PostView(CreatePostView): class PostView(CreateView):
model = Post model = Post
form_class = ReplyForm form_class = ReplyForm
slug_field = "url" slug_field = "url"
@@ -141,7 +130,7 @@ class PostView(CreatePostView):
return kwargs return kwargs
class ReportView(CreatePostView): class ReportView(CreateView):
model = Report model = Report
form_class = ReportForm form_class = ReportForm
success_url = reverse_lazy("board:report_success") success_url = reverse_lazy("board:report_success")