import os import shutil from typing import List from zope import component from zope.interface import implementer from .validators import is_valid_forwarding_address, InvalidForwardingAddressException from ceo_common.interfaces import IFileService, IConfig, IUser @implementer(IFileService) class FileService: def __init__(self): cfg = component.getUtility(IConfig) self.member_home_skel = cfg.get('members_skel') self.club_home_skel = cfg.get('clubs_skel') def create_home_dir(self, user: IUser): if user.is_club(): skel_dir = self.club_home_skel else: skel_dir = self.member_home_skel home = user.home_directory # It's important to NOT use pwd here because if the user was recently # deleted (e.g. as part of a rolled back transaction), their old UID # and GID numbers will still be in the NSS cache. uid = user.uid_number gid = user.gid_number # recursively copy skel dir to user's home shutil.copytree(skel_dir, home) # Set ownership and permissions on user's home. # The setgid bit ensures that all files created under that # directory belong to the owner (useful for clubs). os.chmod(home, mode=0o2751) # rwxr-s--x os.chown(home, uid=uid, gid=gid) # recursively set file ownership for root, dirs, files in os.walk(home): for dir in dirs: os.chown(os.path.join(root, dir), uid=uid, gid=gid) for file in files: os.chown(os.path.join(root, file), uid=uid, gid=gid) def delete_home_dir(self, user: IUser): shutil.rmtree(user.home_directory) def get_forwarding_addresses(self, user: IUser) -> List[str]: forward_file = os.path.join(user.home_directory, '.forward') if not os.path.isfile(forward_file): return [] lines = [ line.strip() for line in open(forward_file).readlines() ] return [ line for line in lines if line != '' and line[0] != '#' ] def set_forwarding_addresses(self, user: IUser, addresses: List[str]): for line in addresses: if not is_valid_forwarding_address(line): raise InvalidForwardingAddressException(line) uid = user.uid_number gid = user.gid_number forward_file = os.path.join(user.home_directory, '.forward') if os.path.exists(forward_file): # create a backup backup_forward_file = forward_file + '.bak' shutil.copyfile(forward_file, backup_forward_file) os.chown(backup_forward_file, uid=uid, gid=gid) else: # create a new ~/.forward file open(forward_file, 'w') os.chown(forward_file, uid=uid, gid=gid) with open(forward_file, 'w') as f: for line in addresses: f.write(line + '\n')