diff --git a/markupwiki/models.py b/markupwiki/models.py index a188387..3400d35 100644 --- a/markupwiki/models.py +++ b/markupwiki/models.py @@ -1,10 +1,13 @@ +import datetime from django.db import models from django.conf import settings from django.contrib.auth.models import User +from django.core.cache import cache from django.core.urlresolvers import reverse from markupfield.fields import MarkupField DEFAULT_MARKUP_TYPE = getattr(settings, 'MARKUPWIKI_DEFAULT_MARKUP_TYPE', 'plain') +WRITE_LOCK_SECONDS = getattr(settings, 'MARKUPWIKI_WRITE_LOCK_SECONDS', 60) PUBLIC, LOCKED, DELETED = range(3) ARTICLE_STATUSES = ( @@ -39,6 +42,14 @@ class Article(models.Model): else: return user.is_authenticated() + def get_write_lock(self, user): + cache_key = 'markupwiki_articlelock_%s' % self.id + lock = cache.get(cache_key) + if lock: + return lock == user.id + + cache.set(cache_key, user.id, WRITE_LOCK_SECONDS) + return True class ArticleVersion(models.Model): article = models.ForeignKey(Article, related_name='versions') diff --git a/markupwiki/views.py b/markupwiki/views.py index 9d7f19a..0ee4cb1 100644 --- a/markupwiki/views.py +++ b/markupwiki/views.py @@ -3,6 +3,7 @@ from django.shortcuts import get_object_or_404, render_to_response, redirect from django.http import HttpResponseForbidden from django.views.decorators.http import require_POST from django.contrib.auth.decorators import login_required, user_passes_test +from django.contrib import messages from django.template import RequestContext from django.utils.functional import wraps from markupwiki.models import Article, PUBLIC, DELETED, LOCKED @@ -75,13 +76,19 @@ def edit_article(request, title): except Article.DoesNotExist: article = None - if article and article.is_locked() and not user.is_staff: - return render_to_response('locked_article.html', {'article': article}, - context_instance=RequestContext(request)) + # check for staff lock + if article and not article.is_editable_by_user(request.user): + return HttpResponseForbidden('not authorized to edit') if request.method == 'GET': # either get an empty ArticleForm or one based on latest version if article: + + if not article.get_write_lock(request.user): + # set message and redirect + messages.info(request, 'Someone else is currently editing this page, please wait and try again.') + return redirect(article) + version = article.versions.latest() form = ArticleForm(data={'body':version.body, 'body_markup_type':version.body_markup_type}) @@ -96,6 +103,11 @@ def edit_article(request, title): creator=request.user) num = 0 else: + if not article.get_write_lock(request.user): + # set message and redirect + messages.error(request, 'You took too long to edit and someone else is now editing this page.') + return redirect(article) + # otherwise get latest num num = article.versions.latest().number + 1