- Created a new `api.md` file detailing the TrackGo HTTP API, including authentication, user management, and employee operations. - Updated `Employee` type to simplify user relation handling by replacing `UserRelation` with a more concise structure. - Enhanced filtering capabilities in employee queries to support an array of positions. - Refactored employee-related services and repositories to accommodate the new position filtering logic. - Added unit and e2e tests to validate the new API documentation and employee management functionalities.
86 lines
4.2 KiB
Markdown
86 lines
4.2 KiB
Markdown
# TrackGo HTTP API
|
||
|
||
JSON keys are camelCase. IDs are UUID v4. List endpoints return `{ data, meta }`.
|
||
|
||
List query includes shared pagination (`page`/`limit` or `offset`/`limit`) plus **`orderBy`** (resource field name) and **`orderType`** (`ASC` or `DESC`, default `ASC`). Unknown `orderBy` values are rejected. Defaults when omitted: users `username`; cycles `cycleNumber`; plans `date`; privilege-keys `sortOrder` then `code`; other lists `code`. Foreign keys on list/detail responses are nested objects (`{ id, code, name }` or `{ id, username }` / `{ id, code }`), not bare UUIDs.
|
||
|
||
List filters: `username`, `privilegeId`, `status`, `search` (username), `orderBy`, `orderType`.
|
||
|
||
## Auth
|
||
|
||
### `POST /auth/register` — public — `201`
|
||
|
||
Creates a **draft** user. Does **not** issue tokens.
|
||
|
||
```json
|
||
{ "username": "alice", "password": "password123" }
|
||
```
|
||
|
||
Response: `{ "id": "uuid", "username": "alice", "status": "draft" }`.
|
||
|
||
Activate with `PATCH /users/:id/status` `{ "status": "active" }` (or SQL bootstrap) then `POST /auth/login`.
|
||
|
||
### `POST /auth/login` — public — `200`
|
||
|
||
Same body as register. Returns `{ accessToken, refreshToken }`.
|
||
|
||
Login, refresh, and JWT validation require `user.status === "active"`. If the user is assigned to an employee, that employee must also be `active`. Failures use `401` with a generic credentials message.
|
||
|
||
### `POST /auth/refresh` — public — `200`
|
||
|
||
### `POST /auth/revoke` — public — `204`
|
||
|
||
### `GET /auth/me` — bearer — `200`
|
||
|
||
## Users
|
||
|
||
Key: `USERS`. **Standard CRUD + import** (list, detail, create, update, status, delete, bulk-delete, bulk-status, import). Extra: `PATCH /users/:id/privilege`.
|
||
|
||
| Method | Path | Action | Status |
|
||
| --- | --- | --- | --- |
|
||
| `GET` | `/users` | view | 200 |
|
||
| `GET` | `/users/:id` | view | 200 |
|
||
| `POST` | `/users` | create | 201 |
|
||
| `PATCH` | `/users/:id` | update | 200 |
|
||
| `PATCH` | `/users/:id/status` | update | 200 |
|
||
| `PATCH` | `/users/:id/privilege` | update | 200 |
|
||
| `DELETE` | `/users/:id` | delete | 204 |
|
||
| `POST` | `/users/bulk-delete` | delete | 200 |
|
||
| `POST` | `/users/bulk-status` | update | 200 |
|
||
| `POST` | `/users/import` | import | 200 |
|
||
|
||
**Create:** `{ username, password, privilegeId?, status?, employeeId? }`. Username 3–32, `^[a-zA-Z0-9_]+$`, stored lowercased. Password 8–72, write-only. Omit status → `draft`. Never send `isSuperadmin` / `passwordHash`.
|
||
|
||
Optional `employeeId` links an existing employee. Unique assigned user → `409`.
|
||
|
||
**Update** `PATCH /users/:id`: `username?`, `password?`, `privilegeId?` (`null` clears), `employeeId?` (`null` unlinks). No `status`. `employeeId` reassigns the linked employee.
|
||
|
||
**Privilege:** `{ privilegeId }` (`null` clears). Assigned privilege must be **active**. Response is the full `UserDto`.
|
||
|
||
List filters: `username`, `privilegeId`, `status`, `search` (username).
|
||
|
||
**DTO:**
|
||
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"username": "alice",
|
||
"isSuperadmin": false,
|
||
"privilege": { "id": "uuid", "code": "ADMIN", "name": "Administrator" },
|
||
"employee": { "id": "uuid", "code": "EMP_01", "name": "Ada Lovelace" },
|
||
"status": "active",
|
||
"createdAt": 1710000000000,
|
||
"updatedAt": 1710000000000,
|
||
"createdBy": { "id": "uuid", "username": "admin" },
|
||
"updatedBy": { "id": "uuid", "username": "admin" }
|
||
}
|
||
```
|
||
|
||
`privilege` / `employee` may be `null`. CSV required: `username`, `password`. Optional: `privilegeId`, `status`. Delete of a user still referenced as `created_by` / `updated_by` → `409`.
|
||
|
||
Bootstrap: first user is draft until `UPDATE users SET status = 'active'`.
|
||
|
||
## Employees
|
||
|
||
Create/update optional `userId` (assign an existing login user) or nested `user` (`id?`, `username?`, `password?`). Nested `user` without `id` creates a login user (`username` + `password` required) or updates the currently linked username. `user.id` / `userId` links an existing user; `username` may be updated, but `password` is rejected (use `PATCH /users/:id`). Nested `user` cannot set `privilegeId`. `user: null` or `userId: null` unlinks. Users link the other way with `employeeId`. DTO nests `user: { id, username } | null`. List filter `userId`. List filter `position` as one or more of `sales` | `driver` | `crew` (`?position=sales&position=driver`). CSV optional `userId`. Unique assigned user → `409`.
|