diff --git a/documentation/GUIDE__AE_API_V3_for_Frontend.md b/documentation/GUIDE__AE_API_V3_for_Frontend.md index 8bcec8c4..ae480be7 100644 --- a/documentation/GUIDE__AE_API_V3_for_Frontend.md +++ b/documentation/GUIDE__AE_API_V3_for_Frontend.md @@ -73,7 +73,7 @@ Modify data in the system. > [!IMPORTANT] > **V3 responses always use random string IDs — never database integers.** -After a successful `POST` create or any `GET`, the response contains: +All V3 responses — `POST` create, `GET` single, `GET` list, search, and `PATCH` update — contain: | Field | Type | Use | | :--- | :--- | :--- | @@ -262,7 +262,150 @@ Frontend guidance: --- -## 7. Event Exhibit Tracking Export (Leads Export) +## 7. User Actions (`/v3/action/user/`) + +Stateful user account operations that are not standard CRUD. All require `x-aether-api-key`. + +> [!IMPORTANT] +> **Migration from legacy `/user/*` routes:** The table below maps each legacy endpoint to its V3 replacement. Run both in parallel during transition; remove legacy routes once traffic logs confirm they are quiet. +> +> | Legacy | V3 Replacement | +> |---|---| +> | `GET /user/authenticate` | `POST /v3/action/user/authenticate` | +> | `POST /user/verify_password` | `POST /v3/action/user/verify_password` | +> | `PATCH /user/{id}/change_password` | `POST /v3/action/user/{id}/change_password` | +> | `GET /user/{id}/new_auth_key` | `GET /v3/action/user/{id}/new_auth_key` | +> | `GET /user/{id}/email_auth_key_url` | `GET /v3/action/user/{id}/email_auth_key_url` | +> | `GET /user/lookup` | `POST /v3/crud/user/search` | +> | `GET /user/lookup_email` | `POST /v3/crud/user/search` | +> | `GET /user/lookup_username` | `POST /v3/crud/user/search` | + +### A. Authenticate + +Authenticate a user by **username + password** or **user_id + auth_key**. + +- **Method:** `POST` +- **Path:** `/v3/action/user/authenticate` +- **Auth:** `x-aether-api-key` + `x-account-id` (scopes username lookups to the correct account) +- **Security improvement:** Credentials are in the **POST body**, not query params — safe from URL logging. + +**Request body:** +```json +{ "username": "scott", "password": "MyPassword123!" } +``` +or: +```json +{ "user_id": "", "auth_key": "", "valid_email": true } +``` + +- `valid_email` (optional `bool`): if `true`, marks `email_verified = true` on success. +- `inc_user_role_list` (optional query param, default `false`): include role list in the returned user object. + +**Response on success:** Full user object (same shape as `GET /v3/crud/user/{id}`). + +**Errors:** `400` missing credentials, `403` wrong password or account disabled, `404` user not found. + +> **Auth key flow:** Auth keys are one-time-use — the key is cleared from the DB immediately on successful authentication. Request a new one via `GET /v3/action/user/{id}/new_auth_key`. + +--- + +### B. Verify Password + +Check a user's current password without changing it. + +- **Method:** `POST` +- **Path:** `/v3/action/user/verify_password` +- **Auth:** `x-aether-api-key` + `x-account-id` + +**Request body:** +```json +{ "user_id": "", "current_password": "MyPassword123!" } +``` +or use `"username"` instead of `"user_id"` to look up by username within the account. + +**Response:** `data: true` on match. `403` on mismatch, `404` if user not found. + +--- + +### C. Change Password + +Change a user's password. Optionally verify the current password first. + +- **Method:** `POST` +- **Path:** `/v3/action/user/{user_id}/change_password` +- **Auth:** `x-aether-api-key` + `x-account-id` + +**Request body:** +```json +{ "new_password": "NewPassword456!", "current_password": "MyPassword123!" } +``` + +- `new_password` is required (minimum 10 characters). +- `current_password` is optional. If provided, it is verified before the change is applied. Omit it for admin-driven resets. + +**Response:** `data: true` on success. `403` if `current_password` provided but wrong. + +--- + +### D. Generate New Auth Key + +Generate a fresh one-time-use auth key for the user and write it to the DB. + +- **Method:** `GET` +- **Path:** `/v3/action/user/{user_id}/new_auth_key` +- **Auth:** `x-aether-api-key` + `x-account-id` + +**Response:** +```json +{ "data": { "auth_key": "" } } +``` + +The returned key can then be passed to `/authenticate` (as `auth_key`) or embedded in a login URL. The user record must have `allow_auth_key = true` for key-based authentication to work. + +--- + +### E. Email Auth Key URL + +Generate a new auth key and email a one-time login link to the user's email address. + +- **Method:** `GET` +- **Path:** `/v3/action/user/{user_id}/email_auth_key_url` +- **Auth:** `x-aether-api-key` + `x-account-id` + +**Query Parameters:** + +| Parameter | Type | Default | Description | +|---|---|---|---| +| `root_url` | `string` | `null` | Base URL the login link is built from. | +| `key_param_name` | `string` | `auth_key` | Query param name used for the auth key in the generated link. | + +**Response:** `data: true` on success (email sent). `500` if delivery failed (check account email config and that the user account is enabled with `allow_auth_key = true`). + +--- + +### F. User Lookups via V3 CRUD Search + +The three legacy lookup routes (`lookup`, `lookup_email`, `lookup_username`) are replaced by standard V3 CRUD search: + +```typescript +// Look up by user_id (Vision ID) +POST /v3/crud/user/search +{ "and": [{ "field": "id_random", "op": "eq", "value": "" }] } + +// Look up by email +POST /v3/crud/user/search +{ "and": [{ "field": "email", "op": "eq", "value": "user@example.com" }] } + +// Look up by username +POST /v3/crud/user/search +{ "and": [{ "field": "username", "op": "eq", "value": "scott" }] } +``` + +Results are automatically scoped to the `x-account-id` provided in the request. + +--- + +## 9. Event Exhibit Tracking Export (Leads Export) Allows an exhibitor to download all lead-capture records for their exhibit as a CSV or XLSX file. @@ -330,7 +473,7 @@ const url = URL.createObjectURL(blob); --- -## 8. Troubleshooting 403 Forbidden +## 10. Troubleshooting 403 Forbidden If you receive a 403 on a valid ID: 1. Verify `x-aether-api-key` is correct.