Staff — Auth & roles
How login, sessions, roles, permissions, and route gates work.
Entry flows
| Path | UI | Outcome |
|---|---|---|
/ |
Role cards (StaffIndexPage) |
Navigate to /garson, /barkasa, or /patron |
/:role |
PinGate |
PIN/password → POST /api/auth/login/ → must match selected role → /masalar |
/login |
LoginPage |
Same auth API; used as admin-style password entry → /masalar |
Logged-in users hitting /, /:role, or /login are redirected to /masalar.
Legacy paths still redirect:
/staff→//staff/:role→/:role/app,/admin(+ optional page slug) → flat POS URLs
Session storage
| Item | Storage | Notes |
|---|---|---|
| Token | localStorage.auth_token |
Sent as Authorization: Bearer … |
| Current user | React Query authMe (+ auth helpers) |
Restored via GET /api/auth/me/ |
| Legacy staff session key | Cleared on read | Old biurla.staff.session.v1 removed |
AuthProvider waits for /auth/me/ (or clear failure) before rendering the app shell. Failed restore clears local auth.
Logout
Confirm dialog → unsubscribe Web Push (best effort) → POST /api/auth/logout/ → clear token → navigate to /.
Roles and profile mapping
Staff roles in the API: patron | garson | barkasa.
In the UI, patron is treated as profile admin (full nav). Mapping: src/lib/staff/roles.ts (ROLE_TO_PROFILE).
PinGate rejects login when session.user.role does not match the selected role card.
Tab access (navigation)
Built by posNavItemsFor(profile, canReservation) in AdminPage.constants.ts. Reservation tab requires reservation.manage.
| Tab (URL) | Garson | Barkasa | Patron |
|---|---|---|---|
Masalar /masalar |
✓ | ✓ | ✓ |
Ürünler /urunler |
✓ | ||
Adisyonlar /checks |
✓ | ✓ | |
Raporlar /reports |
✓ | ✓ | |
İşlem geçmişi /islem-gecmisi |
✓ | ||
Rezervasyon /rezervasyon |
✓* | ✓* | |
Müdavim /mudavim |
✓ | ✓ | |
Ayarlar /ayarlar |
✓ |
*Only if hasPermission(..., "reservation.manage") — true for barkasa and patron; false for garson.
AppAuthGate enforces this: unknown or disallowed slug → redirect to /masalar.
Fine-grained permissions
hasPermission(session, perm) in src/lib/staff-session.ts gates actions inside dialogs (approve, payments, merge, stock, staff manage, etc.).
Important rules:
| Rule | Behavior |
|---|---|
session === null |
Treated as full allow (patron/admin owner path when profile is admin) |
role === "patron" |
All permissions |
| Garson | Add items, payments set, table close/merge, print, ikram/iptal/zayi — no order.approve, no reservation.manage, no product/staff/stock manage |
| Barkasa | Garson set plus order.approve and reservation.manage |
Permission strings include: order.add, order.approve, product.add, print.receipt, item.ikram / iptal / zayi, payment variants, table.close / merge / unmerge, stock.manage, staff.manage, reservation.manage.
STAFF_VIEWS is separate capability metadata (includes mutfak / bar labels for patron/barkasa). It does not create kitchen routes.
Implementation map
| Concern | Files |
|---|---|
| Provider | src/providers/AuthProvider.tsx |
| Login UI | src/features/auth/LoginPage.tsx, src/components/staff/PinGate.tsx |
| Gates | src/features/auth/AppAuthGate.tsx |
| Auth API | src/lib/api/auth.ts |
| Paths | src/lib/auth/paths.ts |
| Permissions | src/lib/staff-session.ts |
| Role labels | src/lib/staff/roles.ts |