feat: add customer authentication and scoped RBAC

This commit is contained in:
lingniu
2026-07-16 13:58:28 +08:00
parent 6d6c9ce534
commit a1195fb97d
28 changed files with 1738 additions and 97 deletions

View File

@@ -8,10 +8,11 @@ const routing = vi.hoisted(() => ({
scheduleIdleRoutePreloads: vi.fn(() => vi.fn()),
shouldPreloadRouteOnIntent: vi.fn(() => true)
}));
const auth = vi.hoisted(() => ({ session: { name: 'test-user', role: 'viewer' as const } as any }));
vi.mock('../routing/routeModules', () => routing);
vi.mock('../auth/AuthGate', () => ({
usePlatformSession: () => ({ session: { name: 'test-user', role: 'viewer' }, logout: vi.fn() })
usePlatformSession: () => ({ session: auth.session, logout: vi.fn() })
}));
import { AppShell } from './AppShell';
@@ -19,6 +20,24 @@ import { AppShell } from './AppShell';
afterEach(() => {
cleanup();
vi.clearAllMocks();
auth.session = { name: 'test-user', role: 'viewer' };
});
test('renders only explicitly assigned customer menus', () => {
auth.session = { name: '客户甲', role: 'customer', userType: 'customer', menuKeys: ['monitor', 'vehicles', 'tracks', 'statistics'] };
render(<MemoryRouter future={ROUTER_FUTURE} initialEntries={['/monitor']}>
<Routes><Route element={<AppShell />}><Route path="*" element={<span></span>} /></Route></Routes>
</MemoryRouter>);
expect(screen.getByRole('link', { name: '全局监控' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: '车辆查询' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: '轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: '里程查询' })).toBeInTheDocument();
expect(screen.queryByRole('link', { name: '历史数据' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: '告警中心' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: '接入管理' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: '账号管理' })).not.toBeInTheDocument();
expect(screen.queryByRole('link', { name: '运维质量' })).not.toBeInTheDocument();
});
test('reschedules likely route preloads when the active module changes', async () => {