Compare commits

...
17 Commits
Author SHA1 Message Date
Matt Wright 3d34d87a97 Bump version number to 1.6.4 2013-06-18 15:00:41 -04:00
Matt Wright 461ace9303 Update docs 2013-06-18 15:00:34 -04:00
Matt Wright d19bb98abd Version 1.6.4 changes. Refer to CHANGES for updates. Fixes #123 #121 #120 $119 2013-06-18 14:56:12 -04:00
Matt Wright c24af5ca6e Whitespace! 2013-05-28 11:11:37 -04:00
Matt Wright 26045fc4dc Use the _external parameter when generating links for emails 2013-05-28 11:11:19 -04:00
Matt Wright bf260d4b7e Add optional next parameter to registration endpoint. Fixes #117. 2013-05-28 11:01:42 -04:00
Matt Wright db56ff74a9 Bump version number to 1.6.3 2013-05-08 12:29:48 -04:00
Matt Wright e03efe0b34 Update CHANGES 2013-05-08 12:29:35 -04:00
Matt Wright c587988a3a Merge branch 'develop' of github.com:mattupstate/flask-security into develop 2013-05-03 12:14:14 -04:00
Matt Wright f2d5245bd8 Import check to account for new version of MongoEngine 2013-05-03 12:13:58 -04:00
Matt Wright 97e1960abd Merge pull request #112 from poundifdef/login_flash
Make flask-login respect SECURITY_FLASH_MESSAGES
2013-04-14 13:40:57 -07:00
Jay Goel e749b77ca7 Make flask-login respect SECURITY_FLASH_MESSAGES 2013-04-14 16:37:23 -04:00
Matt Wright 6f3c163ee7 Merge pull request #111 from joshpurvis/issue110
Changed has_role to accept strings with mongoengine. Fixes #110
2013-04-14 10:05:34 -07:00
Josh Purvis 3b81ec57ea Changed has_role to accept strings with mongoengine. Fixes #110 2013-04-13 15:11:56 -04:00
Matt Wright 38874433c7 Add tests for Peewee support 2013-04-04 18:09:55 -04:00
Matt Wright 4eda3e756f PEP8 polish 2013-04-04 16:39:50 -04:00
Matt Wright 4815b1afed Make find_user method for MongoEngineUserDatastore add contraints to query 2013-04-04 15:50:46 -04:00
20 changed files with 140 additions and 81 deletions
+19
View File
@@ -3,6 +3,25 @@ Flask-Security Changelog
Here you can see the full list of changes between each Flask-Security release. Here you can see the full list of changes between each Flask-Security release.
Version 1.6.4
-------------
Released June 18th 2013
- Added `SECURITY_DEFAULT_REMEMBER_ME` configuration value to unify behavior between endpoints
- Fixed Flask-Login dependency problem
- Added optional `next` parameter to registration endpoint, similar to that of login
Version 1.6.3
-------------
Released May 8th 2013
- Fixed bug in regards to imports with latest version of MongoEngine
Version 1.6.2 Version 1.6.2
------------- -------------
+1 -1
View File
@@ -49,7 +49,7 @@ copyright = u'2012, Matt Wright'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '1.6.2' version = '1.6.4'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version release = version
+3
View File
@@ -220,4 +220,7 @@ Miscellaneous
remember tokens. Remember tokens are remember tokens. Remember tokens are
used instead of user ID's as it is more used instead of user ID's as it is more
secure. Defaults to ``remember-salt``. secure. Defaults to ``remember-salt``.
``SECURITY_DEFAULT_REMEMBER_ME`` Specifies the default "remember me"
value used when logging in a user.
Defaults to ``False``.
======================================= ======================================== ======================================= ========================================
+1 -1
View File
@@ -10,7 +10,7 @@
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
__version__ = '1.6.2' __version__ = '1.6.4'
from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
+1 -2
View File
@@ -14,8 +14,7 @@ from flask import current_app as app, request
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from .signals import password_changed from .signals import password_changed
from .utils import send_mail, encrypt_password, url_for_security, \ from .utils import send_mail, encrypt_password, config_value
config_value
# Convenient references # Convenient references
+2 -3
View File
@@ -15,7 +15,7 @@ from flask import current_app as app, request
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from .utils import send_mail, md5, url_for_security, get_token_status,\ from .utils import send_mail, md5, url_for_security, get_token_status,\
config_value config_value
from .signals import user_confirmed, confirm_instructions_sent from .signals import user_confirmed, confirm_instructions_sent
@@ -27,8 +27,7 @@ _datastore = LocalProxy(lambda: _security.datastore)
def generate_confirmation_link(user): def generate_confirmation_link(user):
token = generate_confirmation_token(user) token = generate_confirmation_token(user)
url = url_for_security('confirm_email', token=token) return url_for_security('confirm_email', token=token, _extenal=True), token
return request.url_root[:-1] + url, token
def send_confirmation_instructions(user): def send_confirmation_instructions(user):
+21 -14
View File
@@ -10,10 +10,10 @@
""" """
from flask import current_app from flask import current_app
from flask.ext.login import AnonymousUser as AnonymousUserBase, \ from flask.ext.login import AnonymousUserMixin, UserMixin as BaseUserMixin, \
UserMixin as BaseUserMixin, LoginManager, current_user LoginManager, current_user
from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \ from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \
identity_loaded identity_loaded
from itsdangerous import URLSafeTimedSerializer from itsdangerous import URLSafeTimedSerializer
from passlib.context import CryptContext from passlib.context import CryptContext
from werkzeug.datastructures import ImmutableList from werkzeug.datastructures import ImmutableList
@@ -22,8 +22,8 @@ from werkzeug.local import LocalProxy
from .utils import config_value as cv, get_config, md5, url_for_security from .utils import config_value as cv, get_config, md5, url_for_security
from .views import create_blueprint from .views import create_blueprint
from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \ from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \
ForgotPasswordForm, ChangePasswordForm, ResetPasswordForm, \ ForgotPasswordForm, ChangePasswordForm, ResetPasswordForm, \
SendConfirmationForm, PasswordlessLoginForm SendConfirmationForm, PasswordlessLoginForm
# Convenient references # Convenient references
_security = LocalProxy(lambda: current_app.extensions['security']) _security = LocalProxy(lambda: current_app.extensions['security'])
@@ -76,6 +76,7 @@ _default_config = {
'LOGIN_SALT': 'login-salt', 'LOGIN_SALT': 'login-salt',
'CHANGE_SALT': 'change-salt', 'CHANGE_SALT': 'change-salt',
'REMEMBER_SALT': 'remember-salt', 'REMEMBER_SALT': 'remember-salt',
'DEFAULT_REMEMBER_ME': False,
'DEFAULT_HTTP_AUTH_REALM': 'Login Required', 'DEFAULT_HTTP_AUTH_REALM': 'Login Required',
'EMAIL_SUBJECT_REGISTER': 'Welcome', 'EMAIL_SUBJECT_REGISTER': 'Welcome',
'EMAIL_SUBJECT_CONFIRM': 'Please confirm your email', 'EMAIL_SUBJECT_CONFIRM': 'Please confirm your email',
@@ -153,8 +154,7 @@ def _token_loader(token):
return user return user
except: except:
pass pass
return AnonymousUser()
return None
def _identity_loader(): def _identity_loader():
@@ -179,8 +179,14 @@ def _get_login_manager(app):
lm.login_view = '%s.login' % cv('BLUEPRINT_NAME', app=app) lm.login_view = '%s.login' % cv('BLUEPRINT_NAME', app=app)
lm.user_loader(_user_loader) lm.user_loader(_user_loader)
lm.token_loader(_token_loader) lm.token_loader(_token_loader)
lm.login_message, lm.login_message_category = cv('MSG_LOGIN', app=app)
lm.needs_refresh_message, lm.needs_refresh_message_category = cv('MSG_REFRESH', app=app) if cv('FLASH_MESSAGES', app=app):
lm.login_message, lm.login_message_category = cv('MSG_LOGIN', app=app)
lm.needs_refresh_message, lm.needs_refresh_message_category = cv('MSG_REFRESH', app=app)
else:
lm.login_message = None
lm.needs_refresh_message = None
lm.init_app(app) lm.init_app(app)
return lm return lm
@@ -241,8 +247,7 @@ class RoleMixin(object):
self.name == getattr(other, 'name', None)) self.name == getattr(other, 'name', None))
def __ne__(self, other): def __ne__(self, other):
return (self.name != other and return not self.__eq__(other)
self.name != getattr(other, 'name', None))
class UserMixin(BaseUserMixin): class UserMixin(BaseUserMixin):
@@ -261,14 +266,16 @@ class UserMixin(BaseUserMixin):
"""Returns `True` if the user identifies with the specified role. """Returns `True` if the user identifies with the specified role.
:param role: A role name or `Role` instance""" :param role: A role name or `Role` instance"""
return role in self.roles if isinstance(role, basestring):
return role in (role.name for role in self.roles)
else:
return role in self.roles
class AnonymousUser(AnonymousUserBase): class AnonymousUser(AnonymousUserMixin):
"""AnonymousUser definition""" """AnonymousUser definition"""
def __init__(self): def __init__(self):
super(AnonymousUser, self).__init__()
self.roles = ImmutableList() self.roles = ImmutableList()
def has_role(self, *args): def has_role(self, *args):
+20 -14
View File
@@ -95,12 +95,11 @@ class UserDatastore(object):
:param user: The user to manipulate :param user: The user to manipulate
:param role: The role to add to the user :param role: The role to add to the user
""" """
rv = False
user, role = self._prepare_role_modify_args(user, role) user, role = self._prepare_role_modify_args(user, role)
if role not in user.roles: if role not in user.roles:
rv = True
user.roles.append(role) user.roles.append(role)
return rv return True
return False
def remove_role_from_user(self, user, role): def remove_role_from_user(self, user, role):
"""Removes a role from a user """Removes a role from a user
@@ -191,7 +190,14 @@ class MongoEngineUserDatastore(MongoEngineDatastore, UserDatastore):
UserDatastore.__init__(self, user_model, role_model) UserDatastore.__init__(self, user_model, role_model)
def find_user(self, **kwargs): def find_user(self, **kwargs):
return self.user_model.objects(**kwargs).first() try:
from mongoengine.queryset import Q, QCombination
except ImportError:
from mongoengine.queryset.visitor import Q, QCombination
queries = map(lambda i: Q(**{i[0]: i[1]}), kwargs.items())
query = QCombination(QCombination.AND, queries)
return self.user_model.objects(query).first()
def find_role(self, role): def find_role(self, role):
return self.role_model.objects(name=role).first() return self.role_model.objects(name=role).first()
@@ -217,10 +223,7 @@ class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
return None return None
def find_role(self, role): def find_role(self, role):
try: return self.role_model.filter(name=role).get()
return self.role_model.filter(name=role).get()
except self.role_model.DoesNotExist:
return None
def create_user(self, **kwargs): def create_user(self, **kwargs):
"""Creates and returns a new user from the given parameters.""" """Creates and returns a new user from the given parameters."""
@@ -231,7 +234,6 @@ class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
self.add_role_to_user(user, role) self.add_role_to_user(user, role)
return user return user
def add_role_to_user(self, user, role): def add_role_to_user(self, user, role):
"""Adds a role tp a user """Adds a role tp a user
@@ -239,10 +241,12 @@ class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
:param role: The role to add to the user :param role: The role to add to the user
""" """
user, role = self._prepare_role_modify_args(user, role) user, role = self._prepare_role_modify_args(user, role)
if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count(): result = self.UserRole.select() \
.where(self.UserRole.user == user.id, self.UserRole.role == role.id)
if result.count():
return False return False
else: else:
self.UserRole.create(user=user, role=role) self.UserRole.create(user=user.id, role=role.id)
return True return True
def remove_role_from_user(self, user, role): def remove_role_from_user(self, user, role):
@@ -252,9 +256,11 @@ class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
:param role: The role to remove from the user :param role: The role to remove from the user
""" """
user, role = self._prepare_role_modify_args(user, role) user, role = self._prepare_role_modify_args(user, role)
if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count(): result = self.UserRole.select() \
self.UserRole.delete().where(self.UserRole.user==user, self.UserRole.role==role) .where(self.UserRole.user == user, self.UserRole.role == role)
if result.count():
self.UserRole.delete().where(
self.UserRole.user == user, self.UserRole.role == role)
return True return True
else: else:
return False return False
+1 -1
View File
@@ -16,7 +16,7 @@ import flask_wtf as wtf
from flask import request, current_app from flask import request, current_app
from flask_wtf import Form as BaseForm, TextField, PasswordField, \ from flask_wtf import Form as BaseForm, TextField, PasswordField, \
SubmitField, HiddenField, BooleanField, ValidationError, Field SubmitField, HiddenField, BooleanField, ValidationError, Field
from flask_login import current_user from flask_login import current_user
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
+2 -3
View File
@@ -14,7 +14,7 @@ from werkzeug.local import LocalProxy
from .signals import login_instructions_sent from .signals import login_instructions_sent
from .utils import send_mail, url_for_security, get_token_status, \ from .utils import send_mail, url_for_security, get_token_status, \
config_value config_value
# Convenient references # Convenient references
@@ -30,8 +30,7 @@ def send_login_instructions(user):
:param token: The login token :param token: The login token
""" """
token = generate_login_token(user) token = generate_login_token(user)
url = url_for_security('token_login', token=token) login_link = url_for_security('token_login', token=token, _external=True)
login_link = request.url_root[:-1] + url
send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email, send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email,
'login_instructions', user=user, login_link=login_link) 'login_instructions', user=user, login_link=login_link)
+2 -3
View File
@@ -14,7 +14,7 @@ from werkzeug.local import LocalProxy
from .signals import password_reset, reset_password_instructions_sent from .signals import password_reset, reset_password_instructions_sent
from .utils import send_mail, md5, encrypt_password, url_for_security, \ from .utils import send_mail, md5, encrypt_password, url_for_security, \
get_token_status, config_value get_token_status, config_value
# Convenient references # Convenient references
@@ -29,8 +29,7 @@ def send_reset_password_instructions(user):
:param user: The user to send the instructions to :param user: The user to send the instructions to
""" """
token = generate_reset_password_token(user) token = generate_reset_password_token(user)
url = url_for_security('reset_password', token=token) reset_link = url_for_security('reset_password', token=token, _external=True)
reset_link = request.url_root[:-1] + url
send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'), user.email, send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'), user.email,
'reset_instructions', 'reset_instructions',
+1 -1
View File
@@ -15,7 +15,7 @@ from werkzeug.local import LocalProxy
from .confirmable import generate_confirmation_link from .confirmable import generate_confirmation_link
from .signals import user_registered from .signals import user_registered
from .utils import do_flash, get_message, send_mail, encrypt_password, \ from .utils import do_flash, get_message, send_mail, encrypt_password, \
config_value config_value
# Convenient references # Convenient references
_security = LocalProxy(lambda: app.extensions['security']) _security = LocalProxy(lambda: app.extensions['security'])
+16 -5
View File
@@ -14,12 +14,13 @@ import blinker
import functools import functools
import hashlib import hashlib
import hmac import hmac
from contextlib import contextmanager from contextlib import contextmanager
from datetime import datetime, timedelta from datetime import datetime, timedelta
from flask import url_for, flash, current_app, request, session, render_template from flask import url_for, flash, current_app, request, session, render_template
from flask.ext.login import login_user as _login_user, \ from flask.ext.login import login_user as _login_user, \
logout_user as _logout_user logout_user as _logout_user
from flask.ext.mail import Message from flask.ext.mail import Message
from flask.ext.principal import Identity, AnonymousIdentity, identity_changed from flask.ext.principal import Identity, AnonymousIdentity, identity_changed
from itsdangerous import BadSignature, SignatureExpired from itsdangerous import BadSignature, SignatureExpired
@@ -37,9 +38,12 @@ _datastore = LocalProxy(lambda: _security.datastore)
_pwd_context = LocalProxy(lambda: _security.pwd_context) _pwd_context = LocalProxy(lambda: _security.pwd_context)
def login_user(user, remember=True): def login_user(user, remember=None):
"""Performs the login and sends the appropriate signal.""" """Performs the login and sends the appropriate signal."""
if remember is None:
remember = config_value('DEFAULT_REMEMBER_ME')
if not _login_user(user, remember): if not _login_user(user, remember):
return False return False
@@ -144,11 +148,18 @@ def url_for_security(endpoint, **values):
return url_for(endpoint, **values) return url_for(endpoint, **values)
def get_post_login_redirect(): def get_post_action_redirect(config_key):
"""Returns the URL to redirect to after a user logs in successfully."""
return (get_url(request.args.get('next')) or return (get_url(request.args.get('next')) or
get_url(request.form.get('next')) or get_url(request.form.get('next')) or
find_redirect('SECURITY_POST_LOGIN_VIEW')) find_redirect(config_key))
def get_post_login_redirect():
return get_post_action_redirect('SECURITY_POST_LOGIN_VIEW')
def get_post_register_redirect():
return get_post_action_redirect('SECURITY_POST_REGISTER_VIEW')
def find_redirect(key): def find_redirect(key):
+11 -14
View File
@@ -10,24 +10,23 @@
""" """
from flask import current_app, redirect, request, render_template, jsonify, \ from flask import current_app, redirect, request, render_template, jsonify, \
after_this_request, Blueprint after_this_request, Blueprint
from flask_login import current_user from flask_login import current_user
from werkzeug.datastructures import MultiDict from werkzeug.datastructures import MultiDict
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from .confirmable import send_confirmation_instructions, \ from .confirmable import send_confirmation_instructions, \
confirm_user, confirm_email_token_status confirm_user, confirm_email_token_status
from .decorators import login_required, anonymous_user_required from .decorators import login_required, anonymous_user_required
from .passwordless import send_login_instructions, \ from .passwordless import send_login_instructions, \
login_token_status login_token_status
from .recoverable import reset_password_token_status, \ from .recoverable import reset_password_token_status, \
send_reset_password_instructions, update_password send_reset_password_instructions, update_password
from .changeable import change_user_password from .changeable import change_user_password
from .registerable import register_user from .registerable import register_user
from .utils import get_url, get_post_login_redirect, do_flash, \ from .utils import config_value, do_flash, get_url, get_post_login_redirect, \
get_message, login_user, logout_user, url_for_security as url_for, \ get_post_register_redirect, get_message, login_user, logout_user, \
config_value url_for_security as url_for
# Convenient references # Convenient references
_security = LocalProxy(lambda: current_app.extensions['security']) _security = LocalProxy(lambda: current_app.extensions['security'])
@@ -123,9 +122,7 @@ def register():
login_user(user) login_user(user)
if not request.json: if not request.json:
post_register_url = get_url(_security.post_register_view) return redirect(get_post_register_redirect())
post_login_url = get_url(_security.post_login_view)
return redirect(post_register_url or post_login_url)
if request.json: if request.json:
return _render_json(form) return _render_json(form)
@@ -173,7 +170,7 @@ def token_login(token):
if invalid or expired: if invalid or expired:
return redirect(url_for('login')) return redirect(url_for('login'))
login_user(user, True) login_user(user)
after_this_request(_commit) after_this_request(_commit)
do_flash(*get_message('PASSWORDLESS_LOGIN_SUCCESSFUL')) do_flash(*get_message('PASSWORDLESS_LOGIN_SUCCESSFUL'))
@@ -221,7 +218,7 @@ def confirm_email(token):
url_for('send_confirmation')) url_for('send_confirmation'))
confirm_user(user) confirm_user(user)
login_user(user, True) login_user(user)
after_this_request(_commit) after_this_request(_commit)
do_flash(*get_message('EMAIL_CONFIRMED')) do_flash(*get_message('EMAIL_CONFIRMED'))
@@ -272,7 +269,7 @@ def reset_password(token):
after_this_request(_commit) after_this_request(_commit)
update_password(user, form.password.data) update_password(user, form.password.data)
do_flash(*get_message('PASSWORD_RESET')) do_flash(*get_message('PASSWORD_RESET'))
login_user(user, True) login_user(user)
return redirect(get_url(_security.post_reset_view) or return redirect(get_url(_security.post_reset_view) or
get_url(_security.post_login_view)) get_url(_security.post_login_view))
+5 -5
View File
@@ -20,7 +20,7 @@ from setuptools import setup
setup( setup(
name='Flask-Security', name='Flask-Security',
version='1.6.2', version='1.6.4',
url='https://github.com/mattupstate/flask-security', url='https://github.com/mattupstate/flask-security',
license='MIT', license='MIT',
author='Matt Wright', author='Matt Wright',
@@ -35,10 +35,10 @@ setup(
platforms='any', platforms='any',
install_requires=[ install_requires=[
'Flask>=0.9', 'Flask>=0.9',
'Flask-Login>=0.1.3', 'Flask-Login==0.2.3',
'Flask-Mail>=0.7.3', 'Flask-Mail==0.7.3',
'Flask-Principal>=0.3.3', 'Flask-Principal==0.3.3',
'Flask-WTF>=0.8', 'Flask-WTF==0.8',
'itsdangerous>=0.17', 'itsdangerous>=0.17',
'passlib>=1.6.1', 'passlib>=1.6.1',
], ],
+8
View File
@@ -68,6 +68,14 @@ class ConfiguredSecurityTests(SecurityTest):
r = self._post('/register', data=data, follow_redirects=True) r = self._post('/register', data=data, follow_redirects=True)
self.assertIn('Post Register', r.data) self.assertIn('Post Register', r.data)
def test_register_with_next_querystring_argument(self):
data = dict(email='dude@lp.com',
password='password',
password_confirm='password')
r = self._post('/register?next=/page1', data=data, follow_redirects=True)
self.assertIn('Page 1', r.data)
def test_register_json(self): def test_register_json(self):
data = '{ "email": "dude@lp.com", "password": "password", "csrf_token":"%s" }' % self.csrf_token data = '{ "email": "dude@lp.com", "password": "password", "csrf_token":"%s" }' % self.csrf_token
r = self._post('/register', data=data, content_type='application/json') r = self._post('/register', data=data, content_type='application/json')
+5 -5
View File
@@ -60,7 +60,7 @@ class DefaultSecurityTests(SecurityTest):
def test_unauthorized_access(self): def test_unauthorized_access(self):
r = self._get('/profile', follow_redirects=True) r = self._get('/profile', follow_redirects=True)
self.assertIn('<li class="message">Please log in to access this page.</li>', r.data) self.assertIn('<li class="info">Please log in to access this page.</li>', r.data)
def test_authorized_access(self): def test_authorized_access(self):
self.authenticate() self.authenticate()
@@ -231,11 +231,11 @@ class MongoEngineSecurityTests(DefaultSecurityTests):
return create_app(auth_config, **kwargs) return create_app(auth_config, **kwargs)
# class PeeweeSecurityTests(DefaultSecurityTests): class PeeweeSecurityTests(DefaultSecurityTests):
# def _create_app(self, auth_config, **kwargs): def _create_app(self, auth_config, **kwargs):
# from tests.test_app.peewee_app import create_app from tests.test_app.peewee_app import create_app
# return create_app(auth_config, **kwargs) return create_app(auth_config, **kwargs)
class DefaultDatastoreTests(SecurityTest): class DefaultDatastoreTests(SecurityTest):
+12 -5
View File
@@ -15,7 +15,14 @@ def compare_user(a, b):
return a.id == b.id and a.email == b.email and a.password == b.password return a.id == b.id and a.email == b.email and a.password == b.password
class RegisterableSignalsTests(SecurityTest): class SignalTest(SecurityTest):
def _create_app(self, auth_config, **kwargs):
from tests.test_app.mongoengine import create_app
return create_app(auth_config, **kwargs)
class RegisterableSignalsTests(SignalTest):
AUTH_CONFIG = { AUTH_CONFIG = {
'SECURITY_CONFIRMABLE': True, 'SECURITY_CONFIRMABLE': True,
@@ -42,7 +49,7 @@ class RegisterableSignalsTests(SecurityTest):
self.assertEqual(mocks.signals_sent(), set()) self.assertEqual(mocks.signals_sent(), set())
class ConfirmableSignalsTests(SecurityTest): class ConfirmableSignalsTests(SignalTest):
AUTH_CONFIG = { AUTH_CONFIG = {
'SECURITY_CONFIRMABLE': True, 'SECURITY_CONFIRMABLE': True,
@@ -103,7 +110,7 @@ class ConfirmableSignalsTests(SecurityTest):
self.assertEqual(mocks.signals_sent(), set()) self.assertEqual(mocks.signals_sent(), set())
class RecoverableSignalsTests(SecurityTest): class RecoverableSignalsTests(SignalTest):
AUTH_CONFIG = { AUTH_CONFIG = {
'SECURITY_RECOVERABLE': True, 'SECURITY_RECOVERABLE': True,
@@ -153,7 +160,7 @@ class RecoverableSignalsTests(SecurityTest):
self.assertEqual(mocks.signals_sent(), set()) self.assertEqual(mocks.signals_sent(), set())
class ChangeableSignalsTests(SecurityTest): class ChangeableSignalsTests(SignalTest):
AUTH_CONFIG = { AUTH_CONFIG = {
'SECURITY_CHANGEABLE': True, 'SECURITY_CHANGEABLE': True,
@@ -204,7 +211,7 @@ class ChangeableSignalsTests(SecurityTest):
self.assertEqual(mocks.signals_sent(), set()) self.assertEqual(mocks.signals_sent(), set())
class PasswordlessTests(SecurityTest): class PasswordlessTests(SignalTest):
AUTH_CONFIG = { AUTH_CONFIG = {
'SECURITY_PASSWORDLESS': True 'SECURITY_PASSWORDLESS': True
+4
View File
@@ -113,6 +113,10 @@ def create_app(config):
def invalid_role(): def invalid_role():
return 'success' if ds.find_role('bogus') is None else 'failure' return 'success' if ds.find_role('bogus') is None else 'failure'
@app.route('/page1')
def page_1():
return 'Page 1'
return app return app
+2 -1
View File
@@ -14,11 +14,12 @@ from flask.ext.security import Security, UserMixin, RoleMixin, \
from tests.test_app import create_app as create_base_app, populate_data, \ from tests.test_app import create_app as create_base_app, populate_data, \
add_context_processors add_context_processors
def create_app(config, **kwargs): def create_app(config, **kwargs):
app = create_base_app(config) app = create_base_app(config)
app.config['DATABASE'] = { app.config['DATABASE'] = {
'name': 'example2.db', 'name': 'example2.db',
'engine': 'peewee.SqliteDatabase', 'engine': 'peewee.SqliteDatabase'
} }
db = Database(app) db = Database(app)