Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/mattupstate/flask-security
Browse files Browse the repository at this point in the history
… into develop
  • Loading branch information
covertgeek committed Jul 6, 2015
2 parents d65c3ca + cbd0db7 commit 17a79ed
Show file tree
Hide file tree
Showing 29 changed files with 295 additions and 118 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,13 @@ env/

*.db
*cache*

# vim
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~

.eggs/README.txt
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ Rotem Yaari
Srijan Choudhary
Tristan Escalada
Vadim Kotov
Walt Askew
33 changes: 14 additions & 19 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,43 +87,38 @@ sends the following signals.

.. data:: user_registered

Sent when a user registers on the site. It is passed a dict with
the `user` and `confirm_token`, the user being logged in and the
(if so configured) the confirmation token issued.
Sent when a user registers on the site. In addition to the app (which is the
sender), it is passed `user` and `confirm_token` arguments.

.. data:: user_confirmed

Sent when a user is confirmed. It is passed `user`, which is the
user being confirmed.
Sent when a user is confirmed. In addition to the app (which is the
sender), it is passed a `user` argument.

.. data:: confirm_instructions_sent

Sent when a user requests confirmation instructions. It is passed
the `user`.
Sent when a user requests confirmation instructions. In addition to the app
(which is the sender), it is passed a `user` argument.

.. data:: login_instructions_sent

Sent when passwordless login is used and user logs in. It is passed
a dict with the `user` and `login_token`, the user being logged in
and the (if so configured) the login token issued.
Sent when passwordless login is used and user logs in. In addition to the app
(which is the sender), it is passed `user` and `login_token` arguments.

.. data:: password_reset

Sent when a user completes a password reset. It is passed the
`user`.
Sent when a user completes a password reset. In addition to the app (which is
the sender), it is passed a `user` argument.

.. data:: password_changed

Sent when a user completes a password change. It is passed the
`user`.
Sent when a user completes a password change. In addition to the app (which is
the sender), it is passed a `user` argument.

.. data:: reset_password_instructions_sent

Sent when a user requests a password reset. It is passed a dict
with the `user` and `token`, the user being logged in and
the (if so configured) the reset token issued.
Sent when a user requests a password reset. In addition to the app (which is
the sender), it is passed `user` and `token` arguments.

All signals are also passed a `app` keyword argument, which is the
current application.

.. _Flask documentation on signals: http://flask.pocoo.org/docs/signals/
14 changes: 11 additions & 3 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,27 @@ Core
passwords. Recommended values for
production systems are ``bcrypt``,
``sha512_crypt``, or ``pbkdf2_sha512``.
Defaults to ``plaintext``.
Defaults to ``plaintext``. Note:
``bcrypt>=2.0.0`` is not currently
supported. If ``bcrypt`` is preferred,
please use ``bcrypt<2.0``.
``SECURITY_PASSWORD_SALT`` Specifies the HMAC salt. This is only
used if the password hash type is set
to something other than plain text.
Defaults to ``None``.
``SECURITY_EMAIL_SENDER`` Specifies the email address to send
emails as. Defaults to
``no-reply@localhost``.
``SECURITY_TOKEN_AUTHENTICATION_KEY`` Specifies the query sting parameter to
``SECURITY_TOKEN_AUTHENTICATION_KEY`` Specifies the query string parameter to
read when using token authentication.
Defaults to ``auth_token``.
``SECURITY_TOKEN_AUTHENTICATION_HEADER`` Specifies the HTTP header to read when
using token authentication. Defaults to
``Authentication-Token``.
``SECURITY_TOKEN_MAX_AGE`` Specifies the number of seconds before
an authentication token expires.
Defaults to None, meaning the token
never expires.
``SECURITY_DEFAULT_HTTP_AUTH_REALM`` Specifies the default authentication
realm when using basic HTTP auth.
Defaults to ``Login Required``
Expand Down Expand Up @@ -159,7 +166,8 @@ Feature Flags
option. Defaults to ``False``.
``SECURITY_TRACKABLE`` Specifies if Flask-Security should track basic user
login statistics. If set to ``True``, ensure your
models have the required fields/attribues. Defaults to
models have the required fields/attribues. Be sure to
use `ProxyFix <http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#proxy-setups>` if you are using a proxy. Defaults to
``False``
``SECURITY_PASSWORDLESS`` Specifies if Flask-Security should enable the
passwordless login feature. If set to ``True``, users
Expand Down
4 changes: 2 additions & 2 deletions docs/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ register form or override validators::
from flask_security.forms import RegisterForm

class ExtendedRegisterForm(RegisterForm):
first_name = TextField('First Name', [Required()])
last_name = TextField('Last Name', [Required()])
first_name = StringField('First Name', [Required()])
last_name = StringField('Last Name', [Required()])

security = Security(app, user_datastore,
register_form=ExtendedRegisterForm)
Expand Down
8 changes: 4 additions & 4 deletions flask_security/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
flask.ext.security
~~~~~~~~~~~~~~~~~~
flask_security
~~~~~~~~~~~~~~
Flask-Security is a Flask extension that aims to add quick and simple
security via Flask-Login, Flask-Principal, Flask-WTF, and passlib.
Expand All @@ -10,8 +10,6 @@
:license: MIT, see LICENSE for more details.
"""

__version__ = '1.7.4'

from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
from .decorators import auth_token_required, http_auth_required, \
Expand All @@ -21,3 +19,5 @@
from .signals import confirm_instructions_sent, password_reset, \
reset_password_instructions_sent, user_confirmed, user_registered
from .utils import login_user, logout_user, url_for_security

__version__ = '1.7.4'
7 changes: 4 additions & 3 deletions flask_security/changeable.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
flask.ext.security.changeable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
flask_security.changeable
~~~~~~~~~~~~~~~~~~~~~~~~~
Flask-Security recoverable module
Expand Down Expand Up @@ -42,4 +42,5 @@ def change_user_password(user, password):
user.password = encrypt_password(password)
_datastore.put(user)
send_password_changed_notice(user)
password_changed.send(app._get_current_object(), user=user)
password_changed.send(app._get_current_object(),
user=user._get_current_object())
4 changes: 2 additions & 2 deletions flask_security/confirmable.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
flask.ext.security.confirmable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
flask_security.confirmable
~~~~~~~~~~~~~~~~~~~~~~~~~~
Flask-Security confirmable module
Expand Down
35 changes: 21 additions & 14 deletions flask_security/core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
flask.ext.security.core
~~~~~~~~~~~~~~~~~~~~~~~
flask_security.core
~~~~~~~~~~~~~~~~~~~
Flask-Security core module
Expand All @@ -10,9 +10,9 @@
"""

