...

Обработчик событий для домена «Пользователи»

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем vyimova, 12 май 2023.

  1. vyimova

    vyimova Участник

    Иногда нужно отслеживать события, происходящие в системе, и выполнять при этом какие-либо действия. Для этих целей подходит компонент «Обработчик событий», настраиваемый в пользовательском модуле. Подробнее об этом компоненте можно узнать в справке ELMA365: Обработка событий в модулях.

    Пример 1

    Задача: отслеживать авторизацию в системе для пользователей, у которых есть учетная запись AD/SAML, и добавлять их в пользовательскую группу «Внутренние пользователи».

    Создание пользовательского модуля

    Создаем в группах компании группу с названием «Внутренние пользователи». Сохраняем ее id (он отображается в url при открытии карточки группы).

    Создаем пользовательский модуль. Называем, например, «Обработчик событий SAML».

    [​IMG]

    Открываем вкладку «Настройки». Создаем свойство «id группы "Внутренние пользователи"» с кодом «target_group_id» и типом «Строка.

    [​IMG]

    Выносим это поле на форму модуля и делаем поле обязательным. Заполняем поле значением id группы, которое скопировали ранее.


    Переходим на вкладку «Обработка событий». Нажимаем на кнопку «+Обработчик».

    Название: Добавление SAML-пользователя в группу
    Домен события: Пользователи
    Событие: Успешная авторизация пользователя
    Тип обработчика: Запуск скрипта

    [​IMG]

    На вкладке «Сценарии» добавляем следующий код функции action():
    Код:
    
    async function action(): Promise<void> {
        
    // получаем авторизовавшегося пользователя
        
    const user_ref Context.data.__item;

        if (!
    user_ref) {
            return;
        }

        
    // фетчим пользователя для получения параметров
        
    const user await user_ref.fetch();
        if (!
    user) {
            return;
        }

        
    // проверяем, что у пользователя заполнено поле "Логин"
        
    if (!user.data.login || user.data.login.length <= 0) {
            return;
        }

        
    // получаем из параметров модуля id группы "Внутренние пользователи"
        
    const target_group_id = Namespace.params.data.target_group_id;
        if (!
    target_group_id) {
            return;
        }

        
    // получаем у пользователя список id групп, в которых он состоит
        
    const user_groups user.data.groupIds;
        
    // проверяем, что среди групп пользователя есть "Внутренние пользователи"
        
    const user_in_group user_groups.includes(target_group_id);
        
    // проверяем, что пользователь не состоит в этой группе
        
    if (user_in_group == true) {
            return;
        }

        
    // получаем объект группы "Внутренние пользователи"
        
    const target_group await System.userGroups.search().where(=> f.__id.eq(target_group_id)).first();
        if (!
    target_group) {
            return;
        }

        
    // добавляем пользователя в эту группу
        
    await target_group.addItem(user);

    }
    Теперь, если авторизоваться, имея логин, пользователь добавится в группу «Внутренние пользователи».

    Особенности реализации

    • При типе события «Успешная авторизация пользователя» осуществляется несколько событий. Если сделать логирование через создание элемента какого-либо приложение, то создастся несколько экземпляров этого приложения.
    • Тип события «Успешная аутентификация пользователя» на момент 26.04.2023 не работает для SAML.
    • После fetch() автокомплит не предлагает для пользователя поля. Может сложиться впечатление, что доступа к полям пользователя нет и код работать не будет. Но код работает и можно брать наименования полей пользователя. Их можно посмотреть в tssdk: https://tssdk.elma365.com/ru/interfaces/_01_items_.userdata.html

    Пример 2

    Задача: отслеживать авторизацию в системе для определенного пользователя, зная его фамилию и имя, и делать запись в элемент приложения «Логи авторизации».

    Создание приложения для логирования

    Создаем раздел «Логи модулей» («modules_logs») и создаем в нем приложение «Логи авторизации» («logs_auth»).

    [​IMG]

    [​IMG]

    В приложении создаем поле «Текст лога» («log_text») типа «Строка - Текст».


    Создание пользовательского модуля

    Также можно отслеживать пользователей по любым параметрам.

    Создаем пользовательский модуль. Называем «Обработчик событий аутентификации».

    [​IMG]

    Открываем вкладку «Настройки». Создаем свойства с типом Строка:

    • «Фамилия пользователя» с кодом «user_lastname»,
    • «Имя пользователя» с кодом «user_firstname».
    Также для связи с Приложением без использования Global создаем поле с типом «Приложение - Один», выбираем приложение «Логи авторизации», вводим название «Лог авторизации», код - «authorization_log».

    [​IMG]

    [​IMG]

    [​IMG]

    [​IMG]

    Поля «Фамилия» и «Имя» выносим на форму модуля и делаем обязательными. Заполняем тестовыми данными, например, «Иванов Иван».

    [​IMG]

    Переходим на вкладку «Обработка событий». Нажимаем на кнопку «+Обработчик».

    Название: Запись лога
    Домен события: Пользователи
    Событие: Успешная авторизация пользователя
    Тип обработчика: Запуск скрипта

    [​IMG]

    На вкладке «Сценарии» добавляем следующий код функции action():
    Код:
    
    async function action(): Promise<void> {
        
    // получаем авторизовавшегося пользователя
        
    const user_ref Context.data.__item;

        if (!
    user_ref) {
            return;
        }

        
    // фетчим пользователя для получения параметров
        
    const user await user_ref.fetch();

        if (!
    user) {
            return;
        }

        if (!
    user.data.fullname) {
            return;
        }

        if (!
    user.data.fullname.lastname || !Namespace.params.data.user_lastname || !user.data.fullname.firstname || !Namespace.params.data.user_firstname) {
            return;
        }

        
    // проверяем, что у пользователя фамилия и имя соответствуют тем значениям, по которым мы осуществляем фильтрацию
        
    if (user.data.fullname.lastname != Namespace.params.data.user_lastname || user.data.fullname.firstname != Namespace.params.data.user_firstname) {
            return;
        }

        
    // пишем в лог, что пользователь найден, выводим для проверки его фамилию-имя
        
    const log = Namespace.params.fields.authorization_log.app.create();
        const 
    current_datetime = new Datetime();
        
    log.data.__name = `Log authorization ${current_datetime.day}.${current_datetime.month}.${current_datetime.year} ${current_datetime.hours}:${current_datetime.minutes}:${current_datetime.seconds}`;
        
    log.data.log_text = `Пользователь найден: ${user.data.fullname.lastname} ${user.data.fullname.firstname}`;
        
    await log.save();
    }
    Теперь, если авторизуется пользователь, имея фамилию и имя как указано в модуле, запишется лог в приложение «Логи авторизации».

    [​IMG]

    Если авторизуется пользователь, у которого фамилия и имя отличаются, лог не запишется.

    Таким образом, с помощью Обработчика событий можно отслеживать данные о пользователях, осуществляющих вход в систему, выставлять определенные условия в зависимости от этих данных и совершать необходимые действия в зависимости от условий.
    Последнее редактирование: 12 май 2023
  2. kurbatov-la

    kurbatov-la Активный участник

    Спасибо за примеры.
    Как у себя получить значение столбца "Последний отклик" в разделе /admin/sessions ?
    В обработчиках событий похожего по смыслу не вижу.
  3. vyimova

    vyimova Участник

    Интересный вопрос. Судя по всему, в объекте Пользователь (который используем в статье) нет поля для хранения таких данных. Возможно, подойдет какой-то другой домен события.