209 lines
6.7 KiB
Python

"""LDAP signals для DepartmentRole и RoleAssignment."""
import logging
from django.conf import settings
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from employees.ldap import DepartmentService
from employees.ldap.errors import (
DirectoryDbError,
DirectoryLdapError,
DirectoryServiceError,
)
from employees.signals.ldap._queue import _enqueue
logger = logging.getLogger(__name__)
def _is_ldap_enabled():
return getattr(settings, "LDAP_ENABLED", False)
@receiver(post_save, sender="employees.DepartmentRole")
def sync_department_role_to_ldap_on_save(sender, instance, created, **kwargs):
del sender, created, kwargs
if not _is_ldap_enabled():
return
if getattr(instance, "_skip_ldap_sync", False):
return
try:
DepartmentService().sync_role_state(instance)
except (DirectoryLdapError, DirectoryServiceError, DirectoryDbError) as e:
logger.exception(
"LDAP department role sync failed",
extra={
"event": "ldap.department_role.sync_failed",
"department_role_id": instance.pk,
"department_id": instance.department_id,
"error_type": type(e).__name__,
},
)
_enqueue(
"department_role_save",
"department_role",
instance.pk,
{"role_pk": str(instance.pk)},
)
except Exception as e:
logger.exception(
"Unexpected LDAP department role sync failure",
extra={
"event": "ldap.department_role.sync_unexpected_failure",
"department_role_id": instance.pk,
"department_id": instance.department_id,
"error_type": type(e).__name__,
},
)
finally:
if hasattr(instance, "_skip_ldap_sync"):
delattr(instance, "_skip_ldap_sync")
@receiver(post_delete, sender="employees.DepartmentRole")
def sync_department_role_to_ldap_on_delete(sender, instance, **kwargs):
del sender, kwargs
if not _is_ldap_enabled():
return
try:
DepartmentService().sync_role_delete(
instance.department,
role_group_dn=(instance.ldap_group_dn or "").strip() or None,
)
except (DirectoryLdapError, DirectoryServiceError, DirectoryDbError) as e:
logger.exception(
"LDAP department role deletion failed",
extra={
"event": "ldap.department_role.delete_failed",
"department_role_id": instance.pk,
"department_id": instance.department_id,
"error_type": type(e).__name__,
},
)
_enqueue(
"department_role_delete",
"department_role",
instance.pk,
{
"department_pk": str(instance.department_id),
"role_group_dn": (instance.ldap_group_dn or "").strip(),
},
)
except Exception as e:
logger.exception(
"Unexpected LDAP department role deletion failure",
extra={
"event": "ldap.department_role.delete_unexpected_failure",
"department_role_id": instance.pk,
"department_id": instance.department_id,
"error_type": type(e).__name__,
},
)
@receiver(post_save, sender="employees.RoleAssignment")
def sync_role_assignment_to_ldap_on_save(sender, instance, created, **kwargs):
del sender, created, kwargs
if not _is_ldap_enabled():
return
if getattr(instance, "_skip_ldap_sync", False):
return
try:
DepartmentService().sync_role_assignment_state(
instance.employee,
instance.role,
is_active=instance.is_active,
)
except (DirectoryLdapError, DirectoryServiceError, DirectoryDbError) as e:
logger.exception(
"LDAP role assignment sync failed",
extra={
"event": "ldap.role_assignment.sync_failed",
"role_assignment_id": instance.pk,
"employee_id": instance.employee_id,
"department_role_id": instance.role_id,
"is_active": instance.is_active,
"error_type": type(e).__name__,
},
)
_enqueue(
"role_assignment",
"role_assignment",
instance.pk,
{
"employee_pk": str(instance.employee_id),
"role_pk": str(instance.role_id),
"is_active": bool(instance.is_active),
},
)
except Exception as e:
logger.exception(
"Unexpected LDAP role assignment sync failure",
extra={
"event": "ldap.role_assignment.sync_unexpected_failure",
"role_assignment_id": instance.pk,
"employee_id": instance.employee_id,
"department_role_id": instance.role_id,
"error_type": type(e).__name__,
},
)
finally:
if hasattr(instance, "_skip_ldap_sync"):
delattr(instance, "_skip_ldap_sync")
@receiver(post_delete, sender="employees.RoleAssignment")
def sync_role_assignment_to_ldap_on_delete(sender, instance, **kwargs):
del sender, kwargs
if not _is_ldap_enabled():
return
try:
DepartmentService().sync_role_assignment_state(
instance.employee,
instance.role,
is_active=False,
)
except (DirectoryLdapError, DirectoryServiceError, DirectoryDbError) as e:
logger.exception(
"LDAP role assignment deletion sync failed",
extra={
"event": "ldap.role_assignment.delete_sync_failed",
"role_assignment_id": instance.pk,
"employee_id": instance.employee_id,
"department_role_id": instance.role_id,
"error_type": type(e).__name__,
},
)
_enqueue(
"role_assignment",
"role_assignment",
instance.pk,
{
"employee_pk": str(instance.employee_id),
"role_pk": str(instance.role_id),
"is_active": False,
},
)
except Exception as e:
logger.exception(
"Unexpected LDAP role assignment deletion sync failure",
extra={
"event": "ldap.role_assignment.delete_sync_unexpected_failure",
"role_assignment_id": instance.pk,
"employee_id": instance.employee_id,
"department_role_id": instance.role_id,
"error_type": type(e).__name__,
},
)