Add ability to download roles / permissions matrix as Excel file

This commit is contained in:
Lance Edgar 2020-06-22 16:00:33 -05:00
parent 6463df7224
commit e5f0831369
2 changed files with 89 additions and 0 deletions

View 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()}

View file

@ -26,12 +26,16 @@ Role Views
from __future__ import unicode_literals, absolute_import
import os
import six
from sqlalchemy import orm
from openpyxl.styles import Font, PatternFill
from rattail.db import model
from rattail.db.auth import (has_permission, grant_permission, revoke_permission,
administrator_role, guest_role, authenticated_role)
from rattail.excel import ExcelWriter
import colander
from deform import widget as dfwidget
@ -278,6 +282,69 @@ class RolesView(PrincipalMasterView):
roles.append(role)
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
def defaults(cls, config):
cls._principal_defaults(config)
@ -286,6 +353,8 @@ class RolesView(PrincipalMasterView):
@classmethod
def _role_defaults(cls, config):
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
# 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),
"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):
template = 'permissions'