Overhaul how available permissions are registered in app config.
Permissions must now be regsistered just like routes and views. This should make things much nicer going forward.
This commit is contained in:
parent
412ac6e12f
commit
9cfbc918e7
|
@ -117,6 +117,18 @@ def make_pyramid_config(settings):
|
|||
config.include('pyramid_mako')
|
||||
config.include('pyramid_tm')
|
||||
|
||||
# Add some permissions magic.
|
||||
config.add_directive('add_tailbone_permission_group', 'tailbone.auth.add_permission_group')
|
||||
config.add_directive('add_tailbone_permission', 'tailbone.auth.add_permission')
|
||||
|
||||
# TODO: This can finally be removed once all CRUD/index views have been
|
||||
# converted to use the new master view etc.
|
||||
for label, perms in settings.get('edbob.permissions'):
|
||||
groupkey = label.lower().replace(' ', '_')
|
||||
config.add_tailbone_permission_group(groupkey, label)
|
||||
for key, label in perms:
|
||||
config.add_tailbone_permission(groupkey, key, label)
|
||||
|
||||
# Configure FormAlchemy.
|
||||
formalchemy.config.engine = TemplateEngine()
|
||||
formalchemy.FieldSet.default_renderers[GPCType] = renderers.GPCFieldRenderer
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
# Copyright © 2010-2015 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -21,28 +20,31 @@
|
|||
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
Authentication & Authorization
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from edbob.util import prettify
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.db.auth import has_permission
|
||||
|
||||
from zope.interface import implementer
|
||||
from pyramid.interfaces import IAuthorizationPolicy
|
||||
from pyramid.security import Everyone, Authenticated
|
||||
|
||||
from .db import Session
|
||||
from tailbone.db import Session
|
||||
|
||||
|
||||
@implementer(IAuthorizationPolicy)
|
||||
class TailboneAuthorizationPolicy(object):
|
||||
|
||||
def permits(self, context, principals, permission):
|
||||
from rattail.db.model import User
|
||||
from rattail.db.auth import has_permission
|
||||
|
||||
for userid in principals:
|
||||
if userid not in (Everyone, Authenticated):
|
||||
user = Session.query(User).get(userid)
|
||||
user = Session.query(model.User).get(userid)
|
||||
if user:
|
||||
return has_permission(Session(), user, permission)
|
||||
if Everyone in principals:
|
||||
|
@ -51,3 +53,29 @@ class TailboneAuthorizationPolicy(object):
|
|||
|
||||
def principals_allowed_by_permission(self, context, permission):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def add_permission_group(config, key, label=None):
|
||||
"""
|
||||
Add a permission group to the app configuration.
|
||||
"""
|
||||
def action():
|
||||
perms = config.get_settings().get('tailbone_permissions', {})
|
||||
group = perms.setdefault(key, {'key': key})
|
||||
group['label'] = label or prettify(key)
|
||||
config.add_settings({'tailbone_permissions': perms})
|
||||
config.action(None, action)
|
||||
|
||||
|
||||
def add_permission(config, groupkey, key, label=None):
|
||||
"""
|
||||
Add a permission to the app configuration.
|
||||
"""
|
||||
def action():
|
||||
perms = config.get_settings().get('tailbone_permissions', {})
|
||||
group = perms.setdefault(groupkey, {'key': groupkey})
|
||||
group.setdefault('label', prettify(groupkey))
|
||||
perm = group.setdefault('perms', {}).setdefault(key, {'key': key})
|
||||
perm['label'] = label or prettify(key)
|
||||
config.add_settings({'tailbone_permissions': perms})
|
||||
config.action(None, action)
|
||||
|
|
|
@ -441,28 +441,42 @@ class MasterView(View):
|
|||
url_prefix = cls.get_url_prefix()
|
||||
permission_prefix = cls.get_permission_prefix()
|
||||
model_key = cls.get_model_key()
|
||||
model_title = cls.get_model_title()
|
||||
model_title_plural = cls.get_model_title_plural()
|
||||
|
||||
config.add_tailbone_permission_group(permission_prefix, model_title_plural)
|
||||
|
||||
# list/search
|
||||
config.add_route(route_prefix, '{0}/'.format(url_prefix))
|
||||
config.add_view(cls, attr='index', route_name=route_prefix,
|
||||
permission='{0}.list'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{0}.list'.format(permission_prefix),
|
||||
"List/Search {0}".format(model_title_plural))
|
||||
|
||||
# create
|
||||
config.add_route('{0}.create'.format(route_prefix), '{0}/new'.format(url_prefix))
|
||||
config.add_view(cls, attr='create', route_name='{0}.create'.format(route_prefix),
|
||||
permission='{0}.create'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{0}.create'.format(permission_prefix),
|
||||
"Create new {0}".format(model_title_plural))
|
||||
|
||||
# view
|
||||
config.add_route('{0}.view'.format(route_prefix), '{0}/{{{1}}}'.format(url_prefix, model_key))
|
||||
config.add_view(cls, attr='view', route_name='{0}.view'.format(route_prefix),
|
||||
permission='{0}.view'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{0}.view'.format(permission_prefix),
|
||||
"View {0} Details".format(model_title))
|
||||
|
||||
# edit
|
||||
config.add_route('{0}.edit'.format(route_prefix), '{0}/{{{1}}}/edit'.format(url_prefix, model_key))
|
||||
config.add_view(cls, attr='edit', route_name='{0}.edit'.format(route_prefix),
|
||||
permission='{0}.edit'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{0}.edit'.format(permission_prefix),
|
||||
"Edit {0}".format(model_title_plural))
|
||||
|
||||
# delete
|
||||
config.add_route('{0}.delete'.format(route_prefix), '{0}/{{{1}}}/delete'.format(url_prefix, model_key))
|
||||
config.add_view(cls, attr='delete', route_name='{0}.delete'.format(route_prefix),
|
||||
permission='{0}.delete'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{0}.delete'.format(permission_prefix),
|
||||
"Delete {0}".format(model_title_plural))
|
||||
|
|
|
@ -49,14 +49,10 @@ class PermissionsField(formalchemy.Field):
|
|||
role.permissions = self.renderer.deserialize()
|
||||
|
||||
|
||||
def OldPermissionsFieldRenderer(permissions, *args, **kwargs):
|
||||
def PermissionsFieldRenderer(permissions, *args, **kwargs):
|
||||
|
||||
perms = permissions
|
||||
|
||||
class PermissionsFieldRenderer(formalchemy.FieldRenderer):
|
||||
|
||||
permissions = perms
|
||||
|
||||
def deserialize(self):
|
||||
perms = []
|
||||
i = len(self.name) + 1
|
||||
|
@ -75,17 +71,18 @@ def OldPermissionsFieldRenderer(permissions, *args, **kwargs):
|
|||
html += tags.hidden(self.name, value='') # ugly hack..or good idea?
|
||||
else:
|
||||
html = ''
|
||||
for group, perms in self.permissions:
|
||||
inner = HTML.tag('p', c=group)
|
||||
for perm, title in perms:
|
||||
checked = has_permission(
|
||||
Session(), role, perm, include_guest=False)
|
||||
for groupkey in sorted(permissions, key=lambda k: permissions[k]['label']):
|
||||
inner = HTML.tag('p', c=permissions[groupkey]['label'])
|
||||
perms = permissions[groupkey]['perms']
|
||||
for key in sorted(perms, key=lambda p: perms[p]['label']):
|
||||
checked = has_permission(Session(), role, key, include_guest=False)
|
||||
label = perms[key]['label']
|
||||
if readonly:
|
||||
span = HTML.tag('span', c="[X]" if checked else "[ ]")
|
||||
inner += HTML.tag('p', class_='perm', c=span + ' ' + title)
|
||||
inner += HTML.tag('p', class_='perm', c=span + ' ' + label)
|
||||
else:
|
||||
inner += tags.checkbox(self.name + '-' + perm,
|
||||
checked=checked, label=title)
|
||||
inner += tags.checkbox(self.name + '-' + key,
|
||||
checked=checked, label=label)
|
||||
html += HTML.tag('div', class_='group', c=inner)
|
||||
return html
|
||||
|
||||
|
@ -116,7 +113,8 @@ class RolesView(MasterView):
|
|||
|
||||
def configure_fieldset(self, fs):
|
||||
fs.append(PermissionsField('permissions'))
|
||||
fs.permissions.set(renderer=OldPermissionsFieldRenderer(self.old_permissions))
|
||||
permissions = self.request.registry.settings.get('tailbone_permissions', {})
|
||||
fs.permissions.set(renderer=PermissionsFieldRenderer(permissions))
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.name,
|
||||
|
@ -159,15 +157,9 @@ class RoleVersionView(VersionView):
|
|||
View which shows version history for a role.
|
||||
"""
|
||||
parent_class = model.Role
|
||||
route_model_view = 'role.read'
|
||||
route_model_view = 'roles.view'
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
# TODO: This can finally be removed once all CRUD/index views have been
|
||||
# converted to use the new master view etc.
|
||||
settings = config.get_settings()
|
||||
RolesView.old_permissions = settings.get('edbob.permissions')
|
||||
|
||||
RolesView.defaults(config)
|
||||
version_defaults(config, RoleVersionView, 'role')
|
||||
|
|
Loading…
Reference in a new issue