Fix wiki/signup permission handling
authorMagnus Hagander <magnus@hagander.net>
Tue, 20 Nov 2018 13:30:34 +0000 (14:30 +0100)
committerMagnus Hagander <magnus@hagander.net>
Tue, 20 Nov 2018 13:30:34 +0000 (14:30 +0100)
1. Show permission denied, not 404 not found, if a user does not have
permissions on a page. The wrong error there was mighty confusing.

2. Make edit permissions imply viewer permissions. Since there is no way
to edit without viewing anyway, and it just makes a lot more sense that
way.

docs/confreg/wiki.md
postgresqleu/confwiki/views.py

index d5f3aa5a66903b7179db55e6542df8d6bd09446f..820da7be19aa88a357f5a27f3c3109acb4163371 100644 (file)
@@ -39,7 +39,8 @@ Public view
 non-registered attendees not supported).
 
 Public edit
-: If all *registered* attendees can edit this page.
+: If all *registered* attendees can edit this page. Permission to edit
+implies permission to view.
 
 History
 : If attendees that have permissions to view the page (through it
@@ -52,7 +53,8 @@ Viewer registration types
 for example if a page should be restricted to speakers.
 
 Editor registration types
-: Registration types that can *edit* this page (if it is not public).
+: Registration types that can *edit* this page (if it is not
+public). Permission to edit implies permission to view.
 
 Viewer attendees
 : Specific attendees that can view this page (if it is not public
@@ -60,7 +62,8 @@ Viewer attendees
 access)
 
 Editor attendees
-: Specific attendees that can *edit* this page.
+: Specific attendees that can *edit* this page. Permission to edit
+implies permission to view.
 
 ## Wiki page subscriptions
 
index b6aa55ede3d67c51421a8f4448e029d6bc69d584..0c33b54847b324ab741587d1260ad4728bd933fb 100644 (file)
@@ -1,5 +1,6 @@
 from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect, Http404
+from django.core.exceptions import PermissionDenied
 from django.contrib.auth.decorators import login_required
 from django.db import transaction, connection
 from django.db.models import Q
@@ -25,15 +26,34 @@ from models import Signup, AttendeeSignup
 from forms import SignupSubmitForm, SignupAdminEditForm, SignupSendmailForm
 from forms import SignupAdminEditSignupForm
 
+def _check_wiki_permissions(page, reg, readwrite=False):
+       # Edit access implies both read and write
+       if page.publicedit:
+               return
+       if page.editor_attendee.filter(id=reg.id).exists() or page.editor_regtype.filter(id=reg.regtype.id).exists():
+               return
+       if readwrite:
+               raise PermissionDenied("Edit permission denied")
+       # Now check read only
+       if page.publicview:
+               return
+       if page.viewer_attendee.filter(id=reg.id).exists() or page.viewer_regtype.filter(id=reg.regtype.id).exists():
+               return
+       raise PermissionDenied("View permission denied")
+
+def _check_signup_permissions(signup, reg):
+       if signup.public:
+               return
+       if signup.attendees.filter(id=reg.id).exists() or signup.regtypes.filter(id=reg.regtype.id).exists():
+               return
+       raise PermissionDenied("Signup permission denied")
+
 @login_required
 def wikipage(request, confurl, wikiurl):
        conference = get_object_or_404(Conference, urlname=confurl)
        reg = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user, payconfirmedat__isnull=False)
-       pageQ = Q(publicview=True) | Q(viewer_attendee=reg) | Q(viewer_regtype=reg.regtype)
-       pages = Wikipage.objects.filter(Q(conference=conference, url=wikiurl) & pageQ).distinct()
-       if len(pages) != 1:
-               raise Http404("Page not found")
-       page = pages[0]
+       page = get_object_or_404(Wikipage, conference=conference, url=wikiurl)
+       _check_wiki_permissions(page, reg)
 
        is_subscribed = WikipageSubscriber.objects.filter(page=page, subscriber=reg).exists()
 
@@ -52,11 +72,8 @@ def wikipage(request, confurl, wikiurl):
 def wikipage_subscribe(request, confurl, wikiurl):
        conference = get_object_or_404(Conference, urlname=confurl)
        reg = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user, payconfirmedat__isnull=False)
-       pageQ = Q(publicview=True) | Q(viewer_attendee=reg) | Q(viewer_regtype=reg.regtype)
-       pages = Wikipage.objects.filter(Q(conference=conference, url=wikiurl) & pageQ).distinct()
-       if len(pages) != 1:
-               raise Http404("Page not found")
-       page = pages[0]
+       page = get_object_or_404(Wikipage, conference=conference, url=wikiurl)
+       _check_wiki_permissions(page, reg)
 
        subs = WikipageSubscriber.objects.filter(page=page, subscriber=reg)
        if subs:
@@ -72,11 +89,10 @@ def wikipage_subscribe(request, confurl, wikiurl):
 def wikipage_history(request, confurl, wikiurl):
        conference = get_object_or_404(Conference, urlname=confurl)
        reg = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user, payconfirmedat__isnull=False)
-       pageQ = Q(publicview=True) | Q(viewer_attendee=reg) | Q(viewer_regtype=reg.regtype)
-       pages = Wikipage.objects.filter(Q(conference=conference, url=wikiurl) & pageQ).distinct()
-       if len(pages) != 1:
-               raise Http404("Page not found")
-       page = pages[0]
+       page = get_object_or_404(Wikipage, conference=conference, url=wikiurl)
+       _check_wiki_permissions(page, reg)
+       if not page.history:
+               raise PermissionDenied()
 
        fromid=toid=None
 
@@ -117,11 +133,8 @@ def wikipage_history(request, confurl, wikiurl):
 def wikipage_edit(request, confurl, wikiurl):
        conference = get_object_or_404(Conference, urlname=confurl)
        reg = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user, payconfirmedat__isnull=False)
-       pageQ = Q(publicedit=True) | Q(editor_attendee=reg) | Q(editor_regtype=reg.regtype)
-       pages = Wikipage.objects.filter(Q(conference=conference, url=wikiurl) & pageQ).distinct()
-       if len(pages) != 1:
-               raise Http404("Page not found")
-       page = pages[0]
+       page = get_object_or_404(Wikipage, conference=conference, url=wikiurl)
+       _check_wiki_permissions(page, reg, True)
 
        baseform = True
        preview = ''
@@ -264,12 +277,9 @@ def admin_edit_page(request, urlname, pageid):
 def signup(request, urlname, signupid):
        conference = get_object_or_404(Conference, urlname=urlname)
        reg = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user, payconfirmedat__isnull=False)
-       signupQ = Q(public=True) | Q(attendees=reg) | Q(regtypes=reg.regtype)
-       signups = Signup.objects.filter(Q(conference=conference, id=signupid) & signupQ).distinct()
+       signup = get_object_or_404(Signup, conference=conference, id=signupid)
+       _check_signup_permissions(signup, reg)
 
-       if len(signups) != 1:
-               raise Http404("Page not found")
-       signup = signups[0]
        attendee_signup = AttendeeSignup.objects.filter(signup=signup, attendee=reg)
        if len(attendee_signup) == 1:
                attendee_signup = attendee_signup[0]