38.6. Пример событийного триггера, обрабатывающего вход в базу данных #

Триггер события login может использоваться для регистрации входа пользователей в систему, для проверки подключения и назначения ролей в зависимости от обстоятельств или для инициализации данных сеанса. Очень важно, чтобы любой событийный триггер, использующий событие login, проверял, не находится ли база данных в состоянии восстановления перед выполнением каких-либо операций записи. Попытка выполнить запись на резервном сервере вызовет ошибку, что не позволит подключиться к нему.

Следующий пример демонстрирует эти возможности.

-- создание тестовых таблиц и ролей
CREATE TABLE user_login_log (
  "user" text,
  "session_start" timestamp with time zone
);
CREATE ROLE day_worker;
CREATE ROLE night_worker;

-- пример триггерной функции
CREATE OR REPLACE FUNCTION init_session()
  RETURNS event_trigger SECURITY DEFINER
  LANGUAGE plpgsql AS
$$
DECLARE
  hour integer = EXTRACT('hour' FROM current_time at time zone 'utc');
  rec boolean;
BEGIN
-- 1. Запрет на вход с 2 до 4 часов ночи
IF hour BETWEEN 2 AND 4 THEN
  RAISE EXCEPTION 'Login forbidden';
END IF;

-- Следующие проверки могут не выполняться на резервных серверах, поэтому
-- до выполнения каких-либо действий нужно проверить, не находится ли
-- база данных в режиме восстановления.
SELECT pg_is_in_recovery() INTO rec;
IF rec THEN
  RETURN;
END IF

-- 2. Назначение ролей. В дневное время назначается роль day_worker,
-- в ночное — night_worker
IF hour BETWEEN 8 AND 20 THEN
  EXECUTE 'REVOKE night_worker FROM ' || quote_ident(session_user);
  EXECUTE 'GRANT    day_worker TO '   || quote_ident(session_user);
ELSE
  EXECUTE 'REVOKE day_worker FROM ' || quote_ident(session_user);
  EXECUTE 'GRANT  night_worker TO ' || quote_ident(session_user);
END IF;

-- 3. Инициализация данных сеанса пользователя
CREATE TEMP TABLE session_storage (x float, y integer);
ALTER TABLE session_storage OWNER TO session_user;

-- 4. Протоколирование времени соединения
INSERT INTO user_login_log VALUES (session_user, current_timestamp);

END;
$$;

-- определение триггера
CREATE EVENT TRIGGER init_session
  ON login
  EXECUTE FUNCTION init_session();
ALTER EVENT TRIGGER init_session ENABLE ALWAYS;