corrected admin view
This commit is contained in:
parent
c59ad6cb70
commit
25c768d013
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ function RequireAuth({ children, role }) {
|
|||
return <Navigate to="/login" state={{ from: location }} replace />;
|
||||
}
|
||||
|
||||
const roleAllowed = !role || user.role === role || (role === 'user' && user.role === 'admin');
|
||||
|
||||
// Role mismatch
|
||||
if (role && user.role !== role) {
|
||||
if (!roleAllowed) {
|
||||
return <Navigate to={user.role === 'admin' ? '/admin' : '/'} replace />;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,14 +98,16 @@ function UserMenu({ adminMode = false }) {
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-52">
|
||||
<DropdownMenuLabel className="truncate">{name}</DropdownMenuLabel>
|
||||
{!adminMode && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={() => navigate('/profile')}>
|
||||
<User className="h-4 w-4" />
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
{user?.role === 'admin' && !adminMode && (
|
||||
<DropdownMenuItem onSelect={() => navigate('/admin')}>
|
||||
<ShieldCheck className="h-4 w-4" />
|
||||
Admin
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem destructive onSelect={handleLogout}>
|
||||
|
|
@ -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 (
|
||||
<header className="sticky top-0 z-40 border-b border-border/70 bg-background/85 shadow-sm shadow-foreground/5 backdrop-blur-xl supports-[backdrop-filter]:bg-background/70">
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue