Created
October 14, 2010 20:49
-
-
Save rslinckx/627023 to your computer and use it in GitHub Desktop.
Suggested improvements of Flask-Principal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
log = logging.getLogger(__name__) | |
from functools import wraps | |
from flask import session, request, g | |
from flaskext.principal import Principal as RealPrincipal, identity_loaded, Identity, AnonymousIdentity | |
__all__ = ['Principal'] | |
class UserIdentity(Identity): | |
def __init__(self, user, auth_type=''): | |
super(UserIdentity, self).__init__(user.id, auth_type=auth_type) | |
self.user = user | |
@property | |
def id(self): | |
return self.name | |
def wrap_identity(f): | |
@wraps(f) | |
def decorate(*args, **kwargs): | |
result = f(*args, **kwargs) | |
user, auth_type = result or (None, None) | |
if user is not None: | |
return UserIdentity(user, auth_type) | |
return decorate | |
class Principal(RealPrincipal): | |
def __init__(self, app=None): | |
super(Principal, self).__init__(use_sessions=False) | |
if app is not None: | |
self.init_app(app) | |
self.get_user_by_id = lambda id: None | |
self.get_user_by_login = lambda login, password: None | |
def init_app(self, app): | |
self._init_app(app) | |
self.lowercase_login = app.config.get('AUTHENTIFIER_LOWERCASE_LOGIN', False) | |
loaders = app.config.get('AUTHENTIFIER_AUTH_TYPES', ['form', 'http-basic', 'session']) | |
if 'form' in loaders: | |
self.login_paths = app.config['AUTHENTIFIER_LOGIN_PATHS'] | |
self.identity_loader(self.authenticate_form) | |
if 'http-basic' in loaders: | |
self.identity_loader(self.authenticate_http_basic) | |
if 'session' in loaders: | |
self.identity_loader(self.authenticate_session) | |
self.identity_saver(self.remember_session) | |
app.before_request(lambda: self.ensure_user(g.identity)) | |
identity_loaded.connect_via(app)(lambda app, identity: self.ensure_user(identity)) | |
# Decorators | |
def user_by_id(self, f): | |
self.get_user_by_id = f | |
return f | |
def user_by_login(self, f): | |
self.get_user_by_login = f | |
return f | |
# Public API | |
def logout(self): | |
self.set_identity(AnonymousIdentity()) | |
def login(self, user): | |
self.set_identity(UserIdentity(user, 'manual')) | |
# Helpers for events | |
@wrap_identity | |
def authenticate_form(self): | |
if request.path in self.login_paths and request.method == 'POST': | |
login, password = request.form.get('login', u''), request.form.get('password', u'') | |
if self.lowercase_login: | |
login = login.lower() | |
if login: | |
return (self.get_user_by_login(login, password), 'form') | |
@wrap_identity | |
def authenticate_http_basic(self): | |
a = request.authorization | |
if a and a['username']: | |
return (self.get_user_by_login(a['username'], a['password']), 'http-basic') | |
@wrap_identity | |
def authenticate_session(self): | |
uid = session.get('uid') | |
if uid: | |
return (self.get_user_by_id(uid), 'session') | |
def remember_session(self, identity): | |
if not isinstance(identity, AnonymousIdentity): | |
session['uid'] = identity.id | |
elif 'uid' in session: | |
del session['uid'] | |
session.modified = True | |
def ensure_user(self, identity): | |
g.user = getattr(identity, 'user', None) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment