You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.9 KiB
109 lines
3.9 KiB
from collections import defaultdict
|
|
from typing import Dict
|
|
|
|
from zope import component
|
|
|
|
from ..AbstractTransaction import AbstractTransaction
|
|
from ceo_common.interfaces import ILDAPService, IConfig, IUser
|
|
from ceo_common.errors import UserAlreadySubscribedError, UserNotSubscribedError
|
|
from ceo_common.logger_factory import logger_factory
|
|
|
|
logger = logger_factory(__name__)
|
|
|
|
|
|
class UpdateMemberPositionsTransaction(AbstractTransaction):
|
|
"""Transaction to update the CSC's executive positions."""
|
|
|
|
operations = [
|
|
'update_positions_ldap',
|
|
'update_exec_group_ldap',
|
|
'subscribe_to_mailing_lists',
|
|
]
|
|
|
|
def __init__(self, positions_reversed: Dict[str, str]):
|
|
# positions_reversed is position -> username
|
|
super().__init__()
|
|
self.ldap_srv = component.getUtility(ILDAPService)
|
|
|
|
# Reverse the dict so it's easier to use (username -> positions)
|
|
self.positions = defaultdict(list)
|
|
for position, username in positions_reversed.items():
|
|
self.positions[username].append(position)
|
|
|
|
# a cached Dict of the Users who need to be modified (username -> User)
|
|
self.users: Dict[str, IUser] = {}
|
|
|
|
# for rollback purposes
|
|
self.old_positions = {} # username -> positions
|
|
self.old_execs = []
|
|
|
|
def child_execute_iter(self):
|
|
cfg = component.getUtility(IConfig)
|
|
mailing_lists = cfg.get('auxiliary mailing lists_exec')
|
|
|
|
# position -> username
|
|
new_positions_reversed = {} # For returning result
|
|
|
|
# retrieve User objects and cache them
|
|
for username in self.positions:
|
|
user = self.ldap_srv.get_user(username)
|
|
self.users[user.uid] = user
|
|
|
|
# Remove positions for old users
|
|
for user in self.ldap_srv.get_users_with_positions():
|
|
if user.uid not in self.positions:
|
|
self.positions[user.uid] = []
|
|
self.users[user.uid] = user
|
|
|
|
# Update positions in LDAP
|
|
for username, new_positions in self.positions.items():
|
|
user = self.users[username]
|
|
old_positions = user.positions[:]
|
|
|
|
user.set_positions(new_positions)
|
|
|
|
self.old_positions[username] = old_positions
|
|
for position in new_positions:
|
|
new_positions_reversed[position] = username
|
|
yield 'update_positions_ldap'
|
|
|
|
# update exec group in LDAP
|
|
exec_group = self.ldap_srv.get_group('exec')
|
|
self.old_execs = exec_group.members[:]
|
|
new_execs = [
|
|
username for username, new_positions in self.positions.items()
|
|
if len(new_positions) > 0
|
|
]
|
|
exec_group.set_members(new_execs)
|
|
yield 'update_exec_group_ldap'
|
|
|
|
# Update mailing list subscriptions
|
|
subscription_failed = False
|
|
for username, new_positions in self.positions.items():
|
|
user = self.users[username]
|
|
for mailing_list in mailing_lists:
|
|
try:
|
|
if len(new_positions) > 0:
|
|
user.subscribe_to_mailing_list(mailing_list)
|
|
else:
|
|
user.unsubscribe_from_mailing_list(mailing_list)
|
|
except (UserAlreadySubscribedError, UserNotSubscribedError):
|
|
pass
|
|
except Exception:
|
|
logger.warning(f'Failed to update mailing list for {user.uid}')
|
|
subscription_failed = True
|
|
if subscription_failed:
|
|
yield 'failed_to_subscribe_to_mailing_lists'
|
|
else:
|
|
yield 'subscribe_to_mailing_lists'
|
|
|
|
self.finish(new_positions_reversed)
|
|
|
|
def rollback(self):
|
|
if 'update_exec_group_ldap' in self.finished_operations:
|
|
exec_group = self.ldap_srv.get_group('exec')
|
|
exec_group.set_members(self.old_execs)
|
|
|
|
for username, positions in self.old_positions.items():
|
|
user = self.users[username]
|
|
user.set_positions(positions)
|
|
|