diff options
Diffstat (limited to 'mediagoblin/edit')
-rw-r--r-- | mediagoblin/edit/forms.py | 15 | ||||
-rw-r--r-- | mediagoblin/edit/lib.py | 2 | ||||
-rw-r--r-- | mediagoblin/edit/routing.py | 8 | ||||
-rw-r--r-- | mediagoblin/edit/views.py | 201 |
4 files changed, 137 insertions, 89 deletions
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 293c3bb2..ef270237 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -17,7 +17,7 @@ import wtforms from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING -from mediagoblin.tools.translate import fake_ugettext_passthrough as _ +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.tools.licenses import licenses_as_choices class EditForm(wtforms.Form): @@ -65,8 +65,19 @@ class EditAccountForm(wtforms.Form): "Enter your old password to prove you own this account.")) new_password = wtforms.PasswordField( _('New password'), - [wtforms.validators.Length(min=6, max=30)], + [ + wtforms.validators.Optional(), + wtforms.validators.Length(min=6, max=30) + ], id="password") + license_preference = wtforms.SelectField( + _('License preference'), + [ + wtforms.validators.Optional(), + wtforms.validators.AnyOf([lic[0] for lic in licenses_as_choices()]), + ], + choices=licenses_as_choices(), + description=_('This will be your default license on upload forms.')) wants_comment_notification = wtforms.BooleanField( label=_("Email me when others comment on my media")) diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py index b4715134..aab537a0 100644 --- a/mediagoblin/edit/lib.py +++ b/mediagoblin/edit/lib.py @@ -17,7 +17,7 @@ def may_edit_media(request, media): """Check, if the request's user may edit the media details""" - if media.uploader == request.user._id: + if media.uploader == request.user.id: return True if request.user.is_admin: return True diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py index 28b73d1e..035a766f 100644 --- a/mediagoblin/edit/routing.py +++ b/mediagoblin/edit/routing.py @@ -14,9 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.routing import add_route +from mediagoblin.tools.routing import add_route -add_route('mediagoblin.edit.profile', '/edit/profile/', +add_route('mediagoblin.edit.profile', '/u/<string:user>/edit/', 'mediagoblin.edit.views:edit_profile') +add_route('mediagoblin.edit.legacy_edit_profile', '/edit/profile/', + 'mediagoblin.edit.views:legacy_edit_profile') add_route('mediagoblin.edit.account', '/edit/account/', 'mediagoblin.edit.views:edit_account') +add_route('mediagoblin.edit.delete_account', '/edit/account/delete/', + 'mediagoblin.edit.views:delete_account') diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 111f9ae8..bfcf65b5 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -14,10 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from webob import exc -from cgi import FieldStorage from datetime import datetime +from werkzeug.exceptions import Forbidden from werkzeug.utils import secure_filename from mediagoblin import messages @@ -26,22 +25,25 @@ from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media -from mediagoblin.decorators import require_active_login, get_user_media_entry, \ - user_may_alter_collection, get_user_collection -from mediagoblin.tools.response import render_to_response, redirect +from mediagoblin.decorators import (require_active_login, active_user_from_url, + get_media_entry_by_id, + user_may_alter_collection, get_user_collection) +from mediagoblin.tools.response import render_to_response, \ + redirect, redirect_obj from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.text import ( convert_to_tag_list_of_dicts, media_tags_as_string) +from mediagoblin.tools.url import slugify from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used import mimetypes -@get_user_media_entry +@get_media_entry_by_id @require_active_login def edit_media(request, media): if not may_edit_media(request, media): - return exc.HTTPForbidden() + raise Forbidden("User may not edit this media") defaults = dict( title=media.title, @@ -57,29 +59,26 @@ def edit_media(request, media): if request.method == 'POST' and form.validate(): # Make sure there isn't already a MediaEntry with such a slug # and userid. - slug_used = check_media_slug_used(request.db, media.uploader, - request.form['slug'], media.id) + slug = slugify(form.slug.data) + slug_used = check_media_slug_used(media.uploader, slug, media.id) if slug_used: form.slug.errors.append( _(u'An entry with that slug already exists for this user.')) else: - media.title = unicode(request.form['title']) - media.description = unicode(request.form.get('description')) + media.title = form.title.data + media.description = form.description.data media.tags = convert_to_tag_list_of_dicts( - request.form.get('tags')) - - media.license = unicode(request.form.get('license', '')) or None - - media.slug = unicode(request.form['slug']) + form.tags.data) + media.license = unicode(form.license.data) or None + media.slug = slug media.save() - return exc.HTTPFound( - location=media.url_for_self(request.urlgen)) + return redirect_obj(request, media) if request.user.is_admin \ - and media.uploader != request.user._id \ + and media.uploader != request.user.id \ and request.method != 'POST': messages.add_message( request, messages.WARNING, @@ -99,7 +98,7 @@ UNSAFE_MIMETYPES = [ 'text/svg+xml'] -@get_user_media_entry +@get_media_entry_by_id @require_active_login def edit_attachments(request, media): if mg_globals.app_config['allow_attachments']: @@ -130,7 +129,7 @@ def edit_attachments(request, media): attachment_public_filepath \ = mg_globals.public_store.get_unique_filepath( - ['media_entries', unicode(media._id), 'attachment', + ['media_entries', unicode(media.id), 'attachment', public_filename]) attachment_public_file = mg_globals.public_store.get_file( @@ -143,7 +142,7 @@ def edit_attachments(request, media): request.files['attachment_file'].stream.close() media.attachment_files.append(dict( - name=request.form['attachment_name'] \ + name=form.attachment_name.data \ or request.files['attachment_file'].filename, filepath=attachment_public_filepath, created=datetime.utcnow(), @@ -154,41 +153,49 @@ def edit_attachments(request, media): messages.add_message( request, messages.SUCCESS, _("You added the attachment %s!") \ - % (request.form['attachment_name'] + % (form.attachment_name.data or request.files['attachment_file'].filename)) - return exc.HTTPFound( - location=media.url_for_self(request.urlgen)) + return redirect(request, + location=media.url_for_self(request.urlgen)) return render_to_response( request, 'mediagoblin/edit/attachments.html', {'media': media, 'form': form}) else: - return exc.HTTPForbidden() + raise Forbidden("Attachments are disabled") + +@require_active_login +def legacy_edit_profile(request): + """redirect the old /edit/profile/?username=USER to /u/USER/edit/""" + username = request.GET.get('username') or request.user.username + return redirect(request, 'mediagoblin.edit.profile', user=username) @require_active_login -def edit_profile(request): - # admins may edit any user profile given a username in the querystring - edit_username = request.GET.get('username') - if request.user.is_admin and request.user.username != edit_username: - user = request.db.User.find_one({'username': edit_username}) +@active_user_from_url +def edit_profile(request, url_user=None): + # admins may edit any user profile + if request.user.username != url_user.username: + if not request.user.is_admin: + raise Forbidden(_("You can only edit your own profile.")) + # No need to warn again if admin just submitted an edited profile if request.method != 'POST': messages.add_message( request, messages.WARNING, _("You are editing a user's profile. Proceed with caution.")) - else: - user = request.user + + user = url_user form = forms.EditProfileForm(request.form, - url=user.get('url'), - bio=user.get('bio')) + url=user.url, + bio=user.bio) if request.method == 'POST' and form.validate(): - user.url = unicode(request.form['url']) - user.bio = unicode(request.form['bio']) + user.url = unicode(form.url.data) + user.bio = unicode(form.bio.data) user.save() @@ -210,45 +217,42 @@ def edit_profile(request): def edit_account(request): user = request.user form = forms.EditAccountForm(request.form, - wants_comment_notification=user.get('wants_comment_notification')) + wants_comment_notification=user.wants_comment_notification, + license_preference=user.license_preference) if request.method == 'POST': form_validated = form.validate() - #if the user has not filled in the new or old password fields - if not form.new_password.data and not form.old_password.data: - if form.wants_comment_notification.validate(form): - user.wants_comment_notification = \ - form.wants_comment_notification.data - user.save() - messages.add_message(request, - messages.SUCCESS, - _("Account settings saved")) - return redirect(request, - 'mediagoblin.user_pages.user_home', - user=user.username) - - #so the user has filled in one or both of the password fields - else: - if form_validated: - password_matches = auth_lib.bcrypt_check_password( - form.old_password.data, - user.pw_hash) - if password_matches: - #the entire form validates and the password matches - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - form.new_password.data) - user.wants_comment_notification = \ - form.wants_comment_notification.data - user.save() - messages.add_message(request, - messages.SUCCESS, - _("Account settings saved")) - return redirect(request, - 'mediagoblin.user_pages.user_home', - user=user.username) - else: - form.old_password.errors.append(_('Wrong password')) + if form_validated and \ + form.wants_comment_notification.validate(form): + user.wants_comment_notification = \ + form.wants_comment_notification.data + + if form_validated and \ + form.new_password.data or form.old_password.data: + password_matches = auth_lib.bcrypt_check_password( + form.old_password.data, + user.pw_hash) + if password_matches: + #the entire form validates and the password matches + user.pw_hash = auth_lib.bcrypt_gen_password_hash( + form.new_password.data) + else: + form.old_password.errors.append(_('Wrong password')) + + if form_validated and \ + form.license_preference.validate(form): + user.license_preference = \ + form.license_preference.data + + if form_validated and not form.errors: + user.save() + messages.add_message(request, + messages.SUCCESS, + _("Account settings saved")) + return redirect(request, + 'mediagoblin.user_pages.user_home', + user=user.username) return render_to_response( request, @@ -258,6 +262,37 @@ def edit_account(request): @require_active_login +def delete_account(request): + """Delete a user completely""" + user = request.user + if request.method == 'POST': + if request.form.get(u'confirmed'): + # Form submitted and confirmed. Actually delete the user account + # Log out user and delete cookies etc. + # TODO: Should we be using MG.auth.views.py:logout for this? + request.session.delete() + + # Delete user account and all related media files etc.... + request.user.delete() + + # We should send a message that the user has been deleted + # successfully. But we just deleted the session, so we + # can't... + return redirect(request, 'index') + + else: # Did not check the confirmation box... + messages.add_message( + request, messages.WARNING, + _('You need to confirm the deletion of your account.')) + + # No POST submission or not confirmed, just show page + return render_to_response( + request, + 'mediagoblin/edit/delete_account.html', + {'user': user}) + + +@require_active_login @user_may_alter_collection @get_user_collection def edit_collection(request, collection): @@ -273,35 +308,33 @@ def edit_collection(request, collection): if request.method == 'POST' and form.validate(): # Make sure there isn't already a Collection with such a slug # and userid. - slug_used = check_collection_slug_used(request.db, collection.creator, - request.form['slug'], collection.id) + slug_used = check_collection_slug_used(collection.creator, + form.slug.data, collection.id) # Make sure there isn't already a Collection with this title existing_collection = request.db.Collection.find_one({ - 'creator': request.user._id, - 'title':request.form['title']}) + 'creator': request.user.id, + 'title':form.title.data}) if existing_collection and existing_collection.id != collection.id: messages.add_message( request, messages.ERROR, _('You already have a collection called "%s"!') % \ - request.form['title']) + form.title.data) elif slug_used: form.slug.errors.append( _(u'A collection with that slug already exists for this user.')) else: - collection.title = unicode(request.form['title']) - collection.description = unicode(request.form.get('description')) - collection.slug = unicode(request.form['slug']) + collection.title = unicode(form.title.data) + collection.description = unicode(form.description.data) + collection.slug = unicode(form.slug.data) collection.save() - return redirect(request, "mediagoblin.user_pages.user_collection", - user=collection.get_creator.username, - collection=collection.slug) + return redirect_obj(request, collection) if request.user.is_admin \ - and collection.creator != request.user._id \ + and collection.creator != request.user.id \ and request.method != 'POST': messages.add_message( request, messages.WARNING, |