diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index e5620ba..7e9be39 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -32,7 +32,7 @@ export const Layout = ({ children, currentPage, breadcrumbs, pageHeader }: Layou
{/* Content Wrapper */} -
+
{/* Mobile Overlay */} {isSidebarOpen && (
{/* Main Content */} -
+
{/* Top Header */}
{/* Main Content Area */} -
+
{/* Page Header */} {pageHeader && ( ; label: string; path: string; + requiredPermission?: { + resource: string; + action?: string; // If not provided, checks for '*' or 'read' + }; } interface SidebarProps { @@ -29,32 +33,32 @@ interface SidebarProps { const superAdminPlatformMenu: MenuItem[] = [ { icon: LayoutDashboard, label: 'Dashboard', path: '/dashboard' }, { icon: Building2, label: 'Tenants', path: '/tenants' }, - { icon: Users, label: 'User Management', path: '/users' }, - { icon: Shield, label: 'Roles', path: '/roles' }, + // { icon: Users, label: 'User Management', path: '/users' }, + // { icon: Shield, label: 'Roles', path: '/roles' }, { icon: Package, label: 'Modules', path: '/modules' }, ]; const superAdminSystemMenu: MenuItem[] = [ { icon: FileText, label: 'Audit Logs', path: '/audit-logs' }, - { icon: Settings, label: 'Settings', path: '/settings' }, + // { icon: Settings, label: 'Settings', path: '/settings' }, ]; // Tenant Admin menu items const tenantAdminPlatformMenu: MenuItem[] = [ { icon: LayoutDashboard, label: 'Dashboard', path: '/tenant' }, - { icon: Shield, label: 'Roles', path: '/tenant/roles' }, - { icon: Users, label: 'Users', path: '/tenant/users' }, - { icon: Package, label: 'Modules', path: '/tenant/modules' }, + { icon: Shield, label: 'Roles', path: '/tenant/roles', requiredPermission: { resource: 'roles' } }, + { icon: Users, label: 'Users', path: '/tenant/users', requiredPermission: { resource: 'users' } }, + { icon: Package, label: 'TenantModules', path: '/tenant/modules', requiredPermission: { resource: 'tenants' } }, ]; const tenantAdminSystemMenu: MenuItem[] = [ - { icon: FileText, label: 'Audit Logs', path: '/tenant/audit-logs' }, - { icon: Settings, label: 'Settings', path: '/tenant/settings' }, + { icon: FileText, label: 'Audit Logs', path: '/tenant/audit-logs', requiredPermission: { resource: 'audit_logs' } }, + { icon: Settings, label: 'Settings', path: '/tenant/settings', requiredPermission: { resource: 'tenants' } }, ]; export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { const location = useLocation(); - const { roles } = useAppSelector((state) => state.auth); + const { roles, permissions } = useAppSelector((state) => state.auth); const { theme, logoUrl } = useAppSelector((state) => state.theme); // Fetch theme for tenant admin @@ -79,12 +83,56 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { useTenantTheme(); } - // Select menu items based on role - const platformMenu = isSuperAdmin ? superAdminPlatformMenu : tenantAdminPlatformMenu; - const systemMenu = isSuperAdmin ? superAdminSystemMenu : tenantAdminSystemMenu; + // Helper function to check if user has permission for a resource + const hasPermission = (resource: string, requiredAction?: string): boolean => { + if (isSuperAdmin) { + return true; // Super admin has all permissions + } + + const allowedActions = requiredAction ? [requiredAction] : ['*', 'read']; + + return permissions.some((perm) => { + // Check if resource matches (exact match or wildcard) + const resourceMatches = perm.resource === resource || perm.resource === '*'; + + // Check if action matches (exact match or wildcard) + const actionMatches = allowedActions.some( + (allowedAction) => perm.action === allowedAction || perm.action === '*' + ); + + return resourceMatches && actionMatches; + }); + }; + + // Filter menu items based on permissions for tenant users + const filterMenuItems = (items: MenuItem[]): MenuItem[] => { + if (isSuperAdmin) { + return items; // Show all items for super admin + } + + return items.filter((item) => { + // If no required permission, always show (e.g., Dashboard, Modules, Settings) + if (!item.requiredPermission) { + return true; + } + + return hasPermission( + item.requiredPermission.resource, + item.requiredPermission.action + ); + }); + }; + + // Select and filter menu items based on role and permissions + const platformMenu = filterMenuItems( + isSuperAdmin ? superAdminPlatformMenu : tenantAdminPlatformMenu + ); + const systemMenu = filterMenuItems( + isSuperAdmin ? superAdminSystemMenu : tenantAdminSystemMenu + ); const MenuSection = ({ title, items }: { title: string; items: MenuItem[] }) => ( -
+
@@ -193,9 +241,9 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { {/* Desktop Sidebar */} -