feat(admin): users and permissions

Sprint 25.

New features/admin/users/ module, net-new /:lang/backoffice/users route +
Dashboard Quick Action.

- users: name, Telegram username, scope (marketplace vs office admin),
  role (inline change), status (active/invited/suspended), last login
- 4 built-in roles (owner/admin/editor/viewer) with flat permission lists
- invitations: email + role + scope form, pending list + revoke (no email
  actually sends - local record only)
- passwordless login confirmed already real (AdminAuthService Telegram QR,
  docs/BACKEND.md item 1) - linked, not reimplemented
- per-user mock session list (device/IP/last-active, revoke) - flagged as
  mock since the real AdminAuthService only ever tracks the current
  browser's session
- per-user audit log dialog (role/status changes), same pattern as
  Sprint 24's per-transaction audit, intentionally separate from the
  system-wide log planned for Sprint 26

docs/ADMIN.md + docs/BACKEND.md (new item 14) updated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-15 11:05:21 +04:00
parent 7d65913245
commit 17adc9e9fd
12 changed files with 455 additions and 3 deletions

View File

@@ -335,6 +335,40 @@ between the two mock feature areas.
- Wired into `/:lang/backoffice/transactions`, replacing the coming-soon
placeholder.
## Sprint 25 - Users & Roles (mock/local)
`features/admin/users/`. Single consolidated page (`admin-users-page`) at
`/:lang/backoffice/users` - not previously in the Quick Actions list or
routes at all, this is a net-new admin section.
- **Users**: name, Telegram username, `scope` (`marketplace` vs `office`
admin - distinguishes tenant-level owners/admins from internal staff),
role, status (`active`/`invited`/`suspended`), last login. Role change is
an inline `<select>`; suspend/reactivate is confirm-gated for suspend
only.
- **Roles/permissions**: 4 built-in roles (`owner`/`admin`/`editor`/`viewer`)
with a flat permission-string list (`products.manage`, `*` for owner,
etc.) - a real permission catalog and custom-role creation don't exist,
intentionally scoped down to what's needed to demonstrate the model.
- **Invitations**: email + role + scope form, pending list with revoke.
No email actually sends - `AdminUsersLocalGateway.inviteUser()` only
creates the local record.
- **Passwordless login**: already existed before this sprint -
`AdminAuthService`'s Telegram QR flow (`docs/ADMIN.md`'s existing admin
login section, `docs/BACKEND.md` item 1). This sprint's Users page links
to it via a hint, doesn't reimplement it.
- **Session manager / device manager**: per-user session list (device, IP,
last active, current-session badge) with per-session revoke, mocked
(`AdminUsersLocalGateway.loadSessions()` fabricates 2 sessions per user
on first view) - the real `AdminAuthService`/session-cookie flow only
ever tracks the *current* browser's session, so multi-device session
listing has no real backend counterpart yet (see `docs/BACKEND.md` item 1).
- **Audit**: per-user audit log (role/status changes), same dialog pattern
as Sprint 24's per-transaction audit - not the system-wide security/audit
log planned for Sprint 26.
- Wired into `AdminDashboardFacade`'s Quick Actions list (`dashboard.actionUsers`
-> `/:lang/backoffice/users`).
## Known gaps / backend needs
- **Dashboard metrics endpoint.** Categories/Products counts are computed