fix: handle empty position_id and unwillingToPerform LDAP error

Problem:
- When clearing employee position (position_id: ''), LDAP sync failed
- Error: LDAP modify failed: 'unwillingToPerform' (code 53)
- System tried to remove user from position group but LDAP refused

Root Causes:
1. Empty string '' not explicitly converted to None
2. unwillingToPerform error not handled (user may not be in group)

Solution:
1. Convert position_id: '' to None (no position) at parsing stage
2. Wrap remove_group_members in try/except
3. Ignore unwillingToPerform errors with warning log
4. Add detailed logging for position group operations

This allows users to clear positions without LDAP sync failures.
This commit is contained in:
admin i 2025-12-08 13:14:40 +03:00
parent 48391600fe
commit 7e8cb9abd8

View File

@ -189,7 +189,10 @@ class UserService:
if "position" in changes or "position_id" in changes:
pos_in_payload = True
val = changes.pop("position", changes.pop("position_id", None))
if isinstance(val, Position) or val is None:
# Обработка пустой строки как None (снятие должности)
if val == "":
new_pos = None
elif isinstance(val, Position) or val is None:
new_pos = val
elif isinstance(val, int):
new_pos = Position.objects.filter(pk=val).first()
@ -280,6 +283,9 @@ class UserService:
# Временное решение - используем методы из DirectoryService
# TODO: убрать после создания PositionService (Сессия 8)
from ..directory_service import DirectoryService
import logging
logger = logging.getLogger(__name__)
svc = DirectoryService()
if old_pos:
old_dn = (old_pos.ldap_group_dn or "").strip()
@ -291,7 +297,29 @@ class UserService:
)
old_dn = maybe or ""
if old_dn:
svc.remove_group_members(conn, old_dn, [current_dn])
try:
logger.info(
f"Removing user {current_dn} "
f"from position group {old_dn}"
)
svc.remove_group_members(
conn, old_dn, [current_dn]
)
except RuntimeError as e:
# Игнорируем unwillingToPerform
# (пользователь не в группе)
error_msg = str(e).lower()
if (
"unwillingtoperform" in error_msg
or "will_not_perform" in error_msg
):
logger.warning(
f"LDAP refused to remove user "
f"from group (possibly not a "
f"member): {e}"
)
else:
raise
if new_pos:
pos_dn = svc._ensure_position_group(conn, new_pos)