Skip to content

Commit 48a1529

Browse files
committed
implement UMG for new and existing users (partial)
1 parent 3ea0d56 commit 48a1529

File tree

2 files changed

+119
-64
lines changed

2 files changed

+119
-64
lines changed

user_sync/config/sign_sync.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,7 @@ def load_directory_groups(self) -> Dict[str, AdobeGroup]:
187187
for sg in sign_group:
188188
# AdobeGroup will return the same memory instance of a pre-existing group,
189189
# so we create it no matter what
190-
group = AdobeGroup.create(sg)
191-
if group is None:
192-
raise AssertionException('Bad Sign group: "{}" in directory group: "{}"'.format(sign_group, dir_group))
193-
if group.umapi_name is None:
194-
group.umapi_name = self.DEFAULT_ORG_NAME
190+
group = self._groupify(sg)
195191

196192
# Note checking a memory equivalency, not group name
197193
# the groups in group_mapping are stored in order of YML file - important
@@ -224,8 +220,10 @@ def load_group_admin_mappings(self, umg):
224220
group_admin_mappings = {}
225221
group_config = self.main_config.get_list_config('user_management', True)
226222
for mapping in group_config.iter_dict_configs():
227-
dir_group = mapping.get_string('directory_group')
223+
dir_group = mapping.get_string('directory_group').lower()
228224
sign_group = mapping.get_list('sign_group', True)
225+
if sign_group is not None:
226+
sign_group = [sg.lower() for sg in sign_group]
229227

230228
group_admin = mapping.get_bool('group_admin', True)
231229
if (sign_group is None or not len(sign_group)) and group_admin:
@@ -238,19 +236,20 @@ def load_group_admin_mappings(self, umg):
238236
raise AssertionException("If UMG is enabled, then at least one Sign group is required in a mapping that enables group admin")
239237
continue
240238

241-
group = AdobeGroup.create(sign_group[0])
242-
if group is None:
243-
raise AssertionException('Bad Sign group: "{}" in directory group: "{}"'.format(sign_group, dir_group))
244-
if group.umapi_name is None:
245-
group.umapi_name = self.DEFAULT_ORG_NAME
246-
247239
admin_groups = mapping.get_list('admin_groups', True)
248240
using_admin_groups = admin_groups is not None and len(admin_groups)
249241

242+
# if group_admin flag is True and we're not using admin_groups list, then
243+
# map the first item in sign_group list and move on
250244
if group_admin and not using_admin_groups:
245+
group = self._groupify(sign_group[0])
251246
if dir_group not in group_admin_mappings:
252247
group_admin_mappings[dir_group] = set()
253248
group_admin_mappings[dir_group].add(group)
249+
continue
250+
251+
if not group_admin:
252+
continue
254253

255254
if not using_admin_groups:
256255
continue
@@ -260,15 +259,31 @@ def load_group_admin_mappings(self, umg):
260259
continue
261260

262261
for ag in admin_groups:
262+
ag = ag.lower()
263263
if ag not in sign_group:
264264
self.logger.warn("Skipping admin group '%s' because it isn't specified in 'sign_group'", ag)
265265
continue
266266
if dir_group not in group_admin_mappings:
267267
group_admin_mappings[dir_group] = set()
268-
group_admin_mappings[dir_group].add(ag)
268+
group_admin_mappings[dir_group].add(self._groupify(ag))
269269

270270
return group_admin_mappings
271271

272+
def _groupify(self, group_name):
273+
"""For a given group name, return AdobeGroup with proper primary
274+
target, error checking, etc"""
275+
group = AdobeGroup.create(group_name.lower())
276+
if group is None:
277+
raise AssertionException(f"Bad sign group '{group_name}' specified")
278+
if group.umapi_name is None:
279+
group.umapi_name = self.DEFAULT_ORG_NAME
280+
return group
281+
282+
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 []
286+
272287
def get_directory_connector_module_name(self) -> str:
273288
# these .get()s can be safely chained because we've already validated the config schema
274289
return self.main_config.get_dict('identity_source').get('type')
@@ -315,6 +330,7 @@ def get_engine_options(self) -> dict:
315330
options['cache'] = self.main_config.get_dict('cache')
316331
options['account_admin_groups'] = self.load_account_admin_groups()
317332
options['group_admin_mappings'] = self.load_group_admin_mappings(options['user_sync']['umg'])
333+
options['primary_group_rules'] = self.load_primary_group_rules(options['user_sync']['umg'])
318334
return options
319335

320336
def check_unused_config_keys(self):

user_sync/engine/sign.py

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def __init__(self, caller_options, target_options: dict[str, dict]):
6969
self.sign_users_matched_no_updates = set()
7070
self.directory_users_excluded = set()
7171
self.sign_only_users_by_org: dict[str, dict[str, DetailedUserInfo]] = {}
72+
self.target_groups_by_org = {}
7273
self.total_sign_only_user_count = 0
7374

7475
def get_groups(self, org):
@@ -92,6 +93,9 @@ def run(self, directory_groups, directory_connector):
9293
for org_name in self.connectors:
9394
self.sign_groups[org_name] = self.get_groups(org_name)
9495
self.default_groups[org_name] = self.get_default_group(org_name)
96+
self.target_groups_by_org[org_name] = set([group for groups in [g['groups']
97+
for g in directory_groups.values()]
98+
for group in groups if group.umapi_name == org_name])
9599

96100
for org_name, sign_connector in self.connectors.items():
97101
self.sign_user_groups[org_name] = sign_connector.get_user_groups()
@@ -203,6 +207,7 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
203207
self.directory_users_excluded.add(directory_user['email'])
204208
continue
205209
else:
210+
is_umg = self.options['user_sync']['umg']
206211
# do not update if admin status should not change
207212
if sign_user.isAccountAdmin != directory_user['is_admin']:
208213
# Update existing users
@@ -214,45 +219,68 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
214219
user_data.isAccountAdmin = directory_user['is_admin']
215220
self.sign_users_role_updates.add(sign_user.email)
216221
users_update_list.append(user_data)
222+
217223
# manage primary group asssignment
218-
# current_group: UserGroupInfo = self.sign_user_primary_groups[org_name][sign_user.id]
219-
current_group = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
220-
should_be_group_admin = directory_user['is_group_admin']
221-
is_group_admin = current_group.isGroupAdmin
224+
current_groups = self.sign_user_groups[org_name].get(sign_user.id)
225+
226+
assigned_groups = {}
227+
if current_groups is not None:
228+
assigned_groups = {g.name.lower(): g for g in current_groups}
229+
if not is_umg:
230+
g = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
231+
assigned_groups = {g.name.lower(): g}
222232

223-
assignment_group = None
233+
desired_groups = set()
224234
if directory_user['sign_groups']:
225-
assignment_group = directory_user['sign_groups'][0].group_name
235+
desired_groups = set([g.group_name.lower() for g in directory_user['sign_groups']])
226236
else:
227-
assignment_group = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
228-
229-
updated_group_info = False
230-
group_to_assign = UserGroupInfo(
231-
id=current_group.id,
232-
name=current_group.name,
233-
isGroupAdmin=is_group_admin,
234-
isPrimaryGroup=current_group.isPrimaryGroup,
235-
status=current_group.status,
236-
createdDate=current_group.createdDate,
237-
settings=current_group.settings,
238-
)
239-
240-
if current_group.name.lower() != assignment_group.lower():
241-
assignment_group_info: GroupInfo = self.sign_groups[org_name][assignment_group.lower()]
242-
self.logger.info(f"Assigning primary group '{assignment_group}' to user {sign_user.email}")
243-
group_to_assign.id = assignment_group_info.groupId
244-
group_to_assign.name = assignment_group_info.groupName
245-
self.sign_users_group_updates.add(sign_user.email)
246-
updated_group_info=True
247-
248-
if is_group_admin != should_be_group_admin:
249-
self.logger.info(f"Changing group Admin role for user '{sign_user.email}', status? {should_be_group_admin}")
250-
group_to_assign.isGroupAdmin = should_be_group_admin
251-
self.sign_users_role_updates.add(sign_user.email)
252-
updated_group_info=True
237+
desired_groups = set([self.get_primary_group(sign_user, self.sign_user_groups[org_name]).name.lower()])
238+
if not is_umg:
239+
desired_groups = set([directory_user['sign_roups'][0].group_name.lower()])
240+
target_groups = set([g.group_name.lower() for g in self.target_groups_by_org[org_name]])
241+
242+
groups_to_assign = []
243+
for dg in desired_groups:
244+
group_info = self.sign_groups[org_name].get(dg)
245+
if group_info is None:
246+
raise AssertionException(f"'{dg}' isn't a valid Sign group")
247+
248+
assigned_group = assigned_groups.get(group_info.groupName.lower())
249+
250+
wants_group_admin = False
251+
if is_umg:
252+
wants_group_admin = directory_user['is_group_admin']
253+
else:
254+
wants_group_admin = dg in directory_user['admin_groups']
255+
256+
change_group_admin = (assigned_group is None and
257+
wants_group_admin) or \
258+
(assigned_group is not None and
259+
assigned_group.isGroupAdmin is not wants_group_admin)
260+
261+
if assigned_group is not None and not change_group_admin:
262+
continue
263+
264+
if assigned_group is None:
265+
self.logger.info(f"Assigning group '{group_info.groupId}' to user {sign_user.email}")
266+
self.sign_users_group_updates.add(sign_user.email)
267+
268+
admin_status = False if not wants_group_admin and assigned_group.isGroupAdmin is not wants_group_admin else True
253269

