Add user post deletion
Users can delete their posts as long as they don't clear their cookies, and as long as server-side user sessions are persistent. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -25,11 +25,12 @@ class PostForm(ModelForm):
|
||||
model = Post
|
||||
fields = ["subject", "name", "text", "capcode", "image"]
|
||||
|
||||
def __init__(self, *args, user, board, ip, **kwargs):
|
||||
def __init__(self, *args, user, board, ip, user_token, **kwargs):
|
||||
super(PostForm, self).__init__(*args, **kwargs)
|
||||
self.user = user
|
||||
self.instance.board = board
|
||||
self.instance.ip = ip
|
||||
self.instance.user_token = user_token
|
||||
self.fields["capcode"].queryset = get_objects_for_user(
|
||||
self.user, "board.use_capcode"
|
||||
)
|
||||
|
||||
@@ -124,6 +124,10 @@ class Post(models.Model):
|
||||
# Image width and height
|
||||
image_width = models.IntegerField(null=True, blank=True)
|
||||
image_height = models.IntegerField(null=True, blank=True)
|
||||
# The user token that was used to make this post. This is used for
|
||||
# verification when a user wants to delete their post. It is not
|
||||
# particularly secret and does not need to be hashed.
|
||||
user_token = models.CharField(max_length=30, null=True)
|
||||
|
||||
class Meta:
|
||||
permissions = [
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
import ipaddress
|
||||
import random
|
||||
import string
|
||||
|
||||
from board.models import Ban, RangeBan
|
||||
|
||||
@@ -45,3 +48,11 @@ def is_banned(ip: str, board: Optional["Board"]) -> bool:
|
||||
return bool(active)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def generate_user_token() -> str:
|
||||
"""
|
||||
Generates a non-secure user token.
|
||||
User tokens need not be secure so this is a simple implementation.
|
||||
"""
|
||||
return "".join(random.choices(string.ascii_letters, k=settings.USER_TOKEN_LENGTH))
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.http import Http404, HttpResponseRedirect
|
||||
from django.http.request import QueryDict
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic import detail, edit
|
||||
from django.views.generic import edit
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
|
||||
@@ -147,6 +147,10 @@ class PostCreateView(CreateView):
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(PostCreateView, self).get_form_kwargs()
|
||||
kwargs["user"] = self.request.user
|
||||
if "user_token" not in self.request.session:
|
||||
# Generate a user token
|
||||
self.request.session["user_token"] = generate_user_token()
|
||||
kwargs["user_token"] = self.request.session["user_token"]
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
@@ -213,6 +217,10 @@ class ReplyCreateView(CreateView):
|
||||
post = get_object_or_404(Post, id=post_id)
|
||||
kwargs["op"] = post
|
||||
kwargs["user"] = self.request.user
|
||||
if "user_token" not in self.request.session:
|
||||
# Generate a user token
|
||||
self.request.session["user_token"] = generate_user_token()
|
||||
kwargs["user_token"] = self.request.session["user_token"]
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
@@ -256,6 +264,13 @@ class PostDeleteView(PermissionRequiredMixin, edit.DeleteView):
|
||||
success_url = reverse_lazy("board:post_delete_success")
|
||||
raise_exception = True
|
||||
|
||||
def has_permission(self) -> bool:
|
||||
object = self.get_object()
|
||||
user_token = self.request.session.get("user_token", None)
|
||||
return self.request.user.has_perm("board.delete_post") or (
|
||||
user_token and object.user_token == user_token
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
success_url = self.get_success_url()
|
||||
if form["image_only"].value() != "0":
|
||||
|
||||
Reference in New Issue
Block a user