Введение
Привет, Habr! Сегодня я хочу поделиться опытом разработки системы контроля доступа (Access Control System, ACS) для low-code платформы "Системный Геном". Задача была непростой: нужно было создать гибкую систему, которая поддерживает иерархии, автоматическую синхронизацию с приложениями и строгий контроль доступа, но при этом остаётся понятной для администраторов и быстрой в работе. В этой статье я расскажу, как мы справились с этой задачей, какие ошибки допустили на старте и как в итоге пришли к решению, которое теперь успешно работает в продакшене.
Наша система закрыта по умолчанию (всё, что не разрешено явно, запрещено), поддерживает иерархические роли и объекты, интегрируется с Системным Геномом и позволяет администраторам легко управлять доступом через веб-интерфейс. Мы также добавили аудит действий, чтобы можно было понять, кто и почему отключил то или иное разрешение. Давайте разберём, как это устроено.
Постановка задачи
Наша low-code платформа позволяет пользователям создавать приложения с помощью визуальных конструкторов. Приложения состоят из рабочих столов, страниц и различных объектов (форм, таблиц, кнопок), которые мы называем "потомками базовых классов Системного Генома" (БК). БК — это, например, таблица в базе данных, класс на бэкенде или кнопка на фронтенде.
Нам нужно было реализовать систему контроля доступа, которая:
Работает как отдельное веб-приложение с удобным интерфейсом.
Поддерживает справочники для типов объектов доступа, объектов доступа, типов действий, ролей и пользователей.
Позволяет задавать связи между ролями, объектами и действиями.
Автоматически синхронизируется с Системным Геномом при публикации приложений.
Учитывает деактивированные разрешения и логирует, кто и когда их отключил.
Работает по принципу "всё запрещено, кроме явно разрешённого".
Изначально мы сделали систему слишком сложной: многоуровневые проверки, избыточные таблицы и запутанная терминология. После нескольких итераций и обсуждений мы пришли к более простому и практичному решению, о котором я расскажу ниже.
Архитектура системы
Система состоит из двух основных частей:
Веб-приложение (вне Системного Генома): здесь хранятся справочники, разрешения и интерфейс для управления доступом.
Интеграция с Системным Геномом: автоматическое заполнение справочников и разрешений при публикации приложений.
Модель данных
Структура данных нашей системы представлена на ER-диаграмме ниже. Мы постарались сделать её простой, но гибкой, чтобы поддерживать иерархии, связи N-N и аудит действий администраторов.

