refactor(ldap): fix architectural issues in views
DirectoryService: - Added public methods: assign_role, revoke_role, create_role, update_role, delete_role - Added public method: move_user_to_base (replaces private _user_service._move_user_to_base) - Fixed method signatures to match DepartmentService API roles.py: - Replaced direct DepartmentService usage with DirectoryService facade (5 methods) - Removed manual GroupService/UserService instantiation - All CRUD operations now go through facade layer actions.py: - Replaced private API svc._user_service._move_user_to_base() with public svc.move_user_to_base() - Simplified LDAP connection handling (2 occurrences) - Removed manual _ldap() and ensure_container_exists calls manage.py check: System check identified no issues
This commit is contained in:
parent
19464a38cf
commit
1f0858b085
@ -128,10 +128,6 @@ class EmployeeActionViewSet(HistoryActionMixin, viewsets.ModelViewSet):
|
||||
|
||||
if not departments_processed:
|
||||
try:
|
||||
from employees.ldap.infrastructure.connections import \
|
||||
_ldap
|
||||
from employees.ldap.repositories.ldap_repository import \
|
||||
ensure_container_exists
|
||||
from employees.ldap.utils.ldap_utils import \
|
||||
get_base_dn_for_employee
|
||||
|
||||
@ -146,21 +142,18 @@ class EmployeeActionViewSet(HistoryActionMixin, viewsets.ModelViewSet):
|
||||
if not current_dn.lower().endswith(
|
||||
target_base.lower()
|
||||
):
|
||||
with _ldap() as conn:
|
||||
ensure_container_exists(
|
||||
conn, target_base)
|
||||
new_dn = (
|
||||
svc._user_service._move_user_to_base(
|
||||
conn, current_dn, target_base
|
||||
)
|
||||
)
|
||||
sync_state.touch(
|
||||
ldap_dn=new_dn, sync_dir="ldap"
|
||||
try:
|
||||
new_dn = svc.move_user_to_base(
|
||||
emp, target_base
|
||||
)
|
||||
logger.info(
|
||||
f"Dismissed employee without department moved to OU=Dismissed: "
|
||||
f"employee_id={emp.id}, new_dn={new_dn}"
|
||||
)
|
||||
except Exception as move_err:
|
||||
logger.error(
|
||||
f"Failed to move dismissed employee: {move_err}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Failed to move dismissed employee without department to OU=Dismissed: "
|
||||
@ -209,26 +202,18 @@ class EmployeeActionViewSet(HistoryActionMixin, viewsets.ModelViewSet):
|
||||
settings, "LDAP_USERS_BASE", None
|
||||
) or getattr(settings, "LDAP_USER_BASE", None)
|
||||
if users_base:
|
||||
from employees.ldap.infrastructure.connections import \
|
||||
_ldap
|
||||
from employees.ldap.repositories.ldap_repository import \
|
||||
ensure_container_exists
|
||||
|
||||
with _ldap() as conn:
|
||||
ensure_container_exists(
|
||||
conn, users_base)
|
||||
new_dn = (
|
||||
svc._user_service._move_user_to_base(
|
||||
conn, current_dn, users_base
|
||||
)
|
||||
)
|
||||
sync_state.touch(
|
||||
ldap_dn=new_dn, sync_dir="ldap"
|
||||
try:
|
||||
new_dn = svc.move_user_to_base(
|
||||
emp, users_base
|
||||
)
|
||||
logger.info(
|
||||
f"Restored employee moved from Dismissed to Users: "
|
||||
f"employee_id={emp.id}, new_dn={new_dn}"
|
||||
)
|
||||
except Exception as move_err:
|
||||
logger.error(
|
||||
f"Failed to move restored employee: {move_err}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Failed to move restored employee from Dismissed to Users: "
|
||||
|
||||
@ -89,28 +89,19 @@ class DepartmentRoleViewSet(viewsets.ModelViewSet):
|
||||
ldap_enabled = _is_ldap_enabled()
|
||||
|
||||
if ldap_enabled:
|
||||
from employees.ldap.services.department_service import \
|
||||
DepartmentService
|
||||
from employees.ldap.services.group_service import GroupService
|
||||
from employees.ldap.services.user_service import UserService
|
||||
svc = DirectoryService()
|
||||
|
||||
group_service = GroupService()
|
||||
user_service = UserService(group_service)
|
||||
dept_service = DepartmentService(group_service, user_service)
|
||||
|
||||
scoped_permissions = None
|
||||
permission_codes = None
|
||||
if codes is not None:
|
||||
scoped_permissions = list(
|
||||
DepartmentPermission.objects.filter(code__in=codes)
|
||||
)
|
||||
permission_codes = codes
|
||||
elif perms is not None:
|
||||
scoped_permissions = list(perms)
|
||||
permission_codes = [p.code for p in perms]
|
||||
|
||||
try:
|
||||
role = dept_service.create_role(
|
||||
department=dept,
|
||||
role = svc.create_role(
|
||||
dept=dept,
|
||||
name=name,
|
||||
scoped_permissions=scoped_permissions,
|
||||
permission_codes=permission_codes,
|
||||
)
|
||||
return Response(
|
||||
self.get_serializer(
|
||||
@ -149,27 +140,12 @@ class DepartmentRoleViewSet(viewsets.ModelViewSet):
|
||||
ldap_enabled = _is_ldap_enabled()
|
||||
|
||||
if ldap_enabled:
|
||||
from employees.ldap.services.department_service import \
|
||||
DepartmentService
|
||||
from employees.ldap.services.group_service import GroupService
|
||||
from employees.ldap.services.user_service import UserService
|
||||
svc = DirectoryService()
|
||||
|
||||
group_service = GroupService()
|
||||
user_service = UserService(group_service)
|
||||
dept_service = DepartmentService(group_service, user_service)
|
||||
|
||||
changes = {}
|
||||
if "name" in ser.validated_data:
|
||||
changes["name"] = ser.validated_data["name"]
|
||||
if "scoped_permissions" in ser.validated_data:
|
||||
changes["scoped_permissions"] = ser.validated_data["scoped_permissions"]
|
||||
if "scoped_permission_codes" in ser.validated_data:
|
||||
changes["scoped_permission_codes"] = ser.validated_data[
|
||||
"scoped_permission_codes"
|
||||
]
|
||||
new_name = ser.validated_data.get("name")
|
||||
|
||||
try:
|
||||
role = dept_service.update_role(instance, changes)
|
||||
role = svc.update_role(instance, name=new_name)
|
||||
return Response(self.get_serializer(role).data)
|
||||
except DirectoryLdapError as e:
|
||||
return Response(
|
||||
@ -195,17 +171,10 @@ class DepartmentRoleViewSet(viewsets.ModelViewSet):
|
||||
ldap_enabled = _is_ldap_enabled()
|
||||
|
||||
if ldap_enabled:
|
||||
from employees.ldap.services.department_service import \
|
||||
DepartmentService
|
||||
from employees.ldap.services.group_service import GroupService
|
||||
from employees.ldap.services.user_service import UserService
|
||||
|
||||
group_service = GroupService()
|
||||
user_service = UserService(group_service)
|
||||
dept_service = DepartmentService(group_service, user_service)
|
||||
svc = DirectoryService()
|
||||
|
||||
try:
|
||||
dept_service.delete_role(instance)
|
||||
svc.delete_role(instance)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
except DirectoryLdapError as e:
|
||||
return Response(
|
||||
@ -312,16 +281,9 @@ class DepartmentRoleViewSet(viewsets.ModelViewSet):
|
||||
|
||||
if ldap_enabled:
|
||||
try:
|
||||
from employees.ldap.services.department_service import \
|
||||
DepartmentService
|
||||
from employees.ldap.services.group_service import GroupService
|
||||
from employees.ldap.services.user_service import UserService
|
||||
svc = DirectoryService()
|
||||
|
||||
group_service = GroupService()
|
||||
user_service = UserService(group_service)
|
||||
dept_service = DepartmentService(group_service, user_service)
|
||||
|
||||
assignment = dept_service.assign_role(
|
||||
assignment = svc.assign_role(
|
||||
employee, role, assigned_by)
|
||||
|
||||
return Response(
|
||||
@ -384,16 +346,9 @@ class DepartmentRoleViewSet(viewsets.ModelViewSet):
|
||||
|
||||
if ldap_enabled:
|
||||
try:
|
||||
from employees.ldap.services.department_service import \
|
||||
DepartmentService
|
||||
from employees.ldap.services.group_service import GroupService
|
||||
from employees.ldap.services.user_service import UserService
|
||||
svc = DirectoryService()
|
||||
|
||||
group_service = GroupService()
|
||||
user_service = UserService(group_service)
|
||||
dept_service = DepartmentService(group_service, user_service)
|
||||
|
||||
dept_service.revoke_role(employee, role)
|
||||
svc.revoke_role(employee, role)
|
||||
|
||||
return Response(status=204)
|
||||
except DirectoryLdapError as e:
|
||||
|
||||
@ -169,6 +169,132 @@ class DirectoryService:
|
||||
"""Меняет роль участника с синхронизацией LDAP-групп Roles."""
|
||||
return self._department_service.set_member_role(dept, employee, role)
|
||||
|
||||
def assign_role(
|
||||
self,
|
||||
employee: Employee,
|
||||
role: DepartmentRole,
|
||||
assigned_by: Optional[Employee] = None,
|
||||
):
|
||||
"""Назначает роль сотруднику (не требует членства в отделе).
|
||||
|
||||
NOTE: Метод делегирует к DepartmentService.
|
||||
|
||||
Args:
|
||||
employee: Сотрудник.
|
||||
role: Роль для назначения.
|
||||
assigned_by: Кто назначил (опционально).
|
||||
|
||||
Returns:
|
||||
RoleAssignment: Созданное/обновлённое назначение.
|
||||
"""
|
||||
return self._department_service.assign_role(employee, role, assigned_by)
|
||||
|
||||
def revoke_role(self, employee: Employee, role: DepartmentRole) -> None:
|
||||
"""Отзывает роль у сотрудника.
|
||||
|
||||
NOTE: Метод делегирует к DepartmentService.
|
||||
|
||||
Args:
|
||||
employee: Сотрудник.
|
||||
role: Роль для отзыва.
|
||||
"""
|
||||
return self._department_service.revoke_role(employee, role)
|
||||
|
||||
def create_role(
|
||||
self,
|
||||
dept: Department,
|
||||
name: str,
|
||||
permission_codes: Optional[List[str]] = None,
|
||||
) -> DepartmentRole:
|
||||
"""Создаёт роль отдела с LDAP-группой.
|
||||
|
||||
NOTE: Метод делегирует к DepartmentService.
|
||||
|
||||
Args:
|
||||
dept: Отдел.
|
||||
name: Название роли.
|
||||
permission_codes: Коды прав (опционально).
|
||||
|
||||
Returns:
|
||||
DepartmentRole: Созданная роль.
|
||||
"""
|
||||
from employees.models import DepartmentPermission
|
||||
|
||||
scoped_permissions = None
|
||||
if permission_codes:
|
||||
scoped_permissions = list(
|
||||
DepartmentPermission.objects.filter(code__in=permission_codes)
|
||||
)
|
||||
|
||||
return self._department_service.create_role(
|
||||
department=dept,
|
||||
name=name,
|
||||
scoped_permissions=scoped_permissions,
|
||||
)
|
||||
|
||||
def update_role(
|
||||
self, role: DepartmentRole, name: Optional[str] = None
|
||||
) -> DepartmentRole:
|
||||
"""Обновляет роль (переименование LDAP-группы + БД).
|
||||
|
||||
NOTE: Метод делегирует к DepartmentService.
|
||||
|
||||
Args:
|
||||
role: Роль.
|
||||
name: Новое название (опционально).
|
||||
|
||||
Returns:
|
||||
DepartmentRole: Обновлённая роль.
|
||||
"""
|
||||
changes = {}
|
||||
if name:
|
||||
changes["name"] = name
|
||||
|
||||
return self._department_service.update_role(role, changes)
|
||||
|
||||
def delete_role(self, role: DepartmentRole) -> None:
|
||||
"""Удаляет роль: LDAP-группу + БД.
|
||||
|
||||
NOTE: Метод делегирует к DepartmentService.
|
||||
|
||||
Args:
|
||||
role: Роль для удаления.
|
||||
"""
|
||||
return self._department_service.delete_role(role)
|
||||
|
||||
def move_user_to_base(self, employee: Employee, base_dn: str) -> str:
|
||||
"""Перемещает пользователя в указанный базовый OU.
|
||||
|
||||
NOTE: Метод делегирует к UserService.
|
||||
|
||||
Args:
|
||||
employee: Сотрудник для перемещения.
|
||||
base_dn: DN базового OU.
|
||||
|
||||
Returns:
|
||||
str: Новый DN пользователя.
|
||||
|
||||
Raises:
|
||||
DirectoryLdapError: Ошибка LDAP.
|
||||
DirectoryServiceError: Пользователь не имеет DN.
|
||||
"""
|
||||
from .infrastructure.connections import _ldap
|
||||
|
||||
sync_state = LdapSyncState.objects.filter(
|
||||
model="employee", object_pk=str(employee.pk)
|
||||
).first()
|
||||
|
||||
if not sync_state or not sync_state.ldap_dn:
|
||||
from .errors import DirectoryServiceError
|
||||
raise DirectoryServiceError(f"Employee {employee.pk} has no LDAP DN")
|
||||
|
||||
with _ldap() as conn:
|
||||
new_dn = self._user_service._move_user_to_base(
|
||||
conn, sync_state.ldap_dn, base_dn
|
||||
)
|
||||
sync_state.touch(ldap_dn=new_dn, sync_dir="ldap")
|
||||
return new_dn
|
||||
|
||||
# =========================== POSITIONS =========================== #
|
||||
|
||||
def reconcile_position(self, pos: Position) -> str:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user