62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
"""
|
||
Вспомогательная логика портала:
|
||
- получение списка 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")
|