from flask import current_app, render_template
from flask.ext.login import AnonymousUserMixin, UserMixin as BaseUserMixin, \
from flask_login import AnonymousUserMixin, UserMixin as BaseUserMixin, \
LoginManager, current_user
from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \
from flask_principal import Principal, RoleNeed, UserNeed, Identity, \
identity_loaded
from itsdangerous import URLSafeTimedSerializer
from passlib.context import CryptContext
Expand Down Expand Up @@ -75,6 +75,7 @@
'EMAIL_SENDER': 'no-reply@localhost',
'TOKEN_AUTHENTICATION_KEY': 'auth_token',
'TOKEN_AUTHENTICATION_HEADER': 'Authentication-Token',
'TOKEN_MAX_AGE': None,
'CONFIRM_SALT': 'confirm-salt',
'RESET_SALT': 'reset-salt',
'LOGIN_SALT': 'login-salt',
Expand Down Expand Up @@ -192,17 +193,17 @@ def _user_loader(user_id):

def _token_loader(token):
try:
data = _security.remember_token_serializer.loads(token)
data = _security.remember_token_serializer.loads(token, max_age=_security.token_max_age)
user = _security.datastore.find_user(id=data[0])
if user and safe_str_cmp(md5(user.password), data[1]):
return user
except:
pass
return AnonymousUser()
return _security.login_manager.anonymous_user()


def _identity_loader():
if not isinstance(current_user._get_current_object(), AnonymousUser):
if not isinstance(current_user._get_current_object(), AnonymousUserMixin):
identity = Identity(current_user.id)
return identity

Expand All @@ -217,9 +218,9 @@ def _on_identity_loaded(sender, identity):
identity.user = current_user


def _get_login_manager(app):
def _get_login_manager(app, anonymous_user):
lm = LoginManager()
lm.anonymous_user = AnonymousUser
lm.anonymous_user = anonymous_user or AnonymousUser
lm.login_view = '%s.login' % cv('BLUEPRINT_NAME', app=app)
lm.user_loader(_user_loader)
lm.token_loader(_token_loader)
Expand Down Expand Up @@ -257,22 +258,23 @@ def _get_serializer(app, name):
return URLSafeTimedSerializer(secret_key=secret_key, salt=salt)


def _get_state(app, datastore, **kwargs):
def _get_state(app, datastore, anonymous_user=None, **kwargs):
for key, value in get_config(app).items():
kwargs[key.lower()] = value

kwargs.update(dict(
app=app,
datastore=datastore,
login_manager=_get_login_manager(app),
login_manager=_get_login_manager(app, anonymous_user),
principal=_get_principal(app),
pwd_context=_get_pwd_context(app),
remember_token_serializer=_get_serializer(app, 'remember'),
login_serializer=_get_serializer(app, 'login'),
reset_serializer=_get_serializer(app, 'reset'),
confirm_serializer=_get_serializer(app, 'confirm'),
_context_processors={},
_send_mail_task=None
_send_mail_task=None,
_unauthorized_callback=None
))

for key, value in _default_forms.items():
Expand Down Expand Up @@ -380,6 +382,9 @@ def mail_context_processor(self, fn):
def send_mail_task(self, fn):
self._send_mail_task = fn

def unauthorized_handler(self, fn):
self._unauthorized_callback = fn


class Security(object):
"""The :class:`Security` class initializes the Flask-Security extension.
Expand All @@ -398,7 +403,8 @@ def init_app(self, app, datastore=None, register_blueprint=True,
login_form=None, confirm_register_form=None,
register_form=None, forgot_password_form=None,
reset_password_form=None, change_password_form=None,
send_confirmation_form=None, passwordless_login_form=None):
send_confirmation_form=None, passwordless_login_form=None,
anonymous_user=None):
"""Initializes the Flask-Security extension for the specified
application and datastore implentation.
Expand All @@ -424,7 +430,8 @@ def init_app(self, app, datastore=None, register_blueprint=True,
reset_password_form=reset_password_form,
change_password_form=change_password_form,
send_confirmation_form=send_confirmation_form,
passwordless_login_form=passwordless_login_form)
passwordless_login_form=passwordless_login_form,
anonymous_user=anonymous_user)

if register_blueprint:
app.register_blueprint(create_blueprint(state, __name__))
Expand Down
6 changes: 3 additions & 3 deletions flask_security/datastore.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
flask.ext.security.datastore
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
flask_security.datastore
~~~~~~~~~~~~~~~~~~~~~~~~
This module contains an user datastore classes.
Expand Down Expand Up @@ -195,7 +195,7 @@ def get_user(self, identifier):
def _is_numeric(self, value):
try:
int(value)
except ValueError:
except (TypeError, ValueError):
return False
return True

Expand Down
Loading

0 comments on commit 17a79ed

Please sign in to comment.