Refactor rights handling

This commit is contained in:
Skia 2015-12-08 11:10:29 +01:00
parent dc37e79f14
commit 475bff14cb
4 changed files with 69 additions and 43 deletions

View File

@ -135,6 +135,46 @@ class User(AbstractBaseUser, PermissionsMixin):
self.username = user_name self.username = user_name
return 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): class LockError(Exception):
"""There was a lock error on the object""" """There was a lock error on the object"""
pass pass
@ -237,7 +277,7 @@ class Page(models.Model):
if self.pk not in Page.lock_mutex.keys(): if self.pk not in Page.lock_mutex.keys():
# print("Page mutex does not exists") # print("Page mutex does not exists")
return False 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") # print("Lock timed out")
self.unset_lock() self.unset_lock()
return False return False
@ -251,7 +291,7 @@ class Page(models.Model):
raise AlreadyLocked("The page is already locked by someone else") raise AlreadyLocked("The page is already locked by someone else")
Page.lock_mutex[self.pk] = {'user': user, Page.lock_mutex[self.pk] = {'user': user,
'time': timezone.now()} 'time': timezone.now()}
print("Locking page") # print("Locking page")
def set_lock_recursive(self, user): def set_lock_recursive(self, user):
""" """
@ -264,7 +304,7 @@ class Page(models.Model):
def unset_lock(self): def unset_lock(self):
"""Always try to unlock, even if there is no lock""" """Always try to unlock, even if there is no lock"""
Page.lock_mutex.pop(self.pk, None) Page.lock_mutex.pop(self.pk, None)
print("Unlocking page") # print("Unlocking page")
def get_lock(self): def get_lock(self):
""" """
@ -322,6 +362,8 @@ class PageRev(models.Model):
return self.page.edit_group return self.page.edit_group
elif attr == "view_group": elif attr == "view_group":
return self.page.view_group return self.page.view_group
elif attr == "unset_lock":
return self.page.unset_lock
else: else:
return object.__getattribute__(self, attr) return object.__getattribute__(self, attr)

View File

@ -3,8 +3,10 @@
{% block page %} {% block page %}
<h3>Page</h3> <h3>Page</h3>
<p><a href="{% url 'core:page_list' %}">Back to list</a></p> <p><a href="{% url 'core:page_list' %}">Back to list</a></p>
{% if user.is_superuser %} {% if can_edit %}
<p><a href="{% url 'core:page_edit' page.get_full_name %}">Edit</a></p> <p><a href="{% url 'core:page_edit' page.get_full_name %}">Edit</a></p>
{% endif %}
{% if can_edit_prop %}
<p><a href="{% url 'core:page_prop' page.get_full_name %}">Prop</a></p> <p><a href="{% url 'core:page_prop' page.get_full_name %}">Prop</a></p>
{% endif %} {% endif %}
<p>You're seeing the page <strong>{{ page.get_display_name }}</strong> - <p>You're seeing the page <strong>{{ page.get_display_name }}</strong> -

View File

@ -23,63 +23,40 @@ class CanEditPropMixin(View):
""" """
def dispatch(self, request, *arg, **kwargs): def dispatch(self, request, *arg, **kwargs):
res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs)
obj = self.object if self.object is None or self.request.user.is_owner(self.object):
user = self.request.user
if obj is None:
return res return res
# TODO: add permission scale validation, to allow some groups other than superuser to manipulate try: # Always unlock when 403
# all objects of a class if they are in the right group self.object.unset_lock()
if user.is_superuser or user.groups.filter(name=obj.owner_group.name).exists(): except: pass
return res
print("Guyuy")
self.object.unset_lock()
raise PermissionDenied 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 This view makes exactly the same this as its direct parent, but checks the group on the edit_group field of the
object object
""" """
def dispatch(self, request, *arg, **kwargs): def dispatch(self, request, *arg, **kwargs):
# TODO: WIP: fix permissions with exceptions! # TODO: WIP: fix permissions with exceptions!
try: res = super(CanEditMixin, self).dispatch(request, *arg, **kwargs)
res = super(CanEditMixin, self).dispatch(request, *arg, **kwargs) if self.object is None or self.request.user.can_edit(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.edit_group.all():
if user.groups.filter(name=g.name).exists():
return res
if isinstance(obj, User) and obj == user:
return res return res
try: # Always unlock when 403
self.object.unset_lock()
except: pass
raise PermissionDenied 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 This view still makes exactly the same this as its direct parent, but checks the group on the view_group field of
the object the object
""" """
def dispatch(self, request, *arg, **kwargs): 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 return res
except PermissionDenied: try: # Always unlock when 403
pass self.object.unset_lock()
res = super(CanEditPropMixin, self).dispatch(request, *arg, **kwargs) except: pass
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
raise PermissionDenied raise PermissionDenied
from .user import * from .user import *

View File

@ -27,6 +27,11 @@ class PageView(CanViewMixin, DetailView):
context = super(PageView, self).get_context_data(**kwargs) context = super(PageView, self).get_context_data(**kwargs)
if "page" not in context.keys(): if "page" not in context.keys():
context['new_page'] = self.kwargs['page_name'] 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 return context
class PageHistView(CanViewMixin, DetailView): class PageHistView(CanViewMixin, DetailView):