No need to store remember_token in DB

This commit is contained in:
Matt Wright
2012-08-14 13:52:30 -04:00
parent f6bb01545d
commit 58e2856612
5 changed files with 34 additions and 35 deletions
+2 -2
View File
@@ -123,6 +123,7 @@ def create_sqlalchemy_app(auth_config=None, register_blueprint=True):
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root@localhost/flask_security_test'
db = SQLAlchemy(app)
app.db = db
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
@@ -137,7 +138,6 @@ def create_sqlalchemy_app(auth_config=None, register_blueprint=True):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
remember_token = db.Column(db.String(255))
last_login_at = db.Column(db.DateTime())
current_login_at = db.Column(db.DateTime())
last_login_ip = db.Column(db.String(100))
@@ -173,6 +173,7 @@ def create_mongoengine_app(auth_config=None):
app.config['MONGODB_PORT'] = 27017
db = MongoEngine(app)
app.db = db
class Role(db.Document, RoleMixin):
name = db.StringField(required=True, unique=True, max_length=80)
@@ -181,7 +182,6 @@ def create_mongoengine_app(auth_config=None):
class User(db.Document, UserMixin):
email = db.StringField(unique=True, max_length=255)
password = db.StringField(required=True, max_length=255)
remember_token = db.StringField(max_length=255)
last_login_at = db.DateTimeField()
current_login_at = db.DateTimeField()
last_login_ip = db.StringField(max_length=100)
-6
View File
@@ -73,9 +73,6 @@ def confirm_by_token(token):
data = serializer.loads(token, max_age=max_age)
user = _datastore.find_user(id=data[0])
if md5(user.email) != data[1]:
raise UserNotFoundError()
if user.confirmed_at:
raise ConfirmationError(get_message('ALREADY_CONFIRMED'))
@@ -94,9 +91,6 @@ def confirm_by_token(token):
except BadSignature:
raise ConfirmationError(get_message('INVALID_CONFIRMATION_TOKEN'))
except UserNotFoundError:
raise ConfirmationError(get_message('INVALID_CONFIRMATION_TOKEN'))
def reset_confirmation_token(user):
"""Resets the specified user's confirmation token and sends the user
+14 -15
View File
@@ -21,7 +21,7 @@ from werkzeug.local import LocalProxy
from . import views, exceptions
from .confirmable import requires_confirmation
from .utils import config_value as cv, get_config, verify_password
from .utils import config_value as cv, get_config, verify_password, md5
# Convenient references
_security = LocalProxy(lambda: current_app.extensions['security'])
@@ -62,6 +62,7 @@ _default_config = {
'CONFIRM_SALT': 'confirm-salt',
'RESET_SALT': 'reset-salt',
'AUTH_SALT': 'auth-salt',
'REMEMBER_SALT': 'remember-salt',
'DEFAULT_HTTP_AUTH_REALM': 'Login Required'
}
@@ -81,17 +82,16 @@ _default_flash_messages = {
def _user_loader(user_id):
try:
return _security.datastore.with_id(user_id)
except Exception, e:
current_app.logger.error('Error getting user: %s' % e)
return _security.datastore.find_user(id=user_id)
except:
return None
def _token_loader(token):
try:
return _security.datastore.find_user(remember_token=token)
except Exception, e:
current_app.logger.error('Error getting user: %s' % e)
data = _security.remember_token_serializer.loads(token)
return _security.datastore.find_user(email=md5(data[0]))
except:
return None
@@ -137,6 +137,10 @@ def _get_serializer(app, salt):
return URLSafeTimedSerializer(secret_key=secret_key, salt=salt)
def _get_remember_token_serializer(app):
return _get_serializer(app, app.config['SECURITY_REMEMBER_SALT'])
def _get_reset_serializer(app):
return _get_serializer(app, app.config['SECURITY_RESET_SALT'])
@@ -157,9 +161,6 @@ class RoleMixin(object):
def __ne__(self, other):
return self.name != other and self.name != getattr(other, 'name', None)
def __str__(self):
return '<Role name=%s>' % self.name
class UserMixin(BaseUserMixin):
"""Mixin for `User` model definitions"""
@@ -170,7 +171,8 @@ class UserMixin(BaseUserMixin):
def get_auth_token(self):
"""Returns the user's authentication token."""
self.remember_token
data = [md5(self.email), self.password]
return _security.remember_token_serializer.dumps(data)
def has_role(self, role):
"""Returns `True` if the user identifies with the specified role.
@@ -178,10 +180,6 @@ class UserMixin(BaseUserMixin):
:param role: A role name or `Role` instance"""
return role in self.roles
def __str__(self):
ctx = (str(self.id), self.email)
return '<User id=%s, email=%s>' % ctx
class AnonymousUser(AnonymousUserBase):
"""AnonymousUser definition"""
@@ -262,6 +260,7 @@ class Security(object):
('login_manager', _get_login_manager(app)),
('principal', _get_principal(app)),
('pwd_context', _get_pwd_context(app)),
('remember_token_serializer', _get_remember_token_serializer(app)),
('token_auth_serializer', _get_token_auth_serializer(app))]:
kwargs[key] = value
+18 -3
View File
@@ -37,6 +37,10 @@ class UserDatastore(object):
raise NotImplementedError(
"User datastore does not implement _save_model method")
def _delete_model(self, model):
raise NotImplementedError(
"User datastore does not implement _delete_model method")
def _do_with_id(self, id):
raise NotImplementedError(
"User datastore does not implement _do_with_id method")
@@ -118,9 +122,6 @@ class UserDatastore(object):
use_hmac=_security.password_hmac)
kwargs['password'] = pwd_hash
kwargs['remember_token'] = utils.get_remember_token(kwargs['email'],
kwargs['password'])
return kwargs
def with_id(self, id):
@@ -170,6 +171,13 @@ class UserDatastore(object):
user = self.user_model(**self._prepare_create_user_args(kwargs))
return self._save_model(user)
def delete_user(self, user):
"""Delete the specified user
:param user: The user to delete_user
"""
self._delete_model(user)
def add_role_to_user(self, user, role):
"""Adds a role to a user if the user does not have it already. Returns
the modified user.
@@ -248,6 +256,10 @@ class SQLAlchemyUserDatastore(UserDatastore):
self.db.session.commit()
return model
def _delete_model(self, model):
self.db.session.delete(model)
self.db.session.commit()
def _do_with_id(self, id):
return self.user_model.query.get(id)
@@ -292,6 +304,9 @@ class MongoEngineUserDatastore(UserDatastore):
model.save()
return model
def _delete_model(self, model):
model.delete()
def _do_with_id(self, id):
try:
return self.user_model.objects.get(id=id)
-9
View File
@@ -44,9 +44,6 @@ def login_user(user, remember=True):
if user.authentication_token is None:
user.authentication_token = generate_authentication_token(user)
if remember:
user.remember_token = get_remember_token(user.email, user.password)
if _security.trackable:
old_current, new_current = user.current_login_at, datetime.utcnow()
user.last_login_at = old_current or new_current
@@ -110,12 +107,6 @@ def generate_token():
return base64.urlsafe_b64encode(os.urandom(30))
def get_remember_token(email, password):
assert email is not None
assert password is not None
return make_secure_token(email, password)
def do_flash(message, category=None):
"""Flash a message depending on if the `FLASH_MESSAGES` configuration
value is set.