]> git.ipfire.org Git - ipfire.org.git/commitdiff
wiki: Implement restoring pages
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 10 Oct 2019 08:49:22 +0000 (09:49 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 10 Oct 2019 08:49:22 +0000 (09:49 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/wiki.py
src/templates/wiki/confirm-restore.html [new file with mode: 0644]
src/templates/wiki/modules/list.html
src/web/__init__.py
src/web/wiki.py

index ea6545258d9161ef1454ccdc53d026ac4327c4f6..f7b40a67eb91288d2d95131721396a09d253e065 100644 (file)
@@ -277,6 +277,7 @@ templates_wiki_DATA = \
        src/templates/wiki/404.html \
        src/templates/wiki/base.html \
        src/templates/wiki/confirm-delete.html \
+       src/templates/wiki/confirm-restore.html \
        src/templates/wiki/diff.html \
        src/templates/wiki/edit.html \
        src/templates/wiki/page.html \
index 1747429ca083d5234e817595d1d1153802d3d9e7..3f19c242083b4c188fad868f12618544e6e44882 100644 (file)
@@ -338,6 +338,9 @@ class Page(misc.Object):
        def breadcrumbs(self):
                return self.backend.wiki.make_breadcrumbs(self.page)
 
+       def is_latest_revision(self):
+               return self.get_latest_revision() == self
+
        def get_latest_revision(self):
                revisions = self.get_revisions()
 
@@ -446,6 +449,12 @@ class Page(misc.Object):
                                sender="IPFire Wiki <wiki@ipfire.org>", recipients=[watcher],
                                page=self, priority=-10)
 
+       def restore(self, author, address):
+               changes = "Restore to revision from %s" % self.timestamp.isoformat()
+
+               return self.backend.wiki.create_page(self.page,
+                       author, self.markdown, changes=changes, address=address)
+
 
 class File(misc.Object):
        def init(self, id, data):
diff --git a/src/templates/wiki/confirm-restore.html b/src/templates/wiki/confirm-restore.html
new file mode 100644 (file)
index 0000000..f9acfae
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends "base.html" %}
+
+{% block title %}{{ _("Restore %s") % page.page }}{% end block %}
+
+{% block content %}
+       <div class="row justify-content-center my-5">
+               <div class="col col-md-6">
+                       <div class="card card-body">
+                               <h5 class=" mb-4">{{ _("Restore %s") % page.page }}</h5>
+
+                               <p>
+                                       {{ _("Do you really want to restore this page to its revision from %s?") % locale.format_date(page.timestamp) }}
+                               </p>
+
+                               <form action="/actions/restore" method="POST">
+                                       {% raw xsrf_form_html() %}
+
+                                       <input type="hidden" name="path" value="{{ page.page }}">
+                                       <input type="hidden" name="revision" value="{{ page.timestamp.isoformat() }}">
+
+                                       <button type="submit" class="btn btn-warning btn-block">
+                                               {{ _("Restore") }}
+                                       </button>
+                               </form>
+                       </div>
+               </div>
+       </div>
+{% end block %}
index 0663fd21a53c84dd206ed560955c099ca4eafeb2..3891a291bad71a90c279d6c6200d4e2e082d77e7 100644 (file)
                                </a>
                        {% end %}
                {% end %}
+
+               {% if not page.is_latest_revision() %}
+                       <a href="{{ page.url }}?action=restore&revision={{ page.timestamp.isoformat() }}" title="{{ _("Restore") }}">
+                               <span class="fas fa-undo ml-1"></span>
+                       </a>
+               {% end %}
        </p>
 {% end %}
index 8343b86d3ecf60534271a679772fb1ce533cced6..ff7cd400b88af394dc000776d191c21b208a1bcd 100644 (file)
@@ -294,6 +294,7 @@ class Application(tornado.web.Application):
                        (r"([A-Za-z0-9\-_\/]+)?/_edit", wiki.ActionEditHandler),
                        (r"([A-Za-z0-9\-_\/]+)?/_render", wiki.ActionRenderHandler),
                        (r"([A-Za-z0-9\-_\/]+)?/_(watch|unwatch)", wiki.ActionWatchHandler),
+                       (r"/actions/restore", wiki.ActionRestoreHandler),
                        (r"/actions/upload", wiki.ActionUploadHandler),
 
                        # Handlers
index e5759e375e27ef6680a869aec85f2c7459b5b1b5..ca0f1b35f949394e0fb0804234c7ed74003391e0 100644 (file)
@@ -126,6 +126,30 @@ class ActionDeleteHandler(auth.CacheMixin, base.BaseHandler):
                self.redirect("%s/_files" % file.path)
 
 
+class ActionRestoreHandler(auth.CacheMixin, base.BaseHandler):
+       @tornado.web.authenticated
+       @base.ratelimit(minutes=60, requests=24)
+       def post(self):
+               path = self.get_argument("path")
+
+               # Check permissions
+               if not self.backend.wiki.check_acl(path, self.current_user):
+                       raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (path, self.current_user))
+
+               # Check if we are asked to render a certain revision
+               revision = self.get_argument("revision", None)
+
+               # Fetch the wiki page
+               page = self.backend.wiki.get_page(path, revision=revision)
+
+               with self.db.transaction():
+                       page = page.restore(
+                               author=self.current_user, address=self.get_remote_ip(),
+                       )
+
+               # Redirect back to page
+               self.redirect(page.page)
+
 
 class ActionWatchHandler(auth.CacheMixin, base.BaseHandler):
        @tornado.web.authenticated
@@ -286,6 +310,11 @@ class PageHandler(auth.CacheMixin, base.BaseHandler):
                        self.render("wiki/diff.html", page=page, a=a, b=b)
                        return
 
+               # Restore
+               elif self.action == "restore":
+                       self.render("wiki/confirm-restore.html", page=page)
+                       return
+
                # Revisions
                elif self.action == "revisions":
                        self.render("wiki/revisions.html", page=page)