708641a8f1
gosh it feels good to get rid of this stuff... fingers crossed that nothing was broken, but am thinking it's safe
165 lines
6.4 KiB
Python
165 lines
6.4 KiB
Python
# -*- coding: utf-8; -*-
|
|
################################################################################
|
|
#
|
|
# Rattail -- Retail Software Framework
|
|
# Copyright © 2010-2021 Lance Edgar
|
|
#
|
|
# This file is part of Rattail.
|
|
#
|
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
# version.
|
|
#
|
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
################################################################################
|
|
"""
|
|
"Principal" master view
|
|
"""
|
|
|
|
from __future__ import unicode_literals, absolute_import
|
|
|
|
import copy
|
|
|
|
from rattail.db.auth import has_permission
|
|
from rattail.core import Object
|
|
from rattail.util import OrderedDict
|
|
|
|
import wtforms
|
|
from webhelpers2.html import HTML
|
|
|
|
from tailbone.db import Session
|
|
from tailbone.views import MasterView
|
|
|
|
|
|
class PrincipalMasterView(MasterView):
|
|
"""
|
|
Master view base class for security principal models, i.e. User and Role.
|
|
"""
|
|
|
|
def get_fallback_templates(self, template, **kwargs):
|
|
return [
|
|
'/principal/{}.mako'.format(template),
|
|
] + super(PrincipalMasterView, self).get_fallback_templates(template, **kwargs)
|
|
|
|
def perm_sortkey(self, item):
|
|
key, value = item
|
|
return value['label'].lower()
|
|
|
|
def find_by_perm(self):
|
|
"""
|
|
View for finding all users who have been granted a given permission
|
|
"""
|
|
permissions = copy.deepcopy(self.request.registry.settings.get('tailbone_permissions', {}))
|
|
|
|
# sort groups, and permissions for each group, for UI's sake
|
|
sorted_perms = sorted(permissions.items(), key=self.perm_sortkey)
|
|
for key, group in sorted_perms:
|
|
group['perms'] = sorted(group['perms'].items(), key=self.perm_sortkey)
|
|
|
|
# group options are stable, permission options may depend on submitted group
|
|
group_choices = [(gkey, group['label']) for gkey, group in sorted_perms]
|
|
permission_choices = [('_any_', "(any)")]
|
|
if self.request.method == 'POST':
|
|
if self.request.POST.get('permission_group') in permissions:
|
|
permission_choices.extend([
|
|
(pkey, perm['label'])
|
|
for pkey, perm in permissions[self.request.POST['permission_group']]['perms']
|
|
])
|
|
|
|
class PermissionForm(wtforms.Form):
|
|
permission_group = wtforms.SelectField(choices=group_choices)
|
|
permission = wtforms.SelectField(choices=permission_choices)
|
|
|
|
principals = None
|
|
form = PermissionForm(self.request.POST)
|
|
if self.request.method == 'POST' and form.validate():
|
|
permission = form.permission.data
|
|
principals = self.find_principals_with_permission(self.Session(), permission)
|
|
|
|
context = {'form': form, 'permissions': sorted_perms, 'principals': principals}
|
|
|
|
if self.get_use_buefy():
|
|
perms = self.get_buefy_perms_data(sorted_perms)
|
|
context['buefy_perms'] = perms
|
|
context['buefy_sorted_groups'] = list(perms)
|
|
context['selected_group'] = self.request.POST.get('permission_group', 'common')
|
|
context['selected_permission'] = self.request.POST.get('permission', None)
|
|
|
|
return self.render_to_response('find_by_perm', context)
|
|
|
|
def get_buefy_perms_data(self, sorted_perms):
|
|
data = OrderedDict()
|
|
for gkey, group in sorted_perms:
|
|
|
|
gperms = []
|
|
for pkey, perm in group['perms']:
|
|
gperms.append({
|
|
'permkey': pkey,
|
|
'label': perm['label'],
|
|
})
|
|
|
|
data[gkey] = {
|
|
'groupkey': gkey,
|
|
'label': group['label'],
|
|
'permissions': gperms,
|
|
}
|
|
|
|
return data
|
|
|
|
@classmethod
|
|
def defaults(cls, config):
|
|
cls._principal_defaults(config)
|
|
cls._defaults(config)
|
|
|
|
@classmethod
|
|
def _principal_defaults(cls, config):
|
|
route_prefix = cls.get_route_prefix()
|
|
url_prefix = cls.get_url_prefix()
|
|
permission_prefix = cls.get_permission_prefix()
|
|
model_title_plural = cls.get_model_title_plural()
|
|
|
|
# find principal by permission
|
|
config.add_route('{}.find_by_perm'.format(route_prefix), '{}/find-by-perm'.format(url_prefix))
|
|
config.add_view(cls, attr='find_by_perm', route_name='{}.find_by_perm'.format(route_prefix),
|
|
permission='{}.find_by_perm'.format(permission_prefix))
|
|
config.add_tailbone_permission(permission_prefix, '{}.find_by_perm'.format(permission_prefix),
|
|
"Find all {} with permission X".format(model_title_plural))
|
|
|
|
|
|
class PermissionsRenderer(Object):
|
|
permissions = None
|
|
include_guest = False
|
|
include_authenticated = False
|
|
|
|
def __call__(self, principal, field):
|
|
self.principal = principal
|
|
return self.render()
|
|
|
|
def render(self):
|
|
principal = self.principal
|
|
html = ''
|
|
for groupkey in sorted(self.permissions, key=lambda k: self.permissions[k]['label'].lower()):
|
|
inner = HTML.tag('p', class_='group-label', c=self.permissions[groupkey]['label'])
|
|
perms = self.permissions[groupkey]['perms']
|
|
rendered = False
|
|
for key in sorted(perms, key=lambda p: perms[p]['label'].lower()):
|
|
checked = has_permission(Session(), principal, key,
|
|
include_guest=self.include_guest,
|
|
include_authenticated=self.include_authenticated)
|
|
if checked:
|
|
label = perms[key]['label']
|
|
span = HTML.tag('span', c="[X]" if checked else "[ ]")
|
|
inner += HTML.tag('p', class_='perm', c=[span, HTML(' '), label])
|
|
rendered = True
|
|
if rendered:
|
|
html += HTML.tag('div', class_='permissions-group', c=[inner])
|
|
return HTML.tag('div', class_='permissions-outer', c=[html or "(none granted)"])
|