Files
interchan/board/views.py
Alek Ratzloff 28ccd7d73b Add IP bans
Users can be banned by IP address now, either by singular IP or in an IP
range. If they are banned and attempt to post, they will be met with a
"you are banned until X date" screen.

There are a few loose threads with this, and IP bans may be obsolete if
I decide to go the accounts-required-for-posting route. But I think this
is a good start for 4chan style posting.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
2022-06-20 15:26:35 -07:00

152 lines
4.8 KiB
Python

from django.conf import settings
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.views.generic import DetailView
from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView
from django.urls import reverse, reverse_lazy
from board.forms import PostForm, ReplyForm, ReportForm
from board.models import Ban, Post, Board, Report
from board.utils import get_client_ip, get_ip_bans
__all__ = ("BannedView", "BoardView", "PostView", "ReportView")
class BannedView(TemplateView):
template_name = "board/banned.html"
def get_context_data(self, **kwargs):
context = super(TemplateView, self).get_context_data(**kwargs)
ip = get_client_ip(self.request)
bans = get_ip_bans(ip)
context["bans"] = bans
context["ip"] = ip
return context
class CreatePostView(CreateView):
"""
Helper class that sets a few variables for posts. This should not be used by itself.
This class sets the following variables on GET and POST:
* self.board
"""
def get(self, request, *args, **kwargs):
self._set_board(kwargs["url"])
return super(CreatePostView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self._set_board(kwargs["url"])
return super(CreatePostView, self).post(request, *args, **kwargs)
def _set_board(self, board_url: str):
board = get_object_or_404(Board, url=board_url)
self.board = board
def get_form_kwargs(self):
kwargs = super(CreatePostView, self).get_form_kwargs()
kwargs["board"] = self.board
kwargs["ip"] = get_client_ip(self.request)
return kwargs
def dispatch(self, request, *args, **kwargs):
self._set_board(kwargs["url"])
if request.method == "POST":
ip = get_client_ip(request)
bans = [
ban
for ban in get_ip_bans(ip)
if ban.board == self.board or not ban.board
]
if bans:
return HttpResponseRedirect(reverse("board:banned"))
return super(CreatePostView, self).dispatch(request, *args, **kwargs)
class BoardView(CreatePostView):
model = Post
form_class = PostForm
slug_field = "url"
slug_url_kwarg = "url"
template_name = "board/board_detail.html"
def get(self, request, *args, **kwargs):
# If the page isn't set, then redirect to the /page/1 url
if "page" not in kwargs:
return HttpResponseRedirect(
reverse("board:board_detail", kwargs={"url": kwargs["url"], "page": 1})
)
return super(BoardView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
page = self.kwargs["page"]
if page not in range(1, self.board.max_pages + 1):
raise Http404()
threads_per_page = self.board.threads_per_page
start = (page - 1) * threads_per_page
end = start + threads_per_page
thread_count = self.board.threads.count()
last_page = (thread_count // threads_per_page) + 1
kwargs["board"] = self.board
kwargs["threads"] = self.board.threads.order_by("-last_bump")[start:end]
kwargs["current_page"] = page
kwargs["pages"] = range(1, last_page + 1)
kwargs["last_page"] = last_page
kwargs["max_upload_size"] = settings.MAX_UPLOAD_SIZE
return super(BoardView, self).get_context_data(**kwargs)
class PostView(CreatePostView):
model = Post
form_class = ReplyForm
slug_field = "url"
slug_url_kwarg = "url"
template_name = "board/post_detail.html"
def get_context_data(self, **kwargs):
kwargs["board"] = self.board
post_id = self.kwargs["id"]
kwargs["post"] = get_object_or_404(Post, id=post_id)
kwargs["max_upload_size"] = settings.MAX_UPLOAD_SIZE
return super(PostView, self).get_context_data(**kwargs)
def get_form_kwargs(self):
kwargs = super(PostView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
kwargs["reply"] = post
return kwargs
class ReportView(CreatePostView):
model = Report
form_class = ReportForm
success_url = reverse_lazy("board:report_success")
def get_context_data(self, **kwargs):
return super(ReportView, self).get_context_data(**kwargs)
@property
def board_url(self) -> str:
return self.kwargs["url"]
@property
def post_id(self) -> int:
return self.kwargs["id"]
def get_form_kwargs(self):
kwargs = super(ReportView, self).get_form_kwargs()
post_id = self.kwargs["id"]
post = get_object_or_404(Post, id=post_id)
kwargs["op"] = post
return kwargs