From c20f244d6632e982d670757edd4b10979a28c0d6 Mon Sep 17 00:00:00 2001 From: Matt Wright Date: Mon, 18 Jun 2012 16:51:43 -0400 Subject: [PATCH] Big code cleanup --- flask_security/__init__.py | 10 ++- flask_security/confirmable.py | 43 ++++++---- flask_security/core.py | 154 +++------------------------------- flask_security/datastore.py | 3 +- flask_security/decorators.py | 91 +++++++++++++++++++- flask_security/forms.py | 66 +++++++++++++++ flask_security/recoverable.py | 46 ++++++---- flask_security/signals.py | 12 +++ flask_security/tokens.py | 26 ++++-- flask_security/utils.py | 4 +- flask_security/views.py | 86 ++++++++++--------- 11 files changed, 318 insertions(+), 223 deletions(-) create mode 100644 flask_security/forms.py diff --git a/flask_security/__init__.py b/flask_security/__init__.py index 74aa214..27ff039 100644 --- a/flask_security/__init__.py +++ b/flask_security/__init__.py @@ -10,4 +10,12 @@ :license: MIT, see LICENSE for more details. """ -from .core import * +from .core import Security, RoleMixin, UserMixin, AnonymousUser, \ + AuthenticationProvider +from .decorators import auth_token_required, http_auth_required, \ + login_required, roles_accepted, roles_required +from .forms import ForgotPasswordForm, LoginForm, RegisterForm, \ + ResetPasswordForm +from .signals import confirm_instructions_sent, password_reset, \ + password_reset_requested, reset_instructions_sent, user_confirmed, \ + user_registered diff --git a/flask_security/confirmable.py b/flask_security/confirmable.py index c78ae75..054a2b9 100644 --- a/flask_security/confirmable.py +++ b/flask_security/confirmable.py @@ -1,22 +1,34 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.confirmable + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security confirmable module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" from datetime import datetime -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 flask import current_app as app, request, url_for from werkzeug.local import LocalProxy -security = LocalProxy(lambda: current_app.security) -logger = LocalProxy(lambda: current_app.logger) +from .exceptions import UserNotFoundError, ConfirmationError, TokenExpiredError +from .utils import generate_token, send_mail +from .signals import user_confirmed, confirm_instructions_sent + + +# Convenient references +_security = LocalProxy(lambda: app.security) + +_datastore = LocalProxy(lambda: app.security.datastore) def find_user_by_confirmation_token(token): if not token: raise ConfirmationError('Confirmation token required') - return security.datastore.find_user(confirmation_token=token) + return _datastore.find_user(confirmation_token=token) def send_confirmation_instructions(user): @@ -29,7 +41,7 @@ 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()) + confirm_instructions_sent.send(user, app=app._get_current_object()) return True @@ -56,7 +68,7 @@ def generate_confirmation_token(user): def should_confirm_email(fn): def wrapped(*args, **kwargs): - if security.confirm_email: + if _security.confirm_email: return fn(*args, **kwargs) return False return wrapped @@ -69,7 +81,7 @@ def requires_confirmation(user): @should_confirm_email def confirmation_token_is_expired(user): - token_expires = datetime.utcnow() - security.confirm_email_within + token_expires = datetime.utcnow() - _security.confirm_email_within return user.confirmation_sent_at < token_expires @@ -86,16 +98,17 @@ def confirm_by_token(token): raise TokenExpiredError(message='Confirmation token is expired', user=user) + # TODO: Clear confirmation_token after confirmation? #user.confirmation_token = None #user.confirmation_sent_at = None user.confirmed_at = datetime.utcnow() - security.datastore._save_model(user) + _datastore._save_model(user) - user_confirmed.send(user, app=current_app._get_current_object()) + user_confirmed.send(user, app=app._get_current_object()) return user def reset_confirmation_token(user): - security.datastore._save_model(generate_confirmation_token(user)) + _datastore._save_model(generate_confirmation_token(user)) send_confirmation_instructions(user) diff --git a/flask_security/core.py b/flask_security/core.py index 7bee606..6784a76 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -10,22 +10,20 @@ """ from datetime import timedelta -from functools import wraps -from flask import current_app, Blueprint, redirect, request +from flask import current_app, Blueprint from flask.ext.login import AnonymousUser as AnonymousUserBase, \ - UserMixin as BaseUserMixin, LoginManager, login_required, \ - current_user, login_url -from flask.ext.principal import Principal, RoleNeed, UserNeed, \ - Permission, identity_loaded -from flask.ext.wtf import Form, TextField, PasswordField, SubmitField, \ - HiddenField, Required, BooleanField, EqualTo, Email -from flask.ext.security import views, exceptions, utils -from flask.ext.security.confirmable import confirmation_token_is_expired, \ - requires_confirmation, reset_confirmation_token + UserMixin as BaseUserMixin, LoginManager, current_user +from flask.ext.principal import Principal, RoleNeed, UserNeed, identity_loaded from passlib.context import CryptContext from werkzeug.datastructures import ImmutableList +from . import views, exceptions, utils +from .confirmable import confirmation_token_is_expired, requires_confirmation, \ + reset_confirmation_token +from .decorators import login_required +from .forms import Form, LoginForm + #: Default Flask-Security configuration _default_config = { @@ -33,10 +31,10 @@ _default_config = { 'FLASH_MESSAGES': True, 'PASSWORD_HASH': 'plaintext', 'AUTH_PROVIDER': 'flask.ext.security::AuthenticationProvider', - 'LOGIN_FORM': 'flask.ext.security::LoginForm', - 'REGISTER_FORM': 'flask.ext.security::RegisterForm', - 'RESET_PASSWORD_FORM': 'flask.ext.security::ResetPasswordForm', - 'FORGOT_PASSWORD_FORM': 'flask.ext.security::ForgotPasswordForm', + 'LOGIN_FORM': 'flask.ext.security.forms::LoginForm', + 'REGISTER_FORM': 'flask.ext.security.forms::RegisterForm', + 'RESET_PASSWORD_FORM': 'flask.ext.security.forms::ResetPasswordForm', + 'FORGOT_PASSWORD_FORM': 'flask.ext.security.forms::ForgotPasswordForm', 'AUTH_URL': '/auth', 'LOGOUT_URL': '/logout', 'REGISTER_URL': '/register', @@ -61,80 +59,6 @@ _default_config = { } -def roles_required(*roles): - """View decorator which specifies that a user must have all the specified - roles. Example:: - - @app.route('/dashboard') - @roles_required('admin', 'editor') - def dashboard(): - return 'Dashboard' - - The current user must have both the `admin` role and `editor` role in order - to view the page. - - :param args: The required roles. - """ - perm = Permission(*[RoleNeed(role) for role in roles]) - - def wrapper(fn): - @wraps(fn) - def decorated_view(*args, **kwargs): - if not current_user.is_authenticated(): - login_view = current_app.security.login_manager.login_view - return redirect(login_url(login_view, request.url)) - - if perm.can(): - return fn(*args, **kwargs) - - current_app.logger.debug('Identity does not provide the ' - 'roles: %s' % [r for r in roles]) - return redirect(request.referrer or '/') - return decorated_view - return wrapper - - -def roles_accepted(*roles): - """View decorator which specifies that a user must have at least one of the - specified roles. Example:: - - @app.route('/create_post') - @roles_accepted('editor', 'author') - def create_post(): - return 'Create Post' - - The current user must have either the `editor` role or `author` role in - order to view the page. - - :param args: The possible roles. - """ - perms = [Permission(RoleNeed(role)) for role in roles] - - def wrapper(fn): - @wraps(fn) - def decorated_view(*args, **kwargs): - if not current_user.is_authenticated(): - login_view = current_app.security.login_manager.login_view - return redirect(login_url(login_view, request.url)) - - for perm in perms: - if perm.can(): - return fn(*args, **kwargs) - - r1 = [r for r in roles] - r2 = [r.name for r in current_user.roles] - - current_app.logger.debug('Current user does not provide a ' - 'required role. Accepted: %s Provided: %s' % (r1, r2)) - - utils.do_flash('You do not have permission to ' - 'view this resource', 'error') - - return redirect(request.referrer or '/') - return decorated_view - return wrapper - - class RoleMixin(object): """Mixin for `Role` model definitions""" def __eq__(self, other): @@ -298,58 +222,6 @@ class Security(object): endpoint='confirm')(views.confirm) -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""" - - email = TextField("Email Address", - validators=[Required(message="Email not provided")]) - password = PasswordField("Password", - validators=[Required(message="Password not provided")]) - remember = BooleanField("Remember Me") - next = HiddenField() - submit = SubmitField("Login") - - def __init__(self, *args, **kwargs): - super(LoginForm, self).__init__(*args, **kwargs) - self.next.data = request.args.get('next', None) - - -class RegisterForm(Form): - """The default register form""" - - email = TextField("Email Address", - validators=[Required(message='Email not provided'), Email()]) - 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(email=self.email.data, password=self.password.data) - - -class ResetPasswordForm(Form): - 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. diff --git a/flask_security/datastore.py b/flask_security/datastore.py index c47a59d..6727084 100644 --- a/flask_security/datastore.py +++ b/flask_security/datastore.py @@ -10,7 +10,8 @@ """ from flask import current_app -from flask.ext.security import exceptions, confirmable + +from . import exceptions, confirmable class UserDatastore(object): diff --git a/flask_security/decorators.py b/flask_security/decorators.py index 12b0461..63ef946 100644 --- a/flask_security/decorators.py +++ b/flask_security/decorators.py @@ -1,7 +1,22 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.decorators + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security decorators module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" from functools import wraps -from flask import current_app as app, Response, request, abort +from flask import current_app as app, Response, request, abort, redirect +from flask.ext.login import login_required, login_url, current_user +from flask.ext.principal import RoleNeed, Permission + +from . import utils + _default_http_auth_msg = """

