Skip to content

Commit 253505d

Browse files
committed
Implement primary group logic
1 parent 9fd130b commit 253505d

File tree

4 files changed

+72
-8
lines changed

4 files changed

+72
-8
lines changed

examples/sign/sign-sync-config.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ user_management:
6767
# group_admin: True
6868
# account_admin: True
6969

70+
# # when UMG is enabled, primary_group_rules is required to specify rules
71+
# # primary group designation. sync tool will log warning if this is present
72+
# # with UMG disabled. omitting it with UMG enabled will cause an error
73+
# primary_group_rules:
74+
# # sign_groups list can specify groups that aren't necessarily assigned
75+
# # the user in the sync tool
76+
# - sign_groups:
77+
# - Sign Group 1
78+
# - Sign Group 2
79+
# # assign the primary group only if the user is a member of all groups
80+
# # specified in sign_groups
81+
# primary_group: Sign Group 2
82+
7083
# Logging options
7184
logging:
7285
log_to_file: True

tests/fixture/sign-sync-config.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ user_management:
5757
admin_groups:
5858
- Sign Users
5959

60+
# when UMG is enabled, primary_group_rules is required to specify rules
61+
# primary group designation. sync tool will log warning if this is present
62+
# with UMG disabled. omitting it with UMG enabled will cause an error
63+
primary_group_rules:
64+
# sign_groups list can specify groups that aren't necessarily assigned
65+
# the user in the sync tool
66+
- sign_groups:
67+
- Sign Group 1
68+
- Sign Group 2
69+
# assign the primary group only if the user is a member of all groups
70+
# specified in sign_groups
71+
primary_group: Sign Group 2
72+
6073
# Logging options
6174
logging:
6275
log_to_file: True

user_sync/config/sign_sync.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ def config_schema() -> Schema:
4141
Optional('admin_groups'): Or(None, [And(str, len)]),
4242
Optional('account_admin', default=False): Or(bool, None)
4343
}],
44+
Optional('primary_group_rules'): [{
45+
'sign_groups': [And(str, len)],
46+
'primary_group': And(str, len),
47+
}],
4448
Optional('account_admin_groups'): list,
4549
'cache': {
4650
'path': And(str, len),
@@ -267,9 +271,16 @@ def _groupify(self, group_name):
267271
return group
268272

269273
def load_primary_group_rules(self, umg):
270-
# group_config = self.main_config.get_list_config('user_management', True)
271-
# return primary_group_rules
272-
return []
274+
primary_group_rules = []
275+
group_config = self.main_config.get_list_config('primary_group_rules', True)
276+
for mapping in group_config.iter_dict_configs():
277+
sign_groups = mapping.get_list('sign_groups')
278+
primary_group = mapping.get_string('primary_group')
279+
primary_group_rules.append({
280+
'sign_groups': set([g.lower() for g in sign_groups]),
281+
'primary_group': primary_group
282+
})
283+
return primary_group_rules
273284

274285
def get_directory_connector_module_name(self) -> str:
275286
# these .get()s can be safely chained because we've already validated the config schema

user_sync/engine/sign.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,25 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
287287
status='DELETED',
288288
)
289289

290+
# figure out primary group for user
291+
sign_groups = set([g.lower() for g in groups_to_update.keys()])\
292+
.union(set([g.lower() for g in assigned_groups.keys()]))
293+
desired_pg = self.resolve_primary_group(sign_groups)
294+
current_pg = [g.name.lower() for g in assigned_groups.values() if g.isPrimaryGroup]
295+
if current_pg:
296+
current_pg = current_pg[0]
297+
else:
298+
current_pg = None
299+
300+
if desired_pg is None:
301+
raise AssertionException(f"Can't identify a primary group for user '{sign_user.email}'")
302+
303+
if current_pg is None or desired_pg.lower() != current_pg:
304+
self.logger.debug(f"Primary group of '{sign_user.email}' is '{desired_pg}'")
305+
groups_to_update[desired_pg.lower()].isPrimaryGroup = True
290306

291307
if groups_to_update:
292-
group_update_data = UserGroupsInfo(groupInfoList=groups_to_update)
308+
group_update_data = UserGroupsInfo(groupInfoList=list(groups_to_update.values()))
293309
user_groups_update_list.append((sign_user.id, group_update_data))
294310

295311
sign_connector.update_users(users_update_list)
@@ -300,6 +316,12 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
300316
self.total_sign_only_user_count += 1
301317
self.sign_only_users_by_org[org_name][user] = data
302318

319+
def resolve_primary_group(self, sign_groups):
320+
rules = self.options['primary_group_rules']
321+
for r in rules:
322+
if set(sign_groups).intersection(r['sign_groups']) == r['sign_groups']:
323+
return r['primary_group']
324+
303325
@staticmethod
304326
def get_primary_group(user, sign_user_groups) -> UserGroupInfo:
305327
user_groups = sign_user_groups.get(user.id)
@@ -459,27 +481,32 @@ def insert_new_users(self, org_name: str, sign_connector: SignConnector, directo
459481
groups = assignment_groups
460482
else:
461483
groups = assignment_groups[0:1]
462-
groups_to_assign = []
484+
groups_to_assign = {}
463485
for group in groups:
464486
wants_group_admin = False
465487
if is_umg:
466488
wants_group_admin = directory_user['is_group_admin']
467489
else:
468490
wants_group_admin = group in directory_user['admin_groups']
469491
group_to_assign = self.sign_groups[org_name][group.group_name.lower()]
470-
groups_to_assign.append(UserGroupInfo(
492+
groups_to_assign[group_to_assign.groupName.lower()] = UserGroupInfo(
471493
id=group_to_assign.groupId,
472494
name=group_to_assign.groupName,
473495
isGroupAdmin=wants_group_admin,
474496
isPrimaryGroup=False,
475497
status='ACTIVE',
476-
))
498+
)
477499
self.logger.info(f"{self.org_string(sign_connector.console_org)}Assigning '{new_user.email}' to group '{group_to_assign.groupName}', group admin?: {wants_group_admin}")
500+
primary_group = self.resolve_primary_group(groups_to_assign.keys())
501+
if primary_group is None:
502+
raise AssertionException(f"Can't identify a primary group for user '{new_user.email}'")
503+
self.logger.debug(f"Primary group of '{new_user.email}' is '{primary_group}'")
504+
groups_to_assign[primary_group.lower()].isPrimaryGroup = True
478505
user_id = sign_connector.insert_user(new_user)
479506
self.sign_users_created.add(directory_user['email'])
480507
self.logger.info(f"{self.org_string(sign_connector.console_org)}Inserted sign user '{new_user.email}', admin?: {new_user.isAccountAdmin}")
481508

482-
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
509+
group_update_data = UserGroupsInfo(groupInfoList=list(groups_to_assign.values()))
483510
sign_connector.update_user_group_single(user_id, group_update_data)
484511
except ClientException as e:
485512
self.logger.error(format(e))

0 commit comments

Comments
 (0)