diff --git a/src/frontend/apps/desk/src/core/__tests__/MainLayout.test.tsx b/src/frontend/apps/desk/src/core/__tests__/MainLayout.test.tsx index 9ff038c7e..02aec078e 100644 --- a/src/frontend/apps/desk/src/core/__tests__/MainLayout.test.tsx +++ b/src/frontend/apps/desk/src/core/__tests__/MainLayout.test.tsx @@ -4,6 +4,7 @@ import { render, screen } from '@testing-library/react'; import { AppWrapper } from '@/tests/utils'; import { MainLayout } from '../MainLayout'; +import { useAuthStore } from '../auth'; import { useConfigStore } from '../config'; jest.mock('next/navigation', () => ({ @@ -19,6 +20,19 @@ describe('MainLayout', () => { useConfigStore.setState({ config: { RELEASE: '1.0.0', FEATURES: { TEAMS: true }, LANGUAGES: [] }, }); + useAuthStore.setState({ + authenticated: true, + userData: { + id: '1', + email: 'test@example.com', + name: 'Test User', + abilities: { + contacts: { canView: true }, + teams: { canView: true }, + mailboxes: { canView: true }, + }, + }, + }); render(, { wrapper: AppWrapper }); @@ -35,10 +49,57 @@ describe('MainLayout', () => { ).toBeInTheDocument(); }); + it('checks menu rendering with no abilities', () => { + useConfigStore.setState({ + config: { RELEASE: '1.0.0', FEATURES: { TEAMS: true }, LANGUAGES: [] }, + }); + useAuthStore.setState({ + authenticated: true, + userData: { + id: '1', + email: 'test@example.com', + name: 'Test User', + abilities: { + contacts: { canView: false }, + teams: { canView: false }, + mailboxes: { canView: false }, + }, + }, + }); + + render(, { wrapper: AppWrapper }); + + expect( + screen.queryByRole('button', { + // Changé de getByRole à queryByRole + name: /Teams button/i, + }), + ).not.toBeInTheDocument(); // + + expect( + screen.queryByRole('button', { + name: /Mail Domains button/i, + }), + ).not.toBeInTheDocument(); + }); + it('checks menu rendering without team feature', () => { useConfigStore.setState({ config: { RELEASE: '1.0.0', FEATURES: { TEAMS: false }, LANGUAGES: [] }, }); + useAuthStore.setState({ + authenticated: true, + userData: { + id: '1', + email: 'test@example.com', + name: 'Test User', + abilities: { + contacts: { canView: true }, + teams: { canView: true }, + mailboxes: { canView: true }, + }, + }, + }); render(, { wrapper: AppWrapper }); diff --git a/src/frontend/apps/desk/src/core/auth/api/types.ts b/src/frontend/apps/desk/src/core/auth/api/types.ts index b3836215c..706706f3c 100644 --- a/src/frontend/apps/desk/src/core/auth/api/types.ts +++ b/src/frontend/apps/desk/src/core/auth/api/types.ts @@ -9,4 +9,20 @@ export interface User { id: string; email: string; name?: string; + abilities?: { + mailboxes: UserAbilities; + contacts: UserAbilities; + teams: UserAbilities; + }; } + +export type UserAbilities = { + canView?: boolean; + canCreate?: boolean; +}; + +export const getDefaultAbilities = (): User['abilities'] => ({ + mailboxes: { canView: true, canCreate: true }, + contacts: { canView: true, canCreate: true }, + teams: { canView: true, canCreate: true }, +}); diff --git a/src/frontend/apps/desk/src/features/mail-domains/access-management/api/__tests__/useMailDomainAccesses.test.tsx b/src/frontend/apps/desk/src/features/mail-domains/access-management/api/__tests__/useMailDomainAccesses.test.tsx index 909297c61..e49afa9c3 100644 --- a/src/frontend/apps/desk/src/features/mail-domains/access-management/api/__tests__/useMailDomainAccesses.test.tsx +++ b/src/frontend/apps/desk/src/features/mail-domains/access-management/api/__tests__/useMailDomainAccesses.test.tsx @@ -35,7 +35,11 @@ describe('getMailDomainAccesses', () => { { id: '2', role: Role.VIEWER, - user: { id: '12', name: 'username2', email: 'user2@test.com' }, + user: { + id: '12', + name: 'username2', + email: 'user2@test.com', + }, can_set_role_to: [Role.VIEWER], }, ], diff --git a/src/frontend/apps/desk/src/features/menu/Menu.tsx b/src/frontend/apps/desk/src/features/menu/Menu.tsx index d8a622e54..7bac98692 100644 --- a/src/frontend/apps/desk/src/features/menu/Menu.tsx +++ b/src/frontend/apps/desk/src/features/menu/Menu.tsx @@ -1,8 +1,8 @@ -import React from 'react'; import { useTranslation } from 'react-i18next'; import IconGroup from '@/assets/icons/icon-group.svg'; import { Box } from '@/components/'; +import { useAuthStore } from '@/core/auth'; import useCunninghamTheme from '@/cunningham/useCunninghamTheme'; import MenuItem from './MenuItems'; @@ -10,6 +10,9 @@ import IconMailDomains from './assets/icon-mails.svg'; export const Menu = () => { const { colorsTokens } = useCunninghamTheme(); + const { userData } = useAuthStore(); + + console.log(userData); const { t } = useTranslation(); return ( @@ -22,17 +25,21 @@ export const Menu = () => { $margin="none" > - - + {userData?.abilities?.teams.canView && ( + + )} + {userData?.abilities?.mailboxes.canView && ( + + )} ); diff --git a/src/frontend/apps/desk/src/pages/mail-domains/index.tsx b/src/frontend/apps/desk/src/pages/mail-domains/index.tsx index 2b5c4dc04..7878e5554 100644 --- a/src/frontend/apps/desk/src/pages/mail-domains/index.tsx +++ b/src/frontend/apps/desk/src/pages/mail-domains/index.tsx @@ -4,7 +4,8 @@ import type { ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { Box } from '@/components'; +import { Box, Text } from '@/components'; +import { useAuthStore } from '@/core/auth'; import { MailDomainsLayout } from '@/features/mail-domains/domains'; import { NextPageWithLayout } from '@/types/next'; @@ -14,14 +15,18 @@ const StyledButton = styled(Button)` const Page: NextPageWithLayout = () => { const { t } = useTranslation(); - + const { userData } = useAuthStore(); + const canCreate = userData?.abilities?.mailboxes.canCreate; const router = useRouter(); return ( - void router.push('/mail-domains/add')}> - {t('Add a mail domain')} - + {canCreate && ( + void router.push('/mail-domains/add')}> + {t('Add a mail domain')} + + )} + {!canCreate && {t('Click on mailbox to view details')}} ); }; diff --git a/src/frontend/apps/desk/src/pages/teams/index.tsx b/src/frontend/apps/desk/src/pages/teams/index.tsx index 13dfde384..b5d447412 100644 --- a/src/frontend/apps/desk/src/pages/teams/index.tsx +++ b/src/frontend/apps/desk/src/pages/teams/index.tsx @@ -1,10 +1,11 @@ import { Button } from '@openfun/cunningham-react'; import { useRouter as useNavigate } from 'next/navigation'; -import type { ReactElement } from 'react'; +import { ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { Box } from '@/components'; +import { Box, Text } from '@/components'; +import { useAuthStore } from '@/core/auth'; import { TeamLayout } from '@/features/teams/team-management'; import { NextPageWithLayout } from '@/types/next'; @@ -15,12 +16,17 @@ const StyledButton = styled(Button)` const Page: NextPageWithLayout = () => { const { t } = useTranslation(); const router = useNavigate(); + const { userData } = useAuthStore(); + const canCreate = userData?.abilities?.teams.canCreate ?? false; return ( - void router.push('/teams/create')}> - {t('Create a new team')} - + {canCreate && ( + void router.push('/teams/create')}> + {t('Create a new team')} + + )} + {!canCreate && {t('Click on team to view details')}} ); }; diff --git a/src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts b/src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts index 5c753fc0a..3eb082d2a 100644 --- a/src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-desk/menu.spec.ts @@ -13,7 +13,7 @@ test.describe('Menu', () => { name: 'Teams', isDefault: true, expectedUrl: '/teams/', - expectedText: 'Create a new team', + expectedText: 'Teams', }, { name: 'Mail Domains', @@ -62,6 +62,92 @@ test.describe('Menu', () => { }); } + test(`it checks that the menu is not displaying when no abilities`, async ({ + page, + }) => { + await page.route('**/api/v1.0/users/me/', async (route) => { + await route.fulfill({ + json: { + "id": "52de4dcf-5ca0-4b7f-9841-3a18e8cb6a95", + "email": "user@chromium.e2e", + "language": "en-us", + "name": "E2E Chromium", + "timezone": "UTC", + "is_device": false, + "is_staff": false, + "abilities": { + "contacts": { + "canView": true, + "canCreate": true + }, + "teams": { + "canView": true, + "canCreate": false + }, + "mailboxes": { + "canView": true, + "canCreate": false + } + } + } + }); + }); + + const menu = page.locator('menu').first(); + + let buttonMenu = menu.getByLabel(`Teams button`); + await buttonMenu.click(); + await expect(page.getByText('Click on team to view details').first()).toBeVisible(); + + buttonMenu = menu.getByLabel(`Mail Domains`); + await buttonMenu.click(); + await expect(page.getByText('Click on mailbox to view details').first()).toBeVisible(); + + }); + + test(`it checks that the menu is not displaying when all abilities`, async ({ + page, + }) => { + await page.route('**/api/v1.0/users/me/', async (route) => { + await route.fulfill({ + json: { + "id": "52de4dcf-5ca0-4b7f-9841-3a18e8cb6a95", + "email": "user@chromium.e2e", + "language": "en-us", + "name": "E2E ChromiumMM", + "timezone": "UTC", + "is_device": false, + "is_staff": false, + "abilities": { + "contacts": { + "canView": true, + "canCreate": true + }, + "teams": { + "canView": true, + "canCreate": true + }, + "mailboxes": { + "canView": true, + "canCreate": true + } + } + } + }); + }); + + const menu = page.locator('menu').first(); + + let buttonMenu = menu.getByLabel(`Teams button`); + await buttonMenu.click(); + await expect(page.getByText('Create a new team').first()).toBeVisible(); + + buttonMenu = menu.getByLabel(`Mail Domains`); + await buttonMenu.click(); + await expect(page.getByText('Add a mail domain').first()).toBeVisible(); + + }); + test(`it checks that the sub menu is still highlighted`, async ({ page, browserName,