From 591213aaf7199d2328975f7f6dfb562a3ac332bc Mon Sep 17 00:00:00 2001 From: David Date: Sun, 30 Nov 2025 13:48:04 +0100 Subject: [PATCH] layout access admin and manager --- .../controllers/users.controller.ts | 6 ++++-- apps/frontend/app/dashboard/layout.tsx | 5 ++++- .../app/dashboard/settings/users/page.tsx | 20 ++++++++++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/backend/src/application/controllers/users.controller.ts b/apps/backend/src/application/controllers/users.controller.ts index 469de6e..cea615e 100644 --- a/apps/backend/src/application/controllers/users.controller.ts +++ b/apps/backend/src/application/controllers/users.controller.ts @@ -164,9 +164,10 @@ export class UsersController { * Get user by ID */ @Get(':id') + @Roles('admin', 'manager') @ApiOperation({ summary: 'Get user by ID', - description: 'Retrieve user details. Users can view users in their org, admins can view any.', + description: 'Retrieve user details. Only ADMIN and MANAGER can access this endpoint.', }) @ApiParam({ name: 'id', @@ -324,10 +325,11 @@ export class UsersController { * List users in organization */ @Get() + @Roles('admin', 'manager') @ApiOperation({ summary: 'List users', description: - 'Retrieve a paginated list of users in your organization. Admins can see all users.', + 'Retrieve a paginated list of users in your organization. Only ADMIN and MANAGER can access this endpoint.', }) @ApiQuery({ name: 'page', diff --git a/apps/frontend/app/dashboard/layout.tsx b/apps/frontend/app/dashboard/layout.tsx index 5c35561..e5a20ca 100644 --- a/apps/frontend/app/dashboard/layout.tsx +++ b/apps/frontend/app/dashboard/layout.tsx @@ -24,7 +24,10 @@ export default function DashboardLayout({ children }: { children: React.ReactNod { name: 'Search Rates', href: '/dashboard/search-advanced', icon: '🔎' }, { name: 'My Profile', href: '/dashboard/profile', icon: '👤' }, { name: 'Organization', href: '/dashboard/settings/organization', icon: '🏢' }, - { name: 'Users', href: '/dashboard/settings/users', icon: '👥' }, + // ADMIN and MANAGER only navigation items + ...(user?.role === 'ADMIN' || user?.role === 'MANAGER' ? [ + { name: 'Users', href: '/dashboard/settings/users', icon: '👥' }, + ] : []), // ADMIN only navigation items ...(user?.role === 'ADMIN' ? [ { name: 'CSV Rates', href: '/dashboard/admin/csv-rates', icon: '📄' }, diff --git a/apps/frontend/app/dashboard/settings/users/page.tsx b/apps/frontend/app/dashboard/settings/users/page.tsx index ef5a208..bbcd431 100644 --- a/apps/frontend/app/dashboard/settings/users/page.tsx +++ b/apps/frontend/app/dashboard/settings/users/page.tsx @@ -6,13 +6,15 @@ 'use client'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { listUsers, updateUser, deleteUser } from '@/lib/api'; import { createInvitation } from '@/lib/api/invitations'; import { useAuth } from '@/lib/context/auth-context'; export default function UsersManagementPage() { + const router = useRouter(); const queryClient = useQueryClient(); const { user: currentUser } = useAuth(); const [showInviteModal, setShowInviteModal] = useState(false); @@ -100,6 +102,22 @@ export default function UsersManagementPage() { }, }); + // Restrict access to ADMIN and MANAGER only + useEffect(() => { + if (currentUser && currentUser.role !== 'ADMIN' && currentUser.role !== 'MANAGER') { + router.push('/dashboard'); + } + }, [currentUser, router]); + + // Don't render until we've checked permissions + if (!currentUser || (currentUser.role !== 'ADMIN' && currentUser.role !== 'MANAGER')) { + return ( +
+
+
+ ); + } + const handleInvite = (e: React.FormEvent) => { e.preventDefault(); setError('');