Removed unnecessary reference to may_edit_collection in edit views.py
[mediagoblin.git] / mediagoblin / edit / views.py
CommitLineData
9bfe1d8e 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
9bfe1d8e
E
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/>.
aba81c9f 16
1c63ad5d 17from webob import exc
3a8c3a38
JW
18from cgi import FieldStorage
19from datetime import datetime
20
21from werkzeug.utils import secure_filename
aba81c9f 22
d9ed098e 23from mediagoblin import messages
10d7496d 24from mediagoblin import mg_globals
152a3bfa 25
4837b2f2 26from mediagoblin.auth import lib as auth_lib
aba81c9f 27from mediagoblin.edit import forms
b5a64f78 28from mediagoblin.edit.lib import may_edit_media
be5be115
AW
29from mediagoblin.decorators import require_active_login, get_user_media_entry, \
30 user_may_alter_collection, get_user_collection
152a3bfa
AW
31from mediagoblin.tools.response import render_to_response, redirect
32from mediagoblin.tools.translate import pass_to_ugettext as _
33from mediagoblin.tools.text import (
a855e92a 34 convert_to_tag_list_of_dicts, media_tags_as_string)
be5be115 35from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
c849e690 36
825b1362
JW
37import mimetypes
38
97ec97db 39
8cd5d4f8 40@get_user_media_entry
aba81c9f
E
41@require_active_login
42def edit_media(request, media):
c849e690
E
43 if not may_edit_media(request, media):
44 return exc.HTTPForbidden()
45
2c437493 46 defaults = dict(
ec82fbd8 47 title=media.title,
5da0bf90 48 slug=media.slug,
1d939966 49 description=media.description,
a6c49d49 50 tags=media_tags_as_string(media.tags),
97ec97db 51 license=media.license)
aba81c9f 52
2c437493
JW
53 form = forms.EditForm(
54 request.POST,
55 **defaults)
56
98857207 57 if request.method == 'POST' and form.validate():
d5e90fe4
CAW
58 # Make sure there isn't already a MediaEntry with such a slug
59 # and userid.
b62b3b98
E
60 slug_used = check_media_slug_used(request.db, media.uploader,
61 request.POST['slug'], media.id)
3a8c3a38 62
b62b3b98 63 if slug_used:
d5e90fe4 64 form.slug.errors.append(
4b1adc13 65 _(u'An entry with that slug already exists for this user.'))
d5e90fe4 66 else:
ec82fbd8 67 media.title = unicode(request.POST['title'])
1d939966 68 media.description = unicode(request.POST.get('description'))
de917303 69 media.tags = convert_to_tag_list_of_dicts(
0712a06d 70 request.POST.get('tags'))
3a8c3a38 71
da6206c4 72 media.license = unicode(request.POST.get('license', '')) or None
25b48323 73
5da0bf90 74 media.slug = unicode(request.POST['slug'])
99a270e9 75
747623cc 76 media.save()
d5e90fe4 77
8d7b549b
E
78 return exc.HTTPFound(
79 location=media.url_for_self(request.urlgen))
98857207 80
bec591d8 81 if request.user.is_admin \
1ceb4fc8 82 and media.uploader != request.user._id \
96a2c366
CAW
83 and request.method != 'POST':
84 messages.add_message(
85 request, messages.WARNING,
4b1adc13 86 _("You are editing another user's media. Proceed with caution."))
96a2c366 87
9038c9f9
CAW
88 return render_to_response(
89 request,
c9c24934
E
90 'mediagoblin/edit/edit.html',
91 {'media': media,
92 'form': form})
46fd661e 93
3a8c3a38 94
825b1362
JW
95# Mimetypes that browsers parse scripts in.
96# Content-sniffing isn't taken into consideration.
97UNSAFE_MIMETYPES = [
98 'text/html',
99 'text/svg+xml']
100
101
3a8c3a38 102@get_user_media_entry
630b57a3 103@require_active_login
3a8c3a38
JW
104def edit_attachments(request, media):
105 if mg_globals.app_config['allow_attachments']:
106 form = forms.EditAttachmentsForm()
107
108 # Add any attachements
109 if ('attachment_file' in request.POST
110 and isinstance(request.POST['attachment_file'], FieldStorage)
111 and request.POST['attachment_file'].file):
112
825b1362
JW
113 # Security measure to prevent attachments from being served as
114 # text/html, which will be parsed by web clients and pose an XSS
115 # threat.
116 #
117 # TODO
118 # This method isn't flawless as some browsers may perform
119 # content-sniffing.
120 # This method isn't flawless as we do the mimetype lookup on the
121 # machine parsing the upload form, and not necessarily the machine
122 # serving the attachments.
123 if mimetypes.guess_type(
124 request.POST['attachment_file'].filename)[0] in \
125 UNSAFE_MIMETYPES:
126 public_filename = secure_filename('{0}.notsafe'.format(
127 request.POST['attachment_file'].filename))
128 else:
129 public_filename = secure_filename(
130 request.POST['attachment_file'].filename)
131
3a8c3a38
JW
132 attachment_public_filepath \
133 = mg_globals.public_store.get_unique_filepath(
eabe6b67 134 ['media_entries', unicode(media._id), 'attachment',
825b1362 135 public_filename])
3a8c3a38
JW
136
137 attachment_public_file = mg_globals.public_store.get_file(
138 attachment_public_filepath, 'wb')
139
140 try:
141 attachment_public_file.write(
142 request.POST['attachment_file'].file.read())
143 finally:
144 request.POST['attachment_file'].file.close()
145
35029581 146 media.attachment_files.append(dict(
3a8c3a38
JW
147 name=request.POST['attachment_name'] \
148 or request.POST['attachment_file'].filename,
149 filepath=attachment_public_filepath,
243c3843 150 created=datetime.utcnow(),
3a8c3a38 151 ))
630b57a3 152
3a8c3a38
JW
153 media.save()
154
155 messages.add_message(
156 request, messages.SUCCESS,
157 "You added the attachment %s!" \
158 % (request.POST['attachment_name']
159 or request.POST['attachment_file'].filename))
160
8d7b549b
E
161 return exc.HTTPFound(
162 location=media.url_for_self(request.urlgen))
3a8c3a38
JW
163 return render_to_response(
164 request,
165 'mediagoblin/edit/attachments.html',
166 {'media': media,
167 'form': form})
168 else:
169 return exc.HTTPForbidden()
170
171
172@require_active_login
173def edit_profile(request):
a0cf14fe
CFD
174 # admins may edit any user profile given a username in the querystring
175 edit_username = request.GET.get('username')
bec591d8 176 if request.user.is_admin and request.user.username != edit_username:
a0cf14fe
CFD
177 user = request.db.User.find_one({'username': edit_username})
178 # No need to warn again if admin just submitted an edited profile
179 if request.method != 'POST':
180 messages.add_message(
181 request, messages.WARNING,
4b1adc13 182 _("You are editing a user's profile. Proceed with caution."))
a0cf14fe
CFD
183 else:
184 user = request.user
185
630b57a3 186 form = forms.EditProfileForm(request.POST,
3a8c3a38
JW
187 url=user.get('url'),
188 bio=user.get('bio'))
630b57a3 189
190 if request.method == 'POST' and form.validate():
c8071fa5
JS
191 user.url = unicode(request.POST['url'])
192 user.bio = unicode(request.POST['bio'])
4c465852 193
c8071fa5 194 user.save()
630b57a3 195
c8071fa5
JS
196 messages.add_message(request,
197 messages.SUCCESS,
198 _("Profile changes saved"))
199 return redirect(request,
200 'mediagoblin.user_pages.user_home',
703d09b9 201 user=user.username)
630b57a3 202
203 return render_to_response(
204 request,
205 'mediagoblin/edit/edit_profile.html',
206 {'user': user,
207 'form': form})
c8071fa5
JS
208
209
210@require_active_login
211def edit_account(request):
c8071fa5 212 user = request.user
252eaf21 213 form = forms.EditAccountForm(request.POST,
fa72e516 214 wants_comment_notification=user.get('wants_comment_notification'))
c8071fa5 215
252eaf21 216 if request.method == 'POST':
fa72e516
DM
217 form_validated = form.validate()
218
219 #if the user has not filled in the new or old password fields
220 if not form.new_password.data and not form.old_password.data:
221 if form.wants_comment_notification.validate(form):
222 user.wants_comment_notification = \
223 form.wants_comment_notification.data
224 user.save()
225 messages.add_message(request,
226 messages.SUCCESS,
227 _("Account settings saved"))
228 return redirect(request,
229 'mediagoblin.user_pages.user_home',
230 user=user.username)
231
232 #so the user has filled in one or both of the password fields
233 else:
234 if form_validated:
235 password_matches = auth_lib.bcrypt_check_password(
236 form.old_password.data,
237 user.pw_hash)
238 if password_matches:
239 #the entire form validates and the password matches
240 user.pw_hash = auth_lib.bcrypt_gen_password_hash(
241 form.new_password.data)
242 user.wants_comment_notification = \
243 form.wants_comment_notification.data
244 user.save()
245 messages.add_message(request,
246 messages.SUCCESS,
247 _("Account settings saved"))
248 return redirect(request,
249 'mediagoblin.user_pages.user_home',
250 user=user.username)
251 else:
252 form.old_password.errors.append(_('Wrong password'))
630b57a3 253
254 return render_to_response(
255 request,
c8071fa5 256 'mediagoblin/edit/edit_account.html',
630b57a3 257 {'user': user,
258 'form': form})
be5be115
AW
259
260
261@require_active_login
262@user_may_alter_collection
263@get_user_collection
264def edit_collection(request, collection):
265 defaults = dict(
266 title=collection.title,
267 slug=collection.slug,
268 description=collection.description)
269
270 form = forms.EditCollectionForm(
271 request.POST,
272 **defaults)
273
274 if request.method == 'POST' and form.validate():
275 # Make sure there isn't already a Collection with such a slug
276 # and userid.
277 slug_used = check_collection_slug_used(request.db, collection.creator,
278 request.POST['slug'], collection.id)
279
280 # Make sure there isn't already a Collection with this title
281 existing_collection = request.db.Collection.find_one({
282 'creator': request.user._id,
283 'title':request.POST['title']})
284
285 if existing_collection and existing_collection.id != collection.id:
286 messages.add_message(
287 request, messages.ERROR, _('You already have a collection called "%s"!' % request.POST['title']))
288 elif slug_used:
289 form.slug.errors.append(
290 _(u'A collection with that slug already exists for this user.'))
291 else:
292 collection.title = unicode(request.POST['title'])
293 collection.description = unicode(request.POST.get('description'))
294 collection.slug = unicode(request.POST['slug'])
295
296 collection.save()
297
298 return redirect(request, "mediagoblin.user_pages.user_collection",
299 user=collection.get_creator.username,
300 collection=collection.slug)
301
302 if request.user.is_admin \
303 and collection.creator != request.user._id \
304 and request.method != 'POST':
305 messages.add_message(
306 request, messages.WARNING,
307 _("You are editing another user's collection. Proceed with caution."))
308
309 return render_to_response(
310 request,
311 'mediagoblin/edit/edit_collection.html',
312 {'collection': collection,
313 'form': form})