Unauthorized

@@ -62,3 +77,77 @@ def auth_token_required(fn): abort(401) return decorated + + +def roles_required(*roles): + """View decorator which specifies that a user must have all the specified + roles. Example:: + + @app.route('/dashboard') + @roles_required('admin', 'editor') + def dashboard(): + return 'Dashboard' + + The current user must have both the `admin` role and `editor` role in order + to view the page. + + :param args: The required roles. + """ + perm = Permission(*[RoleNeed(role) for role in roles]) + + def wrapper(fn): + @wraps(fn) + def decorated_view(*args, **kwargs): + if not current_user.is_authenticated(): + login_view = app.security.login_manager.login_view + return redirect(login_url(login_view, request.url)) + + if perm.can(): + return fn(*args, **kwargs) + + app.logger.debug('Identity does not provide the ' + 'roles: %s' % [r for r in roles]) + return redirect(request.referrer or '/') + return decorated_view + return wrapper + + +def roles_accepted(*roles): + """View decorator which specifies that a user must have at least one of the + specified roles. Example:: + + @app.route('/create_post') + @roles_accepted('editor', 'author') + def create_post(): + return 'Create Post' + + The current user must have either the `editor` role or `author` role in + order to view the page. + + :param args: The possible roles. + """ + perms = [Permission(RoleNeed(role)) for role in roles] + + def wrapper(fn): + @wraps(fn) + def decorated_view(*args, **kwargs): + if not current_user.is_authenticated(): + login_view = app.security.login_manager.login_view + return redirect(login_url(login_view, request.url)) + + for perm in perms: + if perm.can(): + return fn(*args, **kwargs) + + r1 = [r for r in roles] + r2 = [r.name for r in current_user.roles] + + app.logger.debug('Current user does not provide a ' + 'required role. Accepted: %s Provided: %s' % (r1, r2)) + + utils.do_flash('You do not have permission to ' + 'view this resource', 'error') + + return redirect(request.referrer or '/') + return decorated_view + return wrapper diff --git a/flask_security/forms.py b/flask_security/forms.py new file mode 100644 index 0000000..46cc452 --- /dev/null +++ b/flask_security/forms.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.forms + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security forms module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" + +from flask import request +from flask.ext.wtf import Form, TextField, PasswordField, SubmitField, \ + HiddenField, Required, BooleanField, EqualTo, Email + + +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""" + + email = TextField("Email Address", + validators=[Required(message="Email not provided")]) + password = PasswordField("Password", + validators=[Required(message="Password not provided")]) + remember = BooleanField("Remember Me") + next = HiddenField() + submit = SubmitField("Login") + + def __init__(self, *args, **kwargs): + super(LoginForm, self).__init__(*args, **kwargs) + self.next.data = request.args.get('next', None) + + +class RegisterForm(Form): + """The default register form""" + + email = TextField("Email Address", + validators=[Required(message='Email not provided'), Email()]) + 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(email=self.email.data, password=self.password.data) + + +class ResetPasswordForm(Form): + 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) diff --git a/flask_security/recoverable.py b/flask_security/recoverable.py index 0ec377b..38bea7f 100644 --- a/flask_security/recoverable.py +++ b/flask_security/recoverable.py @@ -1,22 +1,36 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.recoverable + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security recoverable module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" 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, \ - password_reset_requested, confirm_instructions_sent -from flask.ext.security.utils import generate_token, send_mail +from flask import current_app as app, request, url_for from werkzeug.local import LocalProxy -security = LocalProxy(lambda: current_app.security) -logger = LocalProxy(lambda: current_app.logger) +from .exceptions import ResetPasswordError, UserNotFoundError, \ + TokenExpiredError +from .signals import password_reset, password_reset_requested, \ + confirm_instructions_sent +from .utils import generate_token, send_mail + + +# Convenient references +_security = LocalProxy(lambda: app.security) + +_datastore = LocalProxy(lambda: app.security.datastore) def find_user_by_reset_token(token): if not token: raise ResetPasswordError('Reset password token required') - return security.datastore.find_user(reset_password_token=token) + return _datastore.find_user(reset_password_token=token) def send_reset_password_instructions(user): @@ -30,7 +44,7 @@ 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()) + confirm_instructions_sent.send(user, app=app._get_current_object()) return True @@ -56,7 +70,7 @@ def generate_reset_password_token(user): def password_reset_token_is_expired(user): - token_expires = datetime.utcnow() - security.reset_password_within + token_expires = datetime.utcnow() - _security.reset_password_within return user.reset_password_sent_at < token_expires @@ -71,18 +85,18 @@ def reset_by_token(token, email, password): user.reset_password_token = None user.reset_password_sent_at = None - user.password = security.pwd_context.encrypt(password) + user.password = _security.pwd_context.encrypt(password) - security.datastore._save_model(user) + _datastore._save_model(user) send_mail('Your password has been reset', user.email, 'reset_notice') - password_reset.send(user, app=current_app._get_current_object()) + password_reset.send(user, app=app._get_current_object()) return user def reset_password_reset_token(user): - security.datastore._save_model(generate_reset_password_token(user)) + _datastore._save_model(generate_reset_password_token(user)) send_reset_password_instructions(user) - password_reset_requested.send(user, app=current_app._get_current_object()) + password_reset_requested.send(user, app=app._get_current_object()) diff --git a/flask_security/signals.py b/flask_security/signals.py index bc77265..7b14aaf 100644 --- a/flask_security/signals.py +++ b/flask_security/signals.py @@ -1,5 +1,17 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.signals + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security signals module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" + import blinker + signals = blinker.Namespace() user_registered = signals.signal("user-registered") diff --git a/flask_security/tokens.py b/flask_security/tokens.py index 19b027f..f68b98e 100644 --- a/flask_security/tokens.py +++ b/flask_security/tokens.py @@ -1,19 +1,31 @@ +# -*- coding: utf-8 -*- +""" + flask.ext.security.tokens + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Flask-Security tokens module + + :copyright: (c) 2012 by Matt Wright. + :license: MIT, see LICENSE for more details. +""" from datetime import datetime -from flask import current_app -from flask.ext.security.exceptions import BadCredentialsError, \ - UserNotFoundError -from flask.ext.security.utils import generate_token +from flask import current_app as app from werkzeug.local import LocalProxy -datastore = LocalProxy(lambda: current_app.security.datastore) +from .exceptions import BadCredentialsError, UserNotFoundError +from .utils import generate_token + + +# Convenient references +_datastore = LocalProxy(lambda: app.security.datastore) def find_user_by_authentication_token(token): if not token: raise BadCredentialsError('Authentication token required') - return datastore.find_user(authentication_token=token) + return _datastore.find_user(authentication_token=token) def generate_authentication_token(user): @@ -38,7 +50,7 @@ def generate_authentication_token(user): def reset_authentication_token(user): user = generate_authentication_token(user) - datastore._save_model(user) + _datastore._save_model(user) return user.authentication_token diff --git a/flask_security/utils.py b/flask_security/utils.py index da80ad8..2b968ca 100644 --- a/flask_security/utils.py +++ b/flask_security/utils.py @@ -11,12 +11,12 @@ import base64 import os - from contextlib import contextmanager from importlib import import_module from flask import url_for, flash, current_app, request, session, render_template -from flask.ext.security.signals import user_registered, password_reset_requested + +from .signals import user_registered, password_reset_requested def generate_token(): diff --git a/flask_security/views.py b/flask_security/views.py index 9e51c35..1efe707 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -9,31 +9,36 @@ :license: MIT, see LICENSE for more details. """ -from flask import current_app, redirect, request, session, render_template +from flask import current_app as app, redirect, request, session, \ + render_template from flask.ext.login import login_user, logout_user from flask.ext.principal import Identity, AnonymousIdentity, identity_changed -from flask.ext.security.confirmable import confirm_by_token, \ - reset_confirmation_token, send_confirmation_instructions -from flask.ext.security.recoverable import reset_by_token, \ - reset_password_reset_token -from flask.ext.security.exceptions import TokenExpiredError, UserNotFoundError, \ - ConfirmationError, BadCredentialsError, ResetPasswordError -from flask.ext.security.utils import get_post_login_redirect, do_flash -from flask.ext.security.signals import user_registered from werkzeug.local import LocalProxy +from .confirmable import confirm_by_token, \ + reset_confirmation_token, send_confirmation_instructions +from .exceptions import TokenExpiredError, UserNotFoundError, \ + ConfirmationError, BadCredentialsError, ResetPasswordError +from .recoverable import reset_by_token, \ + reset_password_reset_token +from .signals import user_registered +from .utils import get_post_login_redirect, do_flash -security = LocalProxy(lambda: current_app.security) -datastore = LocalProxy(lambda: current_app.security.datastore) -logger = LocalProxy(lambda: current_app.logger) + +# Convenient references +_security = LocalProxy(lambda: app.security) + +_datastore = LocalProxy(lambda: app.security.datastore) + +_logger = LocalProxy(lambda: app.logger) def _do_login(user, remember=True): if login_user(user, remember): - identity_changed.send(current_app._get_current_object(), + identity_changed.send(app._get_current_object(), identity=Identity(user.id)) - logger.debug('User %s logged in' % user) + _logger.debug('User %s logged in' % user) return True return False @@ -46,10 +51,10 @@ def authenticate(): authenticate fails the user an appropriate error message is flashed and the user is redirected to the referring page or the login view. """ - form = security.LoginForm() + form = _security.LoginForm() try: - user = security.auth_provider.authenticate(form) + user = _security.auth_provider.authenticate(form) if _do_login(user, remember=form.remember.data): return redirect(get_post_login_redirect()) @@ -63,9 +68,9 @@ def authenticate(): msg = 'Unknown authentication error' do_flash(msg, 'error') - logger.debug('Unsuccessful authentication attempt: %s' % msg) + _logger.debug('Unsuccessful authentication attempt: %s' % msg) - return redirect(request.referrer or security.login_manager.login_view) + return redirect(request.referrer or _security.login_manager.login_view) def logout(): @@ -76,14 +81,14 @@ def logout(): for key in ('identity.name', 'identity.auth_type'): session.pop(key, None) - identity_changed.send(current_app._get_current_object(), + identity_changed.send(app._get_current_object(), identity=AnonymousIdentity()) logout_user() - logger.debug('User logged out') + _logger.debug('User logged out') return redirect(request.args.get('next', None) or - security.post_logout_view) + _security.post_logout_view) def register(): @@ -94,29 +99,30 @@ def register(): Otherwise the user is redirected to the `SECURITY_POST_LOGIN_VIEW` configuration value. """ - form = security.RegisterForm(csrf_enabled=not current_app.testing) + form = _security.RegisterForm(csrf_enabled=not app.testing) # Exit early if the form doesn't validate if form.validate_on_submit(): # Create user and send signal - user = datastore.create_user(**form.to_dict()) - app = current_app._get_current_object() + user = _datastore.create_user(**form.to_dict()) - user_registered.send(user, app=app) + user_registered.send(user, app=app._get_current_object()) # Send confirmation instructions if necessary - if security.confirm_email: + 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: + 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) + return redirect(request.referrer or + _security.register_url) def confirm(): @@ -137,26 +143,27 @@ def confirm(): msg = 'You did not confirm your email within %s. ' \ 'A new confirmation code has been sent to %s' % ( - security.confirm_email_within_text, e.user.email) + _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) + _logger.debug('User %s confirmed' % user) do_flash('Your email has been confirmed. You may now log in.', 'success') - return redirect(security.post_confirm_view or security.post_login_view) + return redirect(_security.post_confirm_view or + _security.post_login_view) def forgot(): """View function that handles the generation of a password reset token. """ - form = security.ForgotPasswordForm(csrf_enabled=not current_app.testing) + form = _security.ForgotPasswordForm(csrf_enabled=not app.testing) if form.validate_on_submit(): try: - user = datastore.find_user(**form.to_dict()) + user = _datastore.find_user(**form.to_dict()) reset_password_reset_token(user) @@ -166,7 +173,7 @@ def forgot(): except UserNotFoundError: do_flash('The email you provided could not be found', 'error') - return redirect(security.post_forgot_view) + return redirect(_security.post_forgot_view) return render_template('security/passwords/new.html', forgot_password_form=form) @@ -176,7 +183,7 @@ def reset(): """View function that handles the reset of a user's password. """ - form = security.ResetPasswordForm(csrf_enabled=not current_app.testing) + form = _security.ResetPasswordForm(csrf_enabled=not app.testing) if form.validate_on_submit(): try: @@ -187,6 +194,7 @@ def reset(): except TokenExpiredError, e: do_flash('You did not reset your password within' - '%s.' % security.reset_password_within_text) + '%s.' % _security.reset_password_within_text) - return redirect(request.referrer or security.reset_password_error_view) + return redirect(request.referrer or + _security.reset_password_error_view)