diff --git a/03 - API Reference/Admin API.md b/03 - API Reference/Admin API.md index f0a0823..de84187 100644 --- a/03 - API Reference/Admin API.md +++ b/03 - API Reference/Admin API.md @@ -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__`) 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 diff --git a/03 - API Reference/User API.md b/03 - API Reference/User API.md index 988bc0e..d8157a1 100644 --- a/03 - API Reference/User API.md +++ b/03 - API Reference/User API.md @@ -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 diff --git a/09 - Audits/Activity Log.md b/09 - Audits/Activity Log.md index a543ac6..794397a 100644 --- a/09 - Audits/Activity Log.md +++ b/09 - Audits/Activity Log.md @@ -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__`); create/register lazily free emails held by previously deleted rows. +2. Purchase request creation threw "Buyer 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`. + +--- +