Polish up some code and add some signals

This commit is contained in:
Matt Wright
2012-06-15 12:13:49 -04:00
parent c123e32ddc
commit 5fdfa544db
6 changed files with 63 additions and 31 deletions
+5 -1
View File
@@ -5,10 +5,11 @@ from flask import current_app, request, url_for
from flask.ext.security.exceptions import UserNotFoundError, \
ConfirmationError, TokenExpiredError
from flask.ext.security.utils import generate_token, send_mail
from flask.ext.security.signals import user_confirmed, \
confirm_instructions_sent
from werkzeug.local import LocalProxy
security = LocalProxy(lambda: current_app.security)
logger = LocalProxy(lambda: current_app.logger)
@@ -28,6 +29,8 @@ def send_confirmation_instructions(user):
'confirmation_instructions',
dict(user=user, confirmation_link=confirmation_link))
confirm_instructions_sent.send(user, app=current_app._get_current_object())
return True
@@ -89,6 +92,7 @@ def confirm_by_token(token):
security.datastore._save_model(user)
user_confirmed.send(user, app=current_app._get_current_object())
return user
+9 -1
View File
@@ -302,6 +302,9 @@ class ForgotPasswordForm(Form):
email = TextField("Email Address",
validators=[Required(message="Email not provided")])
def to_dict(self):
return dict(email=self.email.data)
class LoginForm(Form):
"""The default login form"""
@@ -334,13 +337,18 @@ class RegisterForm(Form):
class ResetPasswordForm(Form):
reset_password_token = HiddenField(validators=[Required()])
token = HiddenField(validators=[Required()])
email = HiddenField(validators=[Required()])
password = PasswordField("Password",
validators=[Required(message="Password not provided")])
password_confirm = PasswordField("Retype Password",
validators=[EqualTo('password', message="Passwords do not match")])
def to_dict(self):
return dict(token=self.token.data,
email=self.email.data,
password=self.password.data)
class AuthenticationProvider(object):
"""The default authentication provider implementation.
+6 -2
View File
@@ -4,12 +4,12 @@ from datetime import datetime
from flask import current_app, request, url_for
from flask.ext.security.exceptions import ResetPasswordError, \
UserNotFoundError, TokenExpiredError
from flask.ext.security.signals import password_reset_requested
from flask.ext.security.signals import password_reset, \
password_reset_requested, confirm_instructions_sent
from flask.ext.security.utils import generate_token, send_mail
from werkzeug.local import LocalProxy
security = LocalProxy(lambda: current_app.security)
logger = LocalProxy(lambda: current_app.logger)
@@ -30,6 +30,8 @@ def send_reset_password_instructions(user):
'reset_instructions',
dict(user=user, reset_link=reset_link))
confirm_instructions_sent.send(user, app=current_app._get_current_object())
return True
@@ -75,6 +77,8 @@ def reset_by_token(token, email, password):
send_mail('Your password has been reset', user.email, 'reset_notice')
password_reset.send(user, app=current_app._get_current_object())
return user
+8
View File
@@ -4,4 +4,12 @@ signals = blinker.Namespace()
user_registered = signals.signal("user-registered")
user_confirmed = signals.signal("user-confirmed")
confirm_instructions_sent = signals.signal("confirm-instructions-sent")
password_reset = signals.signal("password-reset")
password_reset_requested = signals.signal("password-reset-requested")
reset_instructions_sent = signals.signal("reset-instructions-sent")
+33 -25
View File
@@ -24,7 +24,7 @@ from werkzeug.local import LocalProxy
security = LocalProxy(lambda: current_app.security)
datastore = LocalProxy(lambda: current_app.security.datastore)
logger = LocalProxy(lambda: current_app.logger)
@@ -63,7 +63,6 @@ def authenticate():
msg = 'Unknown authentication error'
do_flash(msg, 'error')
logger.debug('Unsuccessful authentication attempt: %s' % msg)
return redirect(request.referrer or security.login_manager.login_view)
@@ -81,10 +80,9 @@ def logout():
identity=AnonymousIdentity())
logout_user()
logger.debug('User logged out')
return redirect(request.args.get('next', None) or \
return redirect(request.args.get('next', None) or
security.post_logout_view)
@@ -99,24 +97,26 @@ def register():
form = security.RegisterForm(csrf_enabled=not current_app.testing)
# Exit early if the form doesn't validate
if not form.validate_on_submit():
return redirect(request.referrer or security.register_url)
if form.validate_on_submit():
# Create user and send signal
user = datastore.create_user(**form.to_dict())
app = current_app._get_current_object()
# Create user and send signal
user = security.datastore.create_user(**form.to_dict())
user_registered.send(user, app=current_app._get_current_object())
user_registered.send(user, app=app)
# Send confirmation instructions if necessary
if security.confirm_email:
send_confirmation_instructions(user)
# Send confirmation instructions if necessary
if security.confirm_email:
send_confirmation_instructions(user)
logger.debug('User %s registered' % user)
logger.debug('User %s registered' % user)
# Login the user if allowed
if (not security.confirm_email) or security.login_without_confirmation:
_do_login(user)
# Login the user if allowed
if not security.confirm_email or security.login_without_confirmation:
_do_login(user)
return redirect(security.post_register_view or security.post_login_view)
return redirect(security.post_register_view or security.post_login_view)
return redirect(request.referrer or security.register_url)
def confirm():
@@ -140,7 +140,6 @@ def confirm():
security.confirm_email_within_text, e.user.email)
do_flash(msg, 'error')
return redirect('/') # TODO: Don't redirect to root
logger.debug('User %s confirmed' % user)
@@ -150,35 +149,44 @@ def confirm():
def forgot():
"""View function that handles the generation of a password reset token.
"""
form = security.ForgotPasswordForm(csrf_enabled=not current_app.testing)
if form.validate_on_submit():
try:
user = security.datastore.find_user(email=form.email.data)
user = datastore.find_user(**form.to_dict())
reset_password_reset_token(user)
do_flash('Instructions to reset your password have been sent to %s' % user.email, 'success')
do_flash('Instructions to reset your password have been '
'sent to %s' % user.email, 'success')
except UserNotFoundError:
do_flash('The email you provided could not be found', 'error')
return redirect(security.post_forgot_view)
return render_template('security/passwords/new.html', forgot_password_form=form)
return render_template('security/passwords/new.html',
forgot_password_form=form)
def reset():
"""View function that handles the reset of a user's password.
"""
form = security.ResetPasswordForm(csrf_enabled=not current_app.testing)
if form.validate_on_submit():
try:
reset_by_token(token=form.reset_password_token.data,
email=form.email.data,
password=form.password.data)
reset_by_token(**form.to_dict())
except ResetPasswordError, e:
do_flash(str(e), 'error')
except TokenExpiredError, e:
do_flash('You did not reset your password within %s.' % security.reset_password_within_text)
do_flash('You did not reset your password within'
'%s.' % security.reset_password_within_text)
return redirect(request.referrer or security.reset_password_error_view)
+2 -2
View File
@@ -236,7 +236,7 @@ class RecoverableTests(SecurityTest):
r = self.client.post('/reset', data={
'email': u.email,
'reset_password_token': u.reset_password_token,
'token': u.reset_password_token,
'password': 'newpassword',
'password_confirm': 'newpassword'
})
@@ -251,7 +251,7 @@ class RecoverableTests(SecurityTest):
data = {
'email': u.email,
'reset_password_token': u.reset_password_token,
'token': u.reset_password_token,
'password': 'newpassword',
'password_confirm': 'newpassword'
}