Пользовательский контекст#
При написании бизнес-логики на стороне БД иногда появляется потребность в получении таких данных, как логин пользователя, идентификатор организации, в которой он находится, а также замещение, под которым он работает, т.е. в получении так называемого пользовательского контекста.
Пользовательский контекст используется в системных триггерах таблиц для хранения истории изменения данных и обновления системных полей, в прикладных представлениях для разграничения прав внутри холдинга и так далее.
Реализация 8.4#
Передача пользовательского контекста со стороны веб-сервера на сторону сервера БД может осуществляться двумя способами:
- C помощью стандартного механизма (CONTEXT_INFO для mssql, set_config для postgresql). Используется настройка useSessionContext для моделей и запросов. Для получения информации о контексте на стороне sql необходимо использовать функции. для mssql:
- dbo.GetLogin - получить текущий логин пользователя.
- dbo.GetOrgId - получить текущую организацию пользователя.
- dbo.GetVirtualLogin - получить логин замещаемого пользователя. Если пользователь работает без режима замещения, то вернет текущий логин пользователя.
- dbo.GetLang - получить текущий язык пользователя. Вернет null (т.к. язык по умолчанию храниться в исходной таблице, а не в таблице перевода), язык пользователя равен языку по умолчанию.
для postgresql:
- lex."getLogin" - получить текущий логин пользователя.
- lex."getOrgId" - получить текущую организацию пользователя.
- lex."getVirtualLogin" - получить логин замещаемого пользователя. Если пользователь работает без режима замещения, то вернет текущий логин пользователя.
- lex."getLang" - получить текущий язык пользователя. Вернет null (т.к. язык по умолчанию храниться в исходной таблице, а не в таблице перевода), язык пользователя равен языку по умолчанию.
- lex."getHost" - получить ip-адрес пользователя.
- С помощью системной таблицы (lex.Context) для хранения информации о контексте (считается устаревшим и не рекомендуется к использованию). Используется настройка useContext у моделей и запросов.
Структура системной таблицы lex.Context:
- Id - идентификатор записи, в качестве значения используется идентификатор сеанса: @@SPID для mssql и pg_backend_pid() для postgresql.
- Login - логин пользователя, с клиента которого был инициирован запуск выполнения текущего запроса.
- OrganizationId - идентификатор организации пользователя, с клиента которого был инициирован запуск выполнения текущего запроса.
- VirtualLogin - логин замещаемого пользователя, если пользователь работает под замещением.
При установке useContext или useSessionContext все запросы на чтение и изменение данных с помощью моделей и запросов будут обернуты в транзакцию. Если выключить использование контекста, то чтение данных с помощью моделей и чтение и изменение данных с помощью запросов выполняется без транзакции (изменение данных с помощью модели всегда выполняется в транзакции).
- для моделей, в которых необходимо разграничение данных в рамках холдинга всегда нужно использовать пользовательский контекст.
- для моделей, в которых не нужно разграничение данных в рамках холдинга, отключить настройку использования пользовательского контекста при чтении данных, при изменении данных настройку лучше оставить, так как пользовательский контекст используется в системных триггерах таблиц для хранения истории изменения данных и обновления системных полей.
- для моделей, в которых не нужно разграничение данных в рамках холдинга, можно отключить настройку использования пользовательского контекста при изменении данных, если будет принято решение об отказе от заполнения такого системного поля, как WUser, при срабатывании триггера таблицы для хранения истории изменения данных и обновления системных полей. В этом случае запрос на изменение данных останется на стороне веб-сервера внутри транзакции, но не будет последовательных запросов на установку и удаление пользовательского контекста.
- для запросов на insert необходимо вручную проставлять системные поля (см. пример). При выполнении запроса на update системные поля проставляются триггером, кроме WOrg (нужно заполнять вручную). Для insert и update должна быть включена настройка useSessionContext. Для запросов select можно выключить useSessionContext, если обращение к пользовательскому контексту не требуется (нужно не забывать учитывать представления, к которым идет обращение. В них может использоваться пользовательский контекст).
- для запросов, в которых не нужно разграничение данных в рамках холдинга, можно отключить настройку использования пользовательского контекста при всех типах действий с данными. В этом случае запрос не будет оборачиваться в транзакцию на стороне веб-сервера и не будет последовательных запросов на установку и удаление пользовательского контекста. При этом прикладному программисту нужно будет самому позаботиться о заполнении системных полей таблиц. То есть передавать в запрос данные пользовательского контекста с клиента с помощью параметров запроса (не рекомендуется так делать. Лучше воспользоваться стандартны механизмом передачи пользовательского контекста), при выполнении команды update не забывать заполнять системные поля WUser, WHost, WDate, в противном случае сработает триггер таблицы для хранения истории изменения данных или обновления системных полей и проставит в качестве значения null. Также в данном случае нужно следить за обращением в скриптах к представлениям. Если в представлении используется пользовательский контекст, то в данном случае оно вернет некорректные данные.