RBAC: Enforce read-only viewer role across backend and frontend
- Add global WriteAccessGuard that blocks POST/PUT/PATCH/DELETE for viewer role - Add @AllowViewer() decorator for endpoints viewers need (switch-org, intro-seen, AI recommendations) - Add useIsReadOnly hook to auth store for frontend role checks - Hide write UI (add/edit/delete/import buttons, inline editors) in all 13 data pages for viewers - Disable inline NumberInputs on Budgets and Monthly Actuals pages for viewers - Skip onboarding wizard for viewer role users Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import api from '../../services/api';
|
||||
import { useIsReadOnly } from '../../stores/authStore';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types & constants
|
||||
@@ -215,6 +216,7 @@ export function CapitalProjectsPage() {
|
||||
const [dragOverYear, setDragOverYear] = useState<number | null>(null);
|
||||
const printModeRef = useRef(false);
|
||||
const queryClient = useQueryClient();
|
||||
const isReadOnly = useIsReadOnly();
|
||||
|
||||
// ---- Data fetching ----
|
||||
|
||||
@@ -511,9 +513,9 @@ export function CapitalProjectsPage() {
|
||||
</Table.Td>
|
||||
<Table.Td>{formatPlannedDate(p.planned_date) || '-'}</Table.Td>
|
||||
<Table.Td>
|
||||
<ActionIcon variant="subtle" onClick={() => handleEdit(p)}>
|
||||
{!isReadOnly && <ActionIcon variant="subtle" onClick={() => handleEdit(p)}>
|
||||
<IconEdit size={16} />
|
||||
</ActionIcon>
|
||||
</ActionIcon>}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user