]> git.ipfire.org Git - ipfire.org.git/blob - src/web/blog.py
65a73a6d736d5dde779ab32a272f9125e37fae2b
[ipfire.org.git] / src / web / blog.py
1 #!/usr/bin/python
2
3 import datetime
4 import email.utils
5 import tornado.web
6
7 from . import auth
8 from . import base
9 from . import ui_modules
10
11 class IndexHandler(auth.CacheMixin, base.BaseHandler):
12 def get(self):
13 posts = self.backend.blog.get_newest(limit=3)
14
15 # Allow this to be cached for 5 minutes
16 if not self.current_user:
17 self.set_expires(300)
18
19 self.render("blog/index.html", posts=posts)
20
21
22 class AuthorHandler(auth.CacheMixin, base.BaseHandler):
23 def get(self, uid):
24 author = self.accounts.get_by_uid(uid)
25 if not author:
26 raise tornado.web.HTTPError(404, "User is unknown")
27
28 # Get all posts from this author
29 posts = self.backend.blog.get_by_author(author)
30 if not posts:
31 raise tornado.web.HTTPError(404, "User has no posts")
32
33 # Allow this to be cached for 10 minutes
34 if not self.current_user:
35 self.set_expires(600)
36
37 self.render("blog/author.html", author=author, posts=posts)
38
39
40 class FeedHandler(base.BaseHandler):
41 def get(self):
42 posts = self.backend.blog.get_newest(limit=50)
43
44 # Render the feed
45 feed = self.render_string("blog/feed.xml", posts=posts,
46 now=email.utils.formatdate())
47
48 # Allow this to be cached for 10 minutes
49 self.set_expires(600)
50
51 # Set correct content type
52 self.set_header("Content-Type", "application/rss+xml")
53
54 # Deliver content
55 self.finish(feed)
56
57
58 class PostHandler(auth.CacheMixin, base.BaseHandler):
59 def get(self, slug):
60 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
61 if not post:
62 raise tornado.web.HTTPError(404)
63
64 # Allow this to be cached for 10 minutes
65 if post.is_published():
66 self.set_expires(600)
67
68 self.render("blog/post.html", post=post)
69
70
71 class PublishHandler(auth.CacheMixin, base.BaseHandler):
72 @tornado.web.authenticated
73 def post(self, slug):
74 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
75 if not post:
76 raise tornado.web.HTTPError(404)
77
78 # Is the post already published?
79 if post.is_published():
80 raise tornado.web.HTTPError(400, "Post is already published")
81
82 # XXX Check that we are only publishing our own posts
83
84 # Publish the post
85 with self.db.transaction():
86 post.publish()
87
88 self.redirect("/post/%s" % post.slug)
89
90
91 class DraftsHandler(auth.CacheMixin, base.BaseHandler):
92 @tornado.web.authenticated
93 def get(self):
94 drafts = self.backend.blog.get_drafts(author=self.current_user)
95
96 self.render("blog/drafts.html", drafts=drafts)
97
98
99 class SearchHandler(auth.CacheMixin, base.BaseHandler):
100 def get(self):
101 q = self.get_argument("q")
102
103 posts = self.backend.blog.search(q, limit=50)
104 if not posts:
105 raise tornado.web.HTTPError(404, "Nothing found")
106
107 self.render("blog/search-results.html", q=q, posts=posts)
108
109
110 class TagHandler(auth.CacheMixin, base.BaseHandler):
111 def get(self, tag):
112 posts = self.backend.blog.get_by_tag(tag)
113 if not posts:
114 raise tornado.web.HTTPError(404, "There are no posts with tag: %s" % tag)
115
116 # Allow this to be cached for 10 minutes
117 self.set_expires(600)
118
119 self.render("blog/tag.html", posts=list(posts), tag=tag)
120
121
122 class YearHandler(auth.CacheMixin, base.BaseHandler):
123 def get(self, year):
124 posts = self.backend.blog.get_by_year(year)
125 if not posts:
126 raise tornado.web.HTTPError(404, "There are no posts in %s" % year)
127
128 # Allow this to be cached for 10 minutes
129 self.set_expires(600)
130
131 self.render("blog/year.html", posts=posts, year=year)
132
133
134 class ComposeHandler(auth.CacheMixin, base.BaseHandler):
135 @tornado.web.authenticated
136 def get(self):
137 self.render("blog/compose.html", post=None)
138
139 @tornado.web.authenticated
140 def post(self):
141 title = self.get_argument("title")
142 text = self.get_argument("text")
143 tags = self.get_argument("tags", "").split(" ")
144
145 with self.db.transaction():
146 post = self.backend.blog.create_post(title, text,
147 author=self.current_user, tags=tags)
148
149 self.redirect("/drafts")
150
151
152 class EditHandler(auth.CacheMixin, base.BaseHandler):
153 @tornado.web.authenticated
154 def get(self, slug):
155 post = self.backend.blog.get_by_slug(slug, published=False)
156 if not post:
157 raise tornado.web.HTTPError(404)
158
159 # Check if post is editable
160 if not post.is_editable(self.current_user):
161 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
162
163 self.render("blog/compose.html", post=post)
164
165 @tornado.web.authenticated
166 def post(self, slug):
167 post = self.backend.blog.get_by_slug(slug, published=False)
168 if not post:
169 raise tornado.web.HTTPError(404)
170
171 # Check if post is editable
172 if not post.is_editable(self.current_user):
173 raise tornado.web.HTTPError(403, "%s cannot edit %s" % (self.current_user, post))
174
175 # Save updated content
176 with self.db.transaction():
177 post.update(
178 title = self.get_argument("title"),
179 text = self.get_argument("text"),
180 tags = self.get_argument("tags", "").split(" "),
181 )
182
183 # Return to blog if the post is already published
184 if post.is_published():
185 self.redirect("/post/%s" % post.slug)
186 return
187
188 # Otherwise return to drafts
189 self.redirect("/drafts")
190
191
192 class HistoryNavigationModule(ui_modules.UIModule):
193 def render(self):
194 return self.render_string("blog/modules/history-navigation.html",
195 years=self.backend.blog.years)
196
197
198 class ListModule(ui_modules.UIModule):
199 def render(self, posts):
200 return self.render_string("blog/modules/list.html", posts=posts)
201
202
203 class PostModule(ui_modules.UIModule):
204 def render(self, post):
205 return self.render_string("blog/modules/post.html", post=post)
206
207
208 class PostsModule(ui_modules.UIModule):
209 def render(self, posts):
210 return self.render_string("blog/modules/posts.html", posts=list(posts))