Разработка модуля аудита действий пользователей 1С-Битрикс
Произошёл инцидент: кто-то изменил цены на 300 товаров, и это заметили только через день. Кто это сделал? Когда? Через административную панель или API? В Битрикс нет встроенного журнала изменений на уровне бизнес-данных. Есть b_event_log для системных событий, но он не фиксирует, кто и что именно поменял в инфоблоке или заказе. Модуль аудита решает именно эту задачу.
Что фиксирует модуль
Аудит охватывает три уровня действий:
Административная панель. Изменения товаров (OnAfterIBlockElementUpdate), разделов, пользователей, настроек сайта, заказов. Для каждого события фиксируется: кто изменил (user_id), когда, что именно изменилось (старое и новое значение поля).
Фронтенд-действия покупателей. Вход/выход, смена пароля, изменение профиля, оформление заказа. Это важно для расследования фрода.
API-вызовы. Если на сайте есть REST API, каждый мутирующий запрос логируется с IP, токеном, методом и телом запроса (с маскированием чувствительных данных).
Схема хранения
CREATE TABLE myvendor_audit_log (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
user_id INT,
user_name VARCHAR(200), -- денормализовано, на случай удаления пользователя
ip INET,
action VARCHAR(100) NOT NULL, -- 'iblock.element.update', 'order.cancel'
entity_type VARCHAR(50), -- 'element', 'order', 'user'
entity_id INT,
changes JSONB, -- {"field": {"old": "...", "new": "..."}}
context JSONB -- доп. данные: user_agent, session_id
);
CREATE INDEX idx_audit_entity ON myvendor_audit_log(entity_type, entity_id);
CREATE INDEX idx_audit_user ON myvendor_audit_log(user_id, created_at DESC);
CREATE INDEX idx_audit_action ON myvendor_audit_log(action, created_at DESC);
Поле changes хранит только изменившиеся поля, не весь объект — это экономит место и делает сравнение наглядным.
Детально: перехват событий Битрикс
Для инфоблоков — пара событий OnBeforeIBlockElementUpdate (читаем старые значения) и OnAfterIBlockElementUpdate (сравниваем с новыми):
// В OnBeforeIBlockElementUpdate — сохраняем старые данные
AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', function(&$fields) {
if (empty($fields['ID'])) return;
$old = \CIBlockElement::GetByID($fields['ID'])->GetNext();
\MyVendor\Audit\Snapshot::set($fields['ID'], $old);
});
// В OnAfterIBlockElementUpdate — сравниваем и логируем
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', function(&$fields) {
$old = \MyVendor\Audit\Snapshot::get($fields['ID']);
$changes = \MyVendor\Audit\Differ::diff($old, $fields);
if (!empty($changes)) {
\MyVendor\Audit\Logger::log('iblock.element.update', 'element', $fields['ID'], $changes);
}
});
Хранить снапшоты в памяти (Snapshot::set) безопасно, потому что они живут в рамках одного запроса.
Просмотр и поиск в административном интерфейсе
Журнал аудита отображается в /bitrix/admin/ с фильтрами: по пользователю, по типу события, по дате, по ID объекта. Для каждой записи — раскрываемая детальная карточка с diff-представлением изменений (визуальное сравнение старого и нового значения).
Поиск по журналу быстрый благодаря индексам по user_id и created_at. Для фильтрации по тексту изменений используется GIN-индекс по JSONB-полю changes.
Ротация логов
Журнал аудита растёт и может занять значительное место. Модуль включает политику ротации: записи старше N дней (настраивается, обычно 90–180 дней) архивируются в отдельную таблицу myvendor_audit_archive или выгружаются в файл и удаляются. Агент запускается ежедневно в 03:00.
Сроки разработки
| Масштаб | Состав | Срок |
|---|---|---|
| Базовый | Журнал изменений инфоблоков + заказов + просмотр | 2–3 недели |
| Средний | + действия покупателей + API-лог + ротация | 4–5 недель |
Перед разработкой важно определить список аудируемых событий — логировать вообще всё не нужно и вредно для производительности. Составьте конкретный список: что, для кого и зачем фиксировать.







