Require pyramid 2.x; remove 1.x-style auth policies
This commit is contained in:
parent
e17ef2edd8
commit
efe477d0db
|
@ -56,7 +56,7 @@ install_requires =
|
|||
paginate_sqlalchemy
|
||||
passlib
|
||||
Pillow
|
||||
pyramid
|
||||
pyramid>=2
|
||||
pyramid_beaker
|
||||
pyramid_deform
|
||||
pyramid_exclog
|
||||
|
|
|
@ -39,7 +39,7 @@ from pyramid.authentication import SessionAuthenticationPolicy
|
|||
from zope.sqlalchemy import register
|
||||
|
||||
import tailbone.db
|
||||
from tailbone.auth import TailboneAuthorizationPolicy
|
||||
from tailbone.auth import TailboneSecurityPolicy
|
||||
from tailbone.config import csrf_token_name, csrf_header_name
|
||||
from tailbone.util import get_effective_theme, get_theme_template_path
|
||||
from tailbone.providers import get_all_providers
|
||||
|
@ -136,14 +136,7 @@ def make_pyramid_config(settings, configure_csrf=True):
|
|||
config.registry['rattail_config'] = rattail_config
|
||||
|
||||
# configure user authorization / authentication
|
||||
# TODO: security policy should become the default, for pyramid 2.x
|
||||
if rattail_config.getbool('tailbone', 'pyramid.use_security_policy',
|
||||
usedb=False, default=False):
|
||||
from tailbone.auth import TailboneSecurityPolicy
|
||||
config.set_security_policy(TailboneSecurityPolicy())
|
||||
else:
|
||||
config.set_authorization_policy(TailboneAuthorizationPolicy())
|
||||
config.set_authentication_policy(SessionAuthenticationPolicy())
|
||||
config.set_security_policy(TailboneSecurityPolicy())
|
||||
|
||||
# maybe require CSRF token protection
|
||||
if configure_csrf:
|
||||
|
|
|
@ -30,9 +30,9 @@ import re
|
|||
from rattail.util import prettify, NOTSET
|
||||
|
||||
from zope.interface import implementer
|
||||
from pyramid.interfaces import IAuthorizationPolicy
|
||||
from pyramid.security import remember, forget, Everyone, Authenticated
|
||||
from pyramid.authentication import SessionAuthenticationPolicy
|
||||
from pyramid.authentication import SessionAuthenticationHelper
|
||||
from pyramid.request import RequestLocalCache
|
||||
from pyramid.security import remember, forget
|
||||
|
||||
from tailbone.db import Session
|
||||
|
||||
|
@ -90,73 +90,9 @@ def set_session_timeout(request, timeout):
|
|||
request.session['_timeout'] = timeout or None
|
||||
|
||||
|
||||
class TailboneAuthenticationPolicy(SessionAuthenticationPolicy):
|
||||
"""
|
||||
Custom authentication policy for Tailbone.
|
||||
|
||||
This is mostly Pyramid's built-in session-based policy, but adds
|
||||
logic to accept Rattail User API Tokens in lieu of current user
|
||||
being identified via the session.
|
||||
|
||||
Note that the traditional Tailbone web app does *not* use this
|
||||
policy, only the Tailbone web API uses it by default.
|
||||
"""
|
||||
|
||||
def unauthenticated_userid(self, request):
|
||||
|
||||
# figure out userid from header token if present
|
||||
credentials = request.headers.get('Authorization')
|
||||
if credentials:
|
||||
match = re.match(r'^Bearer (\S+)$', credentials)
|
||||
if match:
|
||||
token = match.group(1)
|
||||
rattail_config = request.registry.settings.get('rattail_config')
|
||||
app = rattail_config.get_app()
|
||||
auth = app.get_auth_handler()
|
||||
user = auth.authenticate_user_token(Session(), token)
|
||||
if user:
|
||||
return user.uuid
|
||||
|
||||
# otherwise do normal session-based logic
|
||||
return super().unauthenticated_userid(request)
|
||||
|
||||
|
||||
@implementer(IAuthorizationPolicy)
|
||||
class TailboneAuthorizationPolicy(object):
|
||||
|
||||
def permits(self, context, principals, permission):
|
||||
config = context.request.rattail_config
|
||||
model = config.get_model()
|
||||
app = config.get_app()
|
||||
auth = app.get_auth_handler()
|
||||
|
||||
for userid in principals:
|
||||
if userid not in (Everyone, Authenticated):
|
||||
if context.request.user and context.request.user.uuid == userid:
|
||||
return context.request.has_perm(permission)
|
||||
else:
|
||||
# this is pretty rare, but can happen in dev after
|
||||
# re-creating the database, which means new user uuids.
|
||||
# TODO: the odds of this query returning a user in that
|
||||
# case, are probably nil, and we should just skip this bit?
|
||||
user = Session.get(model.User, userid)
|
||||
if user:
|
||||
if auth.has_permission(Session(), user, permission):
|
||||
return True
|
||||
if Everyone in principals:
|
||||
return auth.has_permission(Session(), None, permission)
|
||||
return False
|
||||
|
||||
def principals_allowed_by_permission(self, context, permission):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TailboneSecurityPolicy:
|
||||
|
||||
def __init__(self, api_mode=False):
|
||||
from pyramid.authentication import SessionAuthenticationHelper
|
||||
from pyramid.request import RequestLocalCache
|
||||
|
||||
self.api_mode = api_mode
|
||||
self.session_helper = SessionAuthenticationHelper()
|
||||
self.identity_cache = RequestLocalCache(self.load_identity)
|
||||
|
|
|
@ -30,7 +30,7 @@ from cornice.renderer import CorniceRenderer
|
|||
from pyramid.config import Configurator
|
||||
|
||||
from tailbone import app
|
||||
from tailbone.auth import TailboneAuthenticationPolicy, TailboneAuthorizationPolicy
|
||||
from tailbone.auth import TailboneSecurityPolicy
|
||||
from tailbone.providers import get_all_providers
|
||||
|
||||
|
||||
|
@ -50,14 +50,7 @@ def make_pyramid_config(settings):
|
|||
pyramid_config = Configurator(settings=settings, root_factory=app.Root)
|
||||
|
||||
# configure user authorization / authentication
|
||||
# TODO: security policy should become the default, for pyramid 2.x
|
||||
if rattail_config.getbool('tailbone', 'pyramid.use_security_policy',
|
||||
usedb=False, default=False):
|
||||
from tailbone.auth import TailboneSecurityPolicy
|
||||
pyramid_config.set_security_policy(TailboneSecurityPolicy(api_mode=True))
|
||||
else:
|
||||
pyramid_config.set_authentication_policy(TailboneAuthenticationPolicy())
|
||||
pyramid_config.set_authorization_policy(TailboneAuthorizationPolicy())
|
||||
pyramid_config.set_security_policy(TailboneSecurityPolicy(api_mode=True))
|
||||
|
||||
# always require CSRF token protection
|
||||
pyramid_config.set_default_csrf_options(require_csrf=True,
|
||||
|
|
Loading…
Reference in a new issue