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 \
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()
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):
--- /dev/null
+{% 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 %}
</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 %}
(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
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
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)