py.lib.aw_web_tools

Yohn Y. 2025-10-15 Parent:74f5377d83ab Child:c53a61e27af8

14:0920ae304dfd Go to Latest

py.lib.aw_web_tools/src/aw_web_tools/authelia_helper.py

.. 1.202510.1 + Режим фековой авторизации для адаптера authelia. Режим требуется для отладки, поскольку вряд ли на машине разработчика будет развёрнуто это ПО на ранних стадиях разработки (преальфа). Возможно режим будет полезен при поиска проблем в приложении при авторизации.

History
awgur@9 1 # coding: utf-8
awgur@9 2 """\
awgur@9 3 Поддержка работы с системой авторизации [authelia](https://www.authelia.com/)
awgur@9 4 """
awgur@9 5 import bottle
awgur@9 6 from typing import Optional, List
awgur@9 7 from collections import namedtuple
awgur@9 8
awgur@9 9 from . import Error
awgur@9 10
awgur@9 11
awgur@9 12 # Константы
awgur@9 13 HEADER_USER = 'Remote-User' # Заголовок по умолчанию, в котором система аутентификации передаёт имя УЗ пользователя
awgur@9 14 HEADER_GROUPS = 'Remote-Groups' # Заголовок по умолчанию, в котором система аутентификации передаёт группы пользовтеля
awgur@9 15 HEADER_EMAIL = 'Remote-Email' # Заголовок по умолчанию, в котором система аутентификации передаёт e-mail пользователя
awgur@9 16 HEADER_NAME = 'Remote-Name' # Заголовок по умолчанию, в котором система аутентификации передаёт имя пользователя
awgur@9 17
awgur@9 18
awgur@9 19 class AHError(Error):
awgur@9 20 """\
awgur@9 21 Базовый класс исключений модуля адаптера Authelia
awgur@9 22 """
awgur@9 23
awgur@9 24
awgur@9 25 class AHAuthError(AHError):
awgur@9 26 """\
awgur@9 27 Проблемы с авторизацией пользователя
awgur@9 28 """
awgur@9 29 def __init__(self):
awgur@9 30 super().__init__('Пользователь не авторизован')
awgur@9 31
awgur@9 32
awgur@9 33 AHUser = namedtuple('AHUser', ['uname', 'groups', 'email', 'name'])
awgur@9 34
awgur@9 35
awgur@9 36 class AutheliaHelper(object):
awgur@9 37 def __init__(self,
awgur@9 38 group_filter: Optional[List[str]] = None,
awgur@9 39 header_user: str = HEADER_USER,
awgur@9 40 header_groups: str = HEADER_GROUPS,
awgur@9 41 header_email: str = HEADER_EMAIL,
awgur@14 42 header_name: str = HEADER_NAME,
awgur@14 43 fake_auth: bool = False
awgur@9 44 ):
awgur@9 45 """\
awgur@10 46 :param group_filter: Фильтр передаваемый системой аутентификации групп, которые интересны нам. Если ``None``
awgur@9 47 группы, передаваемые в заголовке не фильтруются
awgur@9 48 :param header_user: Имя заголовка с именем УЗ пользователя.
awgur@9 49 :param header_groups: Имя заголовка с группами пользователя
awgur@10 50 :param header_email: Имя заголовка c e-mail пользователя
awgur@9 51 :param header_name: Имя заголовка с именем пользователя
awgur@14 52 :param fake_auth: Режим без авторизации. Создаётся для отладки или решения проблем с авторизацией.
awgur@14 53 Не проводит авторизацию по заголовкам, а вместо этого подставляет заранее заданные значения.
awgur@9 54 """
awgur@9 55 self.header_user = header_user
awgur@9 56 self.header_groups = header_groups
awgur@9 57 self.header_email = header_email
awgur@9 58 self.header_name = header_name
awgur@14 59 self.fake_auth = fake_auth
awgur@9 60
awgur@9 61 self.group_filter = None
awgur@9 62 self.group_filter_set = None
awgur@9 63 if group_filter is not None:
awgur@9 64 self.group_filter = {}
awgur@9 65 for i in group_filter:
awgur@9 66 self.group_filter[i.lower()] = i
awgur@9 67
awgur@9 68 self.group_filter_set = set(self.group_filter.keys())
awgur@9 69
awgur@9 70 def __call__(self, request: bottle.BaseRequest = bottle.request) -> AHUser:
awgur@9 71 """\
awgur@9 72 Обработка запроса. Если заголовки системы авторизации присутствуют, информацией из них заполняется
awgur@9 73 объект ``AHUser``. Если данные не найдены, то будет возбуждено исключение.
awgur@9 74
awgur@9 75 :param request: Обрабатываемый запрос
awgur@9 76 :returns: Объект ``AHUser`` с данным авторизации.
awgur@9 77 """
awgur@9 78
awgur@14 79 if self.fake_auth:
awgur@14 80 return AHUser(uname='__UNK__', groups=[], name='John Doe', email='devnull@localhost.localdomain')
awgur@14 81
awgur@9 82 uname = request.get_header(self.header_user)
awgur@9 83 email = request.get_header(self.header_email)
awgur@9 84 name = request.get_header(self.header_name)
awgur@9 85 groups = request.get_header(self.header_groups)
awgur@9 86
awgur@9 87 if uname is None:
awgur@9 88 raise AHAuthError()
awgur@9 89
awgur@9 90 if groups is not None:
awgur@9 91 groups = tuple(map(lambda x: x.stip(), groups.split(',')))
awgur@9 92 if self.group_filter is not None:
awgur@9 93 _groups = []
awgur@9 94 _buf = set(map(lambda x: x.lower(), groups))
awgur@9 95
awgur@9 96 for grp in _buf & self.group_filter_set:
awgur@9 97 try:
awgur@9 98 _groups.append(self.group_filter[grp])
awgur@9 99
awgur@9 100 except KeyError:
awgur@9 101 AHError(f'Ошибка в фильтре групп. Для ключа "{grp}" не нашлось значения, хотя оно присутствует '
awgur@9 102 f'в множестве возможных значений.')
awgur@9 103
awgur@9 104 return AHUser(uname=uname, groups=groups, name=name, email=email)