From c592be30f36cc39d269ff761dccd6b463e214460 Mon Sep 17 00:00:00 2001 From: Willi Eggeling Date: Fri, 31 May 2024 14:14:42 +0200 Subject: [PATCH] support named groups in SAML claim * support group names in addition to group IDs * missing groups are automatically created * comma-separated group values are trimmed --- seahub/adfs_auth/backends.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/seahub/adfs_auth/backends.py b/seahub/adfs_auth/backends.py index b5f3c445aaf..112fb8d30de 100644 --- a/seahub/adfs_auth/backends.py +++ b/seahub/adfs_auth/backends.py @@ -20,6 +20,7 @@ from django.conf import settings from django.contrib.auth.backends import ModelBackend +from django.core.cache import cache from seaserv import ccnet_api, seafile_api @@ -34,6 +35,7 @@ SAML_PROVIDER_IDENTIFIER = getattr(settings, 'SAML_PROVIDER_IDENTIFIER', 'saml') SHIBBOLETH_AFFILIATION_ROLE_MAP = getattr(settings, 'SHIBBOLETH_AFFILIATION_ROLE_MAP', {}) +CACHE_KEY_GROUPS = "all_groups_cache" class Saml2Backend(ModelBackend): @@ -196,9 +198,28 @@ def sync_saml_groups(self, user, attributes): # support a list of comma-separated IDs as seafile_groups claim if len(seafile_groups) == 1 and ',' in seafile_groups[0]: - seafile_groups = seafile_groups[0].split(',') + seafile_groups = [group.strip() for group in seafile_groups[0].split(',')] - saml_group_ids = [int(group_id) for group_id in seafile_groups] + saml_group_ids = [] + if all(group_id.isdigit() for group_id in seafile_groups): + # all groups are provided as numeric IDs + saml_group_ids = [int(group_id) for group_id in seafile_groups] + else: + # groups are provided as names, try to get current group information from cache + all_groups = cache.get(CACHE_KEY_GROUPS) + if not all_groups or any(group not in all_groups for group in seafile_groups): + # groups not yet cached or missing entry, reload groups from API + all_groups = {group.group_name: group.id for group in ccnet_api.get_all_groups(-1, -1)} + cache.set(CACHE_KEY_GROUPS, all_groups, 3600) # cache for 1 hour + # create groups which are not yet existing + for group in [group_name for group_name in seafile_groups if group_name not in all_groups]: + new_group = ccnet_api.create_group(group, 'system admin') # we are not operating in user context here + if new_group < 0: + logger.error('failed to create group %s' % group) + return + all_groups[group] = new_group + # generate numeric IDs from group names + saml_group_ids = [id for group, id in all_groups.items() if group in seafile_groups] joined_groups = ccnet_api.get_groups(user.username) joined_group_ids = [g.id for g in joined_groups]