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}) # 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 form = forms.EditProfileForm(request.form, url=user.get("url"), bio=user.get("bio")) if request.method == "POST" and form.validate(): user.url = unicode(request.form["url"]) user.bio = unicode(request.form["bio"]) user.save() messages.add_message(request, messages.SUCCESS, _("Profile changes saved")) return redirect(request, "mediagoblin.user_pages.user_home", user=user.username) return render_to_response(request, "mediagoblin/edit/edit_profile.html", {"user": user, "form": form})
def verify_email(request): """ Email verification view for changing email address """ # If no token, we can't do anything if not "token" in request.GET: return render_404(request) # Catch error if token is faked or expired token = None try: token = get_timed_signer_url("mail_verification_token").loads(request.GET["token"], max_age=10 * 24 * 3600) except BadSignature: messages.add_message(request, messages.ERROR, _("The verification key or user id is incorrect.")) return redirect(request, "index") user = User.query.filter_by(id=int(token["user"])).first() if user: user.email = token["email"] user.save() messages.add_message(request, messages.SUCCESS, _("Your email address has been verified.")) else: messages.add_message(request, messages.ERROR, _("The verification key or user id is incorrect.")) return redirect(request, "mediagoblin.user_pages.user_home", user=user.username)
def media_post_comment(request, media): """ recieves POST from a MediaEntry() comment form, saves the comment. """ if not request.method == 'POST': raise MethodNotAllowed() comment = request.db.MediaComment() comment.media_entry = media.id comment.author = request.user.id comment.content = six.text_type(request.form['comment_content']) # Show error message if commenting is disabled. if not mg_globals.app_config['allow_comments']: messages.add_message( request, messages.ERROR, _("Sorry, comments are disabled.")) elif not comment.content.strip(): messages.add_message( request, messages.ERROR, _("Oops, your comment was empty.")) else: create_activity("post", comment, comment.author, target=media) add_comment_subscription(request.user, media) comment.save() messages.add_message( request, messages.SUCCESS, _('Your comment has been posted!')) trigger_notification(comment, media, request) return redirect_obj(request, media)
def edit_account(request): user = request.user form = forms.EditAccountForm( request.form, wants_comment_notification=user.wants_comment_notification, license_preference=user.license_preference, ) if request.method == "POST": form_validated = form.validate() 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, "mediagoblin/edit/edit_account.html", {"user": user, "form": form})
def _finish_verification(request): """ Complete OpenID Verification Process. If the verification failed, will return false, otherwise, will return the response """ c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore()) # Check the response from the provider response = c.complete(request.args, request.base_url) if response.status == consumer.FAILURE: messages.add_message( request, messages.WARNING, _('Verification of %s failed: %s' % (response.getDisplayIdentifier(), response.message))) elif response.status == consumer.SUCCESS: # Verification was successfull return response elif response.status == consumer.CANCEL: # Verification canceled messages.add_message( request, messages.WARNING, _('Verification cancelled')) return False
def media_confirm_delete(request, media): form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): if form.confirm.data is True: username = media.get_uploader.username # Delete all the associated comments for comment in media.get_comments(): comment.delete() # Delete all files on the public storage try: delete_media_files(media) except OSError, error: _log.error('No such files from the user "{1}"' ' to delete: {0}'.format(str(error), username)) messages.add_message(request, messages.ERROR, _('Some of the files with this entry seem' ' to be missing. Deleting anyway.')) media.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the media.')) return redirect(request, "mediagoblin.user_pages.user_home", user=username) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.")) return redirect(request, location=media.url_for_self(request.urlgen))
def collection_item_confirm_remove(request, collection_item): form = user_forms.ConfirmCollectionItemRemoveForm(request.form) if request.method == 'POST' and form.validate(): collection = collection_item.in_collection if form.confirm.data is True: remove_collection_item(collection_item) messages.add_message( request, messages.SUCCESS, _('You deleted the item from the collection.')) else: messages.add_message( request, messages.ERROR, _("The item was not removed because you didn't check that you were sure.")) return redirect_obj(request, collection) if ((request.user.has_privilege(u'admin') and request.user.id != collection_item.in_collection.creator)): messages.add_message( request, messages.WARNING, _("You are about to delete an item from another user's collection. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/collection_item_confirm_remove.html', {'collection_item': collection_item, 'form': form})
def create_featured_media_textbox(): """ This script searches through the database of which media is featured and returns a string of each entry in the proper format for use in the /mod/feature-media/ page. This string will be used as the default text in the textbox on that page. """ primaries = FeaturedMedia.query.order_by( FeaturedMedia.order.asc()).filter( FeaturedMedia.display_type == u'primary').all() secondaries = FeaturedMedia.query.order_by( FeaturedMedia.order.asc()).filter( FeaturedMedia.display_type == u'secondary').all() tertiaries = FeaturedMedia.query.order_by( FeaturedMedia.order.asc()).filter( FeaturedMedia.display_type == u'tertiary').all() output_text = u'' for display_type, feature_list in [ (_(u'Primary'),primaries), (_(u'Secondary'),secondaries), (_(u'Tertiary'),tertiaries)]: output_text += _( u"""-----------{display_type}-Features--------------------------- """).format(display_type=display_type) for feature in feature_list: media_entry = feature.media_entry output_text += u'/u/{uploader_username}/m/{media_slug}/\n'.format( uploader_username = media_entry.get_actor.username, media_slug = media_entry.slug) return output_text
def normalize_user_or_email_field(allow_email=True, allow_user=True): """ Check if we were passed a field that matches a username and/or email pattern. This is useful for fields that can take either a username or email address. Use the parameters if you want to only allow a username for instance""" message = _(u'Invalid User name or email address.') nomail_msg = _(u"This field does not take email addresses.") nouser_msg = _(u"This field requires an email address.") def _normalize_field(form, field): email = u'@' in field.data if email: # normalize email address casing if not allow_email: raise wtforms.ValidationError(nomail_msg) wtforms.validators.Email()(form, field) field.data = normalize_email(field.data) else: # lower case user names if not allow_user: raise wtforms.ValidationError(nouser_msg) wtforms.validators.Length(min=3, max=30)(form, field) wtforms.validators.Regexp(r'^[-_\w]+$')(form, field) field.data = field.data.lower() if field.data is None: # should not happen, but be cautious anyway raise wtforms.ValidationError(message) return _normalize_field
def media_confirm_delete(request, media): form = user_forms.ConfirmDeleteForm(request.form) if request.method == "POST" and form.validate(): if form.confirm.data is True: username = media.get_uploader.username # Delete MediaEntry and all related files, comments etc. media.delete() messages.add_message(request, messages.SUCCESS, _("You deleted the media.")) location = media.url_to_next(request.urlgen) if not location: location = media.url_to_prev(request.urlgen) if not location: location = request.urlgen("mediagoblin.user_pages.user_home", user=username) return redirect(request, location=location) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.") ) return redirect_obj(request, media) if request.user.is_admin and request.user.id != media.uploader: messages.add_message( request, messages.WARNING, _("You are about to delete another user's media. " "Proceed with caution.") ) return render_to_response( request, "mediagoblin/user_pages/media_confirm_delete.html", {"media": media, "form": form} )
def media_post_comment(request, media): """ recieves POST from a MediaEntry() comment form, saves the comment. """ if not request.method == "POST": raise MethodNotAllowed() comment = request.db.MediaComment() comment.media_entry = media.id comment.author = request.user.id print request.form["comment_content"] comment.content = unicode(request.form["comment_content"]) # Show error message if commenting is disabled. if not mg_globals.app_config["allow_comments"]: messages.add_message(request, messages.ERROR, _("Sorry, comments are disabled.")) elif not comment.content.strip(): messages.add_message(request, messages.ERROR, _("Oops, your comment was empty.")) else: comment.save() messages.add_message(request, messages.SUCCESS, _("Your comment has been posted!")) trigger_notification(comment, media, request) add_comment_subscription(request.user, media) return redirect_obj(request, media)
def forgot_password(request): """ Forgot password view Sends an email with an url to renew forgotten password. Use GET querystring parameter 'username' to pre-populate the input field """ fp_form = auth_forms.ForgotPassForm(request.form, username=request.args.get('username')) if not (request.method == 'POST' and fp_form.validate()): # Either GET request, or invalid form submitted. Display the template return render_to_response(request, 'mediagoblin/plugins/recaptcha/forgot_password.html', {'fp_form': fp_form}) # If we are here: method == POST and form is valid. username casing # has been sanitized. Store if a user was found by email. We should # not reveal if the operation was successful then as we don't want to # leak if an email address exists in the system. found_by_email = '@' in fp_form.username.data if found_by_email: user = User.query.filter_by( email=fp_form.username.data).first() # Don't reveal success in case the lookup happened by email address. success_message = _("If that email address (case sensitive!) is " "registered an email has been sent with " "instructions on how to change your password.") else: # found by username user = User.query.filter_by( username=fp_form.username.data).first() if user is None: messages.add_message(request, messages.WARNING, _("Couldn't find someone with that username.")) return redirect(request, 'mediagoblin.auth.forgot_password') success_message = _("An email has been sent with instructions " "on how to change your password.") if user and user.has_privilege(u'active') is False: # Don't send reminder because user is inactive or has no verified email messages.add_message(request, messages.WARNING, _("Could not send password recovery email as your username is in" "active or your account's email address has not been verified.")) return redirect(request, 'mediagoblin.user_pages.user_home', user=user.username) # SUCCESS. Send reminder and return to login page if user: email_debug_message(request) tools.send_fp_verification_email(user, request) messages.add_message(request, messages.INFO, success_message) return redirect(request, 'mediagoblin.auth.login')
def change_pass(request): form = auth_forms.ChangePassForm(request.form) user = request.user if request.method == 'POST' and form.validate(): if not tools.bcrypt_check_password( form.old_password.data, user.pw_hash): form.old_password.errors.append( _('Wrong password')) return render_to_response( request, 'mediagoblin/plugins/recaptcha/change_pass.html', {'form': form, 'user': user}) # Password matches user.pw_hash = tools.bcrypt_gen_password_hash( form.new_password.data) user.save() messages.add_message( request, messages.SUCCESS, _('Your password was changed successfully')) return redirect(request, 'mediagoblin.edit.account') return render_to_response( request, 'mediagoblin/plugins/recaptcha/change_pass.html', {'form': form, 'user': user})
def verify_email(request): """ Email verification view validates GET parameters against database and unlocks the user account, if you are lucky :) """ # If we don't have userid and token parameters, we can't do anything; 404 if not 'userid' in request.GET or not 'token' in request.GET: return render_404(request) user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) if user and user.verification_key == unicode(request.GET['token']): user.status = u'active' user.email_verified = True user.verification_key = None user.save() messages.add_message( request, messages.SUCCESS, _("Your email address has been verified. " "You may now login, edit your profile, and submit images!")) else: messages.add_message( request, messages.ERROR, _('The verification key or user id is incorrect')) return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username)
def edit_account(request): user = request.user form = forms.EditAccountForm(request.form, wants_comment_notification=user.get("wants_comment_notification")) 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")) return render_to_response(request, "mediagoblin/edit/edit_account.html", {"user": user, "form": form})
def add(request): if request.method == 'GET': return redirect(request, 'mediagoblin.plugins.persona.edit') email = _get_response(request) if email: query = PersonaUserEmails.query.filter_by( persona_email=email ).first() user_exists = query.user if query else None if user_exists: messages.add_message( request, messages.WARNING, _('Sorry, an account is already registered with that Persona' ' email address.')) return redirect(request, 'mediagoblin.plugins.persona.edit') else: # Save the Persona Email to the user new_entry = PersonaUserEmails() new_entry.persona_email = email new_entry.user_id = request.user.id new_entry.save() messages.add_message( request, messages.SUCCESS, _('Your Persona email address was saved successfully.')) return redirect(request, 'mediagoblin.edit.account')
def deauthorize_applications(request): """ Deauthroize OAuth applications """ if request.method == 'POST' and "application" in request.form: token = request.form["application"] access_token = AccessToken.query.filter_by(token=token).first() if access_token is None: messages.add_message( request, messages.ERROR, _("Unknown application, not able to deauthorize") ) else: access_token.delete() messages.add_message( request, messages.SUCCESS, _("Application has been deauthorized") ) access_tokens = AccessToken.query.filter_by(user=request.user.id) applications = [(a.get_requesttoken, a) for a in access_tokens] return render_to_response( request, 'mediagoblin/edit/deauthorize_applications.html', {'applications': applications} )
def register(request): """The registration view. Note that usernames will always be lowercased. Email domains are lowercased while the first part remains case-sensitive. """ # Redirects to indexpage if registrations are disabled if not mg_globals.app_config["allow_registration"]: messages.add_message( request, messages.WARNING, _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") register_form = auth_forms.RegistrationForm(request.form) if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already users_with_username = User.query.filter_by(username=register_form.data['username']).count() users_with_email = User.query.filter_by(email=register_form.data['email']).count() extra_validation_passes = True if users_with_username: register_form.username.errors.append( _(u'Sorry, a user with that name already exists.')) extra_validation_passes = False if users_with_email: register_form.email.errors.append( _(u'Sorry, a user with that email address already exists.')) extra_validation_passes = False if extra_validation_passes: # Create the user user = User() user.username = register_form.data['username'] user.email = register_form.data['email'] user.pw_hash = auth_lib.bcrypt_gen_password_hash( register_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() # log the user in request.session['user_id'] = unicode(user.id) request.session.save() # send verification email email_debug_message(request) send_verification_email(user, request) # redirect the user to their homepage... there will be a # message waiting for them to verify their email return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username) return render_to_response( request, 'mediagoblin/auth/register.html', {'register_form': register_form})
def resend_activation(request): """ The reactivation view Resend the activation email. """ if request.user is None: messages.add_message( request, messages.ERROR, _('You must be logged in so we know who to send the email to!')) return redirect(request, 'mediagoblin.auth.login') if request.user.has_privilege(u'active'): messages.add_message( request, messages.ERROR, _("You've already verified your email address!")) return redirect(request, "mediagoblin.user_pages.user_home", user=request.user.username) email_debug_message(request) send_verification_email(request.user, request) messages.add_message( request, messages.INFO, _('Resent your verification email.')) return redirect( request, 'mediagoblin.user_pages.user_home', user=request.user.username)
def media_confirm_delete(request, media): form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): if form.confirm.data is True: username = media.get_uploader.username # Delete MediaEntry and all related files, comments etc. media.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the media.')) return redirect(request, "mediagoblin.user_pages.user_home", user=username) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.")) return redirect_obj(request, media) if ((request.user.is_admin and request.user.id != media.uploader)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's media. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/media_confirm_delete.html', {'media': media, 'form': form})
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.") ) user = url_user form = forms.EditProfileForm(request.form, url=user.url, bio=user.bio) if request.method == "POST" and form.validate(): user.url = unicode(form.url.data) user.bio = unicode(form.bio.data) user.save() messages.add_message(request, messages.SUCCESS, _("Profile changes saved")) return redirect(request, "mediagoblin.user_pages.user_home", user=user.username) return render_to_response(request, "mediagoblin/edit/edit_profile.html", {"user": user, "form": form})
def media_post_comment(request, media): """ recieves POST from a MediaEntry() comment form, saves the comment. """ assert request.method == 'POST' comment = request.db.MediaComment() comment.media_entry = media.id comment.author = request.user.id comment.content = unicode(request.form['comment_content']) if not comment.content.strip(): messages.add_message( request, messages.ERROR, _("Oops, your comment was empty.")) else: comment.save() messages.add_message( request, messages.SUCCESS, _('Your comment has been posted!')) media_uploader = media.get_uploader #don't send email if you comment on your own post if (comment.author != media_uploader and media_uploader.wants_comment_notification): send_comment_email(media_uploader, comment, media, request) return redirect(request, location=media.url_for_self(request.urlgen))
def forgot_password(request): """ Forgot password view Sends an email with an url to renew forgotten password """ fp_form = auth_forms.ForgotPassForm(request.form, username=request.GET.get('username')) if request.method == 'POST' and fp_form.validate(): # '$or' not available till mongodb 1.5.3 user = request.db.User.find_one( {'username': request.form['username']}) if not user: user = request.db.User.find_one( {'email': request.form['username']}) if user: if user.email_verified and user.status == 'active': user.fp_verification_key = unicode(uuid.uuid4()) user.fp_token_expire = datetime.datetime.now() + \ datetime.timedelta(days=10) user.save() send_fp_verification_email(user, request) messages.add_message( request, messages.INFO, _("An email has been sent with instructions on how to " "change your password.")) email_debug_message(request) else: # special case... we can't send the email because the # username is inactive / hasn't verified their email messages.add_message( request, messages.WARNING, _("Could not send password recovery email as " "your username is inactive or your account's " "email address has not been verified.")) return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username) return redirect(request, 'mediagoblin.auth.login') else: messages.add_message( request, messages.WARNING, _("Couldn't find someone with that username or email.")) return redirect(request, 'mediagoblin.auth.forgot_password') return render_to_response( request, 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form})
def render_400(request, err_msg=None): """ Render a standard 400 page""" _ = pass_to_ugettext title = _("Bad Request") if err_msg is None: err_msg = _("The request sent to the server is invalid, please double check it") return render_error(request, 400, title, err_msg)
def render_403(request): """Render a standard 403 page""" _ = pass_to_ugettext title = _('Operation not allowed') err_msg = _("Sorry Dave, I can't let you do that!</p><p>You have tried " " to perform a function that you are not allowed to. Have you " "been trying to delete all user accounts again?") return render_error(request, 403, title, err_msg)
def _start_verification(request, form, return_to, sreg=True): """ Start OpenID Verification. Returns False if verification fails, otherwise, will return either a redirect or render_to_response object """ openid_url = form.openid.data c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore()) # Try to discover provider try: auth_request = c.begin(openid_url) except DiscoveryFailure: # Discovery failed, return to login page form.openid.errors.append( _('Sorry, the OpenID server could not be found')) return False host = 'http://' + request.host if sreg: # Ask provider for email and nickname auth_request.addExtension(SRegRequest(required=['email', 'nickname'])) # Do we even need this? if auth_request is None: form.openid.errors.append( _('No OpenID service was found for %s' % openid_url)) elif auth_request.shouldSendRedirect(): # Begin the authentication process as a HTTP redirect redirect_url = auth_request.redirectURL( host, return_to) return redirect( request, location=redirect_url) else: # Send request as POST form_html = auth_request.htmlMarkup( host, host + return_to, # Is this necessary? form_tag_attrs={'id': 'openid_message'}) # Beware: this renders a template whose content is a form # and some javascript to submit it upon page load. Non-JS # users will have to click the form submit button to # initiate OpenID authentication. return render_to_response( request, 'mediagoblin/plugins/openid/request_form.html', {'html': form_html}) return False
def media_confirm_delete(request): allowed_state = [u'failed', u'processed'] media = None for media_state in allowed_state: media = request.db.MediaEntry.query.filter_by(id=request.matchdict['media_id'], state=media_state).first() if media: break if not media: return render_404(request) given_username = request.matchdict.get('user') if given_username and (given_username != media.get_uploader.username): return render_404(request) uploader_id = media.uploader if not (request.user.is_admin or request.user.id == uploader_id): raise Forbidden() form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): if form.confirm.data is True: username = media.get_uploader.username # Delete MediaEntry and all related files, comments etc. media.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the media.')) location = media.url_to_next(request.urlgen) if not location: location=media.url_to_prev(request.urlgen) if not location: location=request.urlgen("mediagoblin.user_pages.user_home", user=username) return redirect(request, location=location) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.")) return redirect_obj(request, media) if ((request.user.is_admin and request.user.id != media.uploader)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's media. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/media_confirm_delete.html', {'media': media, 'form': form})
def post_entry(request): _log.debug('Posting entry') if request.method == 'OPTIONS': return json_response({'status': 200}) if request.method != 'POST': _log.debug('Must POST against post_entry') raise BadRequest() if not check_file_field(request, 'file'): _log.debug('File field not found') raise BadRequest() upload_limit, max_file_size = get_upload_file_limits(request.user) callback_url = request.form.get('callback_url') if callback_url: callback_url = unicode(callback_url) try: entry = submit_media( mg_app=request.app, user=request.user, submitted_file=request.files['file'], filename=request.files['file'].filename, title=unicode(request.form.get('title')), description=unicode(request.form.get('description')), license=unicode(request.form.get('license', '')), upload_limit=upload_limit, max_file_size=max_file_size, callback_url=callback_url) return json_response(get_entry_serializable(entry, request.urlgen)) # Handle upload limit issues except FileUploadLimit: raise BadRequest( _(u'Sorry, the file size is too big.')) except UserUploadLimit: raise BadRequest( _('Sorry, uploading this file will put you over your' ' upload limit.')) except UserPastUploadLimit: raise BadRequest( _('Sorry, you have reached your upload limit.')) except Exception as e: ''' This section is intended to catch exceptions raised in mediagoblin.media_types ''' if isinstance(e, InvalidFileType) or \ isinstance(e, FileTypeNotSupported): raise BadRequest(unicode(e)) else: raise
def render_error(request, status=500, title=_('Oops!'), err_msg=_('An error occured')): """Render any error page with a given error code, title and text body Title and description are passed through as-is to allow html. Make sure no user input is contained therein for security reasons. The description will be wrapped in <p></p> tags. """ return Response(render_template(request, 'mediagoblin/error.html', {'err_code': status, 'title': title, 'err_msg': err_msg}), status=status)
def blog_delete(request, **kwargs): """ Deletes a blog and media entries, tags associated with it. """ url_user = request.matchdict.get('user') owner_user = request.db.LocalUser.query.filter( LocalUser.username==url_user ).first() blog_slug = request.matchdict.get('blog_slug', None) blog = get_blog_by_slug(request, blog_slug, author=owner_user.id) if not blog: return render_404(request) form = blog_forms.ConfirmDeleteForm(request.form) if request.user.id == blog.author or request.user.has_privilege(u'admin'): if request.method == 'POST' and form.validate(): if form.confirm.data is True: blog.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the Blog.')) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check " "that you were sure.")) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username) else: if request.user.has_privilege(u'admin'): messages.add_message( request, messages.WARNING, _("You are about to delete another user's Blog. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/blog/blog_confirm_delete.html', {'blog':blog, 'form':form }) else: messages.add_message( request, messages.ERROR, _("The blog was not deleted because you have no rights.")) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username)
def parser_setup(subparser): subparser.description = """\ This command allows the administrator to upload many media files at once.""" subparser.epilog = _( u"""For more information about how to properly run this script (and how to format the metadata csv file), read the MediaGoblin documentation page on command line uploading <http://docs.mediagoblin.org/siteadmin/commandline-upload.html>""") subparser.add_argument( 'username', help=_(u"Name of user these media entries belong to")) subparser.add_argument( 'metadata_path', help=_(u"""Path to the csv file containing metadata information.""")) subparser.add_argument( '--celery', action='store_true', help=_(u"Don't process eagerly, pass off to celery"))
def wrapper(request, *args, **kwargs): if not mgg.app_config["allow_reporting"]: messages.add_message( request, messages.WARNING, _('Sorry, reporting is disabled on this instance.')) return redirect(request, 'index') return controller(request, *args, **kwargs)
def subscribe_comments(request, media): add_comment_subscription(request.user, media) messages.add_message(request, messages.SUCCESS, _('Subscribed to comments on %s!') % media.title) return redirect(request, location=media.url_for_self(request.urlgen))
def post_entry(request): _log.debug('Posting entry') if request.method == 'OPTIONS': return json_response({'status': 200}) if request.method != 'POST': _log.debug('Must POST against post_entry') raise BadRequest() if not check_file_field(request, 'file'): _log.debug('File field not found') raise BadRequest() upload_limit, max_file_size = get_upload_file_limits(request.user) callback_url = request.form.get('callback_url') if callback_url: callback_url = six.text_type(callback_url) try: entry = submit_media( mg_app=request.app, user=request.user, submitted_file=request.files['file'], filename=request.files['file'].filename, title=six.text_type(request.form.get('title')), description=six.text_type(request.form.get('description')), license=six.text_type(request.form.get('license', '')), tags_string=six.text_type(request.form.get('tags', '')), upload_limit=upload_limit, max_file_size=max_file_size, callback_url=callback_url) return json_response(get_entry_serializable(entry, request.urlgen)) # Handle upload limit issues except FileUploadLimit: raise BadRequest(_(u'Sorry, the file size is too big.')) except UserUploadLimit: raise BadRequest( _('Sorry, uploading this file will put you over your' ' upload limit.')) except UserPastUploadLimit: raise BadRequest(_('Sorry, you have reached your upload limit.')) except FileTypeNotSupported as e: raise BadRequest(e)
def wrapper(request, *args, **kwargs): if not mgg.app.auth: messages.add_message( request, messages.WARNING, _('Sorry, authentication is disabled on this instance.')) return redirect(request, 'index') return controller(request, *args, **kwargs)
def collection_confirm_delete(request, collection): form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): username = collection.get_actor.username if form.confirm.data is True: collection_title = collection.title # Firstly like with the MediaEntry delete, lets ensure the # public_id is populated as this is really important! collection.get_public_id(request.urlgen) # Delete all the associated collection items for item in collection.get_collection_items(): obj = item.get_object() obj.save() item.delete() collection.delete() messages.add_message(request, messages.SUCCESS, _('You deleted the collection "%s"') % collection_title) return redirect(request, "mediagoblin.user_pages.user_home", user=username) else: messages.add_message( request, messages.ERROR, _("The collection was not deleted because you didn't check that you were sure.")) return redirect_obj(request, collection) if ((request.user.has_privilege(u'admin') and request.user.id != collection.actor)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's collection. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/collection_confirm_delete.html', {'collection': collection, 'form': form})
class LoginForm(wtforms.Form): openid = wtforms.TextField( _('OpenID'), [ wtforms.validators.InputRequired(), # Can openid's only be urls? wtforms.validators.URL(message='Please enter a valid url.') ])
def pwg_images_addSimple(request): form = AddSimpleForm(request.form) if not form.validate(): _log.error("addSimple: form failed") raise BadRequest() dump = [] for f in form: dump.append("%s=%r" % (f.name, f.data)) _log.info("addSimple: %r %s %r", request.form, " ".join(dump), request.files) if not check_file_field(request, 'image'): raise BadRequest() upload_limit, max_file_size = get_upload_file_limits(request.user) try: entry = submit_media(mg_app=request.app, user=request.user, submitted_file=request.files['image'], filename=request.files['image'].filename, title=six.text_type(form.name.data), description=six.text_type(form.comment.data), upload_limit=upload_limit, max_file_size=max_file_size) collection_id = form.category.data if collection_id > 0: collection = Collection.query.get(collection_id) if collection is not None and collection.creator == request.user.id: add_media_to_collection(collection, entry, "") return { 'image_id': entry.id, 'url': entry.url_for_self(request.urlgen, qualified=True) } # Handle upload limit issues except FileUploadLimit: raise BadRequest(_(u'Sorry, the file size is too big.')) except UserUploadLimit: raise BadRequest( _('Sorry, uploading this file will put you over your' ' upload limit.')) except UserPastUploadLimit: raise BadRequest(_('Sorry, you have reached your upload limit.'))
def collection_confirm_delete(request, collection): form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): username = collection.get_creator.username if form.confirm.data is True: collection_title = collection.title # Delete all the associated collection items for item in collection.get_collection_items(): entry = item.get_media_entry entry.collected = entry.collected - 1 entry.save() item.delete() collection.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the collection "%s"') % collection_title) return redirect(request, "mediagoblin.user_pages.user_home", user=username) else: messages.add_message( request, messages.ERROR, _("The collection was not deleted because you didn't check that you were sure." )) return redirect_obj(request, collection) if ((request.user.is_admin and request.user.id != collection.creator)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's collection. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/collection_confirm_delete.html', { 'collection': collection, 'form': form })
def blog_delete(request, **kwargs): """ Deletes a blog and media entries, tags associated with it. """ url_user = request.matchdict.get('user') owner_user = request.db.User.query.filter_by(username=url_user).first() blog_slug = request.matchdict.get('blog_slug', None) blog = get_blog_by_slug(request, blog_slug, author=owner_user.id) if not blog: return render_404(reequest) form = blog_forms.ConfirmDeleteForm(request.form) if request.user.id == blog.author or request.user.has_privilege(u'admin'): if request.method == 'POST' and form.validate(): if form.confirm.data is True: blog.delete() add_message( request, SUCCESS, _('You deleted the Blog.')) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username) else: add_message( request, ERROR, _("The media was not deleted because you didn't check that you were sure.")) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username) else: if request.user.has_privilege(u'admin'): add_message( request, WARNING, _("You are about to delete another user's Blog. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/blog/blog_confirm_delete.html', {'blog':blog, 'form':form }) else: add_message( request, ERROR, _("The blog was not deleted because you have no rights.")) return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", user=request.user.username)
def silence_comments(request, media): silence_comment_subscription(request.user, media) messages.add_message(request, messages.SUCCESS, _('You will not receive notifications for comments on' ' %s.') % media.title) return redirect(request, location=media.url_for_self(request.urlgen))
def basic_extra_validation(register_form, *args): users_with_username = LocalUser.query.filter_by( username=register_form.username.data).count() users_with_email = LocalUser.query.filter_by( email=register_form.email.data).count() extra_validation_passes = True if users_with_username: register_form.username.errors.append( _(u'Sorry, a user with that name already exists.')) extra_validation_passes = False if users_with_email: register_form.email.errors.append( _(u'Sorry, a user with that email address already exists.')) extra_validation_passes = False return extra_validation_passes
def extract_exif(filename): """ Returns EXIF tags found in file at ``filename`` """ try: with open(filename, 'rb') as image: return process_file(image, details=False) except IOError: raise BadMediaFail(_('Could not read the image file.'))
class RegisterForm(wtforms.Form): username = wtforms.HiddenField('', [ wtforms.validators.InputRequired(), normalize_user_or_email_field(allow_email=False) ]) email = wtforms.StringField(_('Email address'), [ wtforms.validators.InputRequired(), normalize_user_or_email_field(allow_user=False) ])
def link_plugin_assets(plugin_static, plugins_link_dir, printer=simple_printer): """ Arguments: - plugin_static: a mediagoblin.tools.staticdirect.PluginStatic instance representing the static assets of this plugins' configuration - plugins_link_dir: Base directory plugins are linked from """ # link_dir is the final directory we'll link to, a combination of # the plugin assetlink directory and plugin_static.name link_dir = os.path.join(plugins_link_dir.rstrip(os.path.sep), plugin_static.name) # make the link directory parent dirs if necessary if not os.path.lexists(plugins_link_dir): os.makedirs(plugins_link_dir) # See if the link_dir already exists. if os.path.lexists(link_dir): # if this isn't a symlink, there's something wrong... error out. if not os.path.islink(link_dir): printer( _('Could not link "%s": %s exists and is not a symlink\n') % (plugin_static.name, link_dir)) return # if this is a symlink and the path already exists, skip it. if os.path.realpath(link_dir) == plugin_static.file_path: # Is this comment helpful or not? printer( _('Skipping "%s"; already set up.\n') % (plugin_static.name)) return # Otherwise, it's a link that went to something else... unlink it printer( _('Old link found for "%s"; removing.\n') % (plugin_static.name)) os.unlink(link_dir) os.symlink(plugin_static.file_path.rstrip(os.path.sep), link_dir) printer( 'Linked asset directory for plugin "{}":\n {}\nto:\n {}\n'.format( plugin_static.name, plugin_static.file_path.rstrip(os.path.sep), link_dir))
def verify_email(request): """ Email verification view for changing email address """ # If no token, we can't do anything if not 'token' in request.GET: return render_404(request) # Catch error if token is faked or expired token = None try: token = get_timed_signer_url("mail_verification_token") \ .loads(request.GET['token'], max_age=10*24*3600) except BadSignature: messages.add_message( request, messages.ERROR, _('The verification key or user id is incorrect.')) return redirect( request, 'index') user = User.query.filter_by(id=int(token['user'])).first() if user: user.email = token['email'] user.save() messages.add_message( request, messages.SUCCESS, _('Your email address has been verified.')) else: messages.add_message( request, messages.ERROR, _('The verification key or user id is incorrect.')) return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username)
def add_collection(request, media=None): """ View to create a new collection """ submit_form = submit_forms.AddCollectionForm(request.form) if request.method == 'POST' and submit_form.validate(): collection = request.db.Collection() collection.title = str(submit_form.title.data) collection.description = str(submit_form.description.data) collection.actor = request.user.id collection.type = request.db.Collection.USER_DEFINED_TYPE collection.generate_slug() # Make sure this user isn't duplicating an existing collection existing_collection = request.db.Collection.query.filter_by( actor=request.user.id, type=request.db.Collection.USER_DEFINED_TYPE, title=collection.title).first() if existing_collection: messages.add_message( request, messages.ERROR, _('You already have a collection called "%s"!') % collection.title) else: collection.save() messages.add_message( request, messages.SUCCESS, _('Collection "%s" added!') % collection.title) return redirect(request, "mediagoblin.user_pages.user_home", user=request.user.username) return render_to_response( request, 'mediagoblin/submit/collection.html', {'submit_form': submit_form, 'app_config': mg_globals.app_config})
def finish_delete(request): """Finishes the deletion of an OpenID from an user's account""" response = _finish_verification(request) if not response: # Verification failed, redirect to delete openid page. return redirect(request, 'mediagoblin.plugins.openid.delete') query = OpenIDUserURL.query.filter_by( openid_url=response.identity_url ) user = query.first().user if query.first() else None # Need to check this again because of generic openid urls such as google's if user and user.id == int(request.session['user_id']): count = len(user.openid_urls) if count > 1 or user.pw_hash: # User has more then one openid or also has a password. query.first().delete() messages.add_message( request, messages.SUCCESS, _('OpenID was successfully removed.')) return redirect(request, 'mediagoblin.edit.account') elif not count > 1: messages.add_message( request, messages.WARNING, _("You can't delete your only OpenID URL unless you have a " "password set")) return redirect(request, 'mediagoblin.plugins.openid.delete') else: messages.add_message( request, messages.WARNING, _('That OpenID is not registered to this account.')) return redirect(request, 'mediagoblin.plugins.openid.delete')
def edit_media(request, media): if not may_edit_media(request, media): raise Forbidden("User may not edit this media") defaults = dict(title=media.title, slug=media.slug, description=media.description, tags=media_tags_as_string(media.tags), license=media.license) form = forms.EditForm(request.form, **defaults) if request.method == 'POST' and form.validate(): # Make sure there isn't already a MediaEntry with such a slug # and userid. 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 = form.title.data media.description = form.description.data media.tags = convert_to_tag_list_of_dicts(form.tags.data) media.license = unicode(form.license.data) or None media.slug = slug media.save() return redirect_obj(request, media) if request.user.has_privilege(u'admin') \ and media.uploader != request.user.id \ and request.method != 'POST': messages.add_message( request, messages.WARNING, _("You are editing another user's media. Proceed with caution.")) return render_to_response(request, 'mediagoblin/edit/edit.html', { 'media': media, 'form': form })
def verify_email(request): """ Email verification view validates GET parameters against database and unlocks the user account, if you are lucky :) """ # If we don't have userid and token parameters, we can't do anything; 404 if not 'token' in request.GET: return render_404(request) # Catch error if token is faked or expired try: token = get_timed_signer_url("mail_verification_token") \ .loads(request.GET['token'], max_age=10*24*3600) except BadSignature: messages.add_message( request, messages.ERROR, _('The verification key or user id is incorrect.')) return redirect(request, 'index') user = User.query.filter_by(id=int(token)).first() if user and user.has_privilege(u'active') is False: user.verification_key = None user.all_privileges.append( Privilege.query.filter( Privilege.privilege_name == u'active').first()) user.save() messages.add_message( request, messages.SUCCESS, _("Your email address has been verified. " "You may now login, edit your profile, and submit images!")) else: messages.add_message(request, messages.ERROR, _('The verification key or user id is incorrect')) return redirect(request, 'mediagoblin.user_pages.user_home', user=user.username)
def validate(self): if not wtforms.Form.validate(self): return False if self.type.data == 'public' and not self.redirect_uri.data: self.redirect_uri.errors.append( _('This field is required for public clients')) return False return True
def media_confirm_delete(request, media): form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): if form.confirm.data is True: username = media.get_uploader.username media.get_uploader.uploaded = media.get_uploader.uploaded - \ media.file_size media.get_uploader.save() # Delete MediaEntry and all related files, comments etc. media.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the media.')) location = media.url_to_next(request.urlgen) if not location: location=media.url_to_prev(request.urlgen) if not location: location=request.urlgen("mediagoblin.user_pages.user_home", user=username) return redirect(request, location=location) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.")) return redirect_obj(request, media) if ((request.user.has_privilege(u'admin') and request.user.id != media.uploader)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's media. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/media_confirm_delete.html', {'media': media, 'form': form})
def is_unoconv_working(): # TODO: must have libreoffice-headless installed too, need to check for it unoconv = where('unoconv') if not unoconv: return False try: proc = Popen([unoconv, '--show'], stderr=PIPE) output = proc.stderr.read() except OSError, e: _log.warn(_('unoconv failing to run, check log file')) return False
def deauthorize_applications(request): """ Deauthroize OAuth applications """ if request.method == 'POST' and "application" in request.form: token = request.form["application"] access_token = AccessToken.query.filter_by(token=token).first() if access_token is None: messages.add_message( request, messages.ERROR, _("Unknown application, not able to deauthorize")) else: access_token.delete() messages.add_message(request, messages.SUCCESS, _("Application has been deauthorized")) access_tokens = AccessToken.query.filter_by(actor=request.user.id) applications = [(a.get_requesttoken, a) for a in access_tokens] return render_to_response( request, 'mediagoblin/edit/deauthorize_applications.html', {'applications': applications})
def collection_item_confirm_remove(request, collection_item): form = user_forms.ConfirmCollectionItemRemoveForm(request.form) if request.method == 'POST' and form.validate(): username = collection_item.in_collection.get_creator.username collection = collection_item.in_collection if form.confirm.data is True: entry = collection_item.get_media_entry entry.collected = entry.collected - 1 entry.save() collection_item.delete() collection.items = collection.items - 1 collection.save() messages.add_message( request, messages.SUCCESS, _('You deleted the item from the collection.')) else: messages.add_message( request, messages.ERROR, _("The item was not removed because you didn't check that you were sure." )) return redirect_obj(request, collection) if ((request.user.is_admin and request.user.id != collection_item.in_collection.creator)): messages.add_message( request, messages.WARNING, _("You are about to delete an item from another user's collection. " "Proceed with caution.")) return render_to_response( request, 'mediagoblin/user_pages/collection_item_confirm_remove.html', { 'collection_item': collection_item, 'form': form })
def login(request): login_form = forms.LoginForm(request.form) login_failed = False if request.method == 'POST' and login_form.validate(): l = LDAP() username, email = l.login(login_form.username.data, login_form.password.data) if username: user = LocalUser.query.filter( LocalUser.username == username).first() if user: # set up login in session request.session['user_id'] = six.text_type(user.id) request.session.save() if request.form.get('next'): return redirect(request, location=request.form['next']) else: return redirect(request, "index") else: if not mg_globals.app.auth: messages.add_message( request, messages.WARNING, _('Sorry, authentication is disabled on this ' 'instance.')) return redirect(request, 'index') register_form = forms.RegisterForm(username=username, email=email) return render_to_response( request, 'mediagoblin/auth/register.html', { 'register_form': register_form, 'post_url': request.urlgen('mediagoblin.plugins.ldap.register') }) login_failed = True return render_to_response( request, 'mediagoblin/auth/login.html', { 'login_form': login_form, 'next': request.GET.get('next') or request.form.get('next'), 'login_failed': login_failed, 'post_url': request.urlgen('mediagoblin.plugins.ldap.login'), 'allow_registration': mg_globals.app_config["allow_registration"] })
def delete_openid(request): """View to remove an openid from a users account""" form = auth_forms.LoginForm(request.form) if request.method == 'POST' and form.validate(): # Check if a user has this openid query = OpenIDUserURL.query.filter_by( openid_url=form.openid.data ) user = query.first().user if query.first() else None if user and user.id == int(request.session['user_id']): count = len(user.openid_urls) if not count > 1 and not user.pw_hash: # Make sure the user has a pw or another OpenID messages.add_message( request, messages.WARNING, _("You can't delete your only OpenID URL unless you" " have a password set")) elif user: # There is a user, but not the same user who is logged in form.openid.errors.append( _('That OpenID is not registered to this account.')) if not form.errors and not request.session.get('messages'): # Okay to continue with deleting openid return_to = request.urlgen( 'mediagoblin.plugins.openid.finish_delete') success = _start_verification(request, form, return_to, False) if success: return success return render_to_response( request, 'mediagoblin/plugins/openid/delete.html', {'form': form, 'post_url': request.urlgen('mediagoblin.plugins.openid.delete')})
def finish_edit(request): """Finishes the process of adding an openid url to a user""" response = _finish_verification(request) if not response: # Verification failed, redirect to add openid page. return redirect(request, 'mediagoblin.plugins.openid.edit') # Verification was successfull query = OpenIDUserURL.query.filter_by( openid_url=response.identity_url, ).first() user_exists = query.user if query else None if user_exists: # user exists with that openid url, redirect back to edit page messages.add_message( request, messages.WARNING, _('Sorry, an account is already registered to that OpenID.')) return redirect(request, 'mediagoblin.plugins.openid.edit') else: # Save openid to user user = User.query.filter_by( id=request.session['user_id'] ).first() new_entry = OpenIDUserURL() new_entry.openid_url = response.identity_url new_entry.user_id = user.id new_entry.save() messages.add_message( request, messages.SUCCESS, _('Your OpenID url was saved successfully.')) return redirect(request, 'mediagoblin.edit.account')
class EditForm(wtforms.Form): title = wtforms.TextField(_('Title'), [wtforms.validators.Length(min=0, max=500)]) description = wtforms.TextAreaField(_('Description of this work'), description=_("""You can use <a href="http://daringfireball.net/projects/markdown/basics"> Markdown</a> for formatting.""")) tags = wtforms.TextField(_('Tags'), [tag_length_validator], description=_("Separate tags by commas.")) slug = wtforms.TextField(_('Slug'), [ wtforms.validators.InputRequired(message=_("The slug can't be empty")) ], description=_( "The title part of this media's address. " "You usually don't need to change this.")) license = wtforms.SelectField(_('License'), [ wtforms.validators.Optional(), ], choices=licenses_as_choices())
def media_post_comment(request, media): """ recieves POST from a MediaEntry() comment form, saves the comment. """ if not request.method == 'POST': raise MethodNotAllowed() comment = request.db.TextComment() comment.actor = request.user.id comment.content = six.text_type(request.form['comment_content']) # Show error message if commenting is disabled. if not mg_globals.app_config['allow_comments']: messages.add_message( request, messages.ERROR, _("Sorry, comments are disabled.")) elif not comment.content.strip(): messages.add_message( request, messages.ERROR, _("Oops, your comment was empty.")) else: create_activity("post", comment, comment.actor, target=media) add_comment_subscription(request.user, media) comment.save() link = request.db.Comment() link.target = media link.comment = comment link.save() messages.add_message( request, messages.SUCCESS, _('Your comment has been posted!')) trigger_notification(comment, media, request) return redirect_obj(request, media)