]> git.ipfire.org Git - ipfire.org.git/blob - src/web/blog.py
wiki: Only match usernames when a word starts with @
[ipfire.org.git] / src / web / blog.py
1 #!/usr/bin/python
2
3 import datetime
4 import dateutil
5 import email.utils
6 import tornado.web
7
8 from . import base
9 from . import ui_modules
10
11 class IndexHandler(base.AnalyticsMixin, base.BaseHandler):
12 def get(self):
13 latest_post = None
14
15 # Fetch the search query
16 q = self.get_argument("q", None)
17
18 # If the user is searching, perform the search
19 if q:
20 posts = self.backend.blog.search(q)
21
22 # Otherwise fetch the latest posts
23 else:
24 posts = self.backend.blog.get_newest(limit=10)
25
26 # Extract the latest post
27 latest_post = posts.pop(0)
28
29 self.render("blog/index.html", q=q, posts=posts, latest_post=latest_post)
30
31
32 class FeedHandler(base.AnalyticsMixin, base.BaseHandler):
33 def get(self):
34 posts = self.backend.blog.get_newest(limit=10)
35 if not posts:
36 raise tornado.web.HTTPError(404)
37
38 # Allow this to be cached for 10 minutes
39 self.set_expires(600)
40
41 # Set correct content type
42 self.set_header("Content-Type", "application/atom+xml")
43
44 # Render the feed
45 self.render("blog/feed.xml", posts=posts,
46 now=datetime.datetime.now())
47
48
49 class PostHandler(base.AnalyticsMixin, base.BaseHandler):
50 def get(self, slug):
51 post = self.backend.blog.get_by_slug(slug)
52 if not post:
53 raise tornado.web.HTTPError(404)
54
55 self.render("blog/post.html", post=post)
56
57
58 class PublishHandler(base.BaseHandler):
59 @tornado.web.authenticated
60 def prepare(self):
61 # Check if the user has permissions
62 if not self.current_user.is_blog_author():
63 raise tornado.web.HTTPError(403)
64
65 @tornado.web.authenticated
66 def get(self, slug):
67 post = self.backend.blog.get_by_slug(slug)
68 if not post:
69 raise tornado.web.HTTPError(404)
70
71 # Check if current_user is allowed to edit the post
72 if not post.is_editable(self.current_user):
73 raise tornado.web.HTTPError(403)
74
75 # Is the post already published?
76 if post.is_published():
77 raise tornado.web.HTTPError(400, "Post is already published")
78
79 self.render("blog/publish.html", post=post)
80
81 @tornado.web.authenticated
82 def post(self, slug):
83 post = self.backend.blog.get_by_slug(slug)
84 if not post:
85 raise tornado.web.HTTPError(404)
86
87 # Check if current_user is allowed to edit the post
88 if not post.is_editable(self.current_user):
89 raise tornado.web.HTTPError(403)
90
91 # Is the post already published?
92 if post.is_published():
93 raise tornado.web.HTTPError(400, "Post is already published")
94
95 when = self.get_argument("when", None)
96 if when:
97 when = dateutil.parser.parse(when)
98
99 # Publish the post
100 with self.db.transaction():
101 post.publish(when)
102
103 self.redirect("/blog/%s" % post.slug)
104
105
106 class DraftsHandler(base.BaseHandler):
107 @tornado.web.authenticated
108 def prepare(self):
109 # Check if the user has permissions
110 if not self.current_user.is_blog_author():
111 raise tornado.web.HTTPError(403)
112
113 @tornado.web.authenticated
114 def get(self):
115 drafts = self.backend.blog.get_drafts(author=self.current_user)
116
117 self.render("blog/drafts.html", drafts=drafts)
118
119
120 class YearHandler(base.AnalyticsMixin, base.BaseHandler):
121 def get(self, year):
122 posts = self.backend.blog.get_by_year(year)
123 if not posts:
124 raise tornado.web.HTTPError(404, "There are no posts in %s" % year)
125
126 self.render("blog/year.html", posts=posts, year=year)
127
128
129 class WriteHandler(base.BaseHandler):
130 @tornado.web.authenticated
131 def prepare(self):
132 # Check if the user has permissions
133 if not self.current_user.is_blog_author():
134 raise tornado.web.HTTPError(403)
135
136 @tornado.web.authenticated
137 def get(self):
138 self.render("blog/write.html", post=None)
139
140 @tornado.web.authenticated
141 def post(self):
142 title = self.get_argument("title")
143 text = self.get_argument("text")
144 tags = self.get_argument("tags", "").split(" ")
145
146 with self.db.transaction():
147 post = self.backend.blog.create_post(title, text,
148 author=self.current_user, tags=tags)
149
150 # Redirect to the new post
151 self.redirect("/blog/%s" % post.slug)
152
153
154 class EditHandler(base.BaseHandler):
155 @tornado.web.authenticated
156 def get(self, slug):
157 post = self.backend.blog.get_by_slug(slug)
158 if not post:
159 raise tornado.web.HTTPError(404)
160
161 # Check if post is editable
162 if not post.is_editable(self.current_user):
163 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
164
165 self.render("blog/write.html", post=post)
166
167 @tornado.web.authenticated
168 def post(self, slug):
169 post = self.backend.blog.get_by_slug(slug)
170 if not post:
171 raise tornado.web.HTTPError(404, "Could not find post %s" % slug)
172
173 # Check if post is editable
174 if not post.is_editable(self.current_user):
175 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
176
177 # Save updated content
178 with self.db.transaction():
179 post.update(
180 title = self.get_argument("title"),
181 text = self.get_argument("text"),
182 tags = self.get_argument("tags", "").split(" "),
183 )
184
185 # Redirect to the post
186 self.redirect("/blog/%s" % post.slug)
187
188
189 class DeleteHandler(base.BaseHandler):
190 @tornado.web.authenticated
191 def get(self, slug):
192 post = self.backend.blog.get_by_slug(slug)
193 if not post:
194 raise tornado.web.HTTPError(404)
195
196 # Check if post is editable
197 if not post.is_editable(self.current_user):
198 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
199
200 self.render("blog/delete.html", post=post)
201
202 @tornado.web.authenticated
203 def post(self, slug):
204 post = self.backend.blog.get_by_slug(slug)
205 if not post:
206 raise tornado.web.HTTPError(404)
207
208 # Check if post is editable
209 if not post.is_editable(self.current_user):
210 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
211
212 with self.db.transaction():
213 post.delete()
214
215 # Return to drafts
216 self.redirect("/drafts")
217
218
219 class DebugEmailHandler(base.BaseHandler):
220 @tornado.web.authenticated
221 def get(self, slug):
222 if not self.current_user.is_staff():
223 raise tornado.web.HTTPError(403)
224
225 # Fetch the post
226 post = self.backend.blog.get_by_slug(slug)
227 if not post:
228 raise tornado.web.HTTPError(404, "Could not find post %s" % slug)
229
230 self.render("blog/messages/announcement.html", account=self.current_user, post=post)
231
232
233 class HistoryNavigationModule(ui_modules.UIModule):
234 def render(self):
235 return self.render_string("blog/modules/history-navigation.html",
236 years=self.backend.blog.years)
237
238
239 class ListModule(ui_modules.UIModule):
240 def render(self, posts, relative=False, show_author=True):
241 return self.render_string("blog/modules/list.html",
242 posts=posts, relative=relative, show_author=show_author)