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();