diff --git a/docs/api.rst b/docs/api.rst index 0f3a518..4c7c7e6 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,7 +4,7 @@ API === -.. module:: flask.ext.stormpath +.. module:: flask_stormpath This part of the documentation documents all the public classes, functions, and API details in Flask-Stormpath. This documentation is auto generated, and is diff --git a/docs/product.rst b/docs/product.rst index 6f05459..94e407c 100644 --- a/docs/product.rst +++ b/docs/product.rst @@ -1,4 +1,4 @@ -.. module:: flask.ext.stormpath +.. module:: flask_stormpath Product Guide @@ -19,7 +19,7 @@ Let's say you have a simple view which should only be accessible to users who have logged in. Below is a code sample which shows how easy it is to restrict access to your view:: - from flask.ext.stormpath import login_required + from flask_stormpath import login_required @app.route('/secret') @login_required @@ -70,7 +70,7 @@ Now that we've created our Groups, and also added our :class:`User` to the "free users" group -- let's see how we can enforce different types of authorization on our :class:`User` using the :func:`groups_required` decorator:: - from flask.ext.stormpath import groups_required + from flask_stormpath import groups_required @app.route('/admins') @groups_required(['admins']) @@ -135,7 +135,7 @@ Let's say we've defined a simple view that should simply display a user's email address. We can make use of the magical :class:`user` context variable to do this:: - from flask.ext.stormpath import login_required, user + from flask_stormpath import login_required, user @app.route('/email') @login_required diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 2ee3642..c7e7d5f 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -1,5 +1,5 @@ .. _quickstart: -.. module:: flask.ext.stormpath +.. module:: flask_stormpath Quickstart @@ -20,7 +20,7 @@ You can do this in one of two ways: 1. Pass your Flask app into the :class:`StormpathManager` directly:: - from flask.ext.stormpath import StormpathManager + from flask_stormpath import StormpathManager app = Flask(__name__) stormpath_manager = StormpathManager(app) @@ -28,7 +28,7 @@ You can do this in one of two ways: 2. Lazily initialize your :class:`StormpathManager` (this is useful if you have a factory function creating your Flask application):: - from flask.ext.stormpath import StormpathManager + from flask_stormpath import StormpathManager stormpath_manager = StormpathManager() diff --git a/flask_stormpath/decorators.py b/flask_stormpath/decorators.py index daa9508..7b5a246 100644 --- a/flask_stormpath/decorators.py +++ b/flask_stormpath/decorators.py @@ -44,7 +44,7 @@ def wrapper(*args, **kwargs): return func(*args, **kwargs) # If the user is NOT authenticated, this user is unauthorized. - elif not current_user.is_authenticated(): + elif not current_user.is_authenticated: return current_app.login_manager.unauthorized() # If the user authenticated, and the all flag is set, we need to diff --git a/flask_stormpath/models.py b/flask_stormpath/models.py index 48c8c5c..5a06ef7 100644 --- a/flask_stormpath/models.py +++ b/flask_stormpath/models.py @@ -26,6 +26,15 @@ class User(Account): def __repr__(self): return u'User <"%s" ("%s")>' % (self.username or self.email, self.href) + def _ensure_data(self, **kwargs): + # Prevent attempt to fetch Account resource after User was deleted. + # This is required to prevent an exception when delivering deleted + # signal via Blinker as determining the hashable identity of User + # object triggers call to _ensure_data + if self.__dict__.get('_was_deleted'): + return + super(User, self)._ensure_data(**kwargs) + def get_id(self): """ Return the unique user identifier (in our case, the Stormpath resource @@ -33,6 +42,7 @@ def get_id(self): """ return text_type(self.href) + @property def is_active(self): """ A user account is active if, and only if, their account status is @@ -40,12 +50,14 @@ def is_active(self): """ return self.status == 'ENABLED' + @property def is_anonymous(self): """ We don't support anonymous users, so this is always False. """ return False + @property def is_authenticated(self): """ All users will always be authenticated, so this will always return @@ -66,6 +78,10 @@ def delete(self): Send signal after user is deleted. """ return_value = super(User, self).delete() + + # Used to prevent re-fetching of resource + self._was_deleted = True + user_deleted.send(self, user=self) return return_value diff --git a/requirements.txt b/requirements.txt index 10ddb2b..894d552 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ Sphinx>=1.2.1 pytest>=2.5.2 pytest-xdist>=1.10 -blinker==1.3 diff --git a/setup.py b/setup.py index 6964a2f..72c6ac6 100644 --- a/setup.py +++ b/setup.py @@ -52,15 +52,12 @@ def run(self): platforms = 'any', install_requires = [ 'Flask>=0.9.0', - 'Flask-Login==0.2.9', + 'Flask-Login>=0.3.2', 'Flask-WTF>=0.9.5', - 'facebook-sdk==1.0.0', - 'oauth2client==1.2', - 'stormpath==2.1.1', - 'blinker==1.3' - ], - dependency_links=[ - 'git+git://github.com/pythonforfacebook/facebook-sdk.git@e65d06158e48388b3932563f1483ca77065951b3#egg=facebook-sdk-1.0.0-alpha', + 'facebook-sdk>=1.0.0', + 'oauth2client>=3.0.0', + 'stormpath==2.4.4', + 'blinker>=1.4' ], classifiers = [ 'Environment :: Web Environment', diff --git a/tests/helpers.py b/tests/helpers.py index 4e82fc9..7cffaa0 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -11,7 +11,7 @@ from uuid import uuid4 from flask import Flask -from flask.ext.stormpath import StormpathManager +from flask_stormpath import StormpathManager from stormpath.client import Client diff --git a/tests/test_context_processors.py b/tests/test_context_processors.py index 45d60d1..2eb04ee 100644 --- a/tests/test_context_processors.py +++ b/tests/test_context_processors.py @@ -1,8 +1,8 @@ """Run tests against our custom context processors.""" -from flask.ext.stormpath import User, user -from flask.ext.stormpath.context_processors import user_context_processor +from flask_stormpath import User, user +from flask_stormpath.context_processors import user_context_processor from .helpers import StormpathTestCase diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 6b428d1..1c11a4c 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -1,8 +1,8 @@ """Run tests against our custom decorators.""" -from flask.ext.stormpath import User -from flask.ext.stormpath.decorators import groups_required +from flask_stormpath import User +from flask_stormpath.decorators import groups_required from .helpers import StormpathTestCase diff --git a/tests/test_models.py b/tests/test_models.py index 8f6001e..59ad104 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ """Tests for our data models.""" -from flask.ext.stormpath.models import User +from flask_stormpath.models import User from stormpath.resources.account import Account from .helpers import StormpathTestCase @@ -75,17 +75,17 @@ def test_is_active(self): given_name = 'Randall', surname = 'Degges', ) - self.assertEqual(user.is_active(), True) + self.assertEqual(user.is_active, True) # Ensure users who have their accounts explicitly disabled actually # return a proper status when `is_active` is called. user.status = User.STATUS_DISABLED - self.assertEqual(user.is_active(), False) + self.assertEqual(user.is_active, False) # Ensure users who have not verified their accounts return a proper # status when `is_active` is called. user.status = User.STATUS_UNVERIFIED - self.assertEqual(user.is_active(), False) + self.assertEqual(user.is_active, False) def test_is_anonymous(self): with self.app.app_context(): @@ -99,7 +99,7 @@ def test_is_anonymous(self): given_name = 'Randall', surname = 'Degges', ) - self.assertEqual(user.is_anonymous(), False) + self.assertEqual(user.is_anonymous, False) def test_is_authenticated(self): with self.app.app_context(): @@ -112,7 +112,7 @@ def test_is_authenticated(self): given_name = 'Randall', surname = 'Degges', ) - self.assertEqual(user.is_authenticated(), True) + self.assertEqual(user.is_authenticated, True) def test_create(self): with self.app.app_context(): diff --git a/tests/test_settings.py b/tests/test_settings.py index 0d9b0df..2d9b419 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -5,8 +5,8 @@ from os import close, environ, remove, write from tempfile import mkstemp -from flask.ext.stormpath.errors import ConfigurationError -from flask.ext.stormpath.settings import check_settings, init_settings +from flask_stormpath.errors import ConfigurationError +from flask_stormpath.settings import check_settings, init_settings from .helpers import StormpathTestCase diff --git a/tests/test_signals.py b/tests/test_signals.py index c65cf75..7b350d4 100644 --- a/tests/test_signals.py +++ b/tests/test_signals.py @@ -1,7 +1,7 @@ """Run tests for signals.""" -from flask.ext.login import user_logged_in -from flask.ext.stormpath.models import ( +from flask_login import user_logged_in +from flask_stormpath.models import ( User, user_created, user_deleted, diff --git a/tests/test_stormpath.py b/tests/test_stormpath.py index ec4e5c6..4681eb8 100644 --- a/tests/test_stormpath.py +++ b/tests/test_stormpath.py @@ -12,7 +12,7 @@ from uuid import uuid4 from flask import Flask, request -from flask.ext.stormpath import ( +from flask_stormpath import ( StormpathManager, User, groups_required, diff --git a/tests/test_views.py b/tests/test_views.py index e7dd0ca..81b57f4 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,7 +1,7 @@ """Run tests against our custom views.""" -from flask.ext.stormpath.models import User +from flask_stormpath.models import User from .helpers import StormpathTestCase @@ -232,7 +232,7 @@ def test_error_messages(self): self.assertEqual(resp.status_code, 200) self.assertTrue( - 'Invalid username or password.' in resp.data.decode('utf-8')) + 'specified password is incorrect.' in resp.data.decode('utf-8')) self.assertFalse("developerMessage" in resp.data.decode('utf-8')) def test_redirect_to_login_and_register_url(self):