02. Роли и права
2.1. Общая концепция
Платформа использует ролевую модель доступа на трёх уровнях:
- Объектов — какие коллекции и документы доступны пользователю
- Операций — что именно можно делать с объектом (читать, создавать, изменять, удалять, проводить)
- Строк (RLS — Row-Level Security) — какие конкретно записи видит пользователь
Всё описывается декларативно в DSL. Платформа автоматически применяет эти правила при любом обращении к данным (через интерфейс, API или процедуры).
2.2. Синтаксис роли
РОЛЬ ИмяРоли
ДОСТУП ИмяОбъекта СПИСОК_ДЕЙСТВИЙ
ДОСТУП ИмяДругогоОбъекта ПОЛНЫЙ
# Опционально: RLS-ограничения
ОГРАНИЧЕНИЕ_ДОСТУПА ИмяОбъекта ГДЕ Условие
КОНЕЦ_РОЛИ
2.3. Действия (уровни доступа)
| Действие | Разрешает | Применяется для |
|---|---|---|
| ЧТЕНИЕ | Просмотр записей, открытие карточки | Коллекции, документы |
| ДОБАВЛЕНИЕ | Создание новых записей | Коллекции, документы |
| ИЗМЕНЕНИЕ | Редактирование существующих записей | Коллекции, документы |
| УДАЛЕНИЕ | Физическое удаление записей | Коллекции, документы |
| ПРОВЕДЕНИЕ | Проведение и распроведение документа | Только документы |
| ПОЛНЫЙ | Все вышеперечисленные (кроме ПРОВЕДЕНИЕ) | Все объекты |
Важно: Для документов ПОЛНЫЙ НЕ включает ПРОВЕДЕНИЕ — это отдельное право, которое нужно указывать явно.
2.4. Примеры ролей
Простая роль (только чтение):
РОЛЬ Наблюдатель
ДОСТУП Клиенты ЧТЕНИЕ
ДОСТУП ЗаказНаряд ЧТЕНИЕ
ДОСТУП Отчеты ПОЛНЫЙ # Полный доступ к отчётам (они только для чтения)
КОНЕЦ_РОЛИ
Роль менеджера (с RLS "только свои заказы"):
РОЛЬ Менеджер
ДОСТУП Клиенты ЧТЕНИЕ, ДОБАВЛЕНИЕ, ИЗМЕНЕНИЕ
ДОСТУП ЗаказНаряд ЧТЕНИЕ, ДОБАВЛЕНИЕ, ИЗМЕНЕНИЕ, ПРОВЕДЕНИЕ
# Ключевая строка: менеджер видит только те заказы, где он указан как ответственный
ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Менеджер = ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ()
КОНЕЦ_РОЛИ
Директор филиала (мультифирменный учёт):
РОЛЬ ДиректорФилиала
ДОСТУП ЗаказНаряд ПОЛНЫЙ, ПРОВЕДЕНИЕ
# Видит все заказы, но только своей организации
ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Организация = ТЕКУЩАЯ_ОРГАНИЗАЦИЯ()
КОНЕЦ_РОЛИ
Региональный директор (несколько организаций из списка):
РОЛЬ РегиональныйДиректор
ДОСТУП ЗаказНаряд ПОЛНЫЙ, ПРОВЕДЕНИЕ
# Может работать с несколькими фирмами
ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Организация IN ('1', '2', '5')
# Или по названиям (платформа сама преобразует в ID)
# ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Организация IN ('ООО "Альфа"', 'ООО "Бета"')
КОНЕЦ_РОЛИ
2.5. Системные функции для RLS
| Функция | Возвращает | Пример использования |
|---|---|---|
| ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ() | ID текущего пользователя (число) | ГДЕ Менеджер = ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ() |
| ТЕКУЩАЯ_ОРГАНИЗАЦИЯ() | ID организации из контекста сессии | ГДЕ Организация = ТЕКУЩАЯ_ОРГАНИЗАЦИЯ() |
| ТЕКУЩАЯ_РОЛЬ() | Имя роли текущего пользователя (строка) | ГДЕ РольДоступа = ТЕКУЩАЯ_РОЛЬ() |
Как работает ТЕКУЩАЯ_ОРГАНИЗАЦИЯ():
- Пользователь выбирает организацию при входе (или переключает в интерфейсе)
- Платформа хранит этот выбор в сессии
- Все RLS-условия с этой функцией автоматически подставляют ID выбранной организации
2.6. Пользователи
Синтаксис создания пользователя:
ПОЛЬЗОВАТЕЛЬ Логин
ПАРОЛЬ "пароль"
ПОЛНОЕ_ИМЯ "Иванов Иван Иванович"
ЭЛЕКТРОННАЯ_ПОЧТА "ivan@company.ru" # опционально
ТЕЛЕФОН "+7(999)123-45-67" # опционально
РОЛЬ ИмяРоли
КОНЕЦ_ПОЛЬЗОВАТЕЛЯ
Обязательные поля: ПАРОЛЬ, РОЛЬ. Остальные — опциональные.
Примеры пользователей:
ПОЛЬЗОВАТЕЛЬ admin
ПАРОЛЬ "admin123"
ПОЛНОЕ_ИМЯ "Администратор Системы"
ЭЛЕКТРОННАЯ_ПОЧТА "admin@3erp.ru"
РОЛЬ Администратор
КОНЕЦ_ПОЛЬЗОВАТЕЛЯ
ПОЛЬЗОВАТЕЛЬ manager_ivanov
ПАРОЛЬ "qwerty"
ПОЛНОЕ_ИМЯ "Иванов Иван Менеджер"
РОЛЬ Менеджер
КОНЕЦ_ПОЛЬЗОВАТЕЛЯ
2.7. Как RLS работает внутри
Когда пользователь (с ролью Менеджер) выполняет операцию:
1. Запрос через интерфейс (открыть список заказов):
Платформа автоматически модифицирует SQL:
-- Без RLS:
SELECT * FROM ЗаказНаряд
-- С RLS (Менеджер видит только свои):
SELECT * FROM ЗаказНаряд WHERE Менеджер = 123
2. Вызов НАЙТИ_ВСЕ("ЗаказНаряд", "Статус = 'В работе'") в процедуре:
Платформа также добавляет RLS-условие в WHERE:
SELECT * FROM ЗаказНаряд WHERE (Статус = 'В работе') AND (Менеджер = 123)
3. Прямой ЗАПРОС("SELECT ..."):
RLS НЕ РАБОТАЕТ! Если в процедуре используется прямой SQL-запрос через ЗАПРОС(), платформа не может контролировать доступ. Разработчик обязан вручную добавить фильтры RLS в SQL-запрос.
✅ Правильный подход при использовании ЗАПРОС():
ПРОЦЕДУРА ПолучитьМоиЗаказы
# 1. Получаем ID текущего пользователя (число)
ВЫЧИСЛИТЬ ТекущийПользователь = ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ()
ВЫЧИСЛИТЬ IDПользователя = ТекущийПользователь.id
# 2. Явно добавляем условие RLS в SQL-запрос
ВЫЧИСЛИТЬ МойSQL = "SELECT id, Номер, ИтогоСумма FROM ЗаказНаряд WHERE Статус = 'В работе' AND Менеджер = " + IDПользователя
# 3. Выполняем запрос
ВЫЧИСЛИТЬ Результат = ЗАПРОС(МойSQL)
# 4. Возвращаем результат
ВОЗВРАТ Результат
КОНЕЦ_ПРОЦЕДУРЫ
❌ Опасный подход (обход RLS):
ПРОЦЕДУРА ОпаснаяПроцедура
# Нет фильтра по Менеджер — пользователь увидит ВСЕ заказы, включая чужие!
ВЫЧИСЛИТЬ Результат = ЗАПРОС("SELECT id, Номер, ИтогоСумма FROM ЗаказНаряд WHERE Статус = 'В работе'")
ВОЗВРАТ Результат
КОНЕЦ_ПРОЦЕДУРЫ
2.8. Как получить данные текущего пользователя
Функция ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ() возвращает объект пользователя со следующими полями:
| Поле | Тип | Описание |
|---|---|---|
| id | ЧИСЛО | ID пользователя в системе |
| login | СТРОКА | Логин |
| full_name | СТРОКА | Полное имя |
| СТРОКА | Электронная почта | |
| role | СТРОКА | Имя роли |
| role_id | ЧИСЛО | ID роли |
Пример использования:
ПРОЦЕДУРА ПримерСПользователем
ВЫЧИСЛИТЬ Пользователь = ТЕКУЩИЙПОЛЬЗОВАТЕЛЬ()
# Доступ к полям
ВЫЧИСЛИТЬ ID = Пользователь.id
ВЫЧИСЛИТЬ Логин = Пользователь.login
ВЫЧИСЛИТЬ Имя = Пользователь.full_name
ВЫЧИСЛИТЬ Роль = Пользователь.role
# Проверка роли
ЕСЛИ Пользователь.role == "Администратор" ТО
ВЫВЕСТИ "У вас полный доступ"
ИНАЧЕ
ВЫВЕСТИ "Ваша роль: " + Пользователь.role
КОНЕЦ
# Использование в SQL (важно: использовать .id, а не весь объект)
ВЫЧИСЛИТЬ IDПользователя = Пользователь.id
ВЫЧИСЛИТЬ Запрос = "SELECT * FROM Задачи WHERE Исполнитель = " + IDПользователя
ВЫЧИСЛИТЬ МоиЗадачи = ЗАПРОС(Запрос)
КОНЕЦ_ПРОЦЕДУРЫ
2.9. Особые случаи
Несколько ограничений на один объект:
Если для объекта указано несколько ОГРАНИЧЕНИЕ_ДОСТУПА, они объединяются через AND:
РОЛЬ СпециальнаяРоль
ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Организация = ТЕКУЩАЯ_ОРГАНИЗАЦИЯ()
ОГРАНИЧЕНИЕ_ДОСТУПА ЗаказНаряд ГДЕ Статус != "Закрыт"
# Итоговое условие: (Организация = X) AND (Статус != "Закрыт")
КОНЕЦ_РОЛИ
Если у пользователя несколько ролей:
Платформа поддерживает только одну роль на пользователя. Нельзя назначить несколько ролей. Если нужна комбинация прав — создайте отдельную роль с нужными правами.
Доступ к системным коллекциям:
СистемныеКонстанты, Организации, справочник пользователей — у них тоже можно ограничивать доступ:
РОЛЬ Администратор
ДОСТУП СистемныеКонстанты ПОЛНЫЙ
ДОСТУП Пользователи ПОЛНЫЙ
КОНЕЦ_РОЛИ
РОЛЬ ОбычныйПользователь
ДОСТУП СистемныеКонстанты ЧТЕНИЕ # Может читать, но не менять настройки
# Доступа к Пользователи нет вообще
КОНЕЦ_РОЛИ
2.10. Best Practices
- Принцип минимальных привилегий: Давайте пользователю ровно те права, которые нужны для работы. Лучше создать 5 узких ролей, чем 1 универсальную с ПОЛНЫЙ.
- Именование ролей: Используйте понятные названия, отражающие должность или функцию:
МенеджерПоПродажам,Кладовщик,БухгалтерМатериальногоСтола. - RLS-проверки в процедурах: Если в процедуре есть
ЗАПРОС()с прямым SQL, всегда добавляйте явную проверку прав с использованиемТЕКУЩИЙПОЛЬЗОВАТЕЛЬ().idилиТЕКУЩАЯ_ОРГАНИЗАЦИЯ().id. - Предпочтительный подход: Используйте
НАЙТИ,НАЙТИ_ВСЕ,ПРОЧИТАТЬ— они автоматически учитывают RLS. - Тестирование RLS: Создайте тестового пользователя с нужной ролью и проверьте: видит ли он чужие записи в интерфейсе, может ли изменить поле без права ИЗМЕНЕНИЕ, может ли провести документ без права ПРОВЕДЕНИЕ.
- Осторожно с IN ('1','2','3'): Если список организаций большой (десятки), лучше создать отдельную коллекцию "ДоступныеФирмы" и через процедуру динамически формировать RLS. В текущей версии список в IN нужно поддерживать вручную.
- Роль Администратор: Всегда создавайте хотя бы одного пользователя с ролью, имеющей полный доступ ко всем объектам. Иначе можно потерять возможность управлять системой.
- Для отладки RLS используйте
ВЫВЕСТИдля логирования реальных SQL-запросов.