Commit | Line | Data |
---|---|---|
cf46184a A |
1 | # GNU MediaGoblin -- federated, autonomous media hosting |
2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. | |
3 | # | |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
af8f995f | 17 | import logging |
af8f995f A |
18 | _log = logging.getLogger(__name__) |
19 | ||
cf46184a A |
20 | from datetime import datetime |
21 | ||
22 | from werkzeug.exceptions import Forbidden | |
125d7d1a | 23 | from mediagoblin.tools import pluginapi |
cf46184a | 24 | |
cf46184a A |
25 | from mediagoblin import mg_globals |
26 | ||
27 | from mediagoblin.media_types.blog import forms as blog_forms | |
5cb38a28 | 28 | from mediagoblin.media_types.blog.models import Blog, BlogPostData |
0b2ea4bb | 29 | from mediagoblin.media_types.blog.lib import may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog |
5cb38a28 | 30 | |
af8f995f | 31 | from mediagoblin.messages import add_message, SUCCESS, ERROR |
cf46184a A |
32 | from mediagoblin.decorators import (require_active_login, active_user_from_url, |
33 | get_media_entry_by_id, user_may_alter_collection, | |
0b2ea4bb A |
34 | get_user_collection, uses_pagination) |
35 | from mediagoblin.tools.pagination import Pagination | |
cf46184a | 36 | from mediagoblin.tools.response import (render_to_response, |
0b2ea4bb | 37 | redirect, render_404) |
cf46184a A |
38 | from mediagoblin.tools.translate import pass_to_ugettext as _ |
39 | from mediagoblin.tools.template import render_template | |
40 | from mediagoblin.tools.text import ( | |
0b7c64c8 | 41 | convert_to_tag_list_of_dicts, media_tags_as_string, clean_html, |
3e329412 | 42 | cleaned_markdown_conversion) |
5cb38a28 | 43 | |
cf46184a | 44 | from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used |
af8f995f A |
45 | from mediagoblin.db.models import User, Collection, MediaEntry |
46 | ||
fa5a13f8 A |
47 | from mediagoblin.notifications import add_comment_subscription |
48 | ||
cf46184a A |
49 | |
50 | @require_active_login | |
af8f995f | 51 | def blog_edit(request): |
cf46184a | 52 | """ |
afff1492 AM |
53 | View for editing an existing blog or creating a new blog |
54 | if user have not exceeded maximum allowed acount of blogs. | |
cf46184a | 55 | """ |
af8f995f A |
56 | url_user = request.matchdict.get('user', None) |
57 | blog_slug = request.matchdict.get('blog_slug', None) | |
0b7c64c8 | 58 | |
125d7d1a AM |
59 | config = pluginapi.get_config('mediagoblin.media_types.blog') |
60 | max_blog_count = config['max_blog_count'] | |
af8f995f | 61 | form = blog_forms.BlogEditForm(request.form) |
afff1492 | 62 | # creating a blog |
af8f995f A |
63 | if not blog_slug: |
64 | if Blog.query.filter_by(author=request.user.id).count()<max_blog_count: | |
65 | if request.method=='GET': | |
66 | return render_to_response( | |
67 | request, | |
68 | 'mediagoblin/blog/blog_edit_create.html', | |
69 | {'form': form, | |
70 | 'user' : request.user, | |
71 | 'app_config': mg_globals.app_config}) | |
72 | ||
73 | if request.method=='POST' and form.validate(): | |
74 | _log.info("Here") | |
0b2ea4bb | 75 | blog = request.db.Blog() |
af8f995f | 76 | blog.title = unicode(form.title.data) |
0b7c64c8 | 77 | blog.description = unicode(cleaned_markdown_conversion((form.description.data))) |
af8f995f A |
78 | blog.author = request.user.id |
79 | blog.generate_slug() | |
0b7c64c8 | 80 | |
af8f995f | 81 | blog.save() |
1d9d9f1c AM |
82 | return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", |
83 | user=request.user.username | |
84 | ) | |
cf46184a | 85 | else: |
afff1492 AM |
86 | add_message(request, ERROR, "Welcome! You already have created \ |
87 | maximum number of blogs.") | |
1d9d9f1c AM |
88 | return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", |
89 | user=request.user.username) | |
cf46184a | 90 | |
cf46184a | 91 | |
bed960cb | 92 | #Blog already exists. |
cf46184a | 93 | else: |
0b2ea4bb | 94 | blog = request.db.Blog.query.filter_by(slug=blog_slug).first() |
afff1492 AM |
95 | if not blog: |
96 | return render_404(request) | |
af8f995f | 97 | if request.method == 'GET': |
af8f995f A |
98 | defaults = dict( |
99 | title = blog.title, | |
21ac4966 | 100 | description = cleaned_markdown_conversion(blog.description), |
0b7c64c8 AM |
101 | author = request.user.id) |
102 | ||
af8f995f A |
103 | form = blog_forms.BlogEditForm(**defaults) |
104 | ||
105 | return render_to_response( | |
106 | request, | |
107 | 'mediagoblin/blog/blog_edit_create.html', | |
108 | {'form': form, | |
109 | 'user': request.user, | |
110 | 'app_config': mg_globals.app_config}) | |
111 | else: | |
fa5a13f8 | 112 | if request.method == 'POST' and form.validate(): |
145a1738 | 113 | blog.title = unicode(form.title.data) |
21ac4966 | 114 | blog.description = unicode(cleaned_markdown_conversion((form.description.data))) |
145a1738 A |
115 | blog.author = request.user.id |
116 | blog.generate_slug() | |
0b7c64c8 | 117 | |
145a1738 A |
118 | blog.save() |
119 | add_message(request, SUCCESS, "Your blog is updated.") | |
8f6a0bf4 A |
120 | return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", |
121 | user=request.user.username, | |
0b7c64c8 AM |
122 | blog_slug=blog.slug) |
123 | ||
0b2ea4bb | 124 | |
0b7c64c8 | 125 | @require_active_login |
fa5a13f8 | 126 | def blogpost_create(request): |
0b7c64c8 | 127 | |
5cb38a28 | 128 | form = blog_forms.BlogPostEditForm(request.form, license=request.user.license_preference) |
0b7c64c8 | 129 | |
145a1738 | 130 | if request.method == 'POST' and form.validate(): |
5cb38a28 A |
131 | blog_slug = request.matchdict.get('blog_slug') |
132 | blog = request.db.Blog.query.filter_by(slug=blog_slug, | |
133 | author=request.user.id).first() | |
4cf5b010 A |
134 | if not blog: |
135 | return render_404(request) | |
0b7c64c8 | 136 | |
5cb38a28 | 137 | blogpost = request.db.MediaEntry() |
783b5005 | 138 | blogpost.media_type = 'mediagoblin.media_types.blogpost' |
145a1738 | 139 | blogpost.title = unicode(form.title.data) |
21ac4966 | 140 | blogpost.description = unicode(cleaned_markdown_conversion((form.description.data))) |
145a1738 A |
141 | blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data) |
142 | blogpost.license = unicode(form.license.data) or None | |
143 | blogpost.uploader = request.user.id | |
145a1738 | 144 | blogpost.generate_slug() |
0b7c64c8 | 145 | |
4cf5b010 | 146 | set_blogpost_state(request, blogpost) |
145a1738 | 147 | blogpost.save() |
0b7c64c8 | 148 | |
5cb38a28 A |
149 | # connect this blogpost to its blog |
150 | blog_post_data = request.db.BlogPostData() | |
151 | blog_post_data.blog = blog.id | |
152 | blog_post_data.media_entry = blogpost.id | |
153 | blog_post_data.save() | |
0b7c64c8 | 154 | |
145a1738 A |
155 | add_message(request, SUCCESS, _('Woohoo! Submitted!')) |
156 | add_comment_subscription(request.user, blogpost) | |
7b23b1e5 A |
157 | return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", |
158 | user=request.user.username, | |
159 | blog_slug=blog.slug) | |
0b7c64c8 | 160 | |
145a1738 | 161 | return render_to_response( |
fa5a13f8 A |
162 | request, |
163 | 'mediagoblin/blog/blog_post_edit_create.html', | |
164 | {'form': form, | |
165 | 'app_config': mg_globals.app_config, | |
166 | 'user': request.user.username}) | |
e058cdce A |
167 | |
168 | ||
169 | @require_active_login | |
170 | def blogpost_edit(request): | |
afff1492 | 171 | |
8f6a0bf4 A |
172 | blog_slug = request.matchdict.get('blog_slug', None) |
173 | blog_post_slug = request.matchdict.get('blog_post_slug', None) | |
0b7c64c8 | 174 | |
221cde57 | 175 | blogpost = request.db.MediaEntry.query.filter_by(slug=blog_post_slug, uploader=request.user.id).first() |
5cb38a28 | 176 | blog = request.db.Blog.query.filter_by(slug=blog_slug, author=request.user.id).first() |
0b7c64c8 | 177 | |
b5ae9685 A |
178 | if not blogpost or not blog: |
179 | return render_404(request) | |
0b7c64c8 | 180 | |
5cb38a28 A |
181 | defaults = dict( |
182 | title = blogpost.title, | |
21ac4966 | 183 | description = cleaned_markdown_conversion(blogpost.description), |
5cb38a28 A |
184 | tags=media_tags_as_string(blogpost.tags), |
185 | license=blogpost.license) | |
0b7c64c8 | 186 | |
5cb38a28 A |
187 | form = blog_forms.BlogPostEditForm(request.form, **defaults) |
188 | if request.method == 'POST' and form.validate(): | |
189 | blogpost.title = unicode(form.title.data) | |
21ac4966 | 190 | blogpost.description = unicode(cleaned_markdown_conversion((form.description.data))) |
5cb38a28 | 191 | blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data) |
0b7c64c8 | 192 | blogpost.license = unicode(form.license.data) |
4cf5b010 | 193 | set_blogpost_state(request, blogpost) |
5cb38a28 A |
194 | blogpost.generate_slug() |
195 | blogpost.save() | |
0b7c64c8 | 196 | |
5cb38a28 | 197 | add_message(request, SUCCESS, _('Woohoo! edited blogpost is submitted')) |
3e329412 A |
198 | return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", |
199 | user=request.user.username, | |
200 | blog_slug=blog.slug) | |
0b7c64c8 | 201 | |
5cb38a28 | 202 | return render_to_response( |
e058cdce A |
203 | request, |
204 | 'mediagoblin/blog/blog_post_edit_create.html', | |
205 | {'form': form, | |
206 | 'app_config': mg_globals.app_config, | |
207 | 'user': request.user.username, | |
5cb38a28 | 208 | 'blog_post_slug': blog_post_slug |
0b7c64c8 | 209 | }) |
e058cdce | 210 | |
59614310 | 211 | |
eebd8fe3 | 212 | @active_user_from_url |
8762609f | 213 | @uses_pagination |
eebd8fe3 | 214 | def blog_dashboard(request, page, url_user=None): |
afff1492 AM |
215 | """ |
216 | Dashboard for a blog, only accessible to | |
217 | the owner of the blog. | |
218 | """ | |
4aa7058e | 219 | blog_slug = request.matchdict.get('blog_slug', None) |
eebd8fe3 | 220 | blogs = request.db.Blog.query.filter_by(author=url_user.id) |
310c3073 AM |
221 | config = pluginapi.get_config('mediagoblin.media_types.blog') |
222 | max_blog_count = config['max_blog_count'] | |
eebd8fe3 | 223 | if request.user and (request.user.id == url_user.id or request.user.has_privilege(u'admin')): |
4aa7058e AM |
224 | if blog_slug: |
225 | blog = blogs.filter(Blog.slug==blog_slug).first() | |
226 | if not blog: | |
227 | return render_404(request) | |
228 | else: | |
229 | blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc()) | |
230 | pagination = Pagination(page, blog_posts_list) | |
231 | pagination.per_page = 15 | |
232 | blog_posts_on_a_page = pagination() | |
233 | if may_edit_blogpost(request, blog): | |
234 | return render_to_response( | |
235 | request, | |
236 | 'mediagoblin/blog/blog_admin_dashboard.html', | |
237 | {'blog_posts_list': blog_posts_on_a_page, | |
238 | 'blog_slug':blog_slug, | |
239 | 'blog':blog, | |
eebd8fe3 | 240 | 'user':url_user, |
0b7c64c8 AM |
241 | 'pagination':pagination |
242 | }) | |
eebd8fe3 | 243 | if not request.user or request.user.id != url_user.id or not blog_slug: |
0b7c64c8 | 244 | blogs = blogs.all() |
4aa7058e AM |
245 | return render_to_response( |
246 | request, | |
247 | 'mediagoblin/blog/list_of_blogs.html', | |
248 | { | |
249 | 'blogs':blogs, | |
eebd8fe3 | 250 | 'user':url_user, |
310c3073 | 251 | 'max_blog_count':max_blog_count |
0b7c64c8 AM |
252 | }) |
253 | ||
5cb38a28 | 254 | |
eebd8fe3 | 255 | @active_user_from_url |
8762609f | 256 | @uses_pagination |
eebd8fe3 | 257 | def blog_post_listing(request, page, url_user=None): |
afff1492 AM |
258 | """ |
259 | Page, listing all the blog posts of a particular blog. | |
260 | """ | |
0b2ea4bb | 261 | blog_slug = request.matchdict.get('blog_slug', None) |
1d9d9f1c | 262 | blog = request.db.Blog.query.filter_by(slug=blog_slug).first() |
eebd8fe3 | 263 | if not blog: |
3e329412 | 264 | return render_404(request) |
0b7c64c8 | 265 | |
fe741055 | 266 | all_blog_posts = blog.get_all_blog_posts(u'processed').order_by(MediaEntry.created.desc()) |
8762609f AM |
267 | pagination = Pagination(page, all_blog_posts) |
268 | pagination.per_page = 8 | |
269 | blog_posts_on_a_page = pagination() | |
0b7c64c8 | 270 | |
3e329412 A |
271 | return render_to_response( |
272 | request, | |
273 | 'mediagoblin/blog/blog_post_listing.html', | |
8762609f AM |
274 | {'blog_posts': blog_posts_on_a_page, |
275 | 'pagination': pagination, | |
eebd8fe3 | 276 | 'blog_owner': url_user, |
8189f6c7 | 277 | 'blog':blog |
3e329412 | 278 | }) |
afff1492 | 279 | |
0b7c64c8 AM |
280 | |
281 | @require_active_login | |
4cf5b010 | 282 | def draft_view(request): |
afff1492 | 283 | |
0b2ea4bb A |
284 | blog_slug = request.matchdict.get('blog_slug', None) |
285 | blog_post_slug = request.matchdict.get('blog_post_slug', None) | |
4cf5b010 | 286 | user = request.matchdict.get('user') |
0b7c64c8 | 287 | |
4cf5b010 A |
288 | blog = request.db.Blog.query.filter_by(author=request.user.id, slug=blog_slug).first() |
289 | blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', uploader=request.user.id, slug=blog_post_slug).first() | |
0b7c64c8 | 290 | |
4cf5b010 A |
291 | if not blog or not blogpost: |
292 | return render_404(request) | |
0b7c64c8 | 293 | |
4cf5b010 A |
294 | return render_to_response( |
295 | request, | |
296 | 'mediagoblin/blog/blogpost_draft_view.html', | |
297 | {'blogpost':blogpost, | |
298 | 'blog': blog | |
299 | }) | |
afff1492 | 300 | |
310c3073 | 301 | |
0b7c64c8 | 302 | @require_active_login |
4aa7058e | 303 | def blog_delete(request, **kwargs): |
afff1492 AM |
304 | """ |
305 | Deletes a blog and media entries, tags associated with it. | |
306 | """ | |
4aa7058e AM |
307 | url_user = request.matchdict.get('user') |
308 | owner_user = request.db.User.query.filter_by(username=url_user).first() | |
0b7c64c8 | 309 | |
4aa7058e AM |
310 | blog_slug = request.matchdict.get('blog_slug', None) |
311 | blog = request.db.Blog.query.filter_by(slug=blog_slug, author=owner_user.id).first() | |
312 | if not blog: | |
313 | return render_404(reequest) | |
0b7c64c8 | 314 | |
4aa7058e | 315 | form = blog_forms.ConfirmDeleteForm(request.form) |
39fbb834 | 316 | if request.user.id == blog.author or request.user.has_privilege(u'admin'): |
4aa7058e | 317 | if request.method == 'POST' and form.validate(): |
4aa7058e AM |
318 | if form.confirm.data is True: |
319 | blog.delete() | |
320 | add_message( | |
321 | request, SUCCESS, _('You deleted the Blog.')) | |
322 | return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", | |
323 | user=request.user.username) | |
324 | else: | |
325 | add_message( | |
326 | request, ERROR, | |
327 | _("The media was not deleted because you didn't check that you were sure.")) | |
328 | return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", | |
329 | user=request.user.username) | |
330 | else: | |
39fbb834 | 331 | if request.user.has_privilege(u'admin'): |
4aa7058e AM |
332 | add_message( |
333 | request, WARNING, | |
334 | _("You are about to delete another user's Blog. " | |
335 | "Proceed with caution.")) | |
336 | return render_to_response( | |
337 | request, | |
338 | 'mediagoblin/blog/blog_confirm_delete.html', | |
339 | {'blog':blog, | |
340 | 'form':form | |
341 | }) | |
342 | else: | |
343 | add_message( | |
344 | request, ERROR, | |
345 | _("The blog was not deleted because you have no rights.")) | |
346 | return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", | |
347 | user=request.user.username) | |
310c3073 | 348 | |
afff1492 | 349 | |
310c3073 | 350 | def blog_about_view(request): |
afff1492 AM |
351 | """ |
352 | Page containing blog description and statistics | |
353 | """ | |
310c3073 AM |
354 | blog_slug = request.matchdict.get('blog_slug', None) |
355 | url_user = request.matchdict.get('user', None) | |
356 | ||
357 | user = request.db.User.query.filter_by(username=url_user).first() | |
358 | blog = request.db.Blog.query.filter_by(author=user.id, slug=blog_slug).first() | |
359 | ||
360 | if not user or not blog: | |
361 | return render_404(request) | |
362 | ||
310c3073 AM |
363 | else: |
364 | blog_posts_processed = blog.get_all_blog_posts(u'processed').count() | |
365 | return render_to_response( | |
366 | request, | |
367 | 'mediagoblin/blog/blog_about.html', | |
368 | {'user': user, | |
369 | 'blog': blog, | |
370 | 'blogpost_count': blog_posts_processed | |
371 | }) | |
372 | ||
373 | ||
374 | ||
4aa7058e AM |
375 | |
376 | ||
0b7c64c8 AM |
377 | |
378 | ||
379 |