docs: README + casdoor-auth guide for the v1.3 changes

- README: Traefik edge (app at http://localhost), single postgres (casdoor
  DB inside), prod overlay usage, partial receipts, admin panel, dev-mode
  3-step flow, layout for infra/ and 02-casdoor-db.sql
- docs/casdoor-auth.md: new section «Stack changes in this release» (DB
  merge, Traefik, RBAC, partial receipt, calendar, upload, project filter),
  updated addresses and redirect-URI notes
This commit is contained in:
ali_mohaghegh
2026-09-01 17:28:45 +03:30
parent 8825f333a7
commit 31290ffbda
2 changed files with 91 additions and 22 deletions
+43 -4
View File
@@ -10,12 +10,13 @@ scenarios, test results, and how to manage the system yourself.
| What | Address | Credentials |
|---|---|---|
| App (frontend) | http://localhost:3000 | — |
| App (frontend) | http://localhost (Traefik edge; production: your domain) | — |
| API (backend) | http://localhost:8000 (Swagger: `/docs`) | — |
| Casdoor console | http://localhost:8080 | **admin / 123** (built-in org) |
| Casdoor OIDC discovery | http://localhost:8080/.well-known/openid-configuration | — |
| Casdoor public JWKS | http://localhost:8080/.well-known/jwks | — |
| In-network Casdoor (from the api container) | http://casdoor:8000 | — |
| Traefik host routes (local) | `localhost` → app · `api.localhost` → api · `auth.localhost` → casdoor · `s3.localhost` / `storage.localhost` → MinIO | needs those hosts to resolve (or use the host ports) |
### Seeded application users (org `inventory`)
@@ -143,7 +144,7 @@ After that, log in as the admin and use the Organization panel
| 1 | Casdoor unavailable | `POST /auth/login` (token exchange) or JWKS fetch on protected endpoints | Login page: «سرویس احراز هویت (Casdoor) در دسترس نیست»; API: 503 | `Casdoor token endpoint unreachable (…): …` or `JWKS fetch failed (…): …` | `docker compose ps` — casdoor must be `Up`; from the api container: `python -c "import urllib.request; print(urllib.request.urlopen('http://casdoor:8000/').status)"` |
| 2 | Backend unavailable | nginx `/api/` proxy | App shows «اتصال به سرور برقرار نشد» (frontend toast) | none (api is down) | `docker compose ps api`; `docker logs procurement-api`; curl `http://localhost:8000/health` |
| 3 | Invalid client (wrong client_id/secret) | Casdoor token endpoint | 503 «سرویس احراز هویت به درستی پیکربندی نشده است» | `Casdoor rejected password grant: error=invalid_client description=…` | Compare `PROCUREMENT_CASDOOR_CLIENT_ID/SECRET` in docker-compose with the application in the Casdoor console (Applications → inventory-app) |
| 4 | Invalid redirect URI | Casdoor authorization endpoint (browser flows only) | Casdoor's own error page in the browser | — (backend not involved) | The app no longer uses redirects. In the Casdoor console, the app's Redirect URIs must contain `http://localhost:3000/login` |
| 4 | Invalid redirect URI | Casdoor authorization endpoint (browser flows only) | Casdoor's own error page in the browser | — (backend not involved) | The app no longer uses redirects. If a browser OIDC flow is re-enabled, the app's Redirect URIs in the Casdoor console must contain the current app URL (`http://localhost/login` with Traefik) |
| 5 | Invalid / corrupted JWT | Backend JWT verification | 401 «توکن نامعتبر است» / «امضای توکن نامعتبر است» | `JWT unreadable: …` or `JWT kid '…' not found in JWKS` | Decode the token at jwt.io; check `kid` against `http://localhost:8080/.well-known/jwks` |
| 6 | Expired JWT | Backend JWT verification | 401 «توکن نامعتبر یا منقضی شده است» | `JWT verification failed: … Signature has expired` | Token `exp` claim; lifetime = Application → `expireInHours` (24h) |
| 7 | Missing JWT | Protected endpoint dependency | 401 «احراز هویت لازم است…» | normal access log, 401 | Send `Authorization: Bearer <token>`; in the app this means the session was cleared — log in again |
@@ -179,7 +180,7 @@ After that, log in as the admin and use the Organization panel
| 7 | Application exists | ✅ `inventory-app` |
| 8 | Client exists | ✅ `inventory-app-client` (grants incl. `password`) |
| 9 | Test users exist | ✅ razaei, mousavi, mohaghegh, tester (password 123456) |
| 10 | Redirect URI matches | ✅ `http://localhost:3000/login` registered (unused by the new flow, kept for console flows) |
| 10 | Redirect URI matches | ✅ N/A for the in-page flow (redirects unused). The seeded app holds the legacy `http://localhost:3000/login`; the seeder now defaults to `http://localhost/login` |
| 11 | OIDC works | ✅ discovery doc + token endpoint + JWT issuance verified |
| 12 | PKCE works | ➖ **N/A** — the PKCE/redirect flow was replaced by the in-page password-grant login (per the redesign spec); nothing to verify |
| 13 | Login works | ✅ form login in the browser (tester → `/inventory`) |
@@ -196,7 +197,45 @@ After that, log in as the admin and use the Organization panel
---
## 8. Managing Casdoor yourself
## 8. Stack changes in this release
- **One PostgreSQL instance.** The separate casdoor-postgres container is
gone: the app DB (`procurement`) and Casdoor's DB (`casdoor`) now live on
the same `postgres:18` service. The `casdoor` role + database are created
by `sql/02-casdoor-db.sql` on a fresh volume; the migration was done via
`pg_dump`/`pg_restore` (pre-migration backups are kept on the host).
- **Traefik v3 is the public edge.** Ports 80/443 (web/websecure); host rules
for app / api / auth / s3 / storage (env-overridable, localhost defaults).
The frontend nginx now only serves the SPA and proxies `/api` internally.
Production (real domains, Let's Encrypt, HTTP→HTTPS redirect) is a one
command with `docker-compose.prod.yml` — see its header for the env vars.
Note: Traefik must be **v3.6+** (≤3.3 fails against Docker Engine 29.x),
and the docker socket is mounted read-write (Docker Desktop rejects `:ro`).
- **RBAC hardening (Organization / Admin).** Only the `admin` can change
roles (`PATCH /users/{id}`); the procurement manager can only assign
projects to project managers. The user-creation form is removed — users
come from Casdoor via `POST /users/sync` (identity mirroring, roles
untouched). The admin has a dedicated panel at `/admin` (sync + grant/
revoke «مدیر تدارکات»).
- **Developer Mode is now a 3-step admin flow** on the login page: admin
credentials → role switcher (ادمین / مدیر تدارکات / مدیر پروژه) → role-based
routing (admin → `/admin`, manager → office, PM → inventory).
- **Partial goods receipt** in «کالاهای در راه»: submitting any item with a
valid quantity is enough; the rest stays in transit. The ledger shows
«رسیده X از Y» / «در راه Z» and a «رسید جزیی» badge on the quote. The
arrival-confirmation 500 (a `db.begin()` on an already-begun session) was
fixed, and the receipt response now returns the real derived state.
- **Daily control calendar** now renders day-of-month (was rendering the
Jalali year), navigates by real Jalali months, and uses pure Jalali dates
(«امروز ۸ شهریور ۱۴۰۵»), with a blue accent on today and a ring on the
selected day.
- **Uploads** (invoice/proforma) no longer send `Content-Type: application/json`
on multipart requests — the 400/422 «دادهی ارسالشده نامعتبر است» is fixed.
- **Project filter** in the admin inventory views is fixed: empty/undefined
query params are dropped (previously `project_id=undefined` → 400 → empty
dropdowns).
## 9. Managing Casdoor yourself
- **Console:** http://localhost:8080 — log in as **admin / 123**. From there
you can manage Organizations, Users, Applications, Providers, Certificates.