254-
if updated_group_info:
255-
group_update_data = UserGroupsInfo(groupInfoList=[group_to_assign])
270+
if change_group_admin:
271+
self.logger.info(f"Changing group Admin role for user '{sign_user.email}', status? {admin_status}")
272+
self.sign_users_role_updates.add(sign_user.email)
273+
274+
groups_to_assign.append(UserGroupInfo(
275+
id=group_info.groupId,
276+
name=group_info.groupName,
277+
isGroupAdmin=admin_status,
278+
isPrimaryGroup=False,
279+
status='ACTIVE',
280+
))
281+
282+
if groups_to_assign:
283+
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
256284
user_groups_update_list.append((sign_user.id, group_update_data))
257285

258286
sign_connector.update_users(users_update_list)
@@ -375,14 +403,15 @@ def get_directory_user_key(self, directory_user):
375403

376404
@staticmethod
377405
def resolve_group_mappings(directory_groups, group_mapping, account_admin_groups, group_admin_mapping) -> dict:
378-
matched_groups = []
406+
matched_groups = set()
379407

380408
matched_mappings = [m for g, m in group_mapping.items() if g in directory_groups]
381409
matched_mappings.sort(key=lambda x: x['priority'])
382410

383-
for g in matched_mappings:
384-
if g['groups']:
385-
matched_groups.extend(g['groups'])
411+
for m in matched_mappings:
412+
if m['groups']:
413+
for g in m['groups']:
414+
matched_groups.add(g)
386415

387416
is_admin = False
388417
for g in directory_groups:
@@ -400,7 +429,7 @@ def resolve_group_mappings(directory_groups, group_mapping, account_admin_groups
400429
is_group_admin = True
401430
admin_groups.update(target_groups)
402431

403-
return matched_groups, is_admin, is_group_admin, admin_groups
432+
return list(matched_groups), is_admin, is_group_admin, admin_groups
404433

405434
def insert_new_users(self, org_name: str, sign_connector: SignConnector, directory_user: dict, assignment_groups):
406435
"""
@@ -416,23 +445,33 @@ def insert_new_users(self, org_name: str, sign_connector: SignConnector, directo
416445
lastName=directory_user['lastname'],
417446
)
418447
try:
448+
is_umg = self.options['user_sync']['umg']
449+
if is_umg:
450+
groups = assignment_groups
451+
else:
452+
groups = assignment_groups[0:1]
453+
groups_to_assign = []
454+
for group in groups:
455+
wants_group_admin = False
456+
if is_umg:
457+
wants_group_admin = directory_user['is_group_admin']
458+
else:
459+
wants_group_admin = group in directory_user['admin_groups']
460+
group_to_assign = self.sign_groups[org_name][group.group_name.lower()]
461+
groups_to_assign.append(UserGroupInfo(
462+
id=group_to_assign.groupId,
463+
name=group_to_assign.groupName,
464+
isGroupAdmin=wants_group_admin,
465+
isPrimaryGroup=False,
466+
status='ACTIVE',
467+
))
468+
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}")
419469
user_id = sign_connector.insert_user(new_user)
420470
self.sign_users_created.add(directory_user['email'])
421471
self.logger.info(f"{self.org_string(sign_connector.console_org)}Inserted sign user '{new_user.email}', admin?: {new_user.isAccountAdmin}")
422472

423-
assignment_group = assignment_groups[0].group_name
424-
group_to_assign: GroupInfo = self.sign_groups[org_name][assignment_group.lower()]
425-
426-
group_update_data = UserGroupsInfo(groupInfoList=[UserGroupInfo(
427-
id=group_to_assign.groupId,
428-
name=group_to_assign.groupName,
429-
isGroupAdmin=directory_user['is_group_admin'],
430-
isPrimaryGroup=True,
431-
status='ACTIVE',
432-
)])
433-
473+
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
434474
sign_connector.update_user_group_single(user_id, group_update_data)
435-
self.logger.info(f"{self.org_string(sign_connector.console_org)}Assigned '{new_user.email}' to group '{group_to_assign.groupName}', group admin?: {directory_user['is_group_admin']}")
436475
except ClientException as e:
437476
self.logger.error(format(e))
438477

0 commit comments

Comments
 (0)