Source code for univention.admin.guardian_roles

# SPDX-FileCopyrightText: 2024-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

"""|UDM| guardian roles handling"""

import itertools

import univention.admin
import univention.admin.localization
import univention.admin.syntax
from univention.admin.layout import Tab


try:
    from univention.admin.syntax import GuardianRole
except ImportError:  # just during errata updates. Can be removed in UCS 5.2-3
    GuardianRole = univention.admin.syntax.simple


translation = univention.admin.localization.translation('univention.admin')
_ = translation.translate


[docs] def member_role_properties(): return { 'guardianMemberRoles': univention.admin.property( short_description=_('Roles used by Guardian for access permissions, these roles are passed to the members of this group'), long_description=_("Lowercase ASCII alphanumeric string with underscores or dashes, in the format 'app:namespace:role' or 'app:namespace:role&app:namespace:context'"), syntax=GuardianRole, size='Two', multivalue=True, ), }
[docs] def role_properties(): return { 'guardianRoles': univention.admin.property( short_description=_('Roles used by Guardian for access permissions'), long_description=_("Lowercase ASCII alphanumeric string with underscores or dashes, in the format 'app:namespace:role' or 'app:namespace:role&app:namespace:context'"), syntax=GuardianRole, size='Two', multivalue=True, ), 'guardianInheritedRoles': univention.admin.property( short_description=_('Roles used by Guardian for access permissions. Inherited by group membership'), long_description=_('Roles used by Guardian for access permissions. Inherited by group membership'), prevent_umc_default_popup=True, syntax=GuardianRole, size='Two', may_change=False, multivalue=True, dontsearch=True, show_in_lists=True, cli_enabled=False, lazy_loading_fn='open_guardian', ), }
[docs] def register_member_role_mapping(mapping): mapping.register('guardianMemberRoles', 'univentionGuardianMemberRoles', None, None)
[docs] def register_role_mapping(mapping): mapping.register('guardianRoles', 'univentionGuardianRoles', None, None)
[docs] def member_role_layout(): return Tab( _('Guardian'), _('Manage roles that are used for authorization'), advanced=True, layout=[ 'guardianMemberRoles', ], )
[docs] def role_layout(): return Tab( _('Guardian'), _('Manage roles that are used for authorization'), advanced=True, layout=[ 'guardianRoles', 'guardianInheritedRoles', ], )
@univention.admin._ldap_cache(ttl=60) def get_group_role(lo: univention.admin.uldap.access, dn: str) -> list[str]: res = lo.authz_connection.get(dn, attr=['univentionGuardianMemberRoles']) return [x.decode('UTF-8') for x in res.get('univentionGuardianMemberRoles', [])] # TODO: # naive approach to get role strings for groups by searching the LDAP
[docs] def load_roles(lo: univention.admin.uldap.access, groups: list[str]) -> list[str]: return list(set(itertools.chain.from_iterable(get_group_role(lo, group) for group in groups)))
[docs] def get_roles_from_ldap(lo: univention.admin.uldap.access, dn: str) -> list[str]: res = lo.authz_connection.get(dn, attr=['univentionGuardianRoles', 'memberOf']) roles = {x.decode('UTF-8') for x in res.get('univentionGuardianRoles', [])} if 'memberOf' in res: roles.update(load_roles(lo, [x.decode('UTF-8') for x in res['memberOf']])) return list(roles)
[docs] class GuardianBase:
[docs] def open_guardian(self) -> None: if self.exists() and self.has_property('guardianInheritedRoles'): groups = self.get('groups', []) if self.get('primaryGroup'): groups = [*groups, self['primaryGroup']] self.info['guardianInheritedRoles'] = load_roles(self.lo, groups) self.save()