Skip to content

Commit bc6721c

Browse files
committed
Implement primary group logic
1 parent 005fdc8 commit bc6721c

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),
@@ -280,9 +284,16 @@ def _groupify(self, group_name):
280284
return group
281285

282286
def load_primary_group_rules(self, umg):
283-
# group_config = self.main_config.get_list_config('user_management', True)
284-
# return primary_group_rules
285-
return []
287+
primary_group_rules = []
288+
group_config = self.main_config.get_list_config('primary_group_rules', True)
289+
for mapping in group_config.iter_dict_configs():
290+
sign_groups = mapping.get_list('sign_groups')
291+
primary_group = mapping.get_string('primary_group')
292+
primary_group_rules.append({
293+
'sign_groups': set([g.lower() for g in sign_groups]),
294+
'primary_group': primary_group
295+
})
296+
return primary_group_rules
286297

287298
def get_directory_connector_module_name(self) -> str:
288299
# 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
@@ -308,9 +308,25 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
308308
status='DELETED',
309309
)
310310

311+
# figure out primary group for user
312+
sign_groups = set([g.lower() for g in groups_to_update.keys()])\
313+
.union(set([g.lower() for g in assigned_groups.keys()]))
314+
desired_pg = self.resolve_primary_group(sign_groups)
315+
current_pg = [g.name.lower() for g in assigned_groups.values() if g.isPrimaryGroup]
316+
if current_pg:
317+
current_pg = current_pg[0]
318+
else:
319+
current_pg = None
320+
321+
if desired_pg is None:
322+
raise AssertionException(f"Can't identify a primary group for user '{sign_user.email}'")
323+
324+
if current_pg is None or desired_pg.lower() != current_pg:
325+
self.logger.debug(f"Primary group of '{sign_user.email}' is '{desired_pg}'")
326+
groups_to_update[desired_pg.lower()].isPrimaryGroup = True
311327

312328
if groups_to_update:
313-
group_update_data = UserGroupsInfo(groupInfoList=groups_to_update)
329+
group_update_data = UserGroupsInfo(groupInfoList=list(groups_to_update.values()))
314330
user_groups_update_list.append((sign_user.id, group_update_data))
315331

316332
sign_connector.update_users(users_update_list)
@@ -321,6 +337,12 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
321337
self.total_sign_only_user_count += 1
322338
self.sign_only_users_by_org[org_name][user] = data
323339

340+
def resolve_primary_group(self, sign_groups):
341+
rules = self.options['primary_group_rules']
342+
for r in rules:
343+
if set(sign_groups).intersection(r['sign_groups']) == r['sign_groups']:
344+
return r['primary_group']
345+
324346
@staticmethod
325347
def get_primary_group(user, sign_user_groups) -> UserGroupInfo:
326348
user_groups = sign_user_groups.get(user.id)
@@ -480,27 +502,32 @@ def insert_new_users(self, org_name: str, sign_connector: SignConnector, directo
480502
groups = assignment_groups
481503
else:
482504
groups = assignment_groups[0:1]
483-
groups_to_assign = []
505+
groups_to_assign = {}
484506
for group in groups:
485507
wants_group_admin = False
486508
if is_umg:
487509
wants_group_admin = directory_user['is_group_admin']
488510
else:
489511
wants_group_admin = group in directory_user['admin_groups']
490512
group_to_assign = self.sign_groups[org_name][group.group_name.lower()]
491-
groups_to_assign.append(UserGroupInfo(
513+
groups_to_assign[group_to_assign.groupName.lower()] = UserGroupInfo(
492514
id=group_to_assign.groupId,
493515
name=group_to_assign.groupName,
494516
isGroupAdmin=wants_group_admin,
495517
isPrimaryGroup=False,
496518
status='ACTIVE',
497-
))
519+
)
498520
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}")
521+
primary_group = self.resolve_primary_group(groups_to_assign.keys())
522+
if primary_group is None:
523+
raise AssertionException(f"Can't identify a primary group for user '{new_user.email}'")
524+
self.logger.debug(f"Primary group of '{new_user.email}' is '{primary_group}'")
525+
groups_to_assign[primary_group.lower()].isPrimaryGroup = True
499526
user_id = sign_connector.insert_user(new_user)
500527
self.sign_users_created.add(directory_user['email'])
501528
self.logger.info(f"{self.org_string(sign_connector.console_org)}Inserted sign user '{new_user.email}', admin?: {new_user.isAccountAdmin}")
502529

503-
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
530+
group_update_data = UserGroupsInfo(groupInfoList=list(groups_to_assign.values()))
504531
sign_connector.update_user_group_single(user_id, group_update_data)
505532
except ClientException as e:
506533
self.logger.error(format(e))

0 commit comments

Comments
 (0)