fix: require root_url on email_auth_key_url; correct frontend guide for user auth endpoints
- Make root_url a required query param on GET /v3/action/user/{id}/email_auth_key_url
(previously Optional[str]=None, which produced a malformed link in the emailed URL)
- Update GUIDE__AE_API_V3_for_Frontend.md: document root_url as required, add magic link
URL format, note valid_email=True side effect, add 404 error, expand 403 conditions
for authenticate, add 400 for verify_password when no password is set
- Add test_e2e_v3_user_action_routes.py and test_e2e_v3_user_auth_routes.py to tests/README.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -271,7 +271,7 @@ async def action_new_auth_key(
|
||||
@router.get('/{user_id}/email_auth_key_url', response_model=Resp_Body_Base)
|
||||
async def action_email_auth_key_url(
|
||||
user_id: str = Path(min_length=11, max_length=22),
|
||||
root_url: Optional[str] = Query(None, min_length=10, max_length=200),
|
||||
root_url: str = Query(..., min_length=10, max_length=200),
|
||||
key_param_name: str = Query('auth_key', min_length=2, max_length=30),
|
||||
account: AccountContext = Depends(get_account_context),
|
||||
):
|
||||
|
||||
@@ -401,7 +401,7 @@ or:
|
||||
|
||||
**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.
|
||||
**Errors:** `400` missing credentials, `403` wrong password / account disabled / account not yet enabled / account expired, `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`.
|
||||
|
||||
@@ -421,7 +421,7 @@ Check a user's current password without changing it.
|
||||
```
|
||||
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.
|
||||
**Response:** `data: true` on match. `400` if the user has no password set, `403` on mismatch, `404` if user not found.
|
||||
|
||||
---
|
||||
|
||||
@@ -474,10 +474,19 @@ Generate a new auth key and email a one-time login link to the user's email addr
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `root_url` | `string` | `null` | Base URL the login link is built from. |
|
||||
| `root_url` | `string` | *(required)* | Base URL the login link is built from. Must be provided — if omitted the link in the email will be malformed (`None?...`). |
|
||||
| `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`).
|
||||
> [!IMPORTANT]
|
||||
> `root_url` is **required in practice**. The FastAPI query param accepts `null` but the email builder does not guard against it — omitting it produces a broken link in the email.
|
||||
|
||||
**Magic link URL format (default `key_param_name`):**
|
||||
```
|
||||
{root_url}?user_id={user_id_random}&auth_key={auth_key}&valid_email=True
|
||||
```
|
||||
The frontend at `root_url` should read these query params and call `POST /v3/action/user/authenticate` with `{ "user_id": "...", "auth_key": "..." }`. Note that `valid_email=True` is **always** injected — authenticating via a magic link automatically marks the user's email as verified.
|
||||
|
||||
**Response:** `data: true` on success (email sent). `404` if user not found. `500` if delivery failed — common causes: account email not configured, user `enable = false`, or `allow_auth_key = false`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ These consolidated scripts are the primary verification tool for the V3 API.
|
||||
| `test_e2e_v3_search_engine.py` | **Primary Search**: Basic operators, Registry fields, Nested search, and Filter bypass. |
|
||||
| `test_e2e_v3_security_audit.py` | **Core Security**: Verifies multi-tenant isolation, cross-account write blocking, and ID Vision compliance. |
|
||||
| `test_e2e_v3_auth_security.py` | **Primary Auth**: Site bootstrap, Passcode-to-JWT, and permission boundaries. |
|
||||
| `test_e2e_v3_user_action_routes.py` | **V3 User Actions**: Sign-in (username+password and auth-key flow), verify password, change password, new auth key, email magic link, and auth guards. |
|
||||
| `test_e2e_v3_user_auth_routes.py` | **Legacy User Routes**: Tests the pre-V3 `/user/*` endpoints (change_password, new_auth_key, verify_password, lookup, email_auth_key_url, authenticate). |
|
||||
| `test_e2e_v3_actions_file_lifecycle.py` | **Primary Actions**: Upload, Download (ID/Hash/Streaming), and physical Deletion. |
|
||||
| `test_e2e_v3_data_store_lookup.py` | **V3 Parity**: Verifies code-based lookups and latency simulation. |
|
||||
| `test_e2e_redis_extensive.py` | **Redis Stress**: Benchmarks bidirectional ID caching across thousands of records. |
|
||||
@@ -76,6 +78,7 @@ Tests exist to be used — run the relevant suite whenever you touch backend cod
|
||||
| Nested router (`api_crud_v3_nested.py`) changes | `test_e2e_v3_demo_parity.py` |
|
||||
| Search / filter changes | `test_e2e_v3_search_engine.py` |
|
||||
| Auth / account context changes | `test_e2e_v3_security_audit.py`, `test_e2e_v3_auth_security.py` |
|
||||
| User action route changes (sign-in, password, magic link) | `test_e2e_v3_user_action_routes.py` |
|
||||
| File upload / download changes | `test_e2e_v3_actions_file_lifecycle.py` |
|
||||
| Novi-Mailman bridge changes | `test_e2e_v3_action_novi_mailman.py`, `test_e2e_v3_action_novi_mailman_lists.py` |
|
||||
| Event exhibit tracking export changes | `test_e2e_v3_action_event_exhibit_tracking_export.py` |
|
||||
|
||||
Reference in New Issue
Block a user