""" Вспомогательная логика портала: - получение списка AD-групп текущего пользователя (из объекта django-auth-ldap) - подбор доступных Resource по этим группам - выпуск короткоживущего подписанного токена для backend admin panel """ import time from typing import Iterable import jwt from django.conf import settings from .models import Resource, ResourceGroup def get_user_ad_groups(user) -> set[str]: """ django-auth-ldap прикрепляет к user объект `ldap_user` с атрибутом group_names (набор cn всех групп, в которых состоит пользователь в AD). Для локального суперпользователя (не через LDAP) атрибута не будет — возвращаем пустой набор, дальше он видит только ресурсы, явно открытые ModelBackend-группам. """ ldap_user = getattr(user, "ldap_user", None) if ldap_user is None: return set() return set(ldap_user.group_names) def get_available_resources(user) -> Iterable[Resource]: if user.is_superuser: return Resource.objects.filter(is_active=True).select_related("group") ad_groups = get_user_ad_groups(user) if not ad_groups: return Resource.objects.none() group_ids = ResourceGroup.objects.filter(ad_group_name__in=ad_groups).values_list("id", flat=True) return Resource.objects.filter(group_id__in=group_ids, is_active=True).select_related("group") def user_can_access_resource(user, resource: Resource) -> bool: if user.is_superuser: return True return resource.group.ad_group_name in get_user_ad_groups(user) def issue_resource_token(user, resource: Resource) -> str: """ Короткоживущий JWT, который backend admin panel может провалидировать тем же RESOURCE_TOKEN_SECRET (см. docs/architecture.md, раздел 6). """ now = int(time.time()) payload = { "sub": user.username, "email": getattr(user, "email", ""), "group": resource.group.ad_group_name, "resource": resource.slug, "iat": now, "exp": now + settings.RESOURCE_TOKEN_TTL_SECONDS, } return jwt.encode(payload, settings.RESOURCE_TOKEN_SECRET, algorithm="HS256")