""" This module contains the signal handlers of the :py:mod:`osusers` app. The module starts Celery_ tasks. .. _Celery: https://www.celeryproject.org/ """ from __future__ import absolute_import import logging from django.db.models.signals import post_delete, post_save from django.dispatch import receiver from fileservertasks.tasks import ( delete_file_mail_userdir, delete_file_sftp_userdir_chained, set_file_ssh_authorized_keys, setup_file_mail_userdir_chained, setup_file_sftp_userdir_chained, ) from ldaptasks.tasks import ( add_ldap_user_to_group, create_ldap_group, create_ldap_user, delete_ldap_group, delete_ldap_user_chained, remove_ldap_user_from_group, set_ldap_user_password, ) from taskresults.models import TaskResult from .models import AdditionalGroup, Group, SshPublicKey, User, password_set _LOGGER = logging.getLogger(__name__) @receiver(password_set, sender=User) def handle_user_password_set(sender, instance, password, **kwargs): """ Handles password changes on :py:class:`User ` instances. :param sender: sender of the signal :param instance: User instance :param str password: the new password This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "set ldap user password", color = "Wheat", description = ":py:func:`set_ldap_user_password() ` called with username and password, returning :py:const:`True` if the password has been set" ]; } """ taskresult = TaskResult.objects.create_task_result( "handle_user_password_set", set_ldap_user_password.s(instance.username, password), ) _LOGGER.info( "LDAP password change has been requested in task %s", taskresult.task_id ) @receiver(post_save, sender=Group) def handle_group_created(sender, instance, created, **kwargs): """ Handles post creation actions on :py:class:`Group ` instances. :param sender: sender of the signal :param instance: Group instance :param bool created: whether the instance has just been created This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "create ldap group", color = "Wheat", description = ":py:func:`create_ldap_group() ` called with groupname, gid and description, returning group DN" ]; } """ if created: taskresult = TaskResult.objects.create_task_result( "handle_group_created", create_ldap_group.s(instance.groupname, instance.gid, instance.descr), ) _LOGGER.info( "LDAP group creation has been requested in task %s", taskresult.task_id ) _LOGGER.debug("group %s has been %s", instance, created and "created" or "updated") @receiver(post_save, sender=User) def handle_user_created(sender, instance, created, **kwargs): """ Handles post creation actions on :py:class:`User ` instances. :param sender: sender of the signal :param instance: User instance :param bool created: whether the instance has just bean created This signal handler starts a chain of Celery_ tasks. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B -> C -> D; B -> C [folded]; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "create ldap user", color = "Wheat", description = ":py:func:`create_ldap_user() ` called with username, uid, gid, gecos, homeidr, shell, :py:const:`None`, returning username" ]; C [ label = "setup file sftp userdir", color = "LightGreen", description = ":py:func:`setup_file_sftp_userdir_chained() ` called with the result of create ldap user task, returning a dictionary containing username and sftp_directory"]; D [ label = "setup file mail userdir", color = "LightGreen", description = ":py:func:`setup_file_mail_userdir_chained() ` called with result of setup file sftp userdir task, returning dictionary containing username, sftp_directory and mail_directory" ]; } """ if created: task_ldap_1 = create_ldap_user.s( instance.username, instance.uid, instance.group.gid, instance.gecos, instance.homedir, instance.shell, None, ).set(queue="ldap") task_file_1 = setup_file_sftp_userdir_chained.s().set(queue="file") task_file_2 = setup_file_mail_userdir_chained.s().set(queue="file") chain = task_ldap_1 | task_file_1 | task_file_2 task_result = TaskResult.objects.create_task_result( "handle_user_created", chain ) _LOGGER.info( "LDAP user creation has been requested in task %s", task_result.task_id ) _LOGGER.debug("user %s has been %s", instance, created and "created" or "updated") @receiver(post_save, sender=AdditionalGroup) def handle_user_added_to_group(sender, instance, created, **kwargs): """ Handles post creation actions on :py:class:`AdditionalGroup ` instances. :param sender: sender of the signal :param instance: AdditionalGroup instance :param bool created: whether the instance has just bean created This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "add ldap user to group", color = "Wheat", description = ":py:func:`add_ldap_user_to_group() ` called with username and groupname, returning :py:const:`True` if the user has been added to the group" ]; } """ if created: taskresult = TaskResult.objects.create_task_result( "handle_user_added_to_group", add_ldap_user_to_group.s(instance.user.username, instance.group.groupname), ) _LOGGER.info( "Adding user to LDAP group has been requested in task %s", taskresult.task_id, ) @receiver(post_save, sender=SshPublicKey) @receiver(post_delete, sender=SshPublicKey) def handle_ssh_keys_changed(sender, instance, **kwargs): """ Handles changes to :py:class:`SshPublicKey ` instances related to a user. :param sender: sender of the signal :param instance: SshPublicKey instance This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "set file ssh authorized_keys", color = "LightGreen", description = ":py:func:`set_file_ssh_authorized_keys() ` called with username and the corresponding list of keys, returning the path of the ssh_authorized_keys_file" ]; } """ sig = set_file_ssh_authorized_keys.s( instance.user.username, [str(key) for key in SshPublicKey.objects.filter(user=instance.user)], ) taskresult = TaskResult.objects.create_task_result("handle_ssh_keys_changed", sig) _LOGGER.info("Change of SSH keys has been requested in task %s", taskresult.task_id) @receiver(post_delete, sender=Group) def handle_group_deleted(sender, instance, **kwargs): """ Handles cleanup actions to be done after deletion of a :py:class:`Group ` instance. :param sender: sender of the signal :param instance: Group instance This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "delete ldap group", color = "Wheat", description = ":py:func:`delete_ldap_group() ` called with groupname, returning :py:const:`True` if the group has been deleted" ]; } """ taskresult = TaskResult.objects.create_task_result( "handle_group_deleted", delete_ldap_group.s(instance.groupname) ) _LOGGER.info( "LDAP group deletion has been requested in task %s", taskresult.task_id ) @receiver(post_delete, sender=User) def handle_user_deleted(sender, instance, **kwargs): """ Handles cleanup actions to be done after deletion of a :py:class:`User ` instance. :param sender: sender of the signal :param instance: User instance This signal handler starts a chain of Celery_ tasks. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B -> C -> D; B -> C [folded]; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "delete file mail userdir", color = "LightGreen", description = ":py:func:`delete_file_mail_userdir() ` called with username, returning a dictionary containing the username and the deleted mail_directory" ]; C [ label = "delete file sftp userdir", color = "LightGreen", description = ":py:func:`delete_file_sftp_userdir_chained() ` called with the result of delete mail userdir, returning dictionary containing username, deleted mail_directory and deleted sftp_directory" ]; D [ label = "delete ldap user", color = "Wheat", description = ":py:func:`delete_ldap_user_chained() ` called with the result of delete file sftp userdir and adding the deleted user DN to the result" ]; } """ file_task_1 = delete_file_mail_userdir.s(instance.username).set(queue="file") file_task_2 = delete_file_sftp_userdir_chained.s().set(queue="file") ldap_task_1 = delete_ldap_user_chained.s().set(queue="ldap") chain = file_task_1 | file_task_2 | ldap_task_1 _LOGGER.debug("chain signature %s", chain) task_result = TaskResult.objects.create_task_result("handle_user_deleted", chain) _LOGGER.info( "LDAP user deletion has been requested in task %s", task_result.task_id ) @receiver(post_delete, sender=AdditionalGroup) def handle_user_removed_from_group(sender, instance, **kwargs): """ Handles cleanup actions to be done after removing a user from a group by deleting the :py:class:`AdditionalGroup ` instance. :param sender: sender of the signal :param instance: AdditionalGroup instance This signal handler starts a Celery_ task. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "remove ldap user from group", color = "Wheat", description = ":py:func:`remove_ldap_user_from_group() ` called with username and groupname, returning :py:const:`True` if the user has been a member of the group and has been removed from the group" ]; } """ taskresult = TaskResult.objects.create_task_result( "handle_user_removed_from_group", remove_ldap_user_from_group.s(instance.user.username, instance.group.groupname), ) _LOGGER.info( "Removing user from LDAP group has been requested in task %s", taskresult.task_id, )