]>
git.ipfire.org Git - ipfire.org.git/blob - src/web/wiki.py
8 from . import ui_modules
10 class ActionEditHandler(auth
.CacheMixin
, base
.BaseHandler
):
11 @tornado.web
.authenticated
14 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
15 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
18 page
= self
.backend
.wiki
.get_page(path
)
20 # Empty page if it was deleted
21 if page
and page
.was_deleted():
25 self
.render("wiki/edit.html", page
=page
)
27 @tornado.web
.authenticated
30 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
31 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
33 content
= self
.get_argument("content", None)
34 changes
= self
.get_argument("changes")
36 # Create a new page in the database
37 with self
.db
.transaction():
38 page
= self
.backend
.wiki
.create_page(path
,
39 self
.current_user
, content
, changes
=changes
, address
=self
.get_remote_ip())
41 # Add user as a watcher if wanted
42 watch
= self
.get_argument("watch", False)
44 page
.add_watcher(self
.current_user
)
47 if page
.was_deleted():
50 self
.redirect(page
.url
)
54 Updates the search index after the page has been edited
56 # This is being executed in the background and after
57 # the response has been set to the client
58 with self
.db
.transaction():
59 self
.backend
.wiki
.refresh()
62 class ActionUploadHandler(auth
.CacheMixin
, base
.BaseHandler
):
63 @tornado.web
.authenticated
65 path
= self
.get_argument("path")
68 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
69 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
72 filename
, data
, mimetype
= self
.get_file("file")
74 # XXX check valid mimetypes
76 with self
.db
.transaction():
77 file = self
.backend
.wiki
.upload(path
, filename
, data
,
78 mimetype
=mimetype
, author
=self
.current_user
,
79 address
=self
.get_remote_ip())
81 except TypeError as e
:
84 self
.redirect("%s/_files" % path
)
87 class ActionWatchHandler(auth
.CacheMixin
, base
.BaseHandler
):
88 @tornado.web
.authenticated
89 def get(self
, path
, action
):
90 page
= self
.backend
.wiki
.get_page(path
)
92 raise tornado
.web
.HTTPError(404, "Page does not exist: %s" % path
)
95 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
96 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
98 with self
.db
.transaction():
100 page
.add_watcher(self
.current_user
)
101 elif action
== "unwatch":
102 page
.remove_watcher(self
.current_user
)
104 # Redirect back to page
105 self
.redirect(page
.url
)
108 class ActionRenderHandler(auth
.CacheMixin
, base
.BaseHandler
):
109 def check_xsrf_cookie(self
):
112 @tornado.web
.authenticated
113 def post(self
, path
):
114 content
= self
.get_argument("content")
117 html
= self
.backend
.wiki
.render(path
, content
)
122 class FilesHandler(auth
.CacheMixin
, base
.BaseHandler
):
123 @tornado.web
.authenticated
126 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
127 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
129 files
= self
.backend
.wiki
.get_files(path
)
131 self
.render("wiki/files/index.html", path
=path
, files
=files
)
134 class FileHandler(base
.BaseHandler
):
137 return self
.get_argument("action", None)
141 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
142 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
145 file = self
.backend
.wiki
.get_file_by_path(path
)
147 raise tornado
.web
.HTTPError(404, "Could not find %s" % path
)
150 if self
.action
== "detail":
153 for breadcrumb
, title
in self
.backend
.wiki
.make_breadcrumbs(path
):
154 page
= self
.backend
.wiki
.get_page(breadcrumb
)
158 self
.render("wiki/files/detail.html", page
=page
, file=file)
161 size
= self
.get_argument_int("s", None)
163 # Check if image should be resized
164 if file.is_image() and size
:
165 blob
= file.get_thumbnail(size
)
170 self
.set_header("Content-Type", file.mimetype
or "application/octet-stream")
171 self
.set_header("Content-Length", len(blob
))
174 self
.set_expires(3600)
180 class PageHandler(auth
.CacheMixin
, base
.BaseHandler
):
183 return self
.get_argument("action", None)
185 def write_error(self
, status_code
, **kwargs
):
186 # Render a custom page for 404
187 if status_code
== 404:
188 self
.render("wiki/404.html", **kwargs
)
191 # Otherwise raise this to one layer above
192 super().write_error(status_code
, **kwargs
)
194 @tornado.web
.removeslash
197 if not self
.backend
.wiki
.check_acl(path
, self
.current_user
):
198 raise tornado
.web
.HTTPError(403, "Access to %s not allowed for %s" % (path
, self
.current_user
))
200 # Check if we are asked to render a certain revision
201 revision
= self
.get_argument("revision", None)
203 # Fetch the wiki page
204 page
= self
.backend
.wiki
.get_page(path
, revision
=revision
)
207 if self
.action
== "diff":
209 a
= self
.get_argument("a")
210 b
= self
.get_argument("b")
212 # Fetch both versions of the page
213 a
= self
.backend
.wiki
.get_page(path
, revision
=a
)
214 b
= self
.backend
.wiki
.get_page(path
, revision
=b
)
216 raise tornado
.web
.HTTPError(404)
218 # Cannot render a diff for the identical page
220 raise tornado
.web
.HTTPError(400)
222 # Make sure that b is newer than a
226 self
.render("wiki/diff.html", page
=page
, a
=a
, b
=b
)
230 elif self
.action
== "revisions":
231 self
.render("wiki/revisions.html", page
=page
)
234 # If the page does not exist, we send 404
235 if not page
or page
.was_deleted():
236 raise tornado
.web
.HTTPError(404)
238 # Fetch the latest revision
239 latest_revision
= page
.get_latest_revision()
242 self
.render("wiki/page.html", page
=page
, latest_revision
=latest_revision
)
245 class SearchHandler(auth
.CacheMixin
, base
.BaseHandler
):
248 q
= self
.get_argument("q")
250 pages
= self
.backend
.wiki
.search(q
, account
=self
.current_user
, limit
=50)
252 self
.render("wiki/search-results.html", q
=q
, pages
=pages
)
255 class RecentChangesHandler(auth
.CacheMixin
, base
.BaseHandler
):
257 recent_changes
= self
.backend
.wiki
.get_recent_changes(self
.current_user
, limit
=50)
259 self
.render("wiki/recent-changes.html", recent_changes
=recent_changes
)
262 class WatchlistHandler(auth
.CacheMixin
, base
.BaseHandler
):
263 @tornado.web
.authenticated
265 pages
= self
.backend
.wiki
.get_watchlist(self
.current_user
)
267 self
.render("wiki/watchlist.html", pages
=pages
)
270 class WikiDiffModule(ui_modules
.UIModule
):
271 differ
= difflib
.Differ()
273 def render(self
, a
, b
):
274 diff
= self
.differ
.compare(
275 a
.markdown
.splitlines(),
276 b
.markdown
.splitlines(),
279 return self
.render_string("wiki/modules/diff.html", diff
=diff
)
282 class WikiListModule(ui_modules
.UIModule
):
283 def render(self
, pages
, link_revision
=False, show_breadcrumbs
=True,
284 show_author
=True, show_changes
=False):
285 return self
.render_string("wiki/modules/list.html", link_revision
=link_revision
,
286 pages
=pages
, show_breadcrumbs
=show_breadcrumbs
,
287 show_author
=show_author
, show_changes
=show_changes
)
290 class WikiNavbarModule(ui_modules
.UIModule
):
294 Returns the path of the page (without any actions)
296 path
= self
.request
.path
.split("/")
298 if path
and path
[-1].startswith("_"):
301 return "/".join(path
)
303 def render(self
, suffix
=None):
304 _
= self
.locale
.translate
307 page
= self
.request
.path
.split("/")
309 # Drop the action bit
310 if page
and page
[-1].startswith("_"):
313 page
= "/".join(page
)
315 breadcrumbs
= self
.backend
.wiki
.make_breadcrumbs(page
)
316 title
= self
.backend
.wiki
.get_page_title(page
)
318 if self
.request
.path
.endswith("/_edit"):
320 elif self
.request
.path
.endswith("/_files"):
323 return self
.render_string("wiki/modules/navbar.html",
324 breadcrumbs
=breadcrumbs
, page
=page
, page_title
=title
, suffix
=suffix
)