]> git.ipfire.org Git - ipfire.org.git/blame - src/web/blog.py
blog: Add author's avatar
[ipfire.org.git] / src / web / blog.py
CommitLineData
12e5de7e
MT
1#!/usr/bin/python
2
9ea64cef 3import datetime
f0714277 4import email.utils
12e5de7e
MT
5import tornado.web
6
9b8ff27d 7from . import auth
124a8404 8from . import base
f91dfcc7
MT
9from . import ui_modules
10
9b8ff27d 11class IndexHandler(auth.CacheMixin, base.BaseHandler):
8a897d25 12 def get(self):
0a6875dc 13 posts = self.backend.blog.get_newest(limit=3)
8a897d25 14
9d020f28 15 # Allow this to be cached for 5 minutes
9b8ff27d
MT
16 if not self.current_user:
17 self.set_expires(300)
9d020f28 18
8a897d25
MT
19 self.render("blog/index.html", posts=posts)
20
21
9b8ff27d 22class AuthorHandler(auth.CacheMixin, base.BaseHandler):
cfc0823a
MT
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
cdf85ee7 29 posts = self.backend.blog.get_by_author(author)
cfc0823a
MT
30 if not posts:
31 raise tornado.web.HTTPError(404, "User has no posts")
32
9d020f28 33 # Allow this to be cached for 10 minutes
9b8ff27d
MT
34 if not self.current_user:
35 self.set_expires(600)
9d020f28 36
cfc0823a
MT
37 self.render("blog/author.html", author=author, posts=posts)
38
39
f0714277
MT
40class FeedHandler(base.BaseHandler):
41 def get(self):
04dc3625 42 posts = self.backend.blog.get_newest(limit=50)
f0714277 43
04dc3625
MT
44 # Render the feed
45 feed = self.render_string("blog/feed.xml", posts=posts,
46 now=email.utils.formatdate())
f0714277 47
9d020f28
MT
48 # Allow this to be cached for 10 minutes
49 self.set_expires(600)
f0714277
MT
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
9b8ff27d 58class PostHandler(auth.CacheMixin, base.BaseHandler):
12e5de7e 59 def get(self, slug):
df157ede 60 post = self.backend.blog.get_by_slug(slug, published=not self.current_user)
0a6875dc 61 if not post:
12e5de7e
MT
62 raise tornado.web.HTTPError(404)
63
9d020f28 64 # Allow this to be cached for 10 minutes
a864e694
MT
65 if post.is_published():
66 self.set_expires(600)
9d020f28 67
0a6875dc 68 self.render("blog/post.html", post=post)
f91dfcc7
MT
69
70
9b8ff27d 71class PublishHandler(auth.CacheMixin, base.BaseHandler):
9ea64cef
MT
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
fe40c0fa
MT
82 # XXX Check that we are only publishing our own posts
83
9ea64cef
MT
84 # Publish the post
85 with self.db.transaction():
86 post.publish()
87
88 self.redirect("/post/%s" % post.slug)
89
90
9b8ff27d 91class DraftsHandler(auth.CacheMixin, base.BaseHandler):
0b342a05
MT
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
9b8ff27d 99class SearchHandler(auth.CacheMixin, base.BaseHandler):
e6b18dce
MT
100 def get(self):
101 q = self.get_argument("q")
102
0a6875dc 103 posts = self.backend.blog.search(q, limit=50)
e6b18dce
MT
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
9b8ff27d 110class TagHandler(auth.CacheMixin, base.BaseHandler):
4bde7f18
MT
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
9d020f28
MT
116 # Allow this to be cached for 10 minutes
117 self.set_expires(600)
118
f0dc2fc1 119 self.render("blog/tag.html", posts=list(posts), tag=tag)
4bde7f18
MT
120
121
9b8ff27d 122class YearHandler(auth.CacheMixin, base.BaseHandler):
7e64f6a3
MT
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
9d020f28
MT
128 # Allow this to be cached for 10 minutes
129 self.set_expires(600)
130
7e64f6a3
MT
131 self.render("blog/year.html", posts=posts, year=year)
132
133
9b8ff27d 134class ComposeHandler(auth.CacheMixin, base.BaseHandler):
541c952b
MT
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")
dc035dce 143 tags = self.get_argument("tags", "").split(" ")
541c952b
MT
144
145 with self.db.transaction():
146 post = self.backend.blog.create_post(title, text,
147 author=self.current_user, tags=tags)
148
61e0a831 149 self.redirect("/drafts")
541c952b
MT
150
151
9b8ff27d 152class EditHandler(auth.CacheMixin, base.BaseHandler):
541c952b
MT
153 @tornado.web.authenticated
154 def get(self, slug):
00bf122b 155 post = self.backend.blog.get_by_slug(slug, published=False)
541c952b
MT
156 if not post:
157 raise tornado.web.HTTPError(404)
158
e8a81a70
MT
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))
541c952b
MT
162
163 self.render("blog/compose.html", post=post)
164
165 @tornado.web.authenticated
166 def post(self, slug):
00bf122b 167 post = self.backend.blog.get_by_slug(slug, published=False)
541c952b
MT
168 if not post:
169 raise tornado.web.HTTPError(404)
170
e8a81a70
MT
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))
541c952b 174
93725180 175 # Save updated content
541c952b 176 with self.db.transaction():
93725180
MT
177 post.update(
178 title = self.get_argument("title"),
179 text = self.get_argument("text"),
dc035dce 180 tags = self.get_argument("tags", "").split(" "),
93725180 181 )
541c952b
MT
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
61e0a831
MT
188 # Otherwise return to drafts
189 self.redirect("/drafts")
541c952b
MT
190
191
7e64f6a3
MT
192class 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
198class ListModule(ui_modules.UIModule):
199 def render(self, posts):
200 return self.render_string("blog/modules/list.html", posts=posts)
201
202
f91dfcc7
MT
203class PostModule(ui_modules.UIModule):
204 def render(self, post):
205 return self.render_string("blog/modules/post.html", post=post)
8a897d25
MT
206
207
208class PostsModule(ui_modules.UIModule):
209 def render(self, posts):
0a6875dc 210 return self.render_string("blog/modules/posts.html", posts=list(posts))