From 556ae0726b4d47de451c4d3ad35967f05fea143c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 27 Sep 2021 14:03:06 -0700 Subject: [PATCH] Check perms in list views --- bookwyrm/models/list.py | 6 ++++ bookwyrm/views/list.py | 64 +++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index 49fb53757..022a0d981 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -92,6 +92,12 @@ class ListItem(CollectionItemMixin, BookWyrmModel): notification_type="ADD", ) + def raise_not_deletable(self, viewer): + """the associated user OR the list owner can delete""" + if self.book_list.user == viewer: + return + super().raise_not_deletable(viewer) + class Meta: """A book may only be placed into a list once, and each order in the list may be used only once""" diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 695302041..c043e4830 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -3,7 +3,6 @@ from typing import Optional from urllib.parse import urlencode from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied from django.core.paginator import Paginator from django.db import IntegrityError, transaction from django.db.models import Avg, Count, DecimalField, Q, Max @@ -270,8 +269,7 @@ def delete_list(request, list_id): book_list = get_object_or_404(models.List, id=list_id) # only the owner or a moderator can delete a list - if book_list.user != request.user and not request.user.has_perm("moderate_post"): - raise PermissionDenied + book_list.raise_not_editable(request.user) book_list.delete() return redirect("lists") @@ -334,13 +332,11 @@ def remove_book(request, list_id): with transaction.atomic(): book_list = get_object_or_404(models.List, id=list_id) item = get_object_or_404(models.ListItem, id=request.POST.get("item")) - - if not book_list.user == request.user and not item.user == request.user: - return HttpResponseNotFound() + item.raise_not_deletable(request.user) deleted_order = item.order item.delete() - normalize_book_list_ordering(book_list.id, start=deleted_order) + normalize_book_list_ordering(book_list.id, start=deleted_order) return redirect("list", list_id) @@ -351,34 +347,34 @@ def set_book_position(request, list_item_id): Action for when the list user manually specifies a list position, takes special care with the unique ordering per list. """ + list_item = get_object_or_404(models.ListItem, id=list_item_id) + list_item.list.raise_not_editable(request.user) + try: + int_position = int(request.POST.get("position")) + except ValueError: + return HttpResponseBadRequest( + "bad value for position. should be an integer" + ) + + if int_position < 1: + return HttpResponseBadRequest("position cannot be less than 1") + + book_list = list_item.book_list + + # the max position to which a book may be set is the highest order for + # books which are approved + order_max = book_list.listitem_set.filter(approved=True).aggregate( + Max("order") + )["order__max"] + + int_position = min(int_position, order_max) + + original_order = list_item.order + if original_order == int_position: + # no change + return HttpResponse(status=204) + with transaction.atomic(): - list_item = get_object_or_404(models.ListItem, id=list_item_id) - try: - int_position = int(request.POST.get("position")) - except ValueError: - return HttpResponseBadRequest( - "bad value for position. should be an integer" - ) - - if int_position < 1: - return HttpResponseBadRequest("position cannot be less than 1") - - book_list = list_item.book_list - - # the max position to which a book may be set is the highest order for - # books which are approved - order_max = book_list.listitem_set.filter(approved=True).aggregate( - Max("order") - )["order__max"] - - int_position = min(int_position, order_max) - - if request.user not in (book_list.user, list_item.user): - return HttpResponseNotFound() - - original_order = list_item.order - if original_order == int_position: - return HttpResponse(status=204) if original_order > int_position: list_item.order = -1 list_item.save()