Доступ к ДП — модель взаимодействия трёх систем¶
Обзор¶
Доступ к дополнительным параметрам контролируется тремя независимыми системами. Каждая покрывает свой уровень гранулярности, но документированного приоритета между ними нет.
Система 1: ExtParamPermission — «группа видит/редактирует ДП»
Система 2: TaskEntityPermissionsSet — «роль/группа в состоянии видит/редактирует ДП»
Система 3: SmartAccess — «пользователи по смарт-выражению видят/редактирует ДП»
Дополнительно для табличных ДП:
Система 4: ExtParamTableSettingsInSubcat*Permissions — «группа/состояние → доступ к колонке»
Система 1: ExtParamPermission (прямые права группы)¶
Гранулярность: ДП + категория + группа.
| Таблица | PK | Колонки |
|---|---|---|
ExtParamPermission |
(ExtParamID, SubcatID, GroupID) | AllowEdit (bit) |
Логика: если пользователь в группе → AllowEdit=1 → редактирование, иначе — только чтение.
Материализация: ExtParamsRights (621K строк) — кэш, пересчитывается SP ExtParamsRightsRefresh.
Где настраивается: Админка категории → ДП → вкладка «Доступ».
Особенности:
- Нет контроля по состояниям — права статичны
- Нет уровня Disallow — только Read/Write
- Самая старая из трёх систем
Система 2: TaskEntityPermissionsSet (матрица доступа)¶
Гранулярность: ДП + категория + (состояние × роль/группа/экшен).
| Таблица | Назначение |
|---|---|
TaskEntityPermissionsSet |
Заголовок матрицы (EntityAccessType=1 для ДП) |
TaskEntityPermissions |
Строки: (StateID, GroupID, ActionID, роли) → AccessType |
Логика: для текущего состояния задачи определяется уровень доступа (Disallow/Read/Write) по приоритету: группы/роли/экшены > All.
Флаг включения: ExtParamsInSubcat.TaskEntityPermissionControl (bit). Если false — система 2 не применяется.
Где настраивается: Админка категории → ДП → кнопка «Матрица доступа».
Особенности:
- Контроль по состояниям — самая гибкая из трёх
- Три уровня доступа: Disallow, Read, Write
- Известная проблема: таблица-посредник TaskEntityPermissionsSet избыточна
Поведение после маршрутного перехода (v2.267+, патч): до исправления
EntityAccessManagerчиталStateIDизTasksCache; при задержке инвалидации (характерно для k8s-среды) клиент мог получить список ДП со старым статусом — ДП, ставший доступным в новом статусе, не появлялся без F5. Начиная с патча 2.267,StateIDпередаётся в проверку матрицы явно из контекста шага (ExtParams.cs → accessMatrixChecks → taskStateIds → EntityAccessManager.GetAccessForSubcat/GetAccessForTasks).
Подробнее: permissions/database.md §2.6.
Система 3: SmartAccessForExtParamsInSubcat (смарт-доступ)¶
Гранулярность: ДП + категория + SmartExpression → CanRead/CanWrite.
| Таблица | PK | Назначение |
|---|---|---|
SmartAccessForExtParamsInSubcat |
Id | Правило: (SubcatId, ExtParamId?, UsersSmartExpressionId) → CanRead, CanWrite |
SmartAccessForExtParamsInSubcatRules |
Id | Список ДП, на которые действует правило |
SmartAccessForExtParamsInSubcatTriggerExtParams |
Id | При изменении каких ДП пересчитывать |
SmartAccessForExtParamsInSubcatTriggerGroups |
Id | При изменении членства в каких группах пересчитывать |
SmartAccessForExtParamsInSubcatView |
(SmartAccessId, UserId, TaskId) | Материализованный результат (262K строк) |
Логика: SmartExpression возвращает список UserID → для них применяются CanRead/CanWrite. Результат материализуется в View-таблицу.
Флаг включения: ExtParamsInSubcat.SmartAccessControl (bit).
Где настраивается: Админка категории → ДП → «Умный доступ».
Особенности:
- Самая мощная: произвольная логика через SmartExpression
- Материализованный результат — не real-time
- ExtParamId = NULL в заголовке → правило на все ДП категории
Схема дочерних таблиц¶
SmartAccessForExtParamsInSubcat
│ Id, Name, CanRead, CanWrite, UsersSmartExpressionId, ExtParamId?, SubcatId
│
├── Rules (какие ДП скрывать/показывать)
│ SmartAccessId (FK) + ExtParamId (FK → ExtParams)
│
├── TriggerExtParams (при изменении каких ДП пересчитывать View)
│ SmartAccessId (FK) + ExtParamId (FK → ExtParams)
│
└── TriggerGroups (при изменении членства пересчитывать View)
SmartAccessId (FK) + GroupId (FK → Groups)
Известные проблемы:
- Rules и TriggerExtParams структурно идентичны (SmartAccessId + ExtParamId) — параллельные таблицы
- TriggerExtParams и TriggerGroups — два списка триггеров в разных таблицах, можно объединить с дискриминатором
- Четыре таблицы для одного правила — избыточная индирекция
Система 4: Колоночные права табличных ДП¶
Гранулярность: колонка табличного ДП + категория + (группа ИЛИ состояние).
| Таблица | PK | Назначение |
|---|---|---|
ExtParamTableSettingsInSubcat |
Id | Привязка колонки к категории: (ExtParamInSubcatId, ColumnId) + флаги |
ExtParamTableSettingsInSubcatGroupPermissions |
Id | Доступ по группе: +GroupId → AccessType |
ExtParamTableSettingsInSubcatStatePermissions |
Id | Доступ по состоянию: +StateId → AccessType |
Флаги включения (в ExtParamTableSettingsInSubcat):
- GroupAccessControlMode (int) — режим контроля по группам
- StateAccessControlEnabled (bit) — контроль по состояниям
Ограничение: виртуальные группы не поддерживаются
При настройке доступа к колонкам таблицы по группам (через ExtParamTableSettingsInSubcatGroupPermissions) виртуальные группы не используются.
Виртуальные группы (тип «Виртуальная», например «Подписчики задач (всем)») предназначены для ограничений на уровне задач, но не для разграничения прав на уровне колонок таблиц. Для колоночных прав доступны только обычные группы (тип «Обычная» и «Связанная»).
Известные проблемы:
- GroupPermissions и StatePermissions — параллельные таблицы с идентичной структурой. Можно объединить с PermissionType дискриминатором.
- Обе таблицы хранят ExtParamInSubcatId + ColumnId + SubcatId + ExtParamId. Последние два — избыточны: выводятся из ExtParamInSubcatId. Та же болезнь что у TaskEntityPermissionsSet.
Подробнее: ext-params/table/database.md §Права доступа к столбцам.
Взаимодействие систем¶
Что применяется когда¶
| Ситуация | Системы |
|---|---|
| ДП в категории, матрица выключена, SmartAccess выключен | Только система 1 (ExtParamPermission) |
| ДП в категории, матрица включена | Система 1 + Система 2 |
| ДП в категории, SmartAccess включен | Система 1 + Система 3 |
| Колонка табличного ДП, Group/State контроль включен | Система 1 + Система 4 |
| Всё включено | Все четыре системы |
Порядок проверки (бэкенд)¶
Бэкенд-код (fn_AccessGetAccessTypeExtParam, EntityAccessLogicBase.CheckAccess) проверяет системы в определённом порядке, но документированного приоритета нет. Фактическое поведение:
- Система 3 (SmartAccess) — если включена, материализованный View определяет видимость ДП
- Система 2 (матрица) — если включена, определяет AccessType по состоянию/роли
- Система 1 (ExtParamPermission) — базовый уровень Read/Write по группе
- Система 4 (колоночные права) — применяется поверх для табличных ДП
Конфликт: если SmartAccess скрывает ДП (CanRead=0), но матрица разрешает Write — побеждает SmartAccess (ДП скрыт). Обратное: если матрица запрещает, а SmartAccess разрешает — ДП доступен. Фактически SmartAccess работает как маска видимости, а матрица — как уровень доступа.
Схема¶
┌─ ExtParamPermission (Read/Write по группе)
│
ExtParamsInSubcat ────────┼─ TaskEntityPermissionsSet (Disallow/Read/Write по состоянию×роль)
│ │ └── TaskEntityPermissions (строки матрицы)
│ │
│ └─ SmartAccessForExtParamsInSubcat (маска видимости)
│ ├── Rules
│ ├── TriggerExtParams
│ └── TriggerGroups
│
└── ExtParamTableSettingsInSubcat (для табличных ДП)
├── GroupPermissions (Read/Write по группе на колонку)
└── StatePermissions (Read/Write по состоянию на колонку)