Логика работы
Ручное управление через веб-интерфейс:
Администратор вручную заполняет справочники: типы объектов доступа, типы действий, роли, пользователи.
Настраивает связи: какие действия разрешены для типов объектов, какие роли привязаны к пользователям и рабочим столам.
При деактивации разрешения система автоматически записывает, кто и когда это сделал.
Автоматическая синхронизация с Системным Геномом:
При публикации приложения:
Система проходит по всем рабочим столам.
Собирает связанные страницы и их содержимое (формы, таблицы, кнопки).
Проверяет, есть ли у объектов родители (БК), указанные в справочнике типов объектов доступа.
Добавляет найденные объекты в справочник объектов доступа с учётом иерархии.
Для каждой роли, связанной с рабочим столом, создаёт разрешения на все объекты этого рабочего стола. Если разрешение уже существует и деактивировано, оно остаётся деактивированным.
Проверка доступа:
Система закрыта по умолчанию: доступ разрешён только при наличии активного разрешения (поле "Активно" = true).
Для проверки доступа выполняется запрос: SELECT Активно FROM Разрешения WHERE ID_субъекта = ? AND ID_объекта = ? AND ID_действия = ?.
Оптимизация производительности
Чтобы система работала быстро даже при большом количестве пользователей и объектов, мы добавили несколько оптимизаций:
Кэширование: Разрешения кэшируются в Redis. Для каждой роли хранится список разрешённых объектов и действий. При изменении разрешения кэш обновляется.
Индексация: Поля, используемые в запросах (ID субъекта, ID объекта, ID действия), проиндексированы.
Простые ключи: Мы отказались от составных первичных ключей в пользу автоинкрементных ID, что упростило запросы.
Веб-интерфейс: удобство для администраторов
Одна из главных задач была сделать систему понятной для администраторов, которые не всегда обладают глубокими техническими знаниями. Мы разработали веб-интерфейс с акцентом на интуитивность:
Справочники: Представлены в виде таблиц с фильтрами и поиском. Для иерархических справочников ("Роли", "Объекты доступа") используется древовидное представление (мы применили библиотеку jsTree).
Связи N-N: Настройка через визуальный интерфейс. Например, для связи "Роли-Рабочие столы" администратор видит два списка: роли слева, рабочие столы справа. Связывание выполняется перетаскиванием или кнопками.
Управление разрешениями: Таблица с фильтрами по ролям, объектам и действиям. Администратор может деактивировать разрешение, нажав кнопку "Деактивировать". При этом автоматически заполняются поля "Кем деактивировано" (ID текущего администратора) и "Когда деактивировано" (текущая дата/время).
Аудит: В разделе "Журнал деактиваций" администратор видит список деактивированных разрешений с указанием, кто и когда это сделал. При клике на запись отображаются контактные данные администратора (например, email) для связи.
Пример работы системы
Давайте разберём реальный сценарий:
Администратор создаёт тип объекта доступа "Форма" с привязкой к БК "Форма" в Системном Геноме.
Создаёт роль "Редакторы", добавляет в неё пользователя "Иван Иванов" и связывает роль с рабочим столом "Заявки".
При публикации приложения:
Система находит рабочий стол "Заявки", собирает связанные страницы и их содержимое.
Находит форму "Форма заявки", чей родитель (БК "Форма") есть в справочнике типов объектов доступа.
Добавляет "Форма заявки" в справочник объектов доступа.
Создаёт разрешение: "Редакторы" → "Форма заявки" → "Редактирование" → Активно: true.
Другой администратор, "Анна Петрова", решает временно отключить это разрешение. Она нажимает "Деактивировать", и в таблице "Разрешения" обновляются поля:
Активно: false.
Когда деактивировано: "2025-03-23 14:00".
Кем деактивировано: ID Анны Петровой.
Третий администратор видит в журнале деактиваций, что разрешение было отключено Анной, и пишет ей на email, чтобы уточнить причину.
Что мы узнали: ошибки и уроки
Изначально мы сделали систему слишком сложной:
Использовали составные первичные ключи, что усложняло запросы.
Добавили избыточные поля, которые не были нужны для базовой функциональности.
Придумали запутанную терминологию вроде "Сравнитель объектов доступа", которая путала администраторов.
После нескольких итераций мы:
Упростили структуру данных, перейдя на автоинкрементные ключи.
Добавили кэширование и индексацию для повышения производительности.
Сделали интерфейс интуитивным, заменив сложные термины на понятные ("Объекты доступа", "Действия на объекты").
Включили аудит, чтобы администраторы могли легко понять, кто и почему изменил разрешения.
Итог
Наша система контроля доступа теперь работает стабильно и эффективно. Она поддерживает все требования: иерархии, автоматическую синхронизацию с Системным Геномом, строгий контроль доступа и аудит действий. Администраторы могут легко управлять доступом через веб-интерфейс, а разработчики довольны производительностью системы.
Если у вас есть похожая задача, вот несколько советов:
Начинайте с простой структуры данных и добавляйте сложность только по мере необходимости.
Думайте о производительности с самого начала: кэширование и индексация спасут вас от проблем на больших объёмах данных.
Делайте интерфейс интуитивным: администраторы оценят древовидные структуры и визуальные связи.
Надеюсь, наш опыт будет полезен! Если у вас есть вопросы или идеи, как улучшить систему, пишите в комментариях — с радостью обсудим.