Convert blog plugin to use new privileges system
[mediagoblin.git] / mediagoblin / media_types / blog / views.py
CommitLineData
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 17import logging
af8f995f
A
18_log = logging.getLogger(__name__)
19
cf46184a
A
20from datetime import datetime
21
22from werkzeug.exceptions import Forbidden
125d7d1a 23from mediagoblin.tools import pluginapi
cf46184a 24
cf46184a
A
25from mediagoblin import mg_globals
26
27from mediagoblin.media_types.blog import forms as blog_forms
5cb38a28 28from mediagoblin.media_types.blog.models import Blog, BlogPostData
0b2ea4bb 29from mediagoblin.media_types.blog.lib import may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog
5cb38a28 30
af8f995f 31from mediagoblin.messages import add_message, SUCCESS, ERROR
cf46184a
A
32from 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)
35from mediagoblin.tools.pagination import Pagination
cf46184a 36from mediagoblin.tools.response import (render_to_response,
0b2ea4bb 37 redirect, render_404)
cf46184a
A
38from mediagoblin.tools.translate import pass_to_ugettext as _
39from mediagoblin.tools.template import render_template
40from 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 44from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
af8f995f
A
45from mediagoblin.db.models import User, Collection, MediaEntry
46
fa5a13f8
A
47from mediagoblin.notifications import add_comment_subscription
48
cf46184a
A
49
50@require_active_login
af8f995f 51def 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 126def 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
170def 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
8762609f
AM
212@uses_pagination
213def blog_dashboard(request, page):
afff1492
AM
214 """
215 Dashboard for a blog, only accessible to
216 the owner of the blog.
217 """
4aa7058e
AM
218 url_user = request.matchdict.get('user')
219 user = request.db.User.query.filter_by(username=url_user).one()
220 blog_slug = request.matchdict.get('blog_slug', None)
221 blogs = request.db.Blog.query.filter_by(author=user.id)
310c3073
AM
222 config = pluginapi.get_config('mediagoblin.media_types.blog')
223 max_blog_count = config['max_blog_count']
39fbb834 224 if request.user and (request.user.id == user.id or request.user.has_privilege(u'admin')):
4aa7058e
AM
225 if blog_slug:
226 blog = blogs.filter(Blog.slug==blog_slug).first()
227 if not blog:
228 return render_404(request)
229 else:
230 blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc())
231 pagination = Pagination(page, blog_posts_list)
232 pagination.per_page = 15
233 blog_posts_on_a_page = pagination()
234 if may_edit_blogpost(request, blog):
235 return render_to_response(
236 request,
237 'mediagoblin/blog/blog_admin_dashboard.html',
238 {'blog_posts_list': blog_posts_on_a_page,
239 'blog_slug':blog_slug,
240 'blog':blog,
241 'user':user,
0b7c64c8
AM
242 'pagination':pagination
243 })
4aa7058e 244 if not request.user or request.user.id != user.id or not blog_slug:
0b7c64c8 245 blogs = blogs.all()
4aa7058e
AM
246 return render_to_response(
247 request,
248 'mediagoblin/blog/list_of_blogs.html',
249 {
250 'blogs':blogs,
310c3073
AM
251 'user':user,
252 'max_blog_count':max_blog_count
0b7c64c8
AM
253 })
254
5cb38a28 255
8762609f
AM
256@uses_pagination
257def blog_post_listing(request, page):
afff1492
AM
258 """
259 Page, listing all the blog posts of a particular blog.
260 """
3e329412 261 blog_owner = request.matchdict.get('user')
0b2ea4bb 262 blog_slug = request.matchdict.get('blog_slug', None)
3e329412 263 owner_user = User.query.filter_by(username=blog_owner).one()
1d9d9f1c 264 blog = request.db.Blog.query.filter_by(slug=blog_slug).first()
0b7c64c8 265
0b2ea4bb 266 if not owner_user or not blog:
3e329412 267 return render_404(request)
0b7c64c8 268
fe741055 269 all_blog_posts = blog.get_all_blog_posts(u'processed').order_by(MediaEntry.created.desc())
8762609f
AM
270 pagination = Pagination(page, all_blog_posts)
271 pagination.per_page = 8
272 blog_posts_on_a_page = pagination()
0b7c64c8 273
3e329412
A
274 return render_to_response(
275 request,
276 'mediagoblin/blog/blog_post_listing.html',
8762609f
AM
277 {'blog_posts': blog_posts_on_a_page,
278 'pagination': pagination,
8189f6c7
AM
279 'blog_owner': blog_owner,
280 'blog':blog
3e329412 281 })
afff1492 282
0b7c64c8
AM
283
284@require_active_login
4cf5b010 285def draft_view(request):
afff1492 286
0b2ea4bb
A
287 blog_slug = request.matchdict.get('blog_slug', None)
288 blog_post_slug = request.matchdict.get('blog_post_slug', None)
4cf5b010 289 user = request.matchdict.get('user')
0b7c64c8 290
4cf5b010
A
291 blog = request.db.Blog.query.filter_by(author=request.user.id, slug=blog_slug).first()
292 blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', uploader=request.user.id, slug=blog_post_slug).first()
0b7c64c8 293
4cf5b010
A
294 if not blog or not blogpost:
295 return render_404(request)
0b7c64c8 296
4cf5b010
A
297 return render_to_response(
298 request,
299 'mediagoblin/blog/blogpost_draft_view.html',
300 {'blogpost':blogpost,
301 'blog': blog
302 })
afff1492 303
310c3073 304
0b7c64c8 305@require_active_login
4aa7058e 306def blog_delete(request, **kwargs):
afff1492
AM
307 """
308 Deletes a blog and media entries, tags associated with it.
309 """
4aa7058e
AM
310 url_user = request.matchdict.get('user')
311 owner_user = request.db.User.query.filter_by(username=url_user).first()
0b7c64c8 312
4aa7058e
AM
313 blog_slug = request.matchdict.get('blog_slug', None)
314 blog = request.db.Blog.query.filter_by(slug=blog_slug, author=owner_user.id).first()
315 if not blog:
316 return render_404(reequest)
0b7c64c8 317
4aa7058e 318 form = blog_forms.ConfirmDeleteForm(request.form)
39fbb834 319 if request.user.id == blog.author or request.user.has_privilege(u'admin'):
4aa7058e 320 if request.method == 'POST' and form.validate():
4aa7058e
AM
321 if form.confirm.data is True:
322 blog.delete()
323 add_message(
324 request, SUCCESS, _('You deleted the Blog.'))
325 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
326 user=request.user.username)
327 else:
328 add_message(
329 request, ERROR,
330 _("The media was not deleted because you didn't check that you were sure."))
331 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
332 user=request.user.username)
333 else:
39fbb834 334 if request.user.has_privilege(u'admin'):
4aa7058e
AM
335 add_message(
336 request, WARNING,
337 _("You are about to delete another user's Blog. "
338 "Proceed with caution."))
339 return render_to_response(
340 request,
341 'mediagoblin/blog/blog_confirm_delete.html',
342 {'blog':blog,
343 'form':form
344 })
345 else:
346 add_message(
347 request, ERROR,
348 _("The blog was not deleted because you have no rights."))
349 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
350 user=request.user.username)
310c3073 351
afff1492 352
310c3073 353def blog_about_view(request):
afff1492
AM
354 """
355 Page containing blog description and statistics
356 """
310c3073
AM
357 blog_slug = request.matchdict.get('blog_slug', None)
358 url_user = request.matchdict.get('user', None)
359
360 user = request.db.User.query.filter_by(username=url_user).first()
361 blog = request.db.Blog.query.filter_by(author=user.id, slug=blog_slug).first()
362
363 if not user or not blog:
364 return render_404(request)
365
310c3073
AM
366 else:
367 blog_posts_processed = blog.get_all_blog_posts(u'processed').count()
368 return render_to_response(
369 request,
370 'mediagoblin/blog/blog_about.html',
371 {'user': user,
372 'blog': blog,
373 'blogpost_count': blog_posts_processed
374 })
375
376
377
4aa7058e
AM
378
379
0b7c64c8
AM
380
381
382