]> git.ipfire.org Git - ipfire.org.git/blob - src/web/wiki.py
f02fce552b2336a706b650d2807857b411923ee4
[ipfire.org.git] / src / web / wiki.py
1 #!/usr/bin/python3
2
3 import tornado.web
4
5 from . import auth
6 from . import base
7 from . import ui_modules
8
9 class ActionUploadHandler(auth.CacheMixin, base.BaseHandler):
10 @tornado.web.authenticated
11 def post(self):
12 path = self.get_argument("path")
13
14 try:
15 filename, data, mimetype = self.get_file("file")
16
17 # XXX check valid mimetypes
18
19 with self.db.transaction():
20 file = self.backend.wiki.upload(path, filename, data,
21 mimetype=mimetype, author=self.current_user,
22 address=self.get_remote_ip())
23
24 except TypeError as e:
25 raise e
26
27 self.redirect("%s/files" % path)
28
29
30 class FilesHandler(auth.CacheMixin, base.BaseHandler):
31 @tornado.web.authenticated
32 def get(self, path):
33 files = self.backend.wiki.get_files(path)
34
35 self.render("wiki/files/index.html", path=path, files=files)
36
37
38 class FileHandler(auth.CacheMixin, base.BaseHandler):
39 @property
40 def action(self):
41 return self.get_argument("action", None)
42
43 def get(self, path):
44 file = self.backend.wiki.get_file_by_path(path)
45 if not file:
46 raise tornado.web.HTTPError(404, "Could not find %s" % path)
47
48 # Render detail page
49 if self.action == "detail":
50 self.render("wiki/files/detail.html", file=file)
51 return
52
53 size = self.get_argument_int("s", None)
54
55 # Check if image should be resized
56 if file.is_image() and size:
57 blob = file.get_thumbnail(size)
58 else:
59 blob = file.blob
60
61 # Set headers
62 self.set_header("Content-Type", file.mimetype or "application/octet-stream")
63 self.set_header("Content-Length", len(blob))
64
65 # Deliver content
66 self.finish(blob)
67
68
69 class PageHandler(auth.CacheMixin, base.BaseHandler):
70 @property
71 def action(self):
72 return self.get_argument("action", None)
73
74 def write_error(self, status_code, **kwargs):
75 # Render a custom page for 404
76 if status_code == 404:
77 self.render("wiki/404.html", **kwargs)
78 return
79
80 # Otherwise raise this to one layer above
81 super().write_error(status_code, **kwargs)
82
83 @tornado.web.removeslash
84 def get(self, page):
85 # Check if we are asked to render a certain revision
86 revision = self.get_argument("revision", None)
87
88 # Fetch the wiki page
89 page = self.backend.wiki.get_page(page, revision=revision)
90
91 # Edit
92 if self.action == "edit":
93 if not self.current_user:
94 raise tornado.web.HTTPError(401)
95
96 # Empty page if it was deleted
97 if page and page.was_deleted():
98 page = None
99
100 # Render page
101 self.render("wiki/edit.html", page=page)
102 return
103
104 # Revisions
105 elif self.action == "revisions":
106 self.render("wiki/revisions.html", page=page)
107 return
108
109 # If the page does not exist, we send 404
110 if not page or page.was_deleted():
111 raise tornado.web.HTTPError(404)
112
113 # Fetch the latest revision
114 latest_revision = page.get_latest_revision()
115
116 # Render page
117 self.render("wiki/page.html", page=page, latest_revision=latest_revision)
118
119 @tornado.web.authenticated
120 def post(self, page):
121 content = self.get_argument("content", None)
122 changes = self.get_argument("changes")
123
124 # Create a new page in the database
125 with self.db.transaction():
126 page = self.backend.wiki.create_page(page,
127 self.current_user, content, changes=changes, address=self.get_remote_ip())
128
129 # Redirect back
130 if page.was_deleted():
131 self.redirect("/")
132 else:
133 self.redirect(page.url)
134
135 # Update the search index
136 with self.db.transaction():
137 self.backend.wiki.refresh()
138
139
140 class SearchHandler(auth.CacheMixin, base.BaseHandler):
141 @base.blacklisted
142 def get(self):
143 q = self.get_argument("q")
144
145 pages = self.backend.wiki.search(q, limit=50)
146
147 self.render("wiki/search-results.html", q=q, pages=pages)
148
149
150 class RecentChangesHandler(auth.CacheMixin, base.BaseHandler):
151 def get(self):
152 recent_changes = self.backend.wiki.get_recent_changes(limit=50)
153
154 self.render("wiki/recent-changes.html", recent_changes=recent_changes)
155
156
157 class WikiListModule(ui_modules.UIModule):
158 def render(self, pages, link_revision=False, show_breadcrumbs=True, show_changes=False):
159 return self.render_string("wiki/modules/list.html", link_revision=link_revision,
160 pages=pages, show_breadcrumbs=show_breadcrumbs, show_changes=show_changes)
161
162
163 class WikiNavbarModule(ui_modules.UIModule):
164 def render(self, suffix=None):
165 _ = self.locale.translate
166
167 breadcrumbs = self.backend.wiki.make_breadcrumbs(self.request.path)
168
169 # Don't search for a title for the file manager
170 if self.request.path.endswith("/files"):
171 title = _("Files")
172 else:
173 title = self.backend.wiki.get_page_title(self.request.path)
174
175 return self.render_string("wiki/modules/navbar.html",
176 breadcrumbs=breadcrumbs, page_title=title, suffix=suffix)