Blog media type initial migration.
[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
e49b7e02
BP
22import six
23
cf46184a 24from werkzeug.exceptions import Forbidden
125d7d1a 25from mediagoblin.tools import pluginapi
cf46184a 26
cf46184a
A
27from mediagoblin import mg_globals
28
29from mediagoblin.media_types.blog import forms as blog_forms
5cb38a28 30from mediagoblin.media_types.blog.models import Blog, BlogPostData
36990574
BB
31from mediagoblin.media_types.blog.lib import (
32 may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog,
33 get_blog_by_slug)
5cb38a28 34
af8f995f 35from mediagoblin.messages import add_message, SUCCESS, ERROR
cf46184a
A
36from mediagoblin.decorators import (require_active_login, active_user_from_url,
37 get_media_entry_by_id, user_may_alter_collection,
0b2ea4bb
A
38 get_user_collection, uses_pagination)
39from mediagoblin.tools.pagination import Pagination
cf46184a 40from mediagoblin.tools.response import (render_to_response,
0b2ea4bb 41 redirect, render_404)
cf46184a
A
42from mediagoblin.tools.translate import pass_to_ugettext as _
43from mediagoblin.tools.template import render_template
44from mediagoblin.tools.text import (
0b7c64c8 45 convert_to_tag_list_of_dicts, media_tags_as_string, clean_html,
3e329412 46 cleaned_markdown_conversion)
5cb38a28 47
cf46184a 48from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
d88fcb03 49from mediagoblin.db.models import User, Collection, MediaEntry, LocalUser
af8f995f 50
fa5a13f8
A
51from mediagoblin.notifications import add_comment_subscription
52
cf46184a
A
53
54@require_active_login
af8f995f 55def blog_edit(request):
cf46184a 56 """
0f3bf8d4 57 View for editing an existing blog or creating a new blog
afff1492 58 if user have not exceeded maximum allowed acount of blogs.
cf46184a 59 """
af8f995f
A
60 url_user = request.matchdict.get('user', None)
61 blog_slug = request.matchdict.get('blog_slug', None)
0b7c64c8 62
125d7d1a
AM
63 config = pluginapi.get_config('mediagoblin.media_types.blog')
64 max_blog_count = config['max_blog_count']
af8f995f 65 form = blog_forms.BlogEditForm(request.form)
afff1492 66 # creating a blog
af8f995f
A
67 if not blog_slug:
68 if Blog.query.filter_by(author=request.user.id).count()<max_blog_count:
69 if request.method=='GET':
70 return render_to_response(
71 request,
72 'mediagoblin/blog/blog_edit_create.html',
73 {'form': form,
74 'user' : request.user,
75 'app_config': mg_globals.app_config})
76
77 if request.method=='POST' and form.validate():
78 _log.info("Here")
0b2ea4bb 79 blog = request.db.Blog()
e49b7e02
BP
80 blog.title = six.text_type(form.title.data)
81 blog.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
af8f995f
A
82 blog.author = request.user.id
83 blog.generate_slug()
0b7c64c8 84
af8f995f 85 blog.save()
1d9d9f1c
AM
86 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
87 user=request.user.username
88 )
cf46184a 89 else:
afff1492
AM
90 add_message(request, ERROR, "Welcome! You already have created \
91 maximum number of blogs.")
1d9d9f1c
AM
92 return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
93 user=request.user.username)
cf46184a 94
cf46184a 95
bed960cb 96 #Blog already exists.
cf46184a 97 else:
36990574 98 blog = get_blog_by_slug(request, blog_slug)
afff1492
AM
99 if not blog:
100 return render_404(request)
af8f995f 101 if request.method == 'GET':
af8f995f
A
102 defaults = dict(
103 title = blog.title,
21ac4966 104 description = cleaned_markdown_conversion(blog.description),
0b7c64c8
AM
105 author = request.user.id)
106
af8f995f
A
107 form = blog_forms.BlogEditForm(**defaults)
108
109 return render_to_response(
110 request,
111 'mediagoblin/blog/blog_edit_create.html',
112 {'form': form,
113 'user': request.user,
114 'app_config': mg_globals.app_config})
115 else:
fa5a13f8 116 if request.method == 'POST' and form.validate():
e49b7e02
BP
117 blog.title = six.text_type(form.title.data)
118 blog.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
145a1738
A
119 blog.author = request.user.id
120 blog.generate_slug()
0b7c64c8 121
145a1738
A
122 blog.save()
123 add_message(request, SUCCESS, "Your blog is updated.")
8f6a0bf4
A
124 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
125 user=request.user.username,
0b7c64c8
AM
126 blog_slug=blog.slug)
127
0b2ea4bb 128
0b7c64c8 129@require_active_login
fa5a13f8 130def blogpost_create(request):
0b7c64c8 131
5cb38a28 132 form = blog_forms.BlogPostEditForm(request.form, license=request.user.license_preference)
0b7c64c8 133
145a1738 134 if request.method == 'POST' and form.validate():
5cb38a28 135 blog_slug = request.matchdict.get('blog_slug')
36990574 136 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
4cf5b010
A
137 if not blog:
138 return render_404(request)
0b7c64c8 139
5cb38a28 140 blogpost = request.db.MediaEntry()
783b5005 141 blogpost.media_type = 'mediagoblin.media_types.blogpost'
e49b7e02
BP
142 blogpost.title = six.text_type(form.title.data)
143 blogpost.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
145a1738 144 blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
e49b7e02 145 blogpost.license = six.text_type(form.license.data) or None
beb5a4a1 146 blogpost.actor = request.user.id
145a1738 147 blogpost.generate_slug()
0b7c64c8 148
4cf5b010 149 set_blogpost_state(request, blogpost)
145a1738 150 blogpost.save()
0b7c64c8 151
5cb38a28
A
152 # connect this blogpost to its blog
153 blog_post_data = request.db.BlogPostData()
154 blog_post_data.blog = blog.id
155 blog_post_data.media_entry = blogpost.id
156 blog_post_data.save()
0b7c64c8 157
145a1738
A
158 add_message(request, SUCCESS, _('Woohoo! Submitted!'))
159 add_comment_subscription(request.user, blogpost)
7b23b1e5
A
160 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
161 user=request.user.username,
162 blog_slug=blog.slug)
0b7c64c8 163
145a1738 164 return render_to_response(
fa5a13f8
A
165 request,
166 'mediagoblin/blog/blog_post_edit_create.html',
167 {'form': form,
168 'app_config': mg_globals.app_config,
169 'user': request.user.username})
e058cdce
A
170
171
172@require_active_login
173def blogpost_edit(request):
0f3bf8d4 174
8f6a0bf4
A
175 blog_slug = request.matchdict.get('blog_slug', None)
176 blog_post_slug = request.matchdict.get('blog_post_slug', None)
0b7c64c8 177
beb5a4a1 178 blogpost = request.db.MediaEntry.query.filter_by(slug=blog_post_slug, actor=request.user.id).first()
36990574 179 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
0b7c64c8 180
b5ae9685
A
181 if not blogpost or not blog:
182 return render_404(request)
0b7c64c8 183
5cb38a28
A
184 defaults = dict(
185 title = blogpost.title,
21ac4966 186 description = cleaned_markdown_conversion(blogpost.description),
5cb38a28
A
187 tags=media_tags_as_string(blogpost.tags),
188 license=blogpost.license)
0b7c64c8 189
5cb38a28
A
190 form = blog_forms.BlogPostEditForm(request.form, **defaults)
191 if request.method == 'POST' and form.validate():
e49b7e02
BP
192 blogpost.title = six.text_type(form.title.data)
193 blogpost.description = six.text_type(cleaned_markdown_conversion((form.description.data)))
5cb38a28 194 blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
e49b7e02 195 blogpost.license = six.text_type(form.license.data)
4cf5b010 196 set_blogpost_state(request, blogpost)
5cb38a28
A
197 blogpost.generate_slug()
198 blogpost.save()
0b7c64c8 199
5cb38a28 200 add_message(request, SUCCESS, _('Woohoo! edited blogpost is submitted'))
3e329412
A
201 return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
202 user=request.user.username,
203 blog_slug=blog.slug)
0b7c64c8 204
5cb38a28 205 return render_to_response(
e058cdce
A
206 request,
207 'mediagoblin/blog/blog_post_edit_create.html',
208 {'form': form,
209 'app_config': mg_globals.app_config,
210 'user': request.user.username,
5cb38a28 211 'blog_post_slug': blog_post_slug
0b7c64c8 212 })
e058cdce 213
59614310 214
eebd8fe3 215@active_user_from_url
8762609f 216@uses_pagination
eebd8fe3 217def blog_dashboard(request, page, url_user=None):
afff1492
AM
218 """
219 Dashboard for a blog, only accessible to
220 the owner of the blog.
221 """
4aa7058e 222 blog_slug = request.matchdict.get('blog_slug', None)
eebd8fe3 223 blogs = request.db.Blog.query.filter_by(author=url_user.id)
310c3073
AM
224 config = pluginapi.get_config('mediagoblin.media_types.blog')
225 max_blog_count = config['max_blog_count']
eebd8fe3 226 if request.user and (request.user.id == url_user.id or request.user.has_privilege(u'admin')):
4aa7058e 227 if blog_slug:
36990574 228 blog = get_blog_by_slug(request, blog_slug)
4aa7058e
AM
229 if not blog:
230 return render_404(request)
231 else:
232 blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc())
233 pagination = Pagination(page, blog_posts_list)
234 pagination.per_page = 15
235 blog_posts_on_a_page = pagination()
236 if may_edit_blogpost(request, blog):
237 return render_to_response(
238 request,
239 'mediagoblin/blog/blog_admin_dashboard.html',
240 {'blog_posts_list': blog_posts_on_a_page,
241 'blog_slug':blog_slug,
242 'blog':blog,
eebd8fe3 243 'user':url_user,
0b7c64c8
AM
244 'pagination':pagination
245 })
eebd8fe3 246 if not request.user or request.user.id != url_user.id or not blog_slug:
0b7c64c8 247 blogs = blogs.all()
4aa7058e
AM
248 return render_to_response(
249 request,
250 'mediagoblin/blog/list_of_blogs.html',
251 {
252 'blogs':blogs,
eebd8fe3 253 'user':url_user,
310c3073 254 'max_blog_count':max_blog_count
0b7c64c8
AM
255 })
256
5cb38a28 257
eebd8fe3 258@active_user_from_url
8762609f 259@uses_pagination
eebd8fe3 260def blog_post_listing(request, page, url_user=None):
afff1492
AM
261 """
262 Page, listing all the blog posts of a particular blog.
263 """
51f49118 264 blog_slug = request.matchdict['blog_slug']
b56cd89e 265 blog = get_blog_by_slug(request, blog_slug, author=url_user.id)
eebd8fe3 266 if 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,
eebd8fe3 279 'blog_owner': url_user,
8189f6c7 280 'blog':blog
3e329412 281 })
0f3bf8d4 282
0b7c64c8
AM
283
284@require_active_login
4cf5b010 285def draft_view(request):
0b2ea4bb
A
286 blog_slug = request.matchdict.get('blog_slug', None)
287 blog_post_slug = request.matchdict.get('blog_post_slug', None)
4cf5b010 288 user = request.matchdict.get('user')
36990574 289 blog = get_blog_by_slug(request, blog_slug, author=request.user.id)
beb5a4a1 290 blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', actor=request.user.id, slug=blog_post_slug).first()
0b7c64c8 291
4cf5b010
A
292 if not blog or not blogpost:
293 return render_404(request)
0b7c64c8 294
4cf5b010
A
295 return render_to_response(
296 request,
297 'mediagoblin/blog/blogpost_draft_view.html',
298 {'blogpost':blogpost,
299 'blog': blog
300 })
b4997540
JT
301
302
0b7c64c8 303@require_active_login
4aa7058e 304def blog_delete(request, **kwargs):
afff1492 305 """
b4997540 306 Deletes a blog and media entries, tags associated with it.
afff1492 307 """
4aa7058e 308 url_user = request.matchdict.get('user')
b4997540 309 owner_user = request.db.LocalUser.query.filter(
d88fcb03
JT
310 LocalUser.username==url_user
311 ).first()
0b7c64c8 312
4aa7058e 313 blog_slug = request.matchdict.get('blog_slug', None)
36990574 314 blog = get_blog_by_slug(request, blog_slug, author=owner_user.id)
4aa7058e 315 if not blog:
ee7db0a3 316 return render_404(request)
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)
0f3bf8d4
JT
351
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)
0f3bf8d4 359
beb5a4a1 360 user = request.db.LocalUser.query.filter(
361 LocalUser.username==url_user
0f3bf8d4 362 ).first()
36990574 363 blog = get_blog_by_slug(request, blog_slug, author=user.id)
0f3bf8d4 364
310c3073
AM
365 if not user or not blog:
366 return render_404(request)
0f3bf8d4 367
310c3073
AM
368 else:
369 blog_posts_processed = blog.get_all_blog_posts(u'processed').count()
370 return render_to_response(
371 request,
372 'mediagoblin/blog/blog_about.html',
373 {'user': user,
374 'blog': blog,
375 'blogpost_count': blog_posts_processed
376 })