Skip to content

Commit b8111ff

Browse files
committed
implement UMG for new and existing users (partial)
1 parent 57b2eaa commit b8111ff

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
@@ -174,11 +174,7 @@ def load_directory_groups(self) -> Dict[str, AdobeGroup]:
174174
for sg in sign_group:
175175
# AdobeGroup will return the same memory instance of a pre-existing group,
176176
# so we create it no matter what
177-
group = AdobeGroup.create(sg)
178-
if group is None:
179-
raise AssertionException('Bad Sign group: "{}" in directory group: "{}"'.format(sign_group, dir_group))
180-
if group.umapi_name is None:
181-
group.umapi_name = self.DEFAULT_ORG_NAME
177+
group = self._groupify(sg)
182178

183179
# Note checking a memory equivalency, not group name
184180
# the groups in group_mapping are stored in order of YML file - important
@@ -211,8 +207,10 @@ def load_group_admin_mappings(self, umg):
211207
group_admin_mappings = {}
212208
group_config = self.main_config.get_list_config('user_management', True)
213209
for mapping in group_config.iter_dict_configs():
214-
dir_group = mapping.get_string('directory_group')
210+
dir_group = mapping.get_string('directory_group').lower()
215211
sign_group = mapping.get_list('sign_group', True)
212+
if sign_group is not None:
213+
sign_group = [sg.lower() for sg in sign_group]
216214

217215
group_admin = mapping.get_bool('group_admin', True)
218216
if (sign_group is None or not len(sign_group)) and group_admin:
@@ -225,19 +223,20 @@ def load_group_admin_mappings(self, umg):
225223
raise AssertionException("If UMG is enabled, then at least one Sign group is required in a mapping that enables group admin")
226224
continue
227225

228-
group = AdobeGroup.create(sign_group[0])
229-
if group is None:
230-
raise AssertionException('Bad Sign group: "{}" in directory group: "{}"'.format(sign_group, dir_group))
231-
if group.umapi_name is None:
232-
group.umapi_name = self.DEFAULT_ORG_NAME
233-
234226
admin_groups = mapping.get_list('admin_groups', True)
235227
using_admin_groups = admin_groups is not None and len(admin_groups)
236228

229+
# if group_admin flag is True and we're not using admin_groups list, then
230+
# map the first item in sign_group list and move on
237231
if group_admin and not using_admin_groups:
232+
group = self._groupify(sign_group[0])
238233
if dir_group not in group_admin_mappings:
239234
group_admin_mappings[dir_group] = set()
240235
group_admin_mappings[dir_group].add(group)
236+
continue
237+
238+
if not group_admin:
239+
continue
241240

242241
if not using_admin_groups:
243242
continue
@@ -247,15 +246,31 @@ def load_group_admin_mappings(self, umg):
247246
continue
248247

249248
for ag in admin_groups:
249+
ag = ag.lower()
250250
if ag not in sign_group:
251251
self.logger.warn("Skipping admin group '%s' because it isn't specified in 'sign_group'", ag)
252252
continue
253253
if dir_group not in group_admin_mappings:
254254
group_admin_mappings[dir_group] = set()
255-
group_admin_mappings[dir_group].add(ag)
255+
group_admin_mappings[dir_group].add(self._groupify(ag))
256256

257257
return group_admin_mappings
258258

259+
def _groupify(self, group_name):
260+
"""For a given group name, return AdobeGroup with proper primary
261+
target, error checking, etc"""
262+
group = AdobeGroup.create(group_name.lower())
263+
if group is None:
264+
raise AssertionException(f"Bad sign group '{group_name}' specified")
265+
if group.umapi_name is None:
266+
group.umapi_name = self.DEFAULT_ORG_NAME
267+
return group
268+
269+
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 []
273+
259274
def get_directory_connector_module_name(self) -> str:
260275
# these .get()s can be safely chained because we've already validated the config schema
261276
return self.main_config.get_dict('identity_source').get('type')
@@ -299,6 +314,7 @@ def get_engine_options(self) -> dict:
299314
options['cache'] = self.main_config.get_dict('cache')
300315
options['account_admin_groups'] = self.load_account_admin_groups()
301316
options['group_admin_mappings'] = self.load_group_admin_mappings(options['user_sync']['umg'])
317+
options['primary_group_rules'] = self.load_primary_group_rules(options['user_sync']['umg'])
302318
return options
303319

304320
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
@@ -68,6 +68,7 @@ def __init__(self, caller_options, target_options: dict[str, dict]):
6868
self.sign_users_matched_no_updates = set()
6969
self.directory_users_excluded = set()
7070
self.sign_only_users_by_org: dict[str, dict[str, DetailedUserInfo]] = {}
71+
self.target_groups_by_org = {}
7172
self.total_sign_only_user_count = 0
7273

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

9599
for org_name, sign_connector in self.connectors.items():
96100
self.sign_user_groups[org_name] = sign_connector.get_user_groups()
@@ -182,6 +186,7 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
182186
self.directory_users_excluded.add(directory_user['email'])
183187
continue
184188
else:
189+
is_umg = self.options['user_sync']['umg']
185190
# do not update if admin status should not change
186191
if sign_user.isAccountAdmin != directory_user['is_admin']:
187192
# Update existing users
@@ -193,45 +198,68 @@ def update_sign_users(self, directory_users, sign_connector: SignConnector, org_
193198
user_data.isAccountAdmin = directory_user['is_admin']
194199
self.sign_users_role_updates.add(sign_user.email)
195200
users_update_list.append(user_data)
201+
196202
# manage primary group asssignment
197-
# current_group: UserGroupInfo = self.sign_user_primary_groups[org_name][sign_user.id]
198-
current_group = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
199-
should_be_group_admin = directory_user['is_group_admin']
200-
is_group_admin = current_group.isGroupAdmin
203+
current_groups = self.sign_user_groups[org_name].get(sign_user.id)
204+
205+
assigned_groups = {}
206+
if current_groups is not None:
207+
assigned_groups = {g.name.lower(): g for g in current_groups}
208+
if not is_umg:
209+
g = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
210+
assigned_groups = {g.name.lower(): g}
201211

202-
assignment_group = None
212+
desired_groups = set()
203213
if directory_user['sign_groups']:
204-
assignment_group = directory_user['sign_groups'][0].group_name
214+
desired_groups = set([g.group_name.lower() for g in directory_user['sign_groups']])
205215
else:
206-
assignment_group = self.get_primary_group(sign_user, self.sign_user_groups[org_name])
207-
208-
updated_group_info = False
209-
group_to_assign = UserGroupInfo(
210-
id=current_group.id,
211-
name=current_group.name,
212-
isGroupAdmin=is_group_admin,
213-
isPrimaryGroup=current_group.isPrimaryGroup,
214-
status=current_group.status,
215-
createdDate=current_group.createdDate,
216-
settings=current_group.settings,
217-
)
218-
219-
if current_group.name.lower() != assignment_group.lower():
220-
assignment_group_info: GroupInfo = self.sign_groups[org_name][assignment_group.lower()]
221-
self.logger.info(f"Assigning primary group '{assignment_group}' to user {sign_user.email}")
222-
group_to_assign.id = assignment_group_info.groupId
223-
group_to_assign.name = assignment_group_info.groupName
224-
self.sign_users_group_updates.add(sign_user.email)
225-
updated_group_info=True
226-
227-
if is_group_admin != should_be_group_admin:
228-
self.logger.info(f"Changing group Admin role for user '{sign_user.email}', status? {should_be_group_admin}")
229-
group_to_assign.isGroupAdmin = should_be_group_admin
230-
self.sign_users_role_updates.add(sign_user.email)
231-
updated_group_info=True
216+
desired_groups = set([self.get_primary_group(sign_user, self.sign_user_groups[org_name]).name.lower()])
217+
if not is_umg:
218+
desired_groups = set([directory_user['sign_roups'][0].group_name.lower()])
219+
target_groups = set([g.group_name.lower() for g in self.target_groups_by_org[org_name]])
220+
221+
groups_to_assign = []
222+
for dg in desired_groups:
223+
group_info = self.sign_groups[org_name].get(dg)
224+
if group_info is None:
225+
raise AssertionException(f"'{dg}' isn't a valid Sign group")
226+
227+
assigned_group = assigned_groups.get(group_info.groupName.lower())
228+
229+
wants_group_admin = False
230+
if is_umg:
231+
wants_group_admin = directory_user['is_group_admin']
232+
else:
233+
wants_group_admin = dg in directory_user['admin_groups']
234+
235+
change_group_admin = (assigned_group is None and
236+
wants_group_admin) or \
237+
(assigned_group is not None and
238+
assigned_group.isGroupAdmin is not wants_group_admin)
239+
240+
if assigned_group is not None and not change_group_admin:
241+
continue
242+
243+
if assigned_group is None:
244+
self.logger.info(f"Assigning group '{group_info.groupId}' to user {sign_user.email}")
245+
self.sign_users_group_updates.add(sign_user.email)
246+
247+
admin_status = False if not wants_group_admin and assigned_group.isGroupAdmin is not wants_group_admin else True
232248

233-
if updated_group_info:
234-
group_update_data = UserGroupsInfo(groupInfoList=[group_to_assign])
249+
if change_group_admin:
250+
self.logger.info(f"Changing group Admin role for user '{sign_user.email}', status? {admin_status}")
251+
self.sign_users_role_updates.add(sign_user.email)
252+
253+
groups_to_assign.append(UserGroupInfo(
254+
id=group_info.groupId,
255+
name=group_info.groupName,
256+
isGroupAdmin=admin_status,
257+
isPrimaryGroup=False,
258+
status='ACTIVE',
259+
))
260+
261+
if groups_to_assign:
262+
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
235263
user_groups_update_list.append((sign_user.id, group_update_data))
236264

237265
sign_connector.update_users(users_update_list)
@@ -354,14 +382,15 @@ def get_directory_user_key(self, directory_user):
354382

355383
@staticmethod
356384
def resolve_group_mappings(directory_groups, group_mapping, account_admin_groups, group_admin_mapping) -> dict:
357-
matched_groups = []
385+
matched_groups = set()
358386

359387
matched_mappings = [m for g, m in group_mapping.items() if g in directory_groups]
360388
matched_mappings.sort(key=lambda x: x['priority'])
361389

362-
for g in matched_mappings:
363-
if g['groups']:
364-
matched_groups.extend(g['groups'])
390+
for m in matched_mappings:
391+
if m['groups']:
392+
for g in m['groups']:
393+
matched_groups.add(g)
365394

366395
is_admin = False
367396
for g in directory_groups:
@@ -379,7 +408,7 @@ def resolve_group_mappings(directory_groups, group_mapping, account_admin_groups
379408
is_group_admin = True
380409
admin_groups.update(target_groups)
381410

382-
return matched_groups, is_admin, is_group_admin, admin_groups
411+
return list(matched_groups), is_admin, is_group_admin, admin_groups
383412

384413
def insert_new_users(self, org_name: str, sign_connector: SignConnector, directory_user: dict, assignment_groups):
385414
"""
@@ -395,23 +424,33 @@ def insert_new_users(self, org_name: str, sign_connector: SignConnector, directo
395424
lastName=directory_user['lastname'],
396425
)
397426
try:
427+
is_umg = self.options['user_sync']['umg']
428+
if is_umg:
429+
groups = assignment_groups
430+
else:
431+
groups = assignment_groups[0:1]
432+
groups_to_assign = []
433+
for group in groups:
434+
wants_group_admin = False
435+
if is_umg:
436+
wants_group_admin = directory_user['is_group_admin']
437+
else:
438+
wants_group_admin = group in directory_user['admin_groups']
439+
group_to_assign = self.sign_groups[org_name][group.group_name.lower()]
440+
groups_to_assign.append(UserGroupInfo(
441+
id=group_to_assign.groupId,
442+
name=group_to_assign.groupName,
443+
isGroupAdmin=wants_group_admin,
444+
isPrimaryGroup=False,
445+
status='ACTIVE',
446+
))
447+
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}")
398448
user_id = sign_connector.insert_user(new_user)
399449
self.sign_users_created.add(directory_user['email'])
400450
self.logger.info(f"{self.org_string(sign_connector.console_org)}Inserted sign user '{new_user.email}', admin?: {new_user.isAccountAdmin}")
401451

402-
assignment_group = assignment_groups[0].group_name
403-
group_to_assign: GroupInfo = self.sign_groups[org_name][assignment_group.lower()]
404-
405-
group_update_data = UserGroupsInfo(groupInfoList=[UserGroupInfo(
406-
id=group_to_assign.groupId,
407-
name=group_to_assign.groupName,
408-
isGroupAdmin=directory_user['is_group_admin'],
409-
isPrimaryGroup=True,
410-
status='ACTIVE',
411-
)])
412-
452+
group_update_data = UserGroupsInfo(groupInfoList=groups_to_assign)
413453
sign_connector.update_user_group_single(user_id, group_update_data)
414-
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']}")
415454
except ClientException as e:
416455
self.logger.error(format(e))
417456

0 commit comments

Comments
 (0)