#!/usr/bin/python3
-import difflib
import tornado.web
-from . import auth
from . import base
from . import ui_modules
-class ActionEditHandler(auth.CacheMixin, base.BaseHandler):
+class ActionEditHandler(base.BaseHandler):
@tornado.web.authenticated
def get(self, path):
if path is None:
self.backend.wiki.refresh()
-class ActionUploadHandler(auth.CacheMixin, base.BaseHandler):
+class ActionUploadHandler(base.BaseHandler):
@tornado.web.authenticated
@base.ratelimit(minutes=60, requests=24)
def post(self):
try:
filename, data, mimetype = self.get_file("file")
+ # Use filename from request if any
+ filename = self.get_argument("filename", filename)
+
# XXX check valid mimetypes
with self.db.transaction():
self.redirect("%s/_files" % path)
-class ActionWatchHandler(auth.CacheMixin, base.BaseHandler):
+class ActionDeleteHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, 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))
+
+ # Fetch the file
+ file = self.backend.wiki.get_file_by_path(path)
+ if not file:
+ raise tornado.web.HTTPError(404, "Could not find %s" % path)
+
+ self.render("wiki/confirm-delete.html", file=file)
+
+ @tornado.web.authenticated
+ @base.ratelimit(minutes=60, requests=24)
+ def post(self, 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))
+
+ # Fetch the file
+ file = self.backend.wiki.get_file_by_path(path)
+ if not file:
+ raise tornado.web.HTTPError(404, "Could not find %s" % path)
+
+ with self.db.transaction():
+ file.delete(self.current_user)
+
+ self.redirect("%s/_files" % file.path)
+
+
+class ActionRestoreHandler(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)
+ comment = self.get_argument("comment", 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(),
+ comment=comment,
+ )
+
+ # Redirect back to page
+ self.redirect(page.page)
+
+
+class ActionWatchHandler(base.BaseHandler):
@tornado.web.authenticated
@base.ratelimit(minutes=60, requests=180)
def get(self, path, action):
self.redirect(page.url)
-class ActionRenderHandler(auth.CacheMixin, base.BaseHandler):
+class ActionRenderHandler(base.BaseHandler):
def check_xsrf_cookie(self):
pass # disabled
self.finish(html)
-class FilesHandler(auth.CacheMixin, base.BaseHandler):
+class FilesHandler(base.BaseHandler):
@tornado.web.authenticated
def get(self, path):
if path is None:
self.render("wiki/files/index.html", path=path, files=files)
-class FileHandler(base.BaseHandler):
- @property
- def action(self):
- return self.get_argument("action", None)
-
- def get(self, 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))
-
- # Fetch the file
- file = self.backend.wiki.get_file_by_path(path)
- if not file:
- raise tornado.web.HTTPError(404, "Could not find %s" % path)
-
- # Render detail page
- if self.action == "detail":
- page = None
-
- for breadcrumb, title in self.backend.wiki.make_breadcrumbs(path):
- page = self.backend.wiki.get_page(breadcrumb)
- if page:
- break
-
- self.render("wiki/files/detail.html", page=page, file=file)
- return
-
- size = self.get_argument_int("s", None)
-
- # Check if image should be resized
- if file.is_image() and size:
- blob = file.get_thumbnail(size)
- else:
- blob = file.blob
-
- # Set headers
- self.set_header("Content-Type", file.mimetype or "application/octet-stream")
- self.set_header("Content-Length", len(blob))
-
- # Set expires
- self.set_expires(3600)
-
- # Deliver content
- self.finish(blob)
-
-
-class PageHandler(auth.CacheMixin, base.BaseHandler):
- @property
- def action(self):
- return self.get_argument("action", None)
-
- def write_error(self, status_code, **kwargs):
- # Render a custom page for 404
- if status_code == 404:
- self.render("wiki/404.html", **kwargs)
- return
-
- # Otherwise raise this to one layer above
- super().write_error(status_code, **kwargs)
-
- @tornado.web.removeslash
- def get(self, path):
- if path is None:
- 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)
-
- # Diff
- if self.action == "diff":
- # Get both revisions
- a = self.get_argument("a")
- b = self.get_argument("b")
-
- # Fetch both versions of the page
- a = self.backend.wiki.get_page(path, revision=a)
- b = self.backend.wiki.get_page(path, revision=b)
- if not a or not b:
- raise tornado.web.HTTPError(404)
-
- # Cannot render a diff for the identical page
- if a == b:
- raise tornado.web.HTTPError(400)
-
- # Make sure that b is newer than a
- if a > b:
- a, b = b, a
-
- self.render("wiki/diff.html", page=page, a=a, b=b)
- return
-
- # Revisions
- elif self.action == "revisions":
- self.render("wiki/revisions.html", page=page)
- return
-
- # If the page does not exist, we send 404
- if not page or page.was_deleted():
- # Handle /start links which were in the format of DokuWiki
- if path.endswith("/start"):
- # Strip /start from path
- path = path[:-6] or "/"
-
- # Redirect user to page if it exists
- page = self.backend.wiki.page_exists(path)
- if page:
- self.redirect(path)
-
- raise tornado.web.HTTPError(404)
-
- # Fetch the latest revision
- latest_revision = page.get_latest_revision()
-
- # Render page
- self.render("wiki/page.html", page=page, latest_revision=latest_revision)
-
-
-class SearchHandler(auth.CacheMixin, base.BaseHandler):
+class SearchHandler(base.BaseHandler):
@base.ratelimit(minutes=5, requests=25)
def get(self):
q = self.get_argument("q")
self.render("wiki/search-results.html", q=q, pages=pages)
-class RecentChangesHandler(auth.CacheMixin, base.BaseHandler):
+class RecentChangesHandler(base.BaseHandler):
def get(self):
recent_changes = self.backend.wiki.get_recent_changes(self.current_user, limit=50)
self.render("wiki/recent-changes.html", recent_changes=recent_changes)
-class WatchlistHandler(auth.CacheMixin, base.BaseHandler):
+class TreeHandler(base.BaseHandler):
+ def get(self):
+ self.render("wiki/tree.html", pages=self.backend.wiki)
+
+
+class WatchlistHandler(base.BaseHandler):
@tornado.web.authenticated
def get(self):
pages = self.backend.wiki.get_watchlist(self.current_user)
self.render("wiki/watchlist.html", pages=pages)
-class WikiDiffModule(ui_modules.UIModule):
- differ = difflib.Differ()
-
- def render(self, a, b):
- diff = self.differ.compare(
- a.markdown.splitlines(),
- b.markdown.splitlines(),
- )
-
- return self.render_string("wiki/modules/diff.html", diff=diff)
-
-
class WikiListModule(ui_modules.UIModule):
def render(self, pages, link_revision=False, show_breadcrumbs=True,
show_author=True, show_changes=False):
return self.render_string("wiki/modules/list.html", link_revision=link_revision,
pages=pages, show_breadcrumbs=show_breadcrumbs,
show_author=show_author, show_changes=show_changes)
-
-
-class WikiNavbarModule(ui_modules.UIModule):
- @property
- def path(self):
- """
- Returns the path of the page (without any actions)
- """
- path = self.request.path.split("/")
-
- if path and path[-1].startswith("_"):
- path.pop()
-
- return "/".join(path)
-
- def render(self, suffix=None):
- _ = self.locale.translate
-
- # Make the path
- page = self.request.path.split("/")
-
- # Drop the action bit
- if page and page[-1].startswith("_"):
- page.pop()
-
- page = "/".join(page)
-
- breadcrumbs = self.backend.wiki.make_breadcrumbs(page)
- title = self.backend.wiki.get_page_title(page)
-
- if self.request.path.endswith("/_edit"):
- suffix = _("Edit")
- elif self.request.path.endswith("/_files"):
- suffix = _("Files")
-
- return self.render_string("wiki/modules/navbar.html",
- breadcrumbs=breadcrumbs, page=page, page_title=title, suffix=suffix)