Invoke the auth handler to cache user permissions etc.

various changes for sake of "synced" roles feature
This commit is contained in:
Lance Edgar 2021-10-14 10:39:54 -04:00
parent 80589cde2f
commit 22aa55c24b
4 changed files with 74 additions and 12 deletions

View file

@ -52,10 +52,13 @@ class RoleView(PrincipalMasterView):
"""
model_class = model.Role
has_versions = True
touchable = True
grid_columns = [
'name',
'session_timeout',
'sync_me',
'node_type',
'notes',
]
@ -63,6 +66,8 @@ class RoleView(PrincipalMasterView):
'name',
'session_timeout',
'notes',
'sync_me',
'node_type',
'users',
'permissions',
]
@ -93,6 +98,11 @@ class RoleView(PrincipalMasterView):
We must prevent edit for certain built-in roles etc., depending on
current user's permissions.
"""
# role with node type specified, can only be edited from a
# node of the same type
if role.node_type and role.node_type != self.rattail_config.node_type():
return False
# only "root" can edit Administrator
if role is administrator_role(self.Session()):
return self.request.is_root
@ -116,6 +126,11 @@ class RoleView(PrincipalMasterView):
"""
We must prevent deletion for all built-in roles.
"""
# role with node type specified, can only be edited from a
# node of the same type
if role.node_type and role.node_type != self.rattail_config.node_type():
return False
if role is administrator_role(self.Session()):
return False
if role is authenticated_role(self.Session()):
@ -147,6 +162,27 @@ class RoleView(PrincipalMasterView):
# name
f.set_validator('name', self.unique_name)
# session_timeout
f.set_renderer('session_timeout', self.render_session_timeout)
if self.editing and role is guest_role(self.Session()):
f.set_readonly('session_timeout')
# sync_me, node_type
if not self.creating:
include = True
if role is administrator_role(self.Session()):
include = False
elif role is authenticated_role(self.Session()):
include = False
elif role is guest_role(self.Session()):
include = False
if not include:
f.remove('sync_me', 'node_type')
else:
if not self.has_perm('edit_node_sync'):
f.set_readonly('sync_me')
f.set_readonly('node_type')
# notes
f.set_type('notes', 'text_wrapped')
@ -173,11 +209,6 @@ class RoleView(PrincipalMasterView):
elif self.deleting:
f.remove_field('permissions')
# session_timeout
f.set_renderer('session_timeout', self.render_session_timeout)
if self.editing and role is guest_role(self.Session()):
f.set_readonly('session_timeout')
def render_users(self, role, field):
if role is guest_role(self.Session()):
@ -417,6 +448,7 @@ class RoleView(PrincipalMasterView):
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
model_title = cls.get_model_title()
# extra permissions for editing built-in roles etc.
config.add_tailbone_permission(permission_prefix, '{}.edit_authenticated'.format(permission_prefix),
@ -425,6 +457,9 @@ class RoleView(PrincipalMasterView):
"Edit the \"Guest\" Role")
config.add_tailbone_permission(permission_prefix, '{}.edit_my'.format(permission_prefix),
"Edit Role(s) to which current user belongs")
config.add_tailbone_permission(permission_prefix,
'{}.edit_node_sync'.format(permission_prefix),
"Edit the Node Type and Sync flags for a {}".format(model_title))
# download permissions matrix
config.add_tailbone_permission(permission_prefix, '{}.download_permissions_matrix'.format(permission_prefix),

View file

@ -320,6 +320,14 @@ class UserView(PrincipalMasterView):
if self.request.is_root or uuid != admin.uuid:
user._roles.append(model.UserRole(role_uuid=uuid))
# also record a change to the role, for datasync.
# this is done "just in case" the role is to be
# synced to all nodes
if self.Session().rattail_record_changes:
self.Session.add(model.Change(class_name='Role',
instance_uuid=uuid,
deleted=False))
# remove any roles which were *not* specified, although must take care
# not to remove admin role, unless acting as root
for uuid in old_roles:
@ -328,6 +336,14 @@ class UserView(PrincipalMasterView):
role = self.Session.query(model.Role).get(uuid)
user.roles.remove(role)
# also record a change to the role, for datasync.
# this is done "just in case" the role is to be
# synced to all nodes
if self.Session().rattail_record_changes:
self.Session.add(model.Change(class_name='Role',
instance_uuid=uuid,
deleted=False))
def render_person(self, user, field):
person = user.person
if not person: