feat(admin): view a user's shard footprint at /admin/users/:id #56
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/admin-user-view"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds a View action beside Edit in the admin users table. It opens a dedicated, deep-linkable, read-only page at
/admin/users/:idshowing everything the uo-link shard knows about that user, scoped to their linked game accounts:The Edit flow (modal) is untouched.
Backend
All endpoints sit under the existing
adminRouter.use('/users', adminOnly)gate, so editors/moderators get 403.GET /admin/users/:id— single sanitized user (new; needed so the page survives a refresh)GET /admin/users/:id/shard/{accounts,sales,houses,online}— DB-backed, scoped to the user's linked accountsshardState:listHousesByAccounts/listOnlineByAccounts(+ model shapers; extracted ashapeHousehelper out oflistIdoc)salesForAccountsintoutils/shardSales.jsand pointed the existing playergetSalesat it (no logic duplication)Live character rosters reuse the existing admin-bypass
/admin/shard/roster|vendors|charendpoints (which already read any account), so no new routes were needed for them.Frontend
UserDetail.jsx, reusing the sharedCharacterStats/GameAccounts/VendorSalescomponentsGameAccountsgains areadOnlyprop that drops the "link an account" form and self-voice copy for the admin-viewing-another-user caseapi.admin.getUser+api.admin.userShard(id)scope; route inApp.jsx; dynamic page title inAdminLayoutTesting
server/test/adminUserShard.test.js: 404 on unknown user, account-scoping, empty-accounts, and thesalesForAccountscap/filter.🤖 Generated with Claude Code
Add a "View" action beside Edit in the users table that opens a dedicated, read-only page showing everything the uo-link shard knows about a user, scoped to their linked game accounts: character rosters, currently-online characters, houses (IDOC-first), and recent vendor sales. Backend (admin-only, under the existing /users adminOnly gate): - GET /admin/users/:id — single sanitized user (page is deep-linkable) - GET /admin/users/:id/shard/{accounts,sales,houses,online} - shardState: listHousesByAccounts / listOnlineByAccounts (+ model shapers) - Extract salesForAccounts into utils/shardSales; reuse in player getSales - Live rosters reuse the existing admin-bypass /admin/shard/* endpoints, so no new routes for roster/vendors/char Frontend: - UserDetail page reusing CharacterStats / GameAccounts / VendorSales - GameAccounts gains a readOnly prop (drops link form + self-voice copy) - api.admin.getUser + api.admin.userShard(id) scope; route + layout title Tests: adminUserShard.test.js (404, account scoping, empty accounts, salesForAccounts cap/filter). Full server suite 164 pass; client builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