docs: sync from backend 14c231e+378f8f6 — admin user management fixes (v2.8.50–51)
This commit is contained in:
@@ -19,7 +19,7 @@ There is no single `/api/admin` namespace — admin-only endpoints are scattered
|
||||
|
||||
See full descriptions in [[User API]].
|
||||
|
||||
> **Path note:** The frontend and backend both use `/api/users/admin/*` (plural). The singular `/api/user/admin/*` paths for create/delete/status/role/list are **unreachable** — they are not mounted in the backend. Use `/api/users/admin/*` for all user-management calls.
|
||||
> **Path note:** The frontend uses `/api/users/admin/*` (plural — legacy `userRoutes`). The singular `/api/user/admin/*` group (new `userController`) **is also mounted** (`app.ts`). Since backend `14c231e` (v2.8.50) the plural group delegates `toggle-status` and `dependencies` to the new controller so every frontend call routes. Prefer `/api/users/admin/*` for user-management calls.
|
||||
|
||||
| Endpoint | Action |
|
||||
| --- | --- |
|
||||
@@ -39,11 +39,9 @@ See full descriptions in [[User API]].
|
||||
|
||||
> **Verification code length:** The endpoint `POST /api/users/admin/:userId/resend-verification` is served by the legacy userRoutes and generates **8-digit** codes. The new userController generates 6-digit codes and is reached via a different path. Both coexist; the legacy route takes precedence for this path.
|
||||
|
||||
**⚠️ KNOWN BUG — HTTP verb mismatch (status/role updates):** The frontend Redux actions for `updateUserStatus` and `updateUserRole` send `PUT` requests, but the backend registers these handlers under `PATCH`. These calls will receive `404 Method Not Found` responses until the frontend is corrected to use `PATCH`.
|
||||
**✅ FIXED (frontend `d7a2a86` / `6fe1328`, v2.8.50–51):** the old PUT-verb and status-value mismatches are gone — `updateUserStatus` sends `PATCH` with `{ isActive: boolean }` (the field the legacy plural route reads).
|
||||
|
||||
**⚠️ KNOWN BUG — Status value mismatch:** The frontend sends `'inactive'` and `'pending'` as status values when updating user status. The backend only accepts `'active'`, `'suspended'`, or `'deleted'`. Sending `'inactive'` or `'pending'` will be rejected or silently ignored.
|
||||
|
||||
**Hard vs. soft delete note:** The legacy route `DELETE /users/admin/:id` performs a **hard delete** (`findByIdAndDelete`). The current route `DELETE /api/users/admin/:userId` performs a **soft delete** (sets `status='deleted'`). Always use the current `/api/users/admin/:userId` route to preserve data integrity.
|
||||
**Soft delete + email release (backend `378f8f6`, v2.8.51):** `DELETE /api/users/admin/:userId` soft-deletes (sets `status='deleted'`) **and releases the email** (renamed to `deleted_<legacyId>_<email>`) so the address can be reused. Create/register also lazily free emails still held by accounts deleted before this fix. Soft-deleted users are excluded from the admin list and all stats (backend `14c231e`).
|
||||
|
||||
## Listing / marketplace moderation
|
||||
|
||||
|
||||
@@ -179,11 +179,9 @@ The legacy alias `PATCH /api/users/wallet-address` performs the same logic.
|
||||
>
|
||||
> ⚠️ **The frontend consistently calls the PLURAL `/api/users/admin/*`** (see `frontend/src/lib/axios.ts`, all paths under `endpoints.users.admin.*`). So the singular create/delete/status/role/list paths below are *documented*, but in practice the frontend hits the legacy plural group. Both are listed; treat the plural group as the frontend-effective reality.
|
||||
>
|
||||
> ⚠️ **Note on HTTP verbs (KNOWN BUG):** The frontend `updateUserStatus` and `updateUserRole` calls (`frontend/src/actions/user.ts`) use **`PUT`** (`PUT /api/users/admin/:id/status`, `PUT /api/users/admin/:id/role`). The backend registers these as **`PATCH`** only (both the legacy and new routers). The verbs do not match — treat `PATCH` as the authoritative backend verb; the `PUT` calls will not route.
|
||||
> ✅ **Since backend `14c231e` (v2.8.50):** `toggle-status` and `dependencies` are also reachable under the plural prefix (`/api/users/admin/:userId/toggle-status`, `/api/users/admin/:userId/dependencies`) — the legacy router delegates them to the new controller, so the frontend's plural calls now route.
|
||||
>
|
||||
> ⚠️ **Note on status values (KNOWN BUG):** The frontend `updateUserStatus` TypeScript type is `'active' | 'inactive' | 'pending'`. The backend `User.status` enum is `'active' | 'suspended' | 'deleted'`. So:
|
||||
> - `'inactive'` and `'pending'` are **rejected/ignored** by the backend (the new controller only applies `status` when it is one of `active`/`suspended`/`deleted`).
|
||||
> - `'suspended'` — the actually-usable suspend value — is **missing from the frontend type**, so the admin UI cannot send it.
|
||||
> ✅ **Fixed (frontend `d7a2a86`, v2.8.50):** the old PUT-verb and `{status: 'inactive'}` mismatches are gone — `updateUserStatus` now sends `PATCH` with `{ isActive: boolean }`, which is what the legacy plural status route reads.
|
||||
|
||||
### POST /api/user/admin/create
|
||||
|
||||
|
||||
@@ -471,4 +471,61 @@ run end-to-end (require live `ADMIN_TOKEN`).
|
||||
|
||||
---
|
||||
|
||||
### 2026-06-02 — backend@14c231e, frontend@d7a2a86 — make admin user management work end-to-end (v2.8.50)
|
||||
|
||||
**Commits:** `14c231e` (backend), `d7a2a86` (frontend)
|
||||
**Touched (backend):** `src/services/auth/authStore.ts`, `src/services/user/userRoutes.ts`,
|
||||
`__tests__/auth-store-pg-query.test.ts`
|
||||
**Touched (frontend):** `src/actions/user.ts`, `src/types/user.ts`,
|
||||
`src/sections/user/view/user-list-view.tsx`, `src/sections/user/user-table-row.tsx`,
|
||||
`src/sections/user/user-quick-edit-form.tsx`, `src/sections/user/user-new-edit-form.tsx`,
|
||||
`src/sections/request/view/admin/admin-request-list-view.tsx`,
|
||||
`src/sections/overview/app/view/overview-admin-view.tsx`, `Dockerfile`
|
||||
**Why:** Admin could not delete users on dev (`DELETE /api/users/admin/:id` → 404). Root cause:
|
||||
PG rows seeded outside the auth store have NULL `legacy_object_id`; the auth store fabricated a
|
||||
fresh random `_id` on every read, so no admin action keyed on that id could ever resolve.
|
||||
Audit of the admin dashboard surfaced further breakage which is also fixed in this pair of
|
||||
commits:
|
||||
- Backend: legacy-id self-heal on read; `findById` accepts PG uuids; missing
|
||||
`/api/users/admin/:userId/toggle-status` and `/dependencies` routes added (frontend called
|
||||
them under the plural prefix where they did not exist); soft-deleted users excluded from
|
||||
admin list and all stats; list/detail return full profile address fields.
|
||||
- Frontend: `updateUserStatus` sent `{status}` but backend reads `{isActive}` — activating a
|
||||
user actually suspended them; user quick-edit form was a mock (no API call); "حذف کاربر"
|
||||
button in edit form had no handler; bulk deletes used `Promise.all` (partial failures
|
||||
hidden); list query params (`query`/`status`) were ignored by the backend (now
|
||||
`search`/`isActive`); profile payloads now match the backend schema (dotted paths, no
|
||||
whole-profile overwrite); blocked `aria-hidden` console warnings fixed.
|
||||
**Verification:** Backend: 10 tests pass (`auth-store-pg-query`, `user-dependencies-repo`,
|
||||
`repository-factory-modes`), `tsc --noEmit` clean. Frontend: `tsc --noEmit` + eslint clean
|
||||
(jest suite is broken repo-wide — pre-existing ESM transform issue, unrelated). Smoke test
|
||||
against dev pending post-deploy (admin will verify delete in UI).
|
||||
**Linked docs updated:** `03 - API Reference/Admin API.md`, `03 - API Reference/User API.md`
|
||||
(stale KNOWN BUG notes removed; route availability updated).
|
||||
|
||||
---
|
||||
|
||||
### 2026-06-03 — backend@378f8f6, frontend@6fe1328 — unblock user creation & purchase requests for native-PG users (v2.8.51)
|
||||
|
||||
**Commits:** `378f8f6` (backend), `6fe1328` (frontend)
|
||||
**Touched (backend):** `src/services/auth/authStore.ts`, `src/services/auth/authController.ts`,
|
||||
`src/services/user/userRoutes.ts`, `src/services/user/userController.ts`,
|
||||
`src/db/repositories/drizzle/DrizzleMarketplaceRepo.ts`, `DrizzleUserRepo.ts`,
|
||||
`DrizzleTrezorAccountRepo.ts`, `DrizzleDerivedDestinationRepo.ts`,
|
||||
`__tests__/auth-store-pg-query.test.ts`
|
||||
**Touched (frontend):** `src/actions/user.ts`, user section forms/views (error toasts)
|
||||
**Why:** Two follow-up dev blockers after v2.8.50:
|
||||
1. Admin create returned 409 for emails held by soft-deleted accounts (users.email is unique;
|
||||
deleted rows kept the address and are hidden from the list). Fix: delete releases the email
|
||||
(`deleted_<id>_<email>`); create/register lazily free emails held by previously deleted rows.
|
||||
2. Purchase request creation threw "Buyer <id> not found in Postgres id map" — users created
|
||||
natively in PG (auth store / Telegram / Google / admin create) never get id_map rows. Fix:
|
||||
resolveId in 4 Drizzle repos falls back to the entity's own legacy_object_id column and
|
||||
self-heals id_map.
|
||||
**Verification:** 47 backend tests green across 6 suites, tsc clean (both repos), eslint clean.
|
||||
Deployed to dev via CI; admin verifies create-user and create-request flows in UI.
|
||||
**Linked docs updated:** `03 - API Reference/Admin API.md`, `03 - API Reference/User API.md`.
|
||||
|
||||
---
|
||||
|
||||
<!-- Add new entries above this line. Newest at top. -->
|
||||
|
||||
Reference in New Issue
Block a user