From 25c768d0139adb9071f30372a9f995c95a2b74bd Mon Sep 17 00:00:00 2001 From: kaspa Date: Sun, 3 May 2026 20:40:48 -0500 Subject: [PATCH] corrected admin view --- HISTORY.md | 1 + client/App.jsx | 4 +++- client/components/layout/Sidebar.jsx | 23 ++++++++++++++--------- middleware/requireAuth.js | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 43b2a77..8853fff 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -19,6 +19,7 @@ - **authentik client auth method**: Admin OIDC settings now include an advanced `client_secret_basic` / `client_secret_post` token endpoint authentication method selector. The default remains `client_secret_basic`, matching the previous `openid-client` behavior. - **Admin user role management**: Admin Users table now lets an admin promote another user to `admin` or demote an admin back to `user`, with protections against changing your own role or removing the last admin account. - **Single-user mode recovery**: User Settings now shows a Login Mode section while single-user mode is active, allowing the default user to restore multi-user login without needing access to Admin routes. +- **Admin navigation parity**: Admin users now keep the normal app navigation and get an Admin link after Status; `/admin` uses the same top nav so admins can return to Tracker/Bills/Categories/Profile/Settings/Status without typing a URL. Backend `/admin` protection remains unchanged. - **Admin-controlled auth method toggles** in Admin panel (Authentication Methods card): - `local_login_enabled` — enable/disable local username/password login (default: enabled) - `oidc_login_enabled` — enable/disable OIDC/authentik login (default: disabled) diff --git a/client/App.jsx b/client/App.jsx index 3864ccf..3a20eb4 100644 --- a/client/App.jsx +++ b/client/App.jsx @@ -35,8 +35,10 @@ function RequireAuth({ children, role }) { return ; } + const roleAllowed = !role || user.role === role || (role === 'user' && user.role === 'admin'); + // Role mismatch - if (role && user.role !== role) { + if (!roleAllowed) { return ; } diff --git a/client/components/layout/Sidebar.jsx b/client/components/layout/Sidebar.jsx index c047dff..e1e2385 100644 --- a/client/components/layout/Sidebar.jsx +++ b/client/components/layout/Sidebar.jsx @@ -98,14 +98,16 @@ function UserMenu({ adminMode = false }) { {name} - {!adminMode && ( - <> - - navigate('/profile')}> - - Profile - - + + navigate('/profile')}> + + Profile + + {user?.role === 'admin' && !adminMode && ( + navigate('/admin')}> + + Admin + )} @@ -119,7 +121,10 @@ function UserMenu({ adminMode = false }) { export default function Sidebar({ adminMode = false }) { const [mobileOpen, setMobileOpen] = useState(false); - const items = adminMode ? adminNavItems : userNavItems; + const { user } = useAuth(); + const items = user?.role === 'admin' + ? [...userNavItems, ...adminNavItems] + : userNavItems; return (
diff --git a/middleware/requireAuth.js b/middleware/requireAuth.js index 9bce5dd..6e571d3 100644 --- a/middleware/requireAuth.js +++ b/middleware/requireAuth.js @@ -27,7 +27,7 @@ function requireAuth(req, res, next) { } function requireUser(req, res, next) { - if (req.user?.role !== 'user') { + if (!['user', 'admin'].includes(req.user?.role)) { return res.status(403).json({ error: 'Access denied: user account required' }); } next();