diff --git a/docs/PERMISSIONS.md b/docs/PERMISSIONS.md index 687d4f5..ec22596 100644 --- a/docs/PERMISSIONS.md +++ b/docs/PERMISSIONS.md @@ -7,12 +7,13 @@ This document outlines the permission system implemented in the Inventory Manage Permissions follow this naming convention: - Page access: `access:{page_name}` -- Actions: `{action}:{resource}` +- Settings sections: `settings:{section_name}` +- Admin features: `admin:{feature}` Examples: - `access:products` - Can access the Products page -- `create:products` - Can create new products -- `edit:users` - Can edit user accounts +- `settings:user_management` - Can access User Management settings +- `admin:debug` - Can see debug information ## Permission Components @@ -22,10 +23,10 @@ The core component that conditionally renders content based on permissions. ```tsx No permission

} > - +
``` @@ -81,7 +82,7 @@ Specific component for settings with built-in permission checks. {/* Settings content */} @@ -95,8 +96,8 @@ Core hook for checking any permission. ```tsx const { hasPermission, hasPageAccess, isAdmin } = usePermissions(); -if (hasPermission('delete:products')) { - // Can delete products +if (hasPermission('settings:user_management')) { + // Can access user management } ``` @@ -106,8 +107,8 @@ Specialized hook for page-level permissions. ```tsx const { canView, canCreate, canEdit, canDelete } = usePagePermission('products'); -if (canEdit()) { - // Can edit products +if (canView()) { + // Can view products } ``` @@ -119,18 +120,43 @@ Permissions are stored in the database: Admin users automatically have all permissions. -## Common Permission Codes +## Implemented Permission Codes +### Page Access Permissions | Code | Description | |------|-------------| | `access:dashboard` | Access to Dashboard page | +| `access:overview` | Access to Overview page | | `access:products` | Access to Products page | -| `create:products` | Create new products | -| `edit:products` | Edit existing products | -| `delete:products` | Delete products | -| `view:users` | View user accounts | -| `edit:users` | Edit user accounts | -| `manage:permissions` | Assign permissions to users | +| `access:categories` | Access to Categories page | +| `access:brands` | Access to Brands page | +| `access:vendors` | Access to Vendors page | +| `access:purchase_orders` | Access to Purchase Orders page | +| `access:analytics` | Access to Analytics page | +| `access:forecasting` | Access to Forecasting page | +| `access:import` | Access to Import page | +| `access:settings` | Access to Settings page | +| `access:chat` | Access to Chat Archive page | + +### Settings Permissions +| Code | Description | +|------|-------------| +| `settings:global` | Access to Global Settings section | +| `settings:products` | Access to Product Settings section | +| `settings:vendors` | Access to Vendor Settings section | +| `settings:data_management` | Access to Data Management settings | +| `settings:calculation_settings` | Access to Calculation Settings | +| `settings:library_management` | Access to Image Library Management | +| `settings:performance_metrics` | Access to Performance Metrics | +| `settings:prompt_management` | Access to AI Prompt Management | +| `settings:stock_management` | Access to Stock Management | +| `settings:templates` | Access to Template Management | +| `settings:user_management` | Access to User Management | + +### Admin Permissions +| Code | Description | +|------|-------------| +| `admin:debug` | Can see debug information and features | ## Implementation Examples @@ -148,25 +174,31 @@ In `App.tsx`: ### Component Level Protection ```tsx -const { canEdit } = usePagePermission('products'); +const { hasPermission } = usePermissions(); -function handleEdit() { - if (!canEdit()) { +function handleAction() { + if (!hasPermission('settings:user_management')) { toast.error("You don't have permission"); return; } - // Edit logic + // Action logic } ``` ### UI Element Protection ```tsx - - Delete - -``` \ No newline at end of file + + + +``` + +## Notes + +- **Page Access**: These permissions control which pages a user can navigate to +- **Settings Access**: These permissions control access to different sections within the Settings page +- **Admin Features**: Special permissions for administrative functions +- **CRUD Operations**: The application currently focuses on viewing and managing data rather than creating/editing/deleting individual records +- **User Management**: User CRUD operations are handled through the settings interface rather than dedicated user management pages \ No newline at end of file diff --git a/inventory/src/App.tsx b/inventory/src/App.tsx index 329798e..32d2b06 100644 --- a/inventory/src/App.tsx +++ b/inventory/src/App.tsx @@ -103,14 +103,7 @@ function App() { }> {/* Core inventory app routes - will be lazy loaded */} }> - }> - - - - } /> - + }> }> diff --git a/inventory/src/components/auth/PERMISSIONS.md b/inventory/src/components/auth/PERMISSIONS.md index 254aecf..ec22596 100644 --- a/inventory/src/components/auth/PERMISSIONS.md +++ b/inventory/src/components/auth/PERMISSIONS.md @@ -1,67 +1,162 @@ # Permission System Documentation -This document outlines the simplified permission system implemented in the Inventory Manager application. +This document outlines the permission system implemented in the Inventory Manager application. ## Permission Structure Permissions follow this naming convention: - Page access: `access:{page_name}` -- Actions: `{action}:{resource}` +- Settings sections: `settings:{section_name}` +- Admin features: `admin:{feature}` Examples: - `access:products` - Can access the Products page -- `create:products` - Can create new products -- `edit:users` - Can edit user accounts +- `settings:user_management` - Can access User Management settings +- `admin:debug` - Can see debug information -## Permission Component +## Permission Components -### Protected +### PermissionGuard The core component that conditionally renders content based on permissions. ```tsx -No permission

} > - -
+ + ``` Options: -- `permission`: Single permission code (e.g., "create:products") -- `page`: Page name (checks `access:{page}` permission) -- `resource` + `action`: Resource and action (checks `{action}:{resource}` permission) +- `permission`: Single permission code +- `anyPermissions`: Array of permissions (ANY match grants access) +- `allPermissions`: Array of permissions (ALL required) - `adminOnly`: For admin-only sections +- `page`: Page name (checks `access:{page}` permission) - `fallback`: Content to show if permission check fails -### RequireAuth +### PermissionProtectedRoute -Used for basic authentication checks (is user logged in?). +Protects entire pages based on page access permissions. ```tsx - - - -}> - {/* Protected routes */} - + + + +} /> ``` -## Common Permission Codes +### ProtectedSection +Protects sections within a page based on action permissions. + +```tsx + + + +``` + +### PermissionButton + +Button that automatically handles permissions. + +```tsx + + Add Product + +``` + +### SettingsSection + +Specific component for settings with built-in permission checks. + +```tsx + + {/* Settings content */} + +``` + +## Permission Hooks + +### usePermissions + +Core hook for checking any permission. + +```tsx +const { hasPermission, hasPageAccess, isAdmin } = usePermissions(); +if (hasPermission('settings:user_management')) { + // Can access user management +} +``` + +### usePagePermission + +Specialized hook for page-level permissions. + +```tsx +const { canView, canCreate, canEdit, canDelete } = usePagePermission('products'); +if (canView()) { + // Can view products +} +``` + +## Database Schema + +Permissions are stored in the database: +- `permissions` table: Stores all available permissions +- `user_permissions` junction table: Maps permissions to users + +Admin users automatically have all permissions. + +## Implemented Permission Codes + +### Page Access Permissions | Code | Description | |------|-------------| | `access:dashboard` | Access to Dashboard page | +| `access:overview` | Access to Overview page | | `access:products` | Access to Products page | -| `create:products` | Create new products | -| `edit:products` | Edit existing products | -| `delete:products` | Delete products | -| `view:users` | View user accounts | -| `edit:users` | Edit user accounts | -| `manage:permissions` | Assign permissions to users | +| `access:categories` | Access to Categories page | +| `access:brands` | Access to Brands page | +| `access:vendors` | Access to Vendors page | +| `access:purchase_orders` | Access to Purchase Orders page | +| `access:analytics` | Access to Analytics page | +| `access:forecasting` | Access to Forecasting page | +| `access:import` | Access to Import page | +| `access:settings` | Access to Settings page | +| `access:chat` | Access to Chat Archive page | + +### Settings Permissions +| Code | Description | +|------|-------------| +| `settings:global` | Access to Global Settings section | +| `settings:products` | Access to Product Settings section | +| `settings:vendors` | Access to Vendor Settings section | +| `settings:data_management` | Access to Data Management settings | +| `settings:calculation_settings` | Access to Calculation Settings | +| `settings:library_management` | Access to Image Library Management | +| `settings:performance_metrics` | Access to Performance Metrics | +| `settings:prompt_management` | Access to AI Prompt Management | +| `settings:stock_management` | Access to Stock Management | +| `settings:templates` | Access to Template Management | +| `settings:user_management` | Access to User Management | + +### Admin Permissions +| Code | Description | +|------|-------------| +| `admin:debug` | Can see debug information and features | ## Implementation Examples @@ -70,35 +165,40 @@ Used for basic authentication checks (is user logged in?). In `App.tsx`: ```tsx }> + -
+ } /> ``` ### Component Level Protection ```tsx - -
- {/* Form fields */} - -
-
+const { hasPermission } = usePermissions(); + +function handleAction() { + if (!hasPermission('settings:user_management')) { + toast.error("You don't have permission"); + return; + } + // Action logic +} ``` -### Button Protection +### UI Element Protection ```tsx - + + + +``` -// With Protected component - - - -``` \ No newline at end of file +## Notes + +- **Page Access**: These permissions control which pages a user can navigate to +- **Settings Access**: These permissions control access to different sections within the Settings page +- **Admin Features**: Special permissions for administrative functions +- **CRUD Operations**: The application currently focuses on viewing and managing data rather than creating/editing/deleting individual records +- **User Management**: User CRUD operations are handled through the settings interface rather than dedicated user management pages \ No newline at end of file diff --git a/inventory/src/components/layout/AppSidebar.tsx b/inventory/src/components/layout/AppSidebar.tsx index 038fd21..283ca3c 100644 --- a/inventory/src/components/layout/AppSidebar.tsx +++ b/inventory/src/components/layout/AppSidebar.tsx @@ -29,6 +29,8 @@ import { } from "@/components/ui/sidebar"; import { useLocation, useNavigate, Link } from "react-router-dom"; import { Protected } from "@/components/auth/Protected"; +import { useContext } from "react"; +import { AuthContext } from "@/contexts/AuthContext"; const dashboardItems = [ { @@ -112,6 +114,7 @@ export function AppSidebar() { const location = useLocation(); const navigate = useNavigate(); useSidebar(); + const { user } = useContext(AuthContext); const handleLogout = () => { localStorage.removeItem('token'); @@ -119,6 +122,12 @@ export function AppSidebar() { navigate('/login'); }; + // Check if user has access to any items in a section + const hasAccessToSection = (items: typeof inventoryItems): boolean => { + if (user?.is_admin) return true; + return items.some(item => user?.permissions?.includes(item.permission)); + }; + const renderMenuItems = (items: typeof inventoryItems) => { return items.map((item) => { const isActive = @@ -180,58 +189,58 @@ export function AppSidebar() { {/* Dashboard Section */} - - Dashboard - - - {renderMenuItems(dashboardItems)} - - - - + {hasAccessToSection(dashboardItems) && ( + + Dashboard + + + {renderMenuItems(dashboardItems)} + + + + )} {/* Inventory Section */} - - Inventory - - - {renderMenuItems(inventoryItems)} - - - - + {hasAccessToSection(inventoryItems) && ( + + Inventory + + + {renderMenuItems(inventoryItems)} + + + + )} {/* Product Setup Section */} - - Product Setup - - - {renderMenuItems(productSetupItems)} - - - - + {hasAccessToSection(productSetupItems) && ( + + Product Setup + + + {renderMenuItems(productSetupItems)} + + + + )} {/* Chat Section */} - - Chat - - - {renderMenuItems(chatItems)} - - - - + {hasAccessToSection(chatItems) && ( + + Chat + + + {renderMenuItems(chatItems)} + + + + )} {/* Settings Section */} - - - - - + + + + - - - - + + + + diff --git a/inventory/src/components/settings/UserForm.tsx b/inventory/src/components/settings/UserForm.tsx index 5ce6282..b6f8207 100644 --- a/inventory/src/components/settings/UserForm.tsx +++ b/inventory/src/components/settings/UserForm.tsx @@ -291,8 +291,7 @@ export function UserForm({ user, permissions, onSave, onCancel }: UserFormProps) <> {form.watch("is_admin") ? (
-

Permissions

- + Administrators have access to all permissions by default. Individual permissions cannot be edited for admin users.