Refactor to leverage all existing methods of auth handler
instead of importing and calling functions from core rattail
This commit is contained in:
parent
53fc1508f3
commit
232a02b944
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2020 Lance Edgar
|
# Copyright © 2010-2021 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -26,7 +26,7 @@ Tailbone Web API - Auth Views
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from rattail.db.auth import authenticate_user, set_user_password, cache_permissions
|
from rattail.db.auth import set_user_password
|
||||||
|
|
||||||
from cornice import Service
|
from cornice import Service
|
||||||
|
|
||||||
|
@ -82,15 +82,20 @@ class AuthenticationView(APIView):
|
||||||
if error:
|
if error:
|
||||||
return {'error': error}
|
return {'error': error}
|
||||||
|
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
login_user(self.request, user)
|
login_user(self.request, user)
|
||||||
return {
|
return {
|
||||||
'ok': True,
|
'ok': True,
|
||||||
'user': self.get_user_info(user),
|
'user': self.get_user_info(user),
|
||||||
'permissions': list(cache_permissions(Session(), user)),
|
'permissions': list(auth.cache_permissions(Session(), user)),
|
||||||
}
|
}
|
||||||
|
|
||||||
def authenticate_user(self, username, password):
|
def authenticate_user(self, username, password):
|
||||||
return authenticate_user(Session(), username, password)
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
return auth.authenticate_user(Session(), username, password)
|
||||||
|
|
||||||
def why_cant_user_login(self, user):
|
def why_cant_user_login(self, user):
|
||||||
"""
|
"""
|
||||||
|
@ -156,7 +161,7 @@ class AuthenticationView(APIView):
|
||||||
data = self.request.json_body
|
data = self.request.json_body
|
||||||
|
|
||||||
# first make sure "current" password is accurate
|
# first make sure "current" password is accurate
|
||||||
if not authenticate_user(Session(), self.request.user, data['current_password']):
|
if not self.authenticate_user(self.request.user, data['current_password']):
|
||||||
return {'error': "The current/old password you provided is incorrect"}
|
return {'error': "The current/old password you provided is incorrect"}
|
||||||
|
|
||||||
# okay then, set new password
|
# okay then, set new password
|
||||||
|
|
|
@ -93,6 +93,11 @@ def set_session_timeout(request, timeout):
|
||||||
class TailboneAuthorizationPolicy(object):
|
class TailboneAuthorizationPolicy(object):
|
||||||
|
|
||||||
def permits(self, context, principals, permission):
|
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:
|
for userid in principals:
|
||||||
if userid not in (Everyone, Authenticated):
|
if userid not in (Everyone, Authenticated):
|
||||||
if context.request.user and context.request.user.uuid == userid:
|
if context.request.user and context.request.user.uuid == userid:
|
||||||
|
@ -100,10 +105,6 @@ class TailboneAuthorizationPolicy(object):
|
||||||
else:
|
else:
|
||||||
# this is pretty rare, but can happen in dev after
|
# this is pretty rare, but can happen in dev after
|
||||||
# re-creating the database, which means new user uuids.
|
# re-creating the database, which means new user uuids.
|
||||||
config = context.request.rattail_config
|
|
||||||
model = config.get_model()
|
|
||||||
app = config.get_app()
|
|
||||||
auth = app.get_auth_handler()
|
|
||||||
# TODO: the odds of this query returning a user in that
|
# TODO: the odds of this query returning a user in that
|
||||||
# case, are probably nil, and we should just skip this bit?
|
# case, are probably nil, and we should just skip this bit?
|
||||||
user = Session.query(model.User).get(userid)
|
user = Session.query(model.User).get(userid)
|
||||||
|
@ -111,7 +112,7 @@ class TailboneAuthorizationPolicy(object):
|
||||||
if auth.has_permission(Session(), user, permission):
|
if auth.has_permission(Session(), user, permission):
|
||||||
return True
|
return True
|
||||||
if Everyone in principals:
|
if Everyone in principals:
|
||||||
return has_permission(Session(), None, permission)
|
return auth.has_permission(Session(), None, permission)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def principals_allowed_by_permission(self, context, permission):
|
def principals_allowed_by_permission(self, context, permission):
|
||||||
|
|
|
@ -91,12 +91,13 @@ def new_request(event):
|
||||||
auth = app.get_auth_handler()
|
auth = app.get_auth_handler()
|
||||||
request.tailbone_cached_permissions = auth.cache_permissions(
|
request.tailbone_cached_permissions = auth.cache_permissions(
|
||||||
Session(), request.user)
|
Session(), request.user)
|
||||||
else:
|
# TODO: until we know otherwise, let's assume this is not needed
|
||||||
# TODO: not sure why this would really work, or even be
|
# else:
|
||||||
# needed, if there was no rattail config?
|
# # TODO: not sure why this would really work, or even be
|
||||||
from rattail.db.auth import cache_permissions
|
# # needed, if there was no rattail config?
|
||||||
request.tailbone_cached_permissions = cache_permissions(
|
# from rattail.db.auth import cache_permissions
|
||||||
Session(), request.user)
|
# request.tailbone_cached_permissions = cache_permissions(
|
||||||
|
# Session(), request.user)
|
||||||
|
|
||||||
|
|
||||||
def before_render(event):
|
def before_render(event):
|
||||||
|
|
|
@ -50,9 +50,12 @@ class UserLogin(colander.MappingSchema):
|
||||||
|
|
||||||
@colander.deferred
|
@colander.deferred
|
||||||
def current_password_correct(node, kw):
|
def current_password_correct(node, kw):
|
||||||
|
request = kw['request']
|
||||||
|
app = request.rattail_config.get_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
user = kw['user']
|
user = kw['user']
|
||||||
def validate(node, value):
|
def validate(node, value):
|
||||||
if not authenticate_user(Session(), user.username, value):
|
if not auth.authenticate_user(Session(), user.username, value):
|
||||||
raise colander.Invalid(node, "The password is incorrect")
|
raise colander.Invalid(node, "The password is incorrect")
|
||||||
return validate
|
return validate
|
||||||
|
|
||||||
|
@ -175,7 +178,7 @@ class AuthenticationView(View):
|
||||||
return self.redirect(self.request.get_referrer())
|
return self.redirect(self.request.get_referrer())
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
use_buefy = self.get_use_buefy()
|
||||||
schema = ChangePassword().bind(user=self.request.user)
|
schema = ChangePassword().bind(user=self.request.user, request=self.request)
|
||||||
form = forms.Form(schema=schema, request=self.request, use_buefy=use_buefy)
|
form = forms.Form(schema=schema, request=self.request, use_buefy=use_buefy)
|
||||||
if form.validate(newstyle=True):
|
if form.validate(newstyle=True):
|
||||||
set_user_password(self.request.user, form.validated['new_password'])
|
set_user_password(self.request.user, form.validated['new_password'])
|
||||||
|
|
|
@ -28,7 +28,6 @@ from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from rattail.db.auth import has_permission
|
|
||||||
from rattail.core import Object
|
from rattail.core import Object
|
||||||
from rattail.util import OrderedDict
|
from rattail.util import OrderedDict
|
||||||
|
|
||||||
|
@ -144,6 +143,9 @@ class PermissionsRenderer(Object):
|
||||||
return self.render()
|
return self.render()
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
app = self.request.rattail_config.get_app()
|
||||||
|
auth = app.get_handler()
|
||||||
|
|
||||||
principal = self.principal
|
principal = self.principal
|
||||||
html = ''
|
html = ''
|
||||||
for groupkey in sorted(self.permissions, key=lambda k: self.permissions[k]['label'].lower()):
|
for groupkey in sorted(self.permissions, key=lambda k: self.permissions[k]['label'].lower()):
|
||||||
|
@ -151,9 +153,9 @@ class PermissionsRenderer(Object):
|
||||||
perms = self.permissions[groupkey]['perms']
|
perms = self.permissions[groupkey]['perms']
|
||||||
rendered = False
|
rendered = False
|
||||||
for key in sorted(perms, key=lambda p: perms[p]['label'].lower()):
|
for key in sorted(perms, key=lambda p: perms[p]['label'].lower()):
|
||||||
checked = has_permission(Session(), principal, key,
|
checked = auth.has_permission(Session(), principal, key,
|
||||||
include_guest=self.include_guest,
|
include_guest=self.include_guest,
|
||||||
include_authenticated=self.include_authenticated)
|
include_authenticated=self.include_authenticated)
|
||||||
if checked:
|
if checked:
|
||||||
label = perms[key]['label']
|
label = perms[key]['label']
|
||||||
span = HTML.tag('span', c="[X]" if checked else "[ ]")
|
span = HTML.tag('span', c="[X]" if checked else "[ ]")
|
||||||
|
|
|
@ -33,8 +33,7 @@ from sqlalchemy import orm
|
||||||
from openpyxl.styles import Font, PatternFill
|
from openpyxl.styles import Font, PatternFill
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.db.auth import (has_permission, grant_permission, revoke_permission,
|
from rattail.db.auth import administrator_role, guest_role, authenticated_role
|
||||||
administrator_role, guest_role, authenticated_role)
|
|
||||||
from rattail.excel import ExcelWriter
|
from rattail.excel import ExcelWriter
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -158,6 +157,8 @@ class RoleView(PrincipalMasterView):
|
||||||
super(RoleView, self).configure_form(f)
|
super(RoleView, self).configure_form(f)
|
||||||
role = f.model_instance
|
role = f.model_instance
|
||||||
use_buefy = self.get_use_buefy()
|
use_buefy = self.get_use_buefy()
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
# name
|
# name
|
||||||
f.set_validator('name', self.unique_name)
|
f.set_validator('name', self.unique_name)
|
||||||
|
@ -194,7 +195,8 @@ class RoleView(PrincipalMasterView):
|
||||||
|
|
||||||
# permissions
|
# permissions
|
||||||
self.tailbone_permissions = self.get_available_permissions()
|
self.tailbone_permissions = self.get_available_permissions()
|
||||||
f.set_renderer('permissions', PermissionsRenderer(permissions=self.tailbone_permissions))
|
f.set_renderer('permissions', PermissionsRenderer(request=self.request,
|
||||||
|
permissions=self.tailbone_permissions))
|
||||||
f.set_node('permissions', colander.Set())
|
f.set_node('permissions', colander.Set())
|
||||||
f.set_widget('permissions', PermissionsWidget(
|
f.set_widget('permissions', PermissionsWidget(
|
||||||
permissions=self.tailbone_permissions,
|
permissions=self.tailbone_permissions,
|
||||||
|
@ -203,7 +205,9 @@ class RoleView(PrincipalMasterView):
|
||||||
granted = []
|
granted = []
|
||||||
for groupkey in self.tailbone_permissions:
|
for groupkey in self.tailbone_permissions:
|
||||||
for key in self.tailbone_permissions[groupkey]['perms']:
|
for key in self.tailbone_permissions[groupkey]['perms']:
|
||||||
if has_permission(self.Session(), role, key, include_guest=False, include_authenticated=False):
|
if auth.has_permission(self.Session(), role, key,
|
||||||
|
include_guest=False,
|
||||||
|
include_authenticated=False):
|
||||||
granted.append(key)
|
granted.append(key)
|
||||||
f.set_default('permissions', granted)
|
f.set_default('permissions', granted)
|
||||||
elif self.deleting:
|
elif self.deleting:
|
||||||
|
@ -309,13 +313,16 @@ class RoleView(PrincipalMasterView):
|
||||||
permissions, but rather each "available" permission (depends on current
|
permissions, but rather each "available" permission (depends on current
|
||||||
user) will be examined individually, and updated as needed.
|
user) will be examined individually, and updated as needed.
|
||||||
"""
|
"""
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
available = self.tailbone_permissions
|
available = self.tailbone_permissions
|
||||||
for gkey, group in six.iteritems(available):
|
for gkey, group in six.iteritems(available):
|
||||||
for pkey, perm in six.iteritems(group['perms']):
|
for pkey, perm in six.iteritems(group['perms']):
|
||||||
if pkey in permissions:
|
if pkey in permissions:
|
||||||
grant_permission(role, pkey)
|
auth.grant_permission(role, pkey)
|
||||||
else:
|
else:
|
||||||
revoke_permission(role, pkey)
|
auth.revoke_permission(role, pkey)
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
def template_kwargs_view(self, **kwargs):
|
||||||
role = kwargs['instance']
|
role = kwargs['instance']
|
||||||
|
@ -364,13 +371,16 @@ class RoleView(PrincipalMasterView):
|
||||||
return self.redirect(self.request.get_referrer(default=self.request.route_url('roles')))
|
return self.redirect(self.request.get_referrer(default=self.request.route_url('roles')))
|
||||||
|
|
||||||
def find_principals_with_permission(self, session, permission):
|
def find_principals_with_permission(self, session, permission):
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
# TODO: this should search Permission table instead, and work backward to Role?
|
# TODO: this should search Permission table instead, and work backward to Role?
|
||||||
all_roles = session.query(model.Role)\
|
all_roles = session.query(model.Role)\
|
||||||
.order_by(model.Role.name)\
|
.order_by(model.Role.name)\
|
||||||
.options(orm.joinedload(model.Role._permissions))
|
.options(orm.joinedload(model.Role._permissions))
|
||||||
roles = []
|
roles = []
|
||||||
for role in all_roles:
|
for role in all_roles:
|
||||||
if has_permission(session, role, permission, include_guest=False):
|
if auth.has_permission(session, role, permission, include_guest=False):
|
||||||
roles.append(role)
|
roles.append(role)
|
||||||
return roles
|
return roles
|
||||||
|
|
||||||
|
@ -379,6 +389,9 @@ class RoleView(PrincipalMasterView):
|
||||||
View which renders the complete role / permissions matrix data into an
|
View which renders the complete role / permissions matrix data into an
|
||||||
Excel spreadsheet, and returns that file.
|
Excel spreadsheet, and returns that file.
|
||||||
"""
|
"""
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
roles = self.Session.query(model.Role)\
|
roles = self.Session.query(model.Role)\
|
||||||
.order_by(model.Role.name)\
|
.order_by(model.Role.name)\
|
||||||
.all()
|
.all()
|
||||||
|
@ -427,7 +440,8 @@ class RoleView(PrincipalMasterView):
|
||||||
|
|
||||||
# and show an 'X' for any role which has this perm
|
# and show an 'X' for any role which has this perm
|
||||||
for col, role in enumerate(roles, 2):
|
for col, role in enumerate(roles, 2):
|
||||||
if has_permission(self.Session(), role, key, include_guest=False):
|
if auth.has_permission(self.Session(), role, key,
|
||||||
|
include_guest=False):
|
||||||
sheet.cell(row=writing_row, column=col, value="X")
|
sheet.cell(row=writing_row, column=col, value="X")
|
||||||
|
|
||||||
writing_row += 1
|
writing_row += 1
|
||||||
|
|
|
@ -32,7 +32,8 @@ import six
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.db.auth import administrator_role, guest_role, authenticated_role, set_user_password, has_permission
|
from rattail.db.auth import (administrator_role, guest_role,
|
||||||
|
authenticated_role, set_user_password)
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
from deform import widget as dfwidget
|
from deform import widget as dfwidget
|
||||||
|
@ -239,7 +240,8 @@ class UserView(PrincipalMasterView):
|
||||||
if self.viewing:
|
if self.viewing:
|
||||||
permissions = self.request.registry.settings.get('tailbone_permissions', {})
|
permissions = self.request.registry.settings.get('tailbone_permissions', {})
|
||||||
f.append('permissions')
|
f.append('permissions')
|
||||||
f.set_renderer('permissions', PermissionsRenderer(permissions=permissions,
|
f.set_renderer('permissions', PermissionsRenderer(request=self.request,
|
||||||
|
permissions=permissions,
|
||||||
include_guest=True,
|
include_guest=True,
|
||||||
include_authenticated=True))
|
include_authenticated=True))
|
||||||
|
|
||||||
|
@ -389,6 +391,9 @@ class UserView(PrincipalMasterView):
|
||||||
]
|
]
|
||||||
|
|
||||||
def find_principals_with_permission(self, session, permission):
|
def find_principals_with_permission(self, session, permission):
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
auth = app.get_auth_handler()
|
||||||
|
|
||||||
# TODO: this should search Permission table instead, and work backward to User?
|
# TODO: this should search Permission table instead, and work backward to User?
|
||||||
all_users = session.query(model.User)\
|
all_users = session.query(model.User)\
|
||||||
.filter(model.User.active == True)\
|
.filter(model.User.active == True)\
|
||||||
|
@ -398,7 +403,7 @@ class UserView(PrincipalMasterView):
|
||||||
.joinedload(model.Role._permissions))
|
.joinedload(model.Role._permissions))
|
||||||
users = []
|
users = []
|
||||||
for user in all_users:
|
for user in all_users:
|
||||||
if has_permission(session, user, permission):
|
if auth.has_permission(session, user, permission):
|
||||||
users.append(user)
|
users.append(user)
|
||||||
return users
|
return users
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue