Fix Page locking

This commit is contained in:
Skia 2016-11-05 13:37:30 +01:00
parent c0c8b295ba
commit 59f5917b8c
6 changed files with 56 additions and 24 deletions

View File

@ -167,15 +167,14 @@ Welcome to the wiki page!
r.save()
# Adding syntax help page
p = Page(name='Aide_sur_la_syntaxe')
p.save()
p.save(force_lock=True)
PageRev(page=p, title="Aide sur la syntaxe", author=skia, content="""
Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
""").save()
p = Page(name='Services')
p.save()
p.set_lock(skia)
p.save(force_lock=True)
p.view_groups=[settings.SITH_GROUPS['public']['id']]
p.save()
p.save(force_lock=True)
PageRev(page=p, title="Services", author=skia, content="""
| | | |
| :---: | :---: | :---: |
@ -185,10 +184,9 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
""").save()
# Adding README
p = Page(name='README')
p.save()
p.save(force_lock=True)
p.view_groups=[settings.SITH_GROUPS['public']['id']]
p.set_lock(skia)
p.save()
p.save(force_lock=True)
with open(os.path.join(root_path)+'/README.md', 'r') as rm:
PageRev(page=p, title="README", author=skia, content=rm.read()).save()

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('core', '0004_user_godfathers'),
]
operations = [
migrations.AddField(
model_name='page',
name='lock_timeout',
field=models.DateTimeField(verbose_name='lock_timeout', null=True, blank=True, default=None),
),
migrations.AddField(
model_name='page',
name='lock_user',
field=models.ForeignKey(verbose_name='lock user', default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True, related_name='locked_pages'),
),
]

View File

@ -630,7 +630,8 @@ class Page(models.Model):
default=settings.SITH_GROUPS['root']['id'])
edit_groups = models.ManyToManyField(Group, related_name="editable_page", verbose_name=_("edit group"), blank=True)
view_groups = models.ManyToManyField(Group, related_name="viewable_page", verbose_name=_("view group"), blank=True)
lock_mutex = {}
lock_user = models.ForeignKey(User, related_name="locked_pages", verbose_name=_("lock user"), blank=True, null=True, default=None)
lock_timeout = models.DateTimeField(_('lock_timeout'), null=True, blank=True, default=None)
class Meta:
unique_together = ('name', 'parent')
@ -679,7 +680,9 @@ class Page(models.Model):
"""
Performs some needed actions before and after saving a page in database
"""
if not self.is_locked():
locked = kwargs.pop('force_lock', False)
if not locked: locked = self.is_locked()
if not locked:
raise NotLocked("The page is not locked and thus can not be saved")
self.full_clean()
# This reset the _full_name just before saving to maintain a coherent field quicker for queries than the
@ -697,23 +700,20 @@ class Page(models.Model):
This is where the timeout is handled, so a locked page for which the timeout is reach will be unlocked and this
function will return False
"""
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(minutes=5):
if self.lock_timeout and (timezone.now() - self.lock_timeout > timedelta(minutes=5)):
# print("Lock timed out")
self.unset_lock()
return False
return True
return self.lock_user and self.lock_timeout and (timezone.now() - self.lock_timeout < timedelta(minutes=5))
def set_lock(self, user):
"""
Sets a lock on the current page or raise an AlreadyLocked exception
"""
if self.is_locked() and self.get_lock()['user'] != user:
if self.is_locked() and self.get_lock() != user:
raise AlreadyLocked("The page is already locked by someone else")
Page.lock_mutex[self.pk] = {'user': user,
'time': timezone.now()}
self.lock_user = user
self.lock_timeout = timezone.now()
super(Page, self).save()
# print("Locking page")
def set_lock_recursive(self, user):
@ -726,16 +726,18 @@ 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)
self.lock_user = None
self.lock_timeout = None
super(Page, self).save()
# print("Unlocking page")
def get_lock(self):
"""
Returns the page's mutex containing the time and the user in a dict
"""
if self.is_locked():
return Page.lock_mutex[self.pk]
raise NotLocked("The page is not locked and thus can not return its mutex")
if self.lock_user:
return self.lock_user
raise NotLocked("The page is not locked and thus can not return its user")
def get_absolute_url(self):
"""

View File

@ -37,6 +37,12 @@ class CanCreateMixin(View):
This view is made to protect any child view that would create an object, and thus, that can not be protected by any
of the following mixin
"""
def dispatch(self, request, *arg, **kwargs):
res = super(CanCreateMixin, self).dispatch(request, *arg, **kwargs)
if not request.user.is_authenticated():
raise PermissionDenied
return res
def form_valid(self, form):
obj = form.instance
if can_edit_prop(obj, self.request.user):

View File

@ -9,7 +9,7 @@ from django.forms import CheckboxSelectMultiple
from core.models import Page, PageRev, LockError
from core.views.forms import PagePropForm
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin
class PageListView(CanViewMixin, ListView):
model = Page
@ -59,7 +59,7 @@ class PageRevView(CanViewMixin, DetailView):
context['new_page'] = self.kwargs['page_name']
return context
class PageCreateView(CanEditPropMixin, CreateView):
class PageCreateView(CanCreateMixin, CreateView):
model = Page
form_class = modelform_factory(Page,
fields = ['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ],

View File

@ -442,5 +442,6 @@ OLD_MYSQL_INFOS = {
try:
from .settings_custom import *
print("Custom settings imported")
except:
print("Custom settings failed")