feat(auth): WorkflowRoles configurable claim path + ordinis:admin super-role
User report: token has roles в resource_access.ordinis.roles (client-scoped),
backend WorkflowRoles читал hardcoded realm_access.roles → forbidden_role
для всех reviewer actions.
Backend:
- WorkflowRoles: depends OrdinisAuthProperties → reads via rolesClaim path
(же что ScopeContext). Default realm_access.roles, на staging/prod env
var ORDINIS_AUTH_ROLES_CLAIM=resource_access.ordinis.roles (уже wired
в helm helper).
- Nested claim path resolver — mirror ScopeContext.readClaimByPath
- New super-role ADMIN ('ordinis:admin') — holder автоматически проходит
любой workflow check без явного назначения отдельных ролей. Convenience
для small teams.
Frontend (usePermissions.ts):
- tokenRoles() читает оба claim path (realm_access.roles +
resource_access.ordinis.roles) и объединяет — UI gate работает
независимо от backend config
- hasRole() recognizes 'ordinis:admin' как super-role override
- ROLE_ADMIN exported
Docs:
- docs/operator/rbac.md: добавлен ordinis:admin row, JWT claim path note,
Admin profile updated (super-role vs composite explanation)
This commit is contained in:
@@ -28,9 +28,12 @@ Ordinis использует **Keycloak realm roles** (claim `realm_access.roles
|
||||
| `ordinis:schema:reviewer` | Approve / Запросить правки / Отклонить **schema draft** |
|
||||
| `ordinis:schema:publisher` | Publish approved schema draft → live |
|
||||
| `ordinis:record:reviewer` | Approve / Reject **record draft** (Approval Workflow v2) |
|
||||
| `ordinis:admin` | **Super-role** — автоматически разрешает любой workflow action. Convenience для small teams: assign one role вместо трёх. |
|
||||
|
||||
Backend проверяет роль перед каждым действием. Без роли — `403 forbidden_role` с сообщением о требуемой роли. Frontend дополнительно скрывает кнопки, для которых нет роли.
|
||||
|
||||
> **JWT claim path:** на staging/prod backend читает роли из `resource_access.ordinis.roles` (client-scoped roles в Keycloak `ordinis` client). Default fallback — `realm_access.roles`. Настраивается через `ORDINIS_AUTH_ROLES_CLAIM` env var.
|
||||
|
||||
> **Maker side** (создание / submit / withdraw draft'а) специальной ролью не gated — любой authenticated user с required scope может создать draft. Backend защищает invariant maker-checker через `403 self_approve_forbidden` (один и тот же user не может approve свой draft).
|
||||
|
||||
## Полная матрица действий
|
||||
@@ -78,12 +81,16 @@ Backend проверяет роль перед каждым действием.
|
||||
Финальный gatekeeper для production публикации схем. Обычно более узкая группа чем reviewers.
|
||||
|
||||
### Admin (полный доступ)
|
||||
|
||||
**Простой путь** — single role `ordinis:admin` (super-role): backend и frontend оба recognize её как override для любого workflow check'а. Достаточно одного назначения.
|
||||
|
||||
**Канонический путь (composite в Keycloak)** — `ordinis:admin` как composite, агрегирующий:
|
||||
- `ordinis:client:restricted`
|
||||
- `ordinis:schema:reviewer`
|
||||
- `ordinis:schema:publisher`
|
||||
- `ordinis:record:reviewer`
|
||||
|
||||
Или **composite role** `ordinis:admin`, которая агрегирует все четыре.
|
||||
Composite-роль в Keycloak автоматически expands в JWT — token содержит все включённые роли. Это работает и без super-role override.
|
||||
|
||||
## Настройка в Keycloak
|
||||
|
||||
|
||||
Reference in New Issue
Block a user