From a3bf5098ba7ade7347d8b654ce84ad9bfae0b349 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Fri, 24 Jun 2022 16:50:46 -0700 Subject: [PATCH] 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 --- board/utils.py | 23 ++++++++++++++++++++++- board/views.py | 41 +++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/board/utils.py b/board/utils.py index 44cd221..c94fd9a 100644 --- a/board/utils.py +++ b/board/utils.py @@ -1,6 +1,13 @@ -from board.models import Ban, RangeBan +from typing import TYPE_CHECKING +from django.utils import timezone import ipaddress +from board.models import Ban, RangeBan + + +if TYPE_CHECKING: + from board.models import Board + def get_client_ip(request): "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 bans += [rangeban] 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 diff --git a/board/views.py b/board/views.py index 2ac99c2..7fcb90a 100644 --- a/board/views.py +++ b/board/views.py @@ -1,16 +1,17 @@ from typing import Any, Dict from django.conf import settings from django.contrib.auth.mixins import PermissionRequiredMixin +from django.core.exceptions import ImproperlyConfigured from django.db.models import Q from django.http import Http404, HttpResponseRedirect from django.shortcuts import get_object_or_404 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.utils import timezone from board.forms import BanForm, PostForm, ReplyForm, ReportForm from board.models import Ban, BanTemplate, Board, Post, Report -from board.utils import get_client_ip, get_ip_bans +from board.utils import * __all__ = ( "BanCreateView", @@ -40,16 +41,17 @@ class BannedView(TemplateView): 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: * self.board """ def get_form_kwargs(self): - kwargs = super(CreatePostView, self).get_form_kwargs() + kwargs = super(CreateView, self).get_form_kwargs() kwargs["board"] = self.board kwargs["ip"] = get_client_ip(self.request) return kwargs @@ -58,28 +60,15 @@ class CreatePostView(CreateView): # Set the board on this object self.board = get_object_or_404(Board, url=kwargs["url"]) + # Check for bans ip = get_client_ip(request) - # Filter bans by board first - bans = [ - ban for ban in get_ip_bans(ip) if ban.board == self.board or not ban.board - ] - 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) + if request.method == "POST" and is_banned(ip, self.board): + return HttpResponseRedirect(reverse("board:banned")) + else: + return super(CreateView, self).dispatch(request, *args, **kwargs) -class BoardView(CreatePostView): +class BoardView(CreateView): model = Post form_class = PostForm slug_field = "url" @@ -116,7 +105,7 @@ class BoardView(CreatePostView): return super(BoardView, self).get_context_data(**kwargs) -class PostView(CreatePostView): +class PostView(CreateView): model = Post form_class = ReplyForm slug_field = "url" @@ -141,7 +130,7 @@ class PostView(CreatePostView): return kwargs -class ReportView(CreatePostView): +class ReportView(CreateView): model = Report form_class = ReportForm success_url = reverse_lazy("board:report_success")