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 a1bd72979d
commit aa9fcbe964

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)