diff --git a/board/forms.py b/board/forms.py index bb4b557..55fef39 100644 --- a/board/forms.py +++ b/board/forms.py @@ -4,6 +4,7 @@ from django.db import transaction from django.db.models import Q from django import forms from django.forms import ModelForm, ModelChoiceField +from django.forms.models import fields_for_model from django.utils import timezone from board.models import Ban, Post, Report, ReportReason, ReportRecord from hcaptcha.fields import hCaptchaField @@ -124,8 +125,23 @@ class PostModifyForm(ModelForm): class Meta: model = Post - fields = ["bump", "sticky"] + # we specify fields up here too because otherwise they won't be + # recognized by the form to update values + fields: list[str] = ["sticky"] - def clean(self): - super(PostModifyForm, self).clean() - print(self.fields["sticky"]) + def __init__(self, *args, user, **kwargs): + super(PostModifyForm, self).__init__(*args, **kwargs) + self.user = user + fields = [] + if self.user.has_perm("board.set_sticky"): + fields += ["sticky"] + # NOTE: + # We do *not* need to check permissions against these fields we're + # setting down here in the self.clean() function in the case that a + # malicious actor has access to the modify form and injects a "sticky" + # value to their modify request. + # + # We specify fields up in the Meta class, but we reset them down here. + # If the field isn't present in this list, then it doesn't get updated. + # If the field isn't present in the above list, then it doesn't get updated. + self.fields = fields_for_model(Post, fields) diff --git a/board/templates/board/base.html b/board/templates/board/base.html index 30b9b68..0160acd 100644 --- a/board/templates/board/base.html +++ b/board/templates/board/base.html @@ -12,8 +12,11 @@ - {% if perms.board.create_ban %} - + {% if perms.board.add_ban %} + + {% endif %} + {% if can_modify %} + {% endif %} {% block extrajs %}{% endblock %} diff --git a/board/templates/board/post_modify_success.html b/board/templates/board/post_modify_success.html new file mode 100644 index 0000000..d79b679 --- /dev/null +++ b/board/templates/board/post_modify_success.html @@ -0,0 +1,33 @@ +{% extends "board/base.html" %} +{% load i18n static %} +{# Title #} +{% block title %}{% translate "Post modify success" %}{% endblock %} +{# Body #} +{% block content %} +
+ {# We do not use pluralize filter for "seconds" because it's a pain to get it to translate. #} + {% blocktranslate %}Post has been modified. This window will close in {{window_timeout}} second(s).{% endblocktranslate %} +
+ + +{% endblock %} \ No newline at end of file diff --git a/board/templates/board/post_modify_view.html b/board/templates/board/post_modify_view.html index 78543d5..fec8cbc 100644 --- a/board/templates/board/post_modify_view.html +++ b/board/templates/board/post_modify_view.html @@ -5,7 +5,7 @@
{% csrf_token %} - {% if perms.board.can_sticky %} + {% if perms.board.set_sticky %} diff --git a/board/templates/board/post_snippet.html b/board/templates/board/post_snippet.html index f90f73a..2583eca 100644 --- a/board/templates/board/post_snippet.html +++ b/board/templates/board/post_snippet.html @@ -3,10 +3,10 @@
diff --git a/board/urls.py b/board/urls.py index 39eeeb2..a1e14d1 100644 --- a/board/urls.py +++ b/board/urls.py @@ -22,6 +22,9 @@ urlpatterns = [ path("banned", BannedView.as_view(), name="banned"), # Other moderation pages path("modify//", PostModifyView.as_view(), name="post_modify"), + path( + "modify/success/", PostModifySuccessView.as_view(), name="post_modify_success" + ), ] # TODO - make this conditional so we can serve images up with whatever server we want urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/board/views.py b/board/views.py index a2ec22f..6feece7 100644 --- a/board/views.py +++ b/board/views.py @@ -24,6 +24,7 @@ __all__ = ( "BoardView", "PostCreateView", "PostModifyView", + "PostModifySuccessView", "PostView", "PostSuccessView", "ReplyCreateView", @@ -35,6 +36,13 @@ __all__ = ( User = get_user_model() +def can_modify(user): + if not user: + return False + # TODO add more permissions as required + return user.has_perm("board.set_sticky") + + class BannedView(TemplateView): template_name = "board/banned.html" @@ -117,6 +125,7 @@ class BoardView(TemplateView): kwargs["pages"] = range(1, last_page + 1) kwargs["last_page"] = last_page kwargs["max_upload_size"] = settings.MAX_UPLOAD_SIZE + kwargs["can_modify"] = can_modify(self.request.user) return super(BoardView, self).get_context_data(**kwargs) @@ -135,6 +144,7 @@ class PostCreateView(CreateView): context["capcodes"] = get_objects_for_user( get_user(self.request), "board.use_capcode" ) + kwargs["can_modify"] = can_modify(self.request.user) return context def get_form_kwargs(self): @@ -152,19 +162,34 @@ class PostModifyView(PermissionRequiredMixin, edit.UpdateView): model = Post form_class = PostModifyForm template_name = "board/post_modify_view.html" + success_url = reverse_lazy("board:post_modify_success") def has_permission(self) -> bool: - user = self.request.user - if not user: - return False - # TODO add more permissions as required - return user.has_perm("board.can_sticky") + return can_modify(self.request.user) def dispatch(self, request, *args, **kwargs): self.post_obj = get_object_or_404(Post, id=kwargs["pk"]) self.board = self.post_obj.board return super(PostModifyView, self).dispatch(request, *args, **kwargs) + def get_form_kwargs(self) -> Dict[str, Any]: + kwargs = super(PostModifyView, self).get_form_kwargs() + kwargs["user"] = self.request.user + return kwargs + + +class PostModifySuccessView(PermissionRequiredMixin, TemplateView): + template_name = "board/post_modify_success.html" + + def has_permission(self) -> bool: + return can_modify(self.request.user) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["window_timeout"] = settings.BAN_WINDOW_CLOSE_TIMEOUT + context["can_modify"] = self.has_permission() + return context + class ReplyCreateView(CreateView): model = Post @@ -183,6 +208,7 @@ class ReplyCreateView(CreateView): context["capcodes"] = get_objects_for_user( get_user(self.request), "board.use_capcode" ) + kwargs["can_modify"] = can_modify(self.request.user) return context def get_form_kwargs(self): @@ -262,7 +288,7 @@ class ReportSuccessView(TemplateView): class BanCreateView(PermissionRequiredMixin, edit.CreateView): model = Ban form_class = BanForm - permission_required = "ban.create" + permission_required = "board.add_ban" success_url = reverse_lazy("board:ban_success") def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
{{form.sticky.label_tag}} {{form.sticky}}