]> git.ipfire.org Git - ipfire.org.git/blame - src/web/wiki.py
wiki: Adjust width of label for changes box
[ipfire.org.git] / src / web / wiki.py
CommitLineData
181d08f3
MT
1#!/usr/bin/python3
2
c21ffadb 3import difflib
181d08f3
MT
4import tornado.web
5
6from . import auth
7from . import base
6ac7e934 8from . import ui_modules
181d08f3 9
b6e8b28f
MT
10class ActionEditHandler(auth.CacheMixin, base.BaseHandler):
11 @tornado.web.authenticated
12 def post(self):
13 path = self.get_argument("path")
14
15 # Check permissions
16 if not self.backend.wiki.check_acl(path, self.current_user):
17 raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (path, self.current_user))
18
19 content = self.get_argument("content", None)
20 changes = self.get_argument("changes")
21
22 # Create a new page in the database
23 with self.db.transaction():
24 page = self.backend.wiki.create_page(path,
25 self.current_user, content, changes=changes, address=self.get_remote_ip())
26
d64a1e35
MT
27 # Add user as a watcher if wanted
28 watch = self.get_argument("watch", False)
29 if watch:
30 page.add_watcher(self.current_user)
31
b6e8b28f
MT
32 # Redirect back
33 if page.was_deleted():
34 self.redirect("/")
35 else:
36 self.redirect(page.url)
37
38 def on_finish(self):
39 """
40 Updates the search index after the page has been edited
41 """
42 # This is being executed in the background and after
43 # the response has been set to the client
44 with self.db.transaction():
45 self.backend.wiki.refresh()
46
47
f2cfd873
MT
48class ActionUploadHandler(auth.CacheMixin, base.BaseHandler):
49 @tornado.web.authenticated
50 def post(self):
51 path = self.get_argument("path")
52
11afe905
MT
53 # Check permissions
54 if not self.backend.wiki.check_acl(path, self.current_user):
55 raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (path, self.current_user))
56
f2cfd873
MT
57 try:
58 filename, data, mimetype = self.get_file("file")
59
60 # XXX check valid mimetypes
61
62 with self.db.transaction():
63 file = self.backend.wiki.upload(path, filename, data,
64 mimetype=mimetype, author=self.current_user,
65 address=self.get_remote_ip())
66
67 except TypeError as e:
68 raise e
69
70 self.redirect("%s/files" % path)
71
72
d64a1e35
MT
73class ActionWatchHandler(auth.CacheMixin, base.BaseHandler):
74 @tornado.web.authenticated
75 def get(self, action, path):
76 page = self.backend.wiki.get_page(path)
77 if not page:
78 raise tornado.web.HTTPError(404, "Page does not exist: %s" % path)
79
80 with self.db.transaction():
81 if action == "watch":
82 page.add_watcher(self.current_user)
83 elif action == "unwatch":
84 page.remove_watcher(self.current_user)
85
86 # Redirect back to page
87 self.redirect(page.url)
88
89
f2cfd873
MT
90class FilesHandler(auth.CacheMixin, base.BaseHandler):
91 @tornado.web.authenticated
92 def get(self, path):
11afe905
MT
93 # Check permissions
94 if not self.backend.wiki.check_acl(path, self.current_user):
95 raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (path, self.current_user))
96
f2cfd873
MT
97 files = self.backend.wiki.get_files(path)
98
99 self.render("wiki/files/index.html", path=path, files=files)
100
101
568b265b 102class FileHandler(base.BaseHandler):
8cb0bea4
MT
103 @property
104 def action(self):
105 return self.get_argument("action", None)
106
f2cfd873 107 def get(self, path):
11afe905
MT
108 # Check permissions
109 if not self.backend.wiki.check_acl(path, self.current_user):
110 raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (path, self.current_user))
111
112 # Fetch the file
f2cfd873
MT
113 file = self.backend.wiki.get_file_by_path(path)
114 if not file:
115 raise tornado.web.HTTPError(404, "Could not find %s" % path)
116
8cb0bea4
MT
117 # Render detail page
118 if self.action == "detail":
531846f7
MT
119 for breadcrumb, title in self.backend.wiki.make_breadcrumbs(path):
120 page = self.backend.wiki.get_page(breadcrumb)
121 if page:
122 break
123
124 self.render("wiki/files/detail.html", page=page, file=file)
8cb0bea4
MT
125 return
126
79dd9a0f
MT
127 size = self.get_argument_int("s", None)
128
129 # Check if image should be resized
130 if file.is_image() and size:
131 blob = file.get_thumbnail(size)
132 else:
133 blob = file.blob
134
f2cfd873
MT
135 # Set headers
136 self.set_header("Content-Type", file.mimetype or "application/octet-stream")
79dd9a0f 137 self.set_header("Content-Length", len(blob))
f2cfd873 138
568b265b
MT
139 # Set expires
140 self.set_expires(3600)
141
79dd9a0f
MT
142 # Deliver content
143 self.finish(blob)
f2cfd873
MT
144
145
181d08f3 146class PageHandler(auth.CacheMixin, base.BaseHandler):
d398ca08
MT
147 @property
148 def action(self):
149 return self.get_argument("action", None)
150
a446dcb9
MT
151 def write_error(self, status_code, **kwargs):
152 # Render a custom page for 404
153 if status_code == 404:
154 self.render("wiki/404.html", **kwargs)
155 return
156
157 # Otherwise raise this to one layer above
158 super().write_error(status_code, **kwargs)
159
181d08f3
MT
160 @tornado.web.removeslash
161 def get(self, page):
11afe905
MT
162 # Check permissions
163 if not self.backend.wiki.check_acl(page, self.current_user):
164 raise tornado.web.HTTPError(403, "Access to %s not allowed for %s" % (page, self.current_user))
165
7d699684
MT
166 # Check if we are asked to render a certain revision
167 revision = self.get_argument("revision", None)
168
169 # Fetch the wiki page
170 page = self.backend.wiki.get_page(page, revision=revision)
181d08f3 171
c21ffadb
MT
172 # Diff
173 if self.action == "diff":
174 # Get both revisions
175 a = self.get_argument("a")
176 b = self.get_argument("b")
177
178 # Fetch both versions of the page
179 a = self.backend.wiki.get_page(page.page, revision=a)
180 b = self.backend.wiki.get_page(page.page, revision=b)
181 if not a or not b:
182 raise tornado.web.HTTPError(404)
183
184 # Cannot render a diff for the identical page
185 if a == b:
186 raise tornado.web.HTTPError(400)
187
188 # Make sure that b is newer than a
189 if a > b:
190 a, b = b, a
191
192 self.render("wiki/diff.html", page=page, a=a, b=b)
193 return
194
d398ca08 195 # Edit
c21ffadb 196 elif self.action == "edit":
d398ca08
MT
197 if not self.current_user:
198 raise tornado.web.HTTPError(401)
199
200 # Empty page if it was deleted
addc4eb7 201 if page and page.was_deleted():
d398ca08
MT
202 page = None
203
7d699684
MT
204 # Render page
205 self.render("wiki/edit.html", page=page)
206 return
207
208 # Revisions
209 elif self.action == "revisions":
210 self.render("wiki/revisions.html", page=page)
211 return
d398ca08 212
181d08f3
MT
213 # If the page does not exist, we send 404
214 if not page or page.was_deleted():
215 raise tornado.web.HTTPError(404)
216
217 # Fetch the latest revision
218 latest_revision = page.get_latest_revision()
219
220 # Render page
221 self.render("wiki/page.html", page=page, latest_revision=latest_revision)
222
181d08f3
MT
223
224class SearchHandler(auth.CacheMixin, base.BaseHandler):
225 @base.blacklisted
226 def get(self):
227 q = self.get_argument("q")
228
11afe905 229 pages = self.backend.wiki.search(q, account=self.current_user, limit=50)
181d08f3 230
11afe905 231 self.render("wiki/search-results.html", q=q, pages=list(pages))
6ac7e934
MT
232
233
f9db574a
MT
234class RecentChangesHandler(auth.CacheMixin, base.BaseHandler):
235 def get(self):
11afe905 236 recent_changes = self.backend.wiki.get_recent_changes(self.current_user, limit=50)
f9db574a
MT
237
238 self.render("wiki/recent-changes.html", recent_changes=recent_changes)
239
240
c21ffadb
MT
241class WikiDiffModule(ui_modules.UIModule):
242 differ = difflib.Differ()
243
244 def render(self, a, b):
245 diff = self.differ.compare(
246 a.markdown.splitlines(),
247 b.markdown.splitlines(),
248 )
249
250 return self.render_string("wiki/modules/diff.html", diff=diff)
251
252
f9db574a 253class WikiListModule(ui_modules.UIModule):
7d699684
MT
254 def render(self, pages, link_revision=False, show_breadcrumbs=True, show_changes=False):
255 return self.render_string("wiki/modules/list.html", link_revision=link_revision,
66a814d9 256 pages=pages, show_breadcrumbs=show_breadcrumbs, show_changes=show_changes)
f9db574a
MT
257
258
6ac7e934 259class WikiNavbarModule(ui_modules.UIModule):
67573803 260 def render(self, suffix=None):
f2cfd873
MT
261 _ = self.locale.translate
262
67573803
MT
263 breadcrumbs = self.backend.wiki.make_breadcrumbs(self.request.path)
264
f2cfd873
MT
265 # Don't search for a title for the file manager
266 if self.request.path.endswith("/files"):
267 title = _("Files")
268 else:
269 title = self.backend.wiki.get_page_title(self.request.path)
6ac7e934
MT
270
271 return self.render_string("wiki/modules/navbar.html",
67573803 272 breadcrumbs=breadcrumbs, page_title=title, suffix=suffix)