Fix: Refactor LDAP field handling to use get_ldap_str()
- Moved get_ldap_str() helper to ldap_utils.py for reuse - Updated user_service.py to use shared helper from utils - Updated admin.py to safely extract string values from LDAP fields - LDAP fields can be lists, strings, or None - helper handles all cases - Fixes sync_from_ldap_to_django and compare_ldap_django actions - Prevents 'list' object errors when comparing or assigning LDAP fields
This commit is contained in:
parent
be2e899046
commit
a3bd9226a5
@ -13,6 +13,7 @@ from django.db.models import OuterRef, Exists
|
||||
|
||||
from employees.models import Employee, LdapSyncState
|
||||
from .orm_models import LdapUser, LdapGroup, LdapOrganizationalUnit
|
||||
from .utils.ldap_utils import get_ldap_str
|
||||
|
||||
|
||||
class LdapSyncStateInline(admin.TabularInline):
|
||||
@ -335,10 +336,11 @@ class LdapUserAdmin(admin.ModelAdmin):
|
||||
emp = Employee.objects.get(pk=int(ldap_user.employee_number))
|
||||
|
||||
# Обновляем Django из LDAP
|
||||
emp.first_name = ldap_user.given_name or emp.first_name
|
||||
emp.last_name = ldap_user.sn or emp.last_name
|
||||
emp.email = ldap_user.mail or emp.email
|
||||
emp.phone_number = ldap_user.telephone_number or ldap_user.mobile or emp.phone_number
|
||||
emp.first_name = get_ldap_str(ldap_user.given_name) or emp.first_name
|
||||
emp.last_name = get_ldap_str(ldap_user.sn) or emp.last_name
|
||||
emp.email = get_ldap_str(ldap_user.mail) or emp.email
|
||||
ldap_phone = get_ldap_str(ldap_user.telephone_number or ldap_user.mobile)
|
||||
emp.phone_number = ldap_phone or emp.phone_number
|
||||
emp.save()
|
||||
|
||||
# Обновляем LdapSyncState
|
||||
@ -444,16 +446,19 @@ class LdapUserAdmin(admin.ModelAdmin):
|
||||
user_diffs = []
|
||||
|
||||
# Сравниваем поля
|
||||
if ldap_user.given_name != emp.first_name:
|
||||
user_diffs.append(f"Имя: LDAP='{ldap_user.given_name}' vs Django='{emp.first_name}'")
|
||||
ldap_first = get_ldap_str(ldap_user.given_name)
|
||||
if ldap_first != emp.first_name:
|
||||
user_diffs.append(f"Имя: LDAP='{ldap_first}' vs Django='{emp.first_name}'")
|
||||
|
||||
if ldap_user.sn != emp.last_name:
|
||||
user_diffs.append(f"Фамилия: LDAP='{ldap_user.sn}' vs Django='{emp.last_name}'")
|
||||
ldap_last = get_ldap_str(ldap_user.sn)
|
||||
if ldap_last != emp.last_name:
|
||||
user_diffs.append(f"Фамилия: LDAP='{ldap_last}' vs Django='{emp.last_name}'")
|
||||
|
||||
if ldap_user.mail != emp.email:
|
||||
user_diffs.append(f"Email: LDAP='{ldap_user.mail}' vs Django='{emp.email}'")
|
||||
ldap_email = get_ldap_str(ldap_user.mail)
|
||||
if ldap_email != emp.email:
|
||||
user_diffs.append(f"Email: LDAP='{ldap_email}' vs Django='{emp.email}'")
|
||||
|
||||
ldap_phone = ldap_user.telephone_number or ldap_user.mobile
|
||||
ldap_phone = get_ldap_str(ldap_user.telephone_number or ldap_user.mobile)
|
||||
if ldap_phone and ldap_phone != emp.phone_number:
|
||||
user_diffs.append(f"Телефон: LDAP='{ldap_phone}' vs Django='{emp.phone_number}'")
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ from ..infrastructure.connections import _ldap
|
||||
from ..repositories.ldap_repository import (
|
||||
ensure_container_exists,
|
||||
)
|
||||
from ..utils.ldap_utils import cn_candidates
|
||||
from ..utils.ldap_utils import cn_candidates, get_ldap_str
|
||||
from ..utils.text_utils import esc_rdn
|
||||
from .base_service import BaseService
|
||||
from .constants import (
|
||||
@ -47,27 +47,6 @@ from .user_mapper_service import UserMapperService
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_ldap_str(value: Any) -> str:
|
||||
"""Безопасно извлекает строковое значение из LDAP поля.
|
||||
|
||||
LDAP поля могут возвращаться как:
|
||||
- строка (str)
|
||||
- список строк (list)
|
||||
- None
|
||||
|
||||
Args:
|
||||
value: Значение LDAP поля
|
||||
|
||||
Returns:
|
||||
str: Первый элемент (если список) или само значение (если строка), или пустая строка
|
||||
"""
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, list):
|
||||
return value[0] if value else ""
|
||||
return str(value)
|
||||
|
||||
|
||||
class UserService(BaseService):
|
||||
"""Сервис для управления пользователями в LDAP и Django.
|
||||
|
||||
@ -779,8 +758,8 @@ class UserService(BaseService):
|
||||
if "first_name" in model_changes or "last_name" in model_changes:
|
||||
# Формируем новый cn из имени и фамилии
|
||||
parts = []
|
||||
given_name_str = _get_ldap_str(ldap_user.given_name).strip()
|
||||
sn_str = _get_ldap_str(ldap_user.sn).strip()
|
||||
given_name_str = get_ldap_str(ldap_user.given_name).strip()
|
||||
sn_str = get_ldap_str(ldap_user.sn).strip()
|
||||
|
||||
if given_name_str:
|
||||
parts.append(given_name_str)
|
||||
|
||||
@ -25,6 +25,28 @@ def _first(val: Any) -> Any:
|
||||
return val
|
||||
|
||||
|
||||
def get_ldap_str(value: Any) -> str:
|
||||
"""Безопасно извлекает строковое значение из LDAP поля.
|
||||
|
||||
LDAP поля могут возвращаться как:
|
||||
- строка (str)
|
||||
- список строк (list)
|
||||
- None
|
||||
|
||||
Args:
|
||||
value: Значение LDAP поля
|
||||
|
||||
Returns:
|
||||
str: Первый элемент (если список) или само значение (если строка),
|
||||
или пустая строка
|
||||
"""
|
||||
if value is None:
|
||||
return ""
|
||||
if isinstance(value, list):
|
||||
return value[0] if value else ""
|
||||
return str(value)
|
||||
|
||||
|
||||
def _uac_is_active(uac_value: Any) -> bool:
|
||||
"""Определяет активность учётной записи по userAccountControl.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user