Clean up unused permissions, take user to first page/component they can access

This commit is contained in:
2025-03-23 17:18:31 -04:00
parent 7eae4a0b29
commit ce75496770
4 changed files with 184 additions and 76 deletions

View File

@@ -18,6 +18,7 @@ import { Import } from '@/pages/Import';
import { AiValidationDebug } from "@/pages/AiValidationDebug"
import { AuthProvider } from './contexts/AuthContext';
import { Protected } from './components/auth/Protected';
import { FirstAccessiblePage } from './components/auth/FirstAccessiblePage';
const queryClient = new QueryClient();
@@ -78,6 +79,11 @@ function App() {
<MainLayout />
</RequireAuth>
}>
<Route index element={
<Protected page="dashboard" fallback={<FirstAccessiblePage />}>
<Dashboard />
</Protected>
} />
<Route path="/" element={
<Protected page="dashboard">
<Dashboard />

View File

@@ -0,0 +1,44 @@
import { useContext } from "react";
import { Navigate } from "react-router-dom";
import { AuthContext } from "@/contexts/AuthContext";
// Define available pages in order of priority
const PAGES = [
{ path: "/products", permission: "access:products" },
{ path: "/categories", permission: "access:categories" },
{ path: "/vendors", permission: "access:vendors" },
{ path: "/purchase-orders", permission: "access:purchase_orders" },
{ path: "/analytics", permission: "access:analytics" },
{ path: "/forecasting", permission: "access:forecasting" },
{ path: "/import", permission: "access:import" },
{ path: "/settings", permission: "access:settings" },
{ path: "/ai-validation/debug", permission: "access:ai_validation_debug" }
];
export function FirstAccessiblePage() {
const { user } = useContext(AuthContext);
// If user isn't loaded yet, don't render anything
if (!user) {
return null;
}
// Admin users have access to all pages, so this component
// shouldn't be rendering for them (handled by App.tsx)
if (user.is_admin) {
return null;
}
// Find the first page the user has access to
const firstAccessiblePage = PAGES.find(page => {
return user.permissions?.includes(page.permission);
});
// If we found a page, redirect to it
if (firstAccessiblePage) {
return <Navigate to={firstAccessiblePage.path} replace />;
}
// If user has no access to any page, redirect to login
return <Navigate to="/login" replace />;
}

View File

@@ -8,33 +8,90 @@ import { UserManagement } from "@/components/settings/UserManagement";
import { motion } from 'framer-motion';
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Protected } from "@/components/auth/Protected";
import { useContext, useMemo } from "react";
import { AuthContext } from "@/contexts/AuthContext";
// Define available settings tabs with their permission requirements
const SETTINGS_TABS = [
{ id: "data-management", permission: "settings:data_management", label: "Data Management" },
{ id: "stock-management", permission: "settings:stock_management", label: "Stock Management" },
{ id: "performance-metrics", permission: "settings:performance_metrics", label: "Performance Metrics" },
{ id: "calculation-settings", permission: "settings:calculation_settings", label: "Calculation Settings" },
{ id: "templates", permission: "settings:templates", label: "Template Management" },
{ id: "user-management", permission: "settings:user_management", label: "User Management" }
];
export function Settings() {
const { user } = useContext(AuthContext);
// Determine the first tab the user has access to
const defaultTab = useMemo(() => {
// Admin users have access to all tabs
if (user?.is_admin) {
return SETTINGS_TABS[0].id;
}
// Find the first tab the user has permission to access
const firstAccessibleTab = SETTINGS_TABS.find(tab =>
user?.permissions?.includes(tab.permission)
);
// Return the ID of the first accessible tab, or first tab as fallback
return firstAccessibleTab?.id || SETTINGS_TABS[0].id;
}, [user]);
// Check if user has access to any tab
const hasAccessToAnyTab = useMemo(() => {
if (user?.is_admin) return true;
return SETTINGS_TABS.some(tab => user?.permissions?.includes(tab.permission));
}, [user]);
// If user doesn't have access to any tabs, show a helpful message
if (!hasAccessToAnyTab) {
return (
<motion.div layout className="container mx-auto py-6">
<div className="mb-6">
<h1 className="text-3xl font-bold">Settings</h1>
</div>
<Alert>
<AlertDescription>
You don't have permission to access any settings. Please contact an administrator for assistance.
</AlertDescription>
</Alert>
</motion.div>
);
}
return (
<motion.div layout className="container mx-auto py-6">
<div className="mb-6">
<h1 className="text-3xl font-bold">Settings</h1>
</div>
<Tabs defaultValue="data-management" className="space-y-4">
<Tabs defaultValue={defaultTab} className="space-y-4">
<TabsList>
<TabsTrigger value="data-management">Data Management</TabsTrigger>
<TabsTrigger value="stock-management">Stock Management</TabsTrigger>
<TabsTrigger value="performance-metrics">
Performance Metrics
</TabsTrigger>
<Protected permission="edit:system_settings">
<Protected permission="settings:data_management">
<TabsTrigger value="data-management">Data Management</TabsTrigger>
</Protected>
<Protected permission="settings:stock_management">
<TabsTrigger value="stock-management">Stock Management</TabsTrigger>
</Protected>
<Protected permission="settings:performance_metrics">
<TabsTrigger value="performance-metrics">
Performance Metrics
</TabsTrigger>
</Protected>
<Protected permission="settings:calculation_settings">
<TabsTrigger value="calculation-settings">
Calculation Settings
</TabsTrigger>
</Protected>
<TabsTrigger value="templates">
Template Management
</TabsTrigger>
<Protected
permission="view:users"
fallback={null}
>
<Protected permission="settings:templates">
<TabsTrigger value="templates">
Template Management
</TabsTrigger>
</Protected>
<Protected permission="settings:user_management">
<TabsTrigger value="user-management">
User Management
</TabsTrigger>
@@ -42,20 +99,53 @@ export function Settings() {
</TabsList>
<TabsContent value="data-management">
<DataManagement />
<Protected
permission="settings:data_management"
fallback={
<Alert>
<AlertDescription>
You don't have permission to access Data Management.
</AlertDescription>
</Alert>
}
>
<DataManagement />
</Protected>
</TabsContent>
<TabsContent value="stock-management">
<StockManagement />
<Protected
permission="settings:stock_management"
fallback={
<Alert>
<AlertDescription>
You don't have permission to access Stock Management.
</AlertDescription>
</Alert>
}
>
<StockManagement />
</Protected>
</TabsContent>
<TabsContent value="performance-metrics">
<PerformanceMetrics />
<Protected
permission="settings:performance_metrics"
fallback={
<Alert>
<AlertDescription>
You don't have permission to access Performance Metrics.
</AlertDescription>
</Alert>
}
>
<PerformanceMetrics />
</Protected>
</TabsContent>
<TabsContent value="calculation-settings">
<Protected
permission="edit:system_settings"
permission="settings:calculation_settings"
fallback={
<Alert>
<AlertDescription>
@@ -69,12 +159,23 @@ export function Settings() {
</TabsContent>
<TabsContent value="templates">
<TemplateManagement />
<Protected
permission="settings:templates"
fallback={
<Alert>
<AlertDescription>
You don't have permission to access Template Management.
</AlertDescription>
</Alert>
}
>
<TemplateManagement />
</Protected>
</TabsContent>
<TabsContent value="user-management">
<Protected
permission="view:users"
permission="settings:user_management"
fallback={
<Alert>
<AlertDescription>