61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# Dash API
|
|
|
|
```
|
|
http://localhost:4208/api
|
|
```
|
|
|
|
## CORS & cookies
|
|
|
|
All browser requests that need auth must send cookies:
|
|
|
|
```js
|
|
fetch('http://localhost:4208/api/auth/me', {
|
|
credentials: 'include',
|
|
});
|
|
```
|
|
|
|
Sessions use an HTTP-only `token` cookie (`Secure`, `SameSite=Strict`, 24h). The browser must talk to the API over **HTTPS** for login to work — `Secure` cookies are not sent on plain HTTP.
|
|
|
|
## Auth flow
|
|
|
|
1. Call [`GET /auth/me`](routes/auth/me.md) to get `googleClientId` (included in 200 and 401 responses).
|
|
2. Sign in with Google on the frontend (Google Identity Services / One Tap).
|
|
3. POST the Google ID token to [`POST /auth/login`](routes/auth/login.md).
|
|
4. The API sets the session cookie.
|
|
5. Call protected routes with `credentials: 'include'`. The cookie is refreshed automatically when it has less than 2 hours left.
|
|
|
|
## Routes
|
|
|
|
Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/routes/). Source of truth is the code; regenerate with `npm run docs:api`.
|
|
|
|
| File | Endpoint |
|
|
|------|----------|
|
|
| [`routes/article/create.md`](routes/article/create.md) | `POST /article` |
|
|
| [`routes/article/get.md`](routes/article/get.md) | `GET /article/{sku}` |
|
|
| [`routes/article/update.md`](routes/article/update.md) | `PATCH /article/{sku}` |
|
|
| [`routes/article/add-image.md`](routes/article/add-image.md) | `POST /article/{sku}/image` |
|
|
| [`routes/auth/login.md`](routes/auth/login.md) | `POST /auth/login` |
|
|
| [`routes/auth/logout.md`](routes/auth/logout.md) | `POST /auth/logout` |
|
|
| [`routes/auth/me.md`](routes/auth/me.md) | `GET /auth/me` |
|
|
| [`routes/auth/selected-company.md`](routes/auth/selected-company.md) | `PUT /auth/selected-company` |
|
|
| [`routes/category/create.md`](routes/category/create.md) | `POST /category` |
|
|
| [`routes/category/tree.md`](routes/category/tree.md) | `GET /category/tree` |
|
|
| [`routes/category/delete.md`](routes/category/delete.md) | `DELETE /category/{id}` |
|
|
| [`routes/category/articles.md`](routes/category/articles.md) | `GET /category/{id}/articles` |
|
|
| [`routes/company/list.md`](routes/company/list.md) | `GET /company` |
|
|
| [`routes/company/create.md`](routes/company/create.md) | `POST /company` |
|
|
| [`routes/company/delete.md`](routes/company/delete.md) | `DELETE /company/{id}` |
|
|
| [`routes/company/update.md`](routes/company/update.md) | `PUT /company/{id}` |
|
|
| [`routes/health.md`](routes/health.md) | `GET /health` |
|
|
|
|
Machine-readable spec: [`openapi.json`](openapi.json).
|
|
|
|
## DESIGN
|
|
|
|
- for every route we have a file in /src/api/routes
|
|
- that should loosly bound to services in /src/services
|
|
- for every service we have a CLI tester in /scripts/
|
|
- all DB SQL code shall be in /src/db
|
|
- with mssql staements in /src/db/mssql/
|
|
- API docs: `@openapi` JSDoc on handlers → `npm run docs:api` → `docs/api/`
|