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:
+43
-4
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user