Add CalendarClock icon, planner/settings capabilities
- backend/src/auth.js: extract caps from JWT (planner/settings), hasCap/requireCap
- backend/src/routes/config.js: gate categories + test-connection on requireCap('settings')
- frontend/src/types.ts: add caps[] to User, export can() helper
- frontend/src/App.tsx: gate /settings route on can(user, 'settings')
- frontend/src/components/Layout.tsx: gate nav item on can(user, 'settings')
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
773d323060
commit
135f1f6cf0
6 changed files with 39 additions and 13 deletions
|
|
@ -3,6 +3,7 @@ import { AuthGate } from './components/AuthGate'
|
|||
import { Layout } from './components/Layout'
|
||||
import { Planner } from './pages/Planner'
|
||||
import { CategorySettings } from './pages/CategorySettings'
|
||||
import { can } from './types'
|
||||
import type { User } from './types'
|
||||
|
||||
function AppRoutes({ user }: { user: User }) {
|
||||
|
|
@ -11,7 +12,7 @@ function AppRoutes({ user }: { user: User }) {
|
|||
<Routes>
|
||||
<Route path="/" element={<Navigate to="/planner" replace />} />
|
||||
<Route path="/planner" element={<Planner />} />
|
||||
<Route path="/settings" element={user.is_admin ? <CategorySettings /> : <Navigate to="/planner" replace />} />
|
||||
<Route path="/settings" element={can(user, 'settings') ? <CategorySettings /> : <Navigate to="/planner" replace />} />
|
||||
<Route path="*" element={<Navigate to="/planner" replace />} />
|
||||
</Routes>
|
||||
</Layout>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { NavLink } from 'react-router-dom'
|
||||
import { CalendarClock, Settings, LogOut } from 'lucide-react'
|
||||
import { can } from '../types'
|
||||
import type { User } from '../types'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -30,7 +31,7 @@ export function Layout({ user, children }: Props) {
|
|||
|
||||
<div style={{ flex: 1, padding: '0.5rem 0', overflowY: 'auto' }}>
|
||||
<NavItem to="/planner" icon={CalendarClock} label="Planner" />
|
||||
{user.is_admin && <NavItem to="/settings" icon={Settings} label="Category Settings" />}
|
||||
{can(user, 'settings') && <NavItem to="/settings" icon={Settings} label="Category Settings" />}
|
||||
</div>
|
||||
|
||||
<div style={{ padding: '0.75rem 1rem', borderTop: '1px solid var(--surface-2)' }}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ export interface User {
|
|||
email: string
|
||||
name: string
|
||||
is_admin: boolean
|
||||
caps: string[]
|
||||
}
|
||||
|
||||
export function can(user: User, cap: string): boolean {
|
||||
return user.is_admin || user.caps.includes(cap)
|
||||
}
|
||||
|
||||
export interface DayData {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue