""" This module contains the signal handlers of the :py:mod:`userdbs` app. The module starts Celery_ tasks. .. _Celery: http://www.celeryproject.org/ """ import logging from django.db.models.signals import post_delete, post_save from django.dispatch import receiver from passlib.pwd import genword from mysqltasks.tasks import ( create_mysql_database, create_mysql_user, delete_mysql_database, delete_mysql_user, set_mysql_userpassword, ) from pgsqltasks.tasks import ( create_pgsql_database, create_pgsql_user, delete_pgsql_database, delete_pgsql_user, set_pgsql_userpassword, ) from taskresults.models import TaskResult from .models import DB_TYPES, DatabaseUser, UserDatabase, password_set _LOGGER = logging.getLogger(__name__) @receiver(password_set, sender=DatabaseUser) def handle_dbuser_password_set(sender, instance, password, **kwargs): """ Signal handler triggered by password changes for :py:class:`userdbs.models.DatabaseUser` instances. :param sender: the sender of the signal :param instance: the Database user instance :param str password: the new password for the database user This signal handler starts Celery_ tasks depending on the db_type value of the database user. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A -> C; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "set mysql userpassword", color = "PowderBlue", description = ":py:func:`set_mysql_userpassword() ` called with database username and password" ]; C [ label = "set pgsql userpassword", color = "DodgerBlue", description = ":py:func:`set_pgsql_userpassword() ` called with database username and password" ]; } """ if instance.db_type == DB_TYPES.mysql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_password_set", set_mysql_userpassword.s(instance.name, password), "mysql password change", ) _LOGGER.info( "MySQL password change has been requested in task %s", taskresult.task_id ) elif instance.db_type == DB_TYPES.pgsql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_password_set", set_pgsql_userpassword.s(instance.name, password), "pgsql password change", ) _LOGGER.info( "PostgreSQL password change has been requested in task %s", taskresult.task_id, ) else: _LOGGER.warning( "Password change has been requested for unknown database %s" " the request has been ignored.", instance.db_type, ) @receiver(post_save, sender=DatabaseUser) def handle_dbuser_created(sender, instance, created, **kwargs): """ Signal handler triggered after the creation of or updates to :py:class:`userdbs.models.DatabaseUser` instances. :param sender: the sender of the signal :param instance: the DatabaseUser instance :param bool created: whether this signal handler is called for a newly created instance This signal handler starts Celery_ tasks depending on the db_type value of the database user. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A -> C; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "create mysql user", color = "PowderBlue", description = ":py:func:`create_mysql_user() ` called with database username and password" ]; C [ label = "create pgsql user", color = "DodgerBlue", description = ":py:func:`create_pgsql_user ` called with database username and password" ]; } """ if created: password = kwargs.get("password", genword()) # TODO: send GPG encrypted mail with this information if instance.db_type == DB_TYPES.mysql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_created", create_mysql_user.s(instance.name, password), "mysql user creation", ) _LOGGER.info( "A new MySQL user %s creation has been requested in task %s", instance.name, taskresult.task_id, ) elif instance.db_type == DB_TYPES.pgsql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_created", create_pgsql_user.s(instance.name, password), "pgsql user creation", ) _LOGGER.info( "A new PostgreSQL user %s creation has been requested in task" " %s", instance.name, taskresult.task_id, ) else: _LOGGER.warning( "created DatabaseUser for unknown database type %s", instance.db_type ) _LOGGER.debug( "database user %s has been %s", instance, created and "created" or "updated" ) @receiver(post_delete, sender=DatabaseUser) def handle_dbuser_deleted(sender, instance, **kwargs): """ Signal handler triggered after the deletion of :py:class:`userdbs.models.DatabaseUser` instances. :param sender: the sender of the signal :param instance: the DatabaseUser instance This signal handler starts Celery_ tasks depending on the db_type value of the database user. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A -> C; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "delete mysql user", color = "PowderBlue", description = ":py:func:`delete_mysql_user() ` called with username from instance.name" ]; C [ label = "delete pgsql user", color = "DodgerBlue", description = ":py:func:`delete_pgsql_user() ` called with username from instance.name" ]; } """ if instance.db_type == DB_TYPES.mysql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_deleted", delete_mysql_user.s(instance.name), "mysql user deletion", ) _LOGGER.info( "MySQL user %s deletion has been requested in task %s", instance.name, taskresult.task_id, ) elif instance.db_type == DB_TYPES.pgsql: taskresult = TaskResult.objects.create_task_result( "handle_dbuser_deleted", delete_pgsql_user.s(instance.name), "pgsql user deletion", ) _LOGGER.info( "PostgreSQL user %s deletion has been requested in task %s", instance.name, taskresult.task_id, ) else: _LOGGER.warning( "deleted DatabaseUser %s for unknown database type %s", instance.name, instance.db_type, ) _LOGGER.debug("database user %s has been deleted", instance) @receiver(post_save, sender=UserDatabase) def handle_userdb_created(sender, instance, created, **kwargs): """ Signal handler triggered after the creation of or updates to :py:class:`userdbs.models.UserDatabase` instances. :param sender: the sender of the signal :param instance: the UserDatabase instance :param bool created: whether this signal handler has been called for a newly created instance This signal handler starts Celery_ tasks depending on the db_type value of the database user owning the UserDatabase instance. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A -> C; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "create mysql database", color = "PowderBlue", description = ":py:func:`create_mysql_database() ` called with database name and username" ]; C [ label = "create pgsql database", color = "DodgerBlue", description = ":py:func:`create_pgsql_database() ` called with database name and username" ]; } """ if created: if instance.db_user.db_type == DB_TYPES.mysql: taskresult = TaskResult.objects.create_task_result( "handle_userdb_created", create_mysql_database.s(instance.db_name, instance.db_user.name), "mysql database creation", ) _LOGGER.info( "The creation of a new MySQL database %s has been requested in" " task %s", instance.db_name, taskresult.task_id, ) elif instance.db_user.db_type == DB_TYPES.pgsql: taskresult = TaskResult.objects.create_task_result( "handle_userdb_created", create_pgsql_database.s(instance.db_name, instance.db_user.name), "pgsql database creation", ) _LOGGER.info( "The creation of a new PostgreSQL database %s has been" " requested in task %s", instance.db_name, taskresult.task_id, ) else: _LOGGER.warning( "created UserDatabase for unknown database type %s", instance.db_user.db_type, ) _LOGGER.debug( "database %s has been %s", instance, created and "created" or "updated" ) @receiver(post_delete, sender=UserDatabase) def handle_userdb_deleted(sender, instance, **kwargs): """ Signal handler triggered after the deletion of :py:class:`userdbs.models.UserDatabase` instances. :param sender: the sender of the signal :param instance: the UserDatabase instance This signal handler starts Celery_ tasks depending on the db_type value of the database user owning the UserDatabase instance. .. blockdiag:: :desctable: blockdiag { node_width = 200; A -> B; A -> C; A [ label = "", shape = beginpoint, description = "this signal handler" ]; B [ label = "delete mysql database", color = "PowderBlue", description = ":py:func:`delete_mysql_user() ` called with database name and username" ]; C [ label = "delete pgsql database", color = "DodgerBlue", description = ":py:func:`delete_pgsql_user() ` called with database name" ]; } """ if instance.db_user.db_type == DB_TYPES.mysql: taskresult = TaskResult.objects.create_task_result( "handle_userdb_deleted", delete_mysql_database.s(instance.db_name, instance.db_user.name), "mysql database deletion", ) _LOGGER.info( "The deletion of MySQL database %s has been requested in task %s", instance.db_name, taskresult.task_id, ) elif instance.db_user.db_type == DB_TYPES.pgsql: taskresult = TaskResult.objects.create_task_result( "handle_userdb_deleted", delete_pgsql_database.s(instance.db_name), "pgsql database deletion", ) _LOGGER.info( "The deletion of PostgreSQL database %s has been requested in " " task %s", instance.db_name, taskresult.task_id, ) else: _LOGGER.warning( "deleted UserDatabase %s of unknown type %s", instance.db_name, instance.db_type, ) pass _LOGGER.debug("database %s has been deleted", instance)