Add ability to download roles / permissions matrix as Excel file
This commit is contained in:
parent
6463df7224
commit
e5f0831369
12
tailbone/templates/roles/index.mako
Normal file
12
tailbone/templates/roles/index.mako
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/principal/index.mako" />
|
||||||
|
|
||||||
|
<%def name="context_menu_items()">
|
||||||
|
${parent.context_menu_items()}
|
||||||
|
% if master.has_perm('download_permissions_matrix'):
|
||||||
|
<li>${h.link_to("Download Permissions Matrix", url('roles.download_permissions_matrix'))}</li>
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -26,12 +26,16 @@ Role Views
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
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 (has_permission, grant_permission, revoke_permission,
|
||||||
administrator_role, guest_role, authenticated_role)
|
administrator_role, guest_role, authenticated_role)
|
||||||
|
from rattail.excel import ExcelWriter
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
from deform import widget as dfwidget
|
from deform import widget as dfwidget
|
||||||
|
@ -278,6 +282,69 @@ class RolesView(PrincipalMasterView):
|
||||||
roles.append(role)
|
roles.append(role)
|
||||||
return roles
|
return roles
|
||||||
|
|
||||||
|
def download_permissions_matrix(self):
|
||||||
|
"""
|
||||||
|
View which renders the complete role / permissions matrix data into an
|
||||||
|
Excel spreadsheet, and returns that file.
|
||||||
|
"""
|
||||||
|
roles = self.Session.query(model.Role)\
|
||||||
|
.order_by(model.Role.name)\
|
||||||
|
.all()
|
||||||
|
|
||||||
|
permissions = self.get_available_permissions()
|
||||||
|
|
||||||
|
# prep the excel writer
|
||||||
|
path = os.path.join(self.rattail_config.workdir(),
|
||||||
|
'permissions-matrix.xlsx')
|
||||||
|
writer = ExcelWriter(path, None)
|
||||||
|
sheet = writer.sheet
|
||||||
|
|
||||||
|
# write header
|
||||||
|
sheet.cell(row=1, column=1, value="")
|
||||||
|
for i, role in enumerate(roles, 2):
|
||||||
|
sheet.cell(row=1, column=i, value=role.name)
|
||||||
|
|
||||||
|
# font and fill pattern for permission group rows
|
||||||
|
bold = Font(bold=True)
|
||||||
|
group_fill = PatternFill(patternType='solid',
|
||||||
|
fgColor='d9d9d9',
|
||||||
|
bgColor='d9d9d9')
|
||||||
|
|
||||||
|
# now we'll write the rows
|
||||||
|
writing_row = 2
|
||||||
|
for groupkey in sorted(permissions, key=lambda k: permissions[k]['label'].lower()):
|
||||||
|
group = permissions[groupkey]
|
||||||
|
|
||||||
|
# group label is bold, with fill pattern
|
||||||
|
cell = sheet.cell(row=writing_row, column=1, value=group['label'])
|
||||||
|
cell.font = bold
|
||||||
|
cell.fill = group_fill
|
||||||
|
|
||||||
|
# continue fill pattern for rest of group row
|
||||||
|
for col, role in enumerate(roles, 2):
|
||||||
|
cell = sheet.cell(row=writing_row, column=col)
|
||||||
|
cell.fill = group_fill
|
||||||
|
|
||||||
|
# okay, that row is done
|
||||||
|
writing_row += 1
|
||||||
|
|
||||||
|
# now we list each perm in the group
|
||||||
|
perms = group['perms']
|
||||||
|
for key in sorted(perms, key=lambda p: perms[p]['label'].lower()):
|
||||||
|
sheet.cell(row=writing_row, column=1, value=perms[key]['label'])
|
||||||
|
|
||||||
|
# and show an 'X' for any role which has this perm
|
||||||
|
for col, role in enumerate(roles, 2):
|
||||||
|
if has_permission(self.Session(), role, key, include_guest=False):
|
||||||
|
sheet.cell(row=writing_row, column=col, value="X")
|
||||||
|
|
||||||
|
writing_row += 1
|
||||||
|
|
||||||
|
writer.auto_resize()
|
||||||
|
writer.auto_freeze()
|
||||||
|
writer.save()
|
||||||
|
return self.file_response(path)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
cls._principal_defaults(config)
|
cls._principal_defaults(config)
|
||||||
|
@ -286,6 +353,8 @@ class RolesView(PrincipalMasterView):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _role_defaults(cls, config):
|
def _role_defaults(cls, config):
|
||||||
|
route_prefix = cls.get_route_prefix()
|
||||||
|
url_prefix = cls.get_url_prefix()
|
||||||
permission_prefix = cls.get_permission_prefix()
|
permission_prefix = cls.get_permission_prefix()
|
||||||
|
|
||||||
# extra permissions for editing built-in roles etc.
|
# extra permissions for editing built-in roles etc.
|
||||||
|
@ -296,6 +365,14 @@ class RolesView(PrincipalMasterView):
|
||||||
config.add_tailbone_permission(permission_prefix, '{}.edit_my'.format(permission_prefix),
|
config.add_tailbone_permission(permission_prefix, '{}.edit_my'.format(permission_prefix),
|
||||||
"Edit Role(s) to which current user belongs")
|
"Edit Role(s) to which current user belongs")
|
||||||
|
|
||||||
|
# download permissions matrix
|
||||||
|
config.add_tailbone_permission(permission_prefix, '{}.download_permissions_matrix'.format(permission_prefix),
|
||||||
|
"Download complete Role/Permissions matrix")
|
||||||
|
config.add_route('{}.download_permissions_matrix'.format(route_prefix), '{}/permissions-matrix'.format(url_prefix),
|
||||||
|
request_method='GET')
|
||||||
|
config.add_view(cls, attr='download_permissions_matrix', route_name='{}.download_permissions_matrix'.format(route_prefix),
|
||||||
|
permission='{}.download_permissions_matrix'.format(permission_prefix))
|
||||||
|
|
||||||
|
|
||||||
class PermissionsWidget(dfwidget.Widget):
|
class PermissionsWidget(dfwidget.Widget):
|
||||||
template = 'permissions'
|
template = 'permissions'
|
||||||
|
|
Loading…
Reference in a new issue