mirror of
https://github.com/wassname/flask-security.git
synced 2026-06-27 16:10:11 +08:00
Use a stateful object instead of arbitrary assignment of extension on app object
This commit is contained in:
+3
-3
@@ -149,8 +149,8 @@ def create_sqlalchemy_app(auth_config=None, register_blueprint=True):
|
||||
roles = db.relationship('Role', secondary=roles_users,
|
||||
backref=db.backref('users', lazy='dynamic'))
|
||||
|
||||
Security(app, SQLAlchemyUserDatastore(db, User, Role),
|
||||
register_blueprint=register_blueprint)
|
||||
app.security = Security(app, SQLAlchemyUserDatastore(db, User, Role),
|
||||
register_blueprint=register_blueprint)
|
||||
|
||||
if not register_blueprint:
|
||||
from example import security
|
||||
@@ -192,7 +192,7 @@ def create_mongoengine_app(auth_config=None):
|
||||
authentication_token = db.StringField(max_length=255)
|
||||
roles = db.ListField(db.ReferenceField(Role), default=[])
|
||||
|
||||
Security(app, MongoEngineUserDatastore(db, User, Role))
|
||||
app.security = Security(app, MongoEngineUserDatastore(db, User, Role))
|
||||
|
||||
@app.before_first_request
|
||||
def before_first_request():
|
||||
|
||||
@@ -21,9 +21,9 @@ from .signals import user_confirmed, confirm_instructions_sent
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: app.security)
|
||||
_security = LocalProxy(lambda: app.extensions['security'])
|
||||
|
||||
_datastore = LocalProxy(lambda: app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: _security.datastore)
|
||||
|
||||
|
||||
def send_confirmation_instructions(user, token):
|
||||
|
||||
+38
-20
@@ -17,11 +17,15 @@ from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \
|
||||
identity_loaded
|
||||
from passlib.context import CryptContext
|
||||
from werkzeug.datastructures import ImmutableList
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
from . import views, exceptions
|
||||
from .confirmable import requires_confirmation
|
||||
from .utils import config_value as cv, get_config
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: current_app.extensions['security'])
|
||||
|
||||
|
||||
#: Default Flask-Security configuration
|
||||
_default_config = {
|
||||
@@ -75,7 +79,7 @@ _default_flash_messages = {
|
||||
|
||||
def _user_loader(user_id):
|
||||
try:
|
||||
return current_app.security.datastore.with_id(user_id)
|
||||
return _security.datastore.with_id(user_id)
|
||||
except Exception, e:
|
||||
current_app.logger.error('Error getting user: %s' % e)
|
||||
return None
|
||||
@@ -83,7 +87,7 @@ def _user_loader(user_id):
|
||||
|
||||
def _token_loader(token):
|
||||
try:
|
||||
return current_app.security.datastore.find_user(remember_token=token)
|
||||
return _security.datastore.find_user(remember_token=token)
|
||||
except Exception, e:
|
||||
current_app.logger.error('Error getting user: %s' % e)
|
||||
return None
|
||||
@@ -189,6 +193,13 @@ class AnonymousUser(AnonymousUserBase):
|
||||
return False
|
||||
|
||||
|
||||
class _SecurityState(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key.lower(), value)
|
||||
|
||||
|
||||
class Security(object):
|
||||
"""The :class:`Security` class initializes the Flask-Security extension.
|
||||
|
||||
@@ -196,7 +207,11 @@ class Security(object):
|
||||
:param datastore: An instance of a user datastore.
|
||||
"""
|
||||
def __init__(self, app=None, datastore=None, **kwargs):
|
||||
self.init_app(app, datastore, **kwargs)
|
||||
self.app = app
|
||||
self.datastore = datastore
|
||||
|
||||
if app is not None and datastore is not None:
|
||||
self.init_app(app, datastore, **kwargs)
|
||||
|
||||
def init_app(self, app, datastore, register_blueprint=True):
|
||||
"""Initializes the Flask-Security extension for the specified
|
||||
@@ -205,8 +220,6 @@ class Security(object):
|
||||
:param app: The application.
|
||||
:param datastore: An instance of a user datastore.
|
||||
"""
|
||||
if app is None or datastore is None:
|
||||
return
|
||||
|
||||
for key, value in _default_config.items():
|
||||
app.config.setdefault('SECURITY_' + key, value)
|
||||
@@ -214,18 +227,6 @@ class Security(object):
|
||||
for key, value in _default_flash_messages.items():
|
||||
app.config.setdefault('SECURITY_MSG_' + key, value)
|
||||
|
||||
self.datastore = datastore
|
||||
self.auth_provider = AuthenticationProvider()
|
||||
self.login_manager = _get_login_manager(app)
|
||||
self.principal = _get_principal(app)
|
||||
self.pwd_context = _get_pwd_context(app)
|
||||
self.reset_serializer = _get_reset_serializer(app)
|
||||
self.confirm_serializer = _get_confirm_serializer(app)
|
||||
self.token_auth_serializer = _get_token_auth_serializer(app)
|
||||
|
||||
for key, value in get_config(app).items():
|
||||
setattr(self, key.lower(), value)
|
||||
|
||||
identity_loaded.connect_via(app)(_on_identity_loaded)
|
||||
|
||||
if register_blueprint:
|
||||
@@ -234,13 +235,30 @@ class Security(object):
|
||||
url_prefix=cv('URL_PREFIX', app=app))
|
||||
app.register_blueprint(bp)
|
||||
|
||||
app.security = self
|
||||
if not hasattr(app, 'extensions'):
|
||||
app.extensions = {}
|
||||
|
||||
kwargs = {}
|
||||
for key, value in get_config(app).items():
|
||||
kwargs[key.lower()] = value
|
||||
|
||||
app.extensions['security'] = _SecurityState(
|
||||
app=app,
|
||||
datastore=datastore,
|
||||
auth_provider=AuthenticationProvider(),
|
||||
login_manager=_get_login_manager(app),
|
||||
principal=_get_principal(app),
|
||||
pwd_context=_get_pwd_context(app),
|
||||
reset_serializer=_get_reset_serializer(app),
|
||||
confirm_serializer=_get_confirm_serializer(app),
|
||||
token_auth_serializer=_get_token_auth_serializer(app),
|
||||
**kwargs)
|
||||
|
||||
|
||||
class AuthenticationProvider(object):
|
||||
"""The default authentication provider implementation."""
|
||||
def _get_user(self, username_or_email):
|
||||
datastore = current_app.security.datastore
|
||||
datastore = _security.datastore
|
||||
|
||||
try:
|
||||
return datastore.find_user(email=username_or_email)
|
||||
@@ -286,7 +304,7 @@ class AuthenticationProvider(object):
|
||||
raise exceptions.BadCredentialsError('Account requires confirmation')
|
||||
|
||||
# compare passwords
|
||||
if current_app.security.pwd_context.verify(password, user.password):
|
||||
if _security.pwd_context.verify(password, user.password):
|
||||
return user
|
||||
|
||||
# bad match
|
||||
|
||||
@@ -10,9 +10,13 @@
|
||||
"""
|
||||
|
||||
from flask import current_app
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
from . import exceptions, utils
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: current_app.extensions['security'])
|
||||
|
||||
|
||||
class UserDatastore(object):
|
||||
"""Abstracted user datastore. Always extend this class and implement the
|
||||
@@ -88,7 +92,7 @@ class UserDatastore(object):
|
||||
password = kwargs.get('password', None)
|
||||
|
||||
kwargs.setdefault('active', True)
|
||||
kwargs.setdefault('roles', current_app.security.default_roles)
|
||||
kwargs.setdefault('roles', _security.default_roles)
|
||||
|
||||
if email is None:
|
||||
raise exceptions.UserCreationError('Missing email argument')
|
||||
@@ -105,8 +109,9 @@ class UserDatastore(object):
|
||||
|
||||
kwargs['roles'] = roles
|
||||
|
||||
pwd_context = current_app.security.pwd_context
|
||||
pwd_context = _security.pwd_context
|
||||
pw = kwargs['password']
|
||||
|
||||
if not pwd_context.identify(pw):
|
||||
kwargs['password'] = pwd_context.encrypt(pw)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ from .exceptions import UserNotFoundError
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: current_app.security)
|
||||
_security = LocalProxy(lambda: current_app.extensions['security'])
|
||||
|
||||
_logger = LocalProxy(lambda: current_app.logger)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ from .exceptions import UserNotFoundError
|
||||
|
||||
|
||||
# Convenient reference
|
||||
_datastore = LocalProxy(lambda: app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: app.extensions['security'].datastore)
|
||||
|
||||
|
||||
def valid_user_email(form, field):
|
||||
|
||||
@@ -20,9 +20,9 @@ from .utils import send_mail, get_max_age, md5, get_message
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: app.security)
|
||||
_security = LocalProxy(lambda: app.extensions['security'])
|
||||
|
||||
_datastore = LocalProxy(lambda: app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: _security.datastore)
|
||||
|
||||
|
||||
def send_reset_password_instructions(user, reset_token):
|
||||
|
||||
@@ -15,7 +15,7 @@ from werkzeug.local import LocalProxy
|
||||
from flask_security import views
|
||||
|
||||
|
||||
_datastore = LocalProxy(lambda: current_app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
|
||||
|
||||
|
||||
def pprint(obj):
|
||||
|
||||
@@ -16,9 +16,9 @@ from .utils import md5
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: app.security)
|
||||
_security = LocalProxy(lambda: app.extensions['security'])
|
||||
|
||||
_datastore = LocalProxy(lambda: app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: _security.datastore)
|
||||
|
||||
|
||||
def generate_authentication_token(user):
|
||||
|
||||
@@ -17,10 +17,15 @@ from datetime import datetime, timedelta
|
||||
|
||||
from flask import url_for, flash, current_app, request, session, render_template
|
||||
from flask.ext.login import make_secure_token
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
from .signals import user_registered, password_reset_requested
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: current_app.extensions['security'])
|
||||
|
||||
|
||||
def md5(data):
|
||||
return hashlib.md5(data).hexdigest()
|
||||
|
||||
@@ -150,7 +155,7 @@ def send_mail(subject, recipient, template, context=None):
|
||||
context = context or {}
|
||||
|
||||
msg = Message(subject,
|
||||
sender=current_app.security.email_sender,
|
||||
sender=_security.email_sender,
|
||||
recipients=[recipient])
|
||||
|
||||
base = 'security/email'
|
||||
|
||||
@@ -33,9 +33,9 @@ from flask_security.utils import get_url, get_post_login_redirect, do_flash, \
|
||||
|
||||
|
||||
# Convenient references
|
||||
_security = LocalProxy(lambda: app.security)
|
||||
_security = LocalProxy(lambda: app.extensions['security'])
|
||||
|
||||
_datastore = LocalProxy(lambda: app.security.datastore)
|
||||
_datastore = LocalProxy(lambda: _security.datastore)
|
||||
|
||||
_logger = LocalProxy(lambda: app.logger)
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ class ExpiredConfirmationTest(SecurityTest):
|
||||
self.assertIn(e, outbox[0].html)
|
||||
self.assertNotIn(token, outbox[0].html)
|
||||
|
||||
expire_text = self.app.security.confirm_email_within
|
||||
expire_text = self.AUTH_CONFIG['SECURITY_CONFIRM_EMAIL_WITHIN']
|
||||
text = 'You did not confirm your account within %s' % expire_text
|
||||
|
||||
self.assertIn(text, r.data)
|
||||
|
||||
Reference in New Issue
Block a user