aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/auth/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/auth/views.py')
-rw-r--r--mediagoblin/auth/views.py197
1 files changed, 100 insertions, 97 deletions
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 5b77c122..dc408911 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -17,18 +17,15 @@
import uuid
import datetime
-from webob import exc
-
-from mediagoblin import messages
-from mediagoblin import mg_globals
+from mediagoblin import messages, mg_globals
+from mediagoblin.db.models import User
from mediagoblin.tools.response import render_to_response, redirect, render_404
from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.db.util import ObjectId, InvalidId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
from mediagoblin.auth.lib import send_verification_email, \
send_fp_verification_email
-
+from sqlalchemy import or_
def email_debug_message(request):
"""
@@ -44,8 +41,10 @@ def email_debug_message(request):
def register(request):
- """
- Your classic registration view!
+ """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"]:
@@ -59,14 +58,8 @@ def register(request):
if request.method == 'POST' and register_form.validate():
# TODO: Make sure the user doesn't exist already
- username = unicode(request.form['username'].lower())
- em_user, em_dom = unicode(request.form['email']).split("@", 1)
- em_dom = em_dom.lower()
- email = em_user + "@" + em_dom
- users_with_username = request.db.User.find(
- {'username': username}).count()
- users_with_email = request.db.User.find(
- {'email': email}).count()
+ 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
@@ -81,16 +74,16 @@ def register(request):
if extra_validation_passes:
# Create the user
- user = request.db.User()
- user.username = username
- user.email = email
+ user = User()
+ user.username = register_form.data['username']
+ user.email = register_form.data['email']
user.pw_hash = auth_lib.bcrypt_gen_password_hash(
- request.form['password'])
+ register_form.password.data)
user.verification_key = unicode(uuid.uuid4())
- user.save(validate=True)
+ user.save()
# log the user in
- request.session['user_id'] = unicode(user._id)
+ request.session['user_id'] = unicode(user.id)
request.session.save()
# send verification email
@@ -119,21 +112,29 @@ def login(request):
login_failed = False
- if request.method == 'POST' and login_form.validate():
- user = request.db.User.find_one(
- {'username': request.form['username'].lower()})
+ if request.method == 'POST':
+
+ username = login_form.data['username']
- if user and user.check_login(request.form['password']):
- # set up login in session
- request.session['user_id'] = unicode(user._id)
- request.session.save()
+ if login_form.validate():
+ user = User.query.filter(
+ or_(
+ User.username == username,
+ User.email == username,
- if request.form.get('next'):
- return exc.HTTPFound(location=request.form['next'])
- else:
- return redirect(request, "index")
+ )).first()
- else:
+ if user and user.check_login(login_form.password.data):
+ # set up login in session
+ request.session['user_id'] = unicode(user.id)
+ request.session.save()
+
+ if request.form.get('next'):
+ return redirect(request, location=request.form['next'])
+ else:
+ return redirect(request, "index")
+
+ # Some failure during login occured if we are here!
# Prevent detecting who's on this system by testing login
# attempt timings
auth_lib.fake_login_attempt()
@@ -166,8 +167,7 @@ def verify_email(request):
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']))})
+ user = User.query.filter_by(id=request.args['userid']).first()
if user and user.verification_key == unicode(request.GET['token']):
user.status = u'active'
@@ -204,7 +204,7 @@ def resend_activation(request):
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.email_verified:
@@ -212,12 +212,12 @@ def resend_activation(request):
request,
messages.ERROR,
_("You've already verified your email address!"))
-
+
return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username'])
request.user.verification_key = unicode(uuid.uuid4())
request.user.save()
-
+
email_debug_message(request)
send_verification_email(request.user, request)
@@ -234,61 +234,66 @@ def forgot_password(request):
"""
Forgot password view
- Sends an email with an url to renew forgotten password
+ 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.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."))
+ 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/auth/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')
- return render_to_response(
- request,
- 'mediagoblin/auth/forgot_password.html',
- {'fp_form': fp_form})
+ success_message=_("An email has been sent with instructions "
+ "on how to change your password.")
+
+ if user and not(user.email_verified and user.status == 'active'):
+ # 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:
+ user.fp_verification_key = unicode(uuid.uuid4())
+ user.fp_token_expire = datetime.datetime.now() + \
+ datetime.timedelta(days=10)
+ user.save()
+
+ email_debug_message(request)
+ send_fp_verification_email(user, request)
+
+ messages.add_message(request, messages.INFO, success_message)
+ return redirect(request, 'mediagoblin.auth.login')
def verify_forgot_password(request):
@@ -305,11 +310,9 @@ def verify_forgot_password(request):
formdata_userid = formdata['vars']['userid']
formdata_vars = formdata['vars']
- # check if it's a valid Id
- try:
- user = request.db.User.find_one(
- {'_id': ObjectId(unicode(formdata_userid))})
- except InvalidId:
+ # check if it's a valid user id
+ user = User.query.filter_by(id=formdata_userid).first()
+ if not user:
return render_404(request)
# check if we have a real user and correct token
@@ -322,7 +325,7 @@ def verify_forgot_password(request):
if request.method == 'POST' and cp_form.validate():
user.pw_hash = auth_lib.bcrypt_gen_password_hash(
- request.form['password'])
+ cp_form.password.data)
user.fp_verification_key = None
user.fp_token_expire = None
user.save()
@@ -338,7 +341,7 @@ def verify_forgot_password(request):
'mediagoblin/auth/change_fp.html',
{'cp_form': cp_form})
- # in case there is a valid id but no user whit that id in the db
+ # in case there is a valid id but no user with that id in the db
# or the token expired
else:
return render_404(request)