From 475bff14cb496574b204acee31718e295469f4da Mon Sep 17 00:00:00 2001 From: Skia Date: Tue, 8 Dec 2015 11:10:29 +0100 Subject: [PATCH] Refactor rights handling --- core/models.py | 48 ++++++++++++++++++++++-- core/templates/core/page_detail.html | 4 +- core/views/__init__.py | 55 ++++++++-------------------- core/views/page.py | 5 +++ 4 files changed, 69 insertions(+), 43 deletions(-) diff --git a/core/models.py b/core/models.py index 8e691e57..16b7289d 100644 --- a/core/models.py +++ b/core/models.py @@ -135,6 +135,46 @@ class User(AbstractBaseUser, PermissionsMixin): self.username = user_name return user_name + def is_owner(self, obj): + """ + Determine if the object is owned by the user + """ + # TODO: add permission scale validation, to allow some groups other than superuser to manipulate + # all objects of a class if they are in the right group + if not hasattr(obj, "owner_group"): + return False + if self.is_superuser or self.groups.filter(name=obj.owner_group.name).exists(): + return True + return False + + def can_edit(self, obj): + """ + Determine if the object can be edited by the user + """ + if not hasattr(obj, "edit_group"): + return False + if self.is_owner(obj): + return True + for g in obj.edit_group.all(): + if self.groups.filter(name=g.name).exists(): + return True + return False + + def can_view(self, obj): + """ + Determine if the object can be viewed by the user + """ + if not hasattr(obj, "view_group"): + return False + if self.can_edit(obj): + return True + for g in obj.view_group.all(): + if self.groups.filter(name=g.name).exists(): + return True + if isinstance(obj, User) and obj == self: + return True + return False + class LockError(Exception): """There was a lock error on the object""" pass @@ -237,7 +277,7 @@ class Page(models.Model): if self.pk not in Page.lock_mutex.keys(): # print("Page mutex does not exists") return False - if (timezone.now()-Page.lock_mutex[self.pk]['time']) > timedelta(seconds=5): + if (timezone.now()-Page.lock_mutex[self.pk]['time']) > timedelta(minutes=5): # print("Lock timed out") self.unset_lock() return False @@ -251,7 +291,7 @@ class Page(models.Model): raise AlreadyLocked("The page is already locked by someone else") Page.lock_mutex[self.pk] = {'user': user, 'time': timezone.now()} - print("Locking page") + # print("Locking page") def set_lock_recursive(self, user): """ @@ -264,7 +304,7 @@ class Page(models.Model): def unset_lock(self): """Always try to unlock, even if there is no lock""" Page.lock_mutex.pop(self.pk, None) - print("Unlocking page") + # print("Unlocking page") def get_lock(self): """ @@ -322,6 +362,8 @@ class PageRev(models.Model): return self.page.edit_group elif attr == "view_group": return self.page.view_group + elif attr == "unset_lock": + return self.page.unset_lock else: return object.__getattribute__(self, attr) diff --git a/core/templates/core/page_detail.html b/core/templates/core/page_detail.html index 8255312b..ea9b7412 100644 --- a/core/templates/core/page_detail.html +++ b/core/templates/core/page_detail.html @@ -3,8 +3,10 @@ {% block page %}

Page

Back to list

- {% if user.is_superuser %} + {% if can_edit %}

Edit

+ {% endif %} + {% if can_edit_prop %}

Prop

{% endif %}

You're seeing the page {{ page.get_display_name }} - diff --git a/core/views/__init__.py b/core/views/__init__.py index 2112f219..9991e740 100644 --- a/core/views/__init__.py +++ b/core/views/__init__.py @@ -23,63 +23,40 @@ class CanEditPropMixin(View): """ def dispatch(self, request, *arg, **kwargs): res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) - obj = self.object - user = self.request.user - if obj is None: + if self.object is None or self.request.user.is_owner(self.object): return res - # TODO: add permission scale validation, to allow some groups other than superuser to manipulate - # all objects of a class if they are in the right group - if user.is_superuser or user.groups.filter(name=obj.owner_group.name).exists(): - return res - print("Guyuy") - self.object.unset_lock() + try: # Always unlock when 403 + self.object.unset_lock() + except: pass raise PermissionDenied - return HttpResponseForbidden("403, Forbidden") -class CanEditMixin(CanEditPropMixin): +class CanEditMixin(View): """ This view makes exactly the same this as its direct parent, but checks the group on the edit_group field of the object """ def dispatch(self, request, *arg, **kwargs): # TODO: WIP: fix permissions with exceptions! - try: - res = super(CanEditMixin, self).dispatch(request, *arg, **kwargs) - return res - except PermissionDenied: - pass - res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) - obj = self.object - user = self.request.user - if obj is None: - return res - for g in obj.edit_group.all(): - if user.groups.filter(name=g.name).exists(): - return res - if isinstance(obj, User) and obj == user: + res = super(CanEditMixin, self).dispatch(request, *arg, **kwargs) + if self.object is None or self.request.user.can_edit(self.object): return res + try: # Always unlock when 403 + self.object.unset_lock() + except: pass raise PermissionDenied - return HttpResponseForbidden("403, Forbidden") -class CanViewMixin(CanEditMixin): +class CanViewMixin(View): """ This view still makes exactly the same this as its direct parent, but checks the group on the view_group field of the object """ def dispatch(self, request, *arg, **kwargs): - try: - res = super(CanViewMixin, self).dispatch(request, *arg, **kwargs) + res = super(CanViewMixin, self).dispatch(request, *arg, **kwargs) + if self.object is None or self.request.user.can_view(self.object): return res - except PermissionDenied: - pass - res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) - obj = self.object - user = self.request.user - if obj is None: - return res - for g in obj.view_group.all(): - if user.groups.filter(name=g.name).exists(): - return res + try: # Always unlock when 403 + self.object.unset_lock() + except: pass raise PermissionDenied from .user import * diff --git a/core/views/page.py b/core/views/page.py index 9b99fbc1..c8cbd13e 100644 --- a/core/views/page.py +++ b/core/views/page.py @@ -27,6 +27,11 @@ class PageView(CanViewMixin, DetailView): context = super(PageView, self).get_context_data(**kwargs) if "page" not in context.keys(): context['new_page'] = self.kwargs['page_name'] + if self.request.user.is_owner(self.object): + context['can_edit_prop'] = True + if self.request.user.can_edit(self.object): + context['can_edit'] = True + return context class PageHistView(CanViewMixin, DetailView):