3ERP

3ERP - простая и бесплатная программа для бухгалтерского и оперативного учёта в учреждениях сферы торговли и услуг, общественного питания, складского хранения, автосервиса, медицины, логистики, производства, управления работами и заявками, поддерживающая до 100 пользователей, на русском языке и полностью бесплатная для 1 пользователя. На сайт (скачать)

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 СТРОКА Полное имя
email СТРОКА Электронная почта
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-запросов.
3532 | 0 | 3532 | 354 | 168 | 35