From 608fa1798326b8289a5459dd6774eb64779075cf Mon Sep 17 00:00:00 2001 From: Bridger Maxwell Date: Mon, 23 Jan 2012 18:05:16 -0500 Subject: [PATCH 1/5] Adding delete functionality --HG-- branch : bridgerwiki --- simplewiki/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simplewiki/models.py b/simplewiki/models.py index 8098a54e5a..d01ca553aa 100644 --- a/simplewiki/models.py +++ b/simplewiki/models.py @@ -220,6 +220,8 @@ class Revision(models.Model): counter = models.IntegerField(verbose_name=_('Revision#'), default=1, editable=False) previous_revision = models.ForeignKey('self', blank=True, null=True, editable=False) + deleted = models.IntegerField(verbose_name=_('Deleted group'), default=0) + def get_user(self): return self.revision_user if self.revision_user else _('Anonymous') From b3797a41f3df1306eceb5a37ec4b55a60624a7da Mon Sep 17 00:00:00 2001 From: Bridger Maxwell Date: Tue, 24 Jan 2012 15:58:22 -0500 Subject: [PATCH 2/5] Got most of admin deleting and user deleting implemented. Need to work on interface for encountering deleted articles. --HG-- branch : bridgerwiki --- simplewiki/models.py | 12 +++++++++ simplewiki/views.py | 61 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/simplewiki/models.py b/simplewiki/models.py index d01ca553aa..bf6c75aa80 100644 --- a/simplewiki/models.py +++ b/simplewiki/models.py @@ -220,12 +220,24 @@ class Revision(models.Model): counter = models.IntegerField(verbose_name=_('Revision#'), default=1, editable=False) previous_revision = models.ForeignKey('self', blank=True, null=True, editable=False) + # Deleted has three values. 0 is normal, non-deleted. 1 is if it was deleted by a normal user. It should + # be a NEW revision, so that it appears in the history. 2 is a special flag that can be applied or removed + # from a normal revision. It means it has been admin-deleted, and can only been seen by an admin. It doesn't + # show up in the history. deleted = models.IntegerField(verbose_name=_('Deleted group'), default=0) def get_user(self): return self.revision_user if self.revision_user else _('Anonymous') + + def adminSetDeleted(self, deleted): + self.deleted = deleted + super(Revision, self).save() def save(self, **kwargs): + #Really, the only time this should not happen is when the revision is being marked as deleted + print "kwargs" , kwargs, not ('is_deletion_modification' in kwargs and kwars['is_deletion_modification']) + print "save was just called" + # Check if contents have changed... if not, silently ignore save if self.article and self.article.current_revision: if self.article.current_revision.contents == self.contents: diff --git a/simplewiki/views.py b/simplewiki/views.py index 3fbd1f3b9a..9f8e9adfbf 100644 --- a/simplewiki/views.py +++ b/simplewiki/views.py @@ -38,6 +38,7 @@ def view(request, wiki_url): d = {'wiki_article': article, 'wiki_write': article.can_write_l(request.user), 'wiki_attachments_write': article.can_attach(request.user), + 'wiki_current_revision_deleted' : not (article.current_revision.deleted == 0), } d.update(csrf(request)) return render_to_response('simplewiki_view.html', d) @@ -149,9 +150,15 @@ def edit(request, wiki_url): if f.is_valid(): new_revision = f.save(commit=False) new_revision.article = article - # Check that something has actually been changed... - if not new_revision.get_diff(): - return (None, HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),)))) + + if request.POST.__contains__('delete'): + if (article.current_revision.deleted == 1): #This article has already been deleted. Redirect + return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) + new_revision.contents = "Article Deletion Revision\n===" + new_revision.deleted = 1 + elif not new_revision.get_diff(): + return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) + if not request.user.is_anonymous(): new_revision.revision_user = request.user new_revision.save() @@ -160,7 +167,9 @@ def edit(request, wiki_url): new_revision.article.save() return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) else: - f = EditForm({'contents': article.current_revision.contents, 'title': article.title}) + startContents = article.current_revision.contents if (article.current_revision.deleted == 0) else 'Headline\n===\n\n' + + f = EditForm({'contents': startContents, 'title': article.title}) d = {'wiki_form': f, 'wiki_write': True, 'wiki_article': article, @@ -192,18 +201,40 @@ def history(request, wiki_url, page=1): history = Revision.objects.filter(article__exact = article).order_by('-counter') if request.method == 'POST': - if request.POST.__contains__('revision'): + if request.POST.__contains__('revision'): #They selected a version, but they can be either deleting or changing the version perm_err = check_permissions(request, article, check_write=True, check_locked=True) if perm_err: return perm_err try: r = int(request.POST['revision']) - article.current_revision = Revision.objects.get(id=r) - article.save() + revision = Revision.objects.get(id=r) + if request.POST.__contains__('change'): + article.current_revision = revision + article.save() + elif request.POST.__contains__('delete') and request.user.is_superuser: + if (revision.deleted == 0): + revision.adminSetDeleted(2) + elif request.POST.__contains__('restore') and request.user.is_superuser: + print "revision.deleted: " , revision.deleted + if (revision.deleted == 2): + print "save was just called" + revision.adminSetDeleted(0) + print "revison.deleted is now " , revision.deleted + elif request.POST.__contains__('delete_all') and request.user.is_superuser: + Revision.objects.filter(article__exact = article, deleted = 0).update(deleted = 2) + except: pass finally: return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) + # + # + # + # + # + # %else: + # + # page_count = (history.count()+(page_size-1)) / page_size if p > page_count: @@ -219,7 +250,8 @@ def history(request, wiki_url, page=1): 'wiki_write': article.can_write_l(request.user), 'wiki_attachments_write': article.can_attach(request.user), 'wiki_article': article, - 'wiki_history': history[beginItem:beginItem+page_size],} + 'wiki_history': history[beginItem:beginItem+page_size], + 'show_delete_revision' : request.user.is_superuser,} d.update(csrf(request)) return render_to_response('simplewiki_history.html', d) @@ -394,16 +426,21 @@ def fetch_from_url(request, url): return (article, path, err) -def check_permissions(request, article, check_read=False, check_write=False, check_locked=False): +def check_permissions(request, article, check_read=False, check_write=False, check_locked=False, check_deleted=True): read_err = check_read and not article.can_read(request.user) write_err = check_write and not article.can_write(request.user) locked_err = check_locked and article.locked - - if read_err or write_err or locked_err: + + deleted_err = check_deleted and not (article.current_revision.deleted == 0) + if request.user.is_superuser: + deleted_err = False + + if read_err or write_err or locked_err or deleted_err: d = {'wiki_article': article, 'wiki_err_noread': read_err, 'wiki_err_nowrite': write_err, - 'wiki_err_locked': locked_err,} + 'wiki_err_locked': locked_err, + 'wiki_err_deleted': deleted_err,} d.update(csrf(request)) # TODO: Make this a little less jarring by just displaying an error # on the current page? (no such redirect happens for an anon upload yet) From 056924ad6fccf6e859bb373f2b72e05258ca4ca4 Mon Sep 17 00:00:00 2001 From: Bridger Maxwell Date: Tue, 24 Jan 2012 20:05:14 -0500 Subject: [PATCH 3/5] Got most of deleting working. --HG-- branch : bridgerwiki --- simplewiki/views.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/simplewiki/views.py b/simplewiki/views.py index 9f8e9adfbf..7d09085c55 100644 --- a/simplewiki/views.py +++ b/simplewiki/views.py @@ -32,7 +32,7 @@ def view(request, wiki_url): if err: return err - perm_err = check_permissions(request, article, check_read=True) + perm_err = check_permissions(request, article, check_read=True, check_deleted=True) if perm_err: return perm_err d = {'wiki_article': article, @@ -81,7 +81,7 @@ def create(request, wiki_url): d.update(csrf(request)) return render_to_response('simplewiki_error.html', d) - perm_err = check_permissions(request, path[-1], check_locked=False, check_write=True) + perm_err = check_permissions(request, path[-1], check_locked=False, check_write=True, check_deleted=True) if perm_err: return perm_err # Ensure doesn't already exist @@ -136,7 +136,7 @@ def edit(request, wiki_url): return err # Check write permissions - perm_err = check_permissions(request, article, check_write=True, check_locked=True) + perm_err = check_permissions(request, article, check_write=True, check_locked=True, check_deleted=False) if perm_err: return perm_err @@ -187,7 +187,7 @@ def history(request, wiki_url, page=1): if err: return err - perm_err = check_permissions(request, article, check_read=True) + perm_err = check_permissions(request, article, check_read=True, check_deleted=False) if perm_err: return perm_err @@ -285,12 +285,18 @@ def search_articles(request): else: # Need to throttle results by splitting them into pages... results = Article.objects.all() + + if request.user.is_superuser: + results = results.order_by('current_revision__deleted') + else: + print "tried to filter" + results = results.filter(current_revision__deleted = 0) if results.count() == 1 and querystring: return HttpResponseRedirect(reverse('wiki_view', args=(results[0].get_url(),))) else: d = {'wiki_search_results': results, - 'wiki_search_query': querystring} + 'wiki_search_query': querystring,} d.update(csrf(request)) return render_to_response('simplewiki_searchresults.html', d) @@ -426,13 +432,15 @@ def fetch_from_url(request, url): return (article, path, err) -def check_permissions(request, article, check_read=False, check_write=False, check_locked=False, check_deleted=True): +def check_permissions(request, article, check_read=False, check_write=False, check_locked=False, check_deleted=False): read_err = check_read and not article.can_read(request.user) + write_err = check_write and not article.can_write(request.user) + locked_err = check_locked and article.locked deleted_err = check_deleted and not (article.current_revision.deleted == 0) - if request.user.is_superuser: + if (request.user.is_superuser): deleted_err = False if read_err or write_err or locked_err or deleted_err: From 614f15664058b3a125688949ede8709a37948247 Mon Sep 17 00:00:00 2001 From: Bridger Maxwell Date: Tue, 24 Jan 2012 20:56:12 -0500 Subject: [PATCH 4/5] Added UI for locking article. Did more testing/bug fixes on deletion. Seems stable. --HG-- branch : bridgerwiki --- simplewiki/models.py | 21 +++++++++++++++------ simplewiki/views.py | 14 ++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/simplewiki/models.py b/simplewiki/models.py index bf6c75aa80..21a379cb34 100644 --- a/simplewiki/models.py +++ b/simplewiki/models.py @@ -85,6 +85,8 @@ class Article(models.Model): def can_read(self, user): """ Check read permissions and return True/False.""" + if user.is_superuser: + return True if self.permissions: perms = self.permissions.can_read.all() return perms.count() == 0 or (user in perms) @@ -93,6 +95,8 @@ class Article(models.Model): def can_write(self, user): """ Check write permissions and return True/False.""" + if user.is_superuser: + return True if self.permissions: perms = self.permissions.can_write.all() return perms.count() == 0 or (user in perms) @@ -101,6 +105,8 @@ class Article(models.Model): def can_write_l(self, user): """Check write permissions and locked status""" + if user.is_superuser: + return True return not self.locked and self.can_write(user) def can_attach(self, user): @@ -229,18 +235,16 @@ class Revision(models.Model): def get_user(self): return self.revision_user if self.revision_user else _('Anonymous') + # Called after the deleted fied has been changed (between 0 and 2). This bypasses the normal checks put in + # save that update the revision or reject the save if contents haven't changed def adminSetDeleted(self, deleted): self.deleted = deleted super(Revision, self).save() def save(self, **kwargs): - #Really, the only time this should not happen is when the revision is being marked as deleted - print "kwargs" , kwargs, not ('is_deletion_modification' in kwargs and kwars['is_deletion_modification']) - print "save was just called" - # Check if contents have changed... if not, silently ignore save if self.article and self.article.current_revision: - if self.article.current_revision.contents == self.contents: + if self.deleted == 0 and self.article.current_revision.contents == self.contents: return else: import datetime @@ -256,7 +260,8 @@ class Revision(models.Model): self.counter = previous_revision[0].counter + 1 else: self.counter = 1 - self.previous_revision = self.article.current_revision + if (self.article.current_revision.deleted == 0): + self.previous_revision = self.article.current_revision # Create pre-parsed contents - no need to parse on-the-fly ext = WIKI_MARKDOWN_EXTENSIONS @@ -288,6 +293,10 @@ class Revision(models.Model): super(Revision, self).delete(**kwargs) def get_diff(self): + if (self.deleted == 1): + yield "Article Deletion" + return + if self.previous_revision: previous = self.previous_revision.contents.splitlines(1) else: diff --git a/simplewiki/views.py b/simplewiki/views.py index 7d09085c55..a49d135aee 100644 --- a/simplewiki/views.py +++ b/simplewiki/views.py @@ -154,7 +154,7 @@ def edit(request, wiki_url): if request.POST.__contains__('delete'): if (article.current_revision.deleted == 1): #This article has already been deleted. Redirect return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) - new_revision.contents = "Article Deletion Revision\n===" + new_revision.contents = "" new_revision.deleted = 1 elif not new_revision.get_diff(): return HttpResponseRedirect(reverse('wiki_view', args=(article.get_url(),))) @@ -189,6 +189,7 @@ def history(request, wiki_url, page=1): perm_err = check_permissions(request, article, check_read=True, check_deleted=False) if perm_err: + print "returned error " , perm_err return perm_err page_size = 10 @@ -215,14 +216,15 @@ def history(request, wiki_url, page=1): if (revision.deleted == 0): revision.adminSetDeleted(2) elif request.POST.__contains__('restore') and request.user.is_superuser: - print "revision.deleted: " , revision.deleted if (revision.deleted == 2): - print "save was just called" revision.adminSetDeleted(0) - print "revison.deleted is now " , revision.deleted elif request.POST.__contains__('delete_all') and request.user.is_superuser: Revision.objects.filter(article__exact = article, deleted = 0).update(deleted = 2) - + elif request.POST.__contains__('lock_article'): + print "changing locked article " , article.locked + article.locked = not article.locked + print "changed locked article " , article.locked + article.save() except: pass finally: @@ -289,7 +291,6 @@ def search_articles(request): if request.user.is_superuser: results = results.order_by('current_revision__deleted') else: - print "tried to filter" results = results.filter(current_revision__deleted = 0) if results.count() == 1 and querystring: @@ -442,6 +443,7 @@ def check_permissions(request, article, check_read=False, check_write=False, che deleted_err = check_deleted and not (article.current_revision.deleted == 0) if (request.user.is_superuser): deleted_err = False + locked_err = False if read_err or write_err or locked_err or deleted_err: d = {'wiki_article': article, From 08e7d0693182a11a0cc19b51b616e8dc61939815 Mon Sep 17 00:00:00 2001 From: Bridger Maxwell Date: Wed, 25 Jan 2012 11:43:13 -0500 Subject: [PATCH 5/5] Fixed bug for first article creation. --HG-- branch : bridgerwiki --- simplewiki/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplewiki/models.py b/simplewiki/models.py index 21a379cb34..71add3c0fc 100644 --- a/simplewiki/models.py +++ b/simplewiki/models.py @@ -260,7 +260,7 @@ class Revision(models.Model): self.counter = previous_revision[0].counter + 1 else: self.counter = 1 - if (self.article.current_revision.deleted == 0): + if (self.article.current_revision and self.article.current_revision.deleted == 0): self.previous_revision = self.article.current_revision # Create pre-parsed contents - no need to parse on-the-fly