Skip to content

Commit

Permalink
Simplification de l'authentification
Browse files Browse the repository at this point in the history
  • Loading branch information
NerOcrO committed May 13, 2024
1 parent 069d283 commit e21365d
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 164 deletions.
6 changes: 5 additions & 1 deletion src/app/(both)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ClientSafeProvider, getProviders } from 'next-auth/react'
import { PropsWithChildren, ReactElement } from 'react'

import { getProfilAtih } from '../../authentification'
Expand All @@ -9,7 +10,10 @@ export default async function Layout({ children }: PropsWithChildren): Promise<R
return (
<>
<AccesRapide />
<EnTete profil={await getProfilAtih()} />
<EnTete
profil={await getProfilAtih()}
providers={await getProviders() as Record<'pasrel', ClientSafeProvider>}
/>
<main
className="main pt-4"
id="main"
Expand Down
7 changes: 7 additions & 0 deletions src/app/(both)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Metadata } from 'next'
import { ClientSafeProvider, getProviders } from 'next-auth/react'
import { ReactElement } from 'react'

import { getProfilAtih } from '../../authentification'
Expand All @@ -11,10 +12,16 @@ export const metadata: Metadata = {
export default async function PageAccueil(): Promise<ReactElement> {
const profil = await getProfilAtih()

let providers = undefined
if (!profil.isConnected) {
providers = await getProviders() as Record<'pasrel', ClientSafeProvider>
}

return (
<Accueil
isAdmin={profil.isAdmin}
isConnected={profil.isConnected}
providers={providers}
/>
)
}
23 changes: 0 additions & 23 deletions src/app/(deconnecte)/connexion/page.tsx

This file was deleted.

25 changes: 0 additions & 25 deletions src/app/(deconnecte)/layout.tsx

This file was deleted.

10 changes: 1 addition & 9 deletions src/authentification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,10 @@ export async function getProfilAtih(): Promise<ProfilAtih> {
}
}

export async function checkIfConnected(): Promise<void> {
const session = await getServerSession(authOptions)

if (session) {
redirect('/')
}
}

export async function checkIfNotConnected(): Promise<void> {
const session = await getServerSession(authOptions)

if (!session) {
redirect('/connexion')
redirect('/')
}
}
28 changes: 19 additions & 9 deletions src/components/Accueil/Accueil.test.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
import { screen } from '@testing-library/react'
import { fireEvent, screen } from '@testing-library/react'
import * as nextAuth from 'next-auth/react'

import PageAccueil from '../../app/(both)/page'
import * as authentification from '../../authentification'
import { renderComponent } from '../../testShared'
import { renderComponent, spyPasrel } from '../../testShared'

describe('page d’accueil', () => {
describe('en étant déconnecté', () => {
it('quand j’affiche la page alors je peux me connecter', async () => {
it('quand j’affiche la page alors je peux m’authentifier', async () => {
// GIVEN
vi.spyOn(authentification, 'getProfilAtih').mockResolvedValueOnce({
isAdmin: false,
isConnected: false,
nomEtablissement: '',
})
// @ts-expect-error
vi.spyOn(nextAuth, 'getProviders').mockResolvedValueOnce(spyPasrel)
vi.spyOn(nextAuth, 'signIn').mockImplementationOnce(vi.fn())

// WHEN
renderComponent(await PageAccueil())
const boutonSeConnecter = screen.getByRole('button', { name: 'Se connecter' })

// WHEN
fireEvent.click(boutonSeConnecter)

// THEN
const lienSeConnecter = screen.getByRole('link', { name: 'Se connecter' })
expect(lienSeConnecter).toHaveAttribute('href', 'connexion')
expect(nextAuth.signIn).toHaveBeenCalledWith('pasrel')
})
})

describe('en tant qu’utilisateur et connecté', () => {
describe('en tant qu’utilisateur et étant connecté', () => {
it('quand j’affiche la page alors je peux créer un inventaire', async () => {
vi.spyOn(authentification, 'getProfilAtih').mockResolvedValueOnce({
isAdmin: false,
Expand All @@ -35,12 +41,14 @@ describe('page d’accueil', () => {
renderComponent(await PageAccueil())

// THEN
const lienAccederAuxInventaires = screen.queryByRole('link', { name: 'Accéder aux inventaires' })
expect(lienAccederAuxInventaires).not.toBeInTheDocument()
const lienCreerUnInventaire = screen.getByRole('link', { name: 'Créer un inventaire' })
expect(lienCreerUnInventaire).toHaveAttribute('href', 'creer-un-inventaire')
})
})

describe('en tant qu’admin', () => {
describe('en tant qu’admin et étant connecté', () => {
it('quand j’affiche la page alors je peux accéder aux inventaires', async () => {
vi.spyOn(authentification, 'getProfilAtih').mockResolvedValueOnce({
isAdmin: true,
Expand All @@ -52,8 +60,10 @@ describe('page d’accueil', () => {
renderComponent(await PageAccueil())

// THEN
const lienAccederAuxInventaires = screen.queryByRole('link', { name: 'Accéder aux inventaires' })
const lienAccederAuxInventaires = screen.getByRole('link', { name: 'Accéder aux inventaires' })
expect(lienAccederAuxInventaires).toHaveAttribute('href', 'inventaires')
const lienCreerUnInventaire = screen.queryByRole('link', { name: 'Créer un inventaire' })
expect(lienCreerUnInventaire).not.toBeInTheDocument()
})
})
})
22 changes: 11 additions & 11 deletions src/components/Accueil/Accueil.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import Link from 'next/link'
import { ClientSafeProvider } from 'next-auth/react'
import { ReactElement } from 'react'

import Connexion from '../Connexion/Connexion'

type AccueilProps = Readonly<{
isAdmin: boolean
isConnected: boolean
providers?: Readonly<Record<'pasrel', ClientSafeProvider>>
}>

export default function Accueil({ isAdmin, isConnected }: AccueilProps): ReactElement {
export default function Accueil({ isAdmin, isConnected, providers }: AccueilProps): ReactElement {
return (
<div className="o-banner o-banner--has-breadcrumb">
<div className="container">
Expand Down Expand Up @@ -57,16 +61,12 @@ export default function Accueil({ isAdmin, isConnected }: AccueilProps): ReactEl
) : null
}
{
!isConnected && (
<div>
<Link
className="btn btn--plain btn--primary"
href="connexion"
>
Se connecter
</Link>
</div>
)
!isConnected && providers ? (
<Connexion
providers={providers}
styleDuBouton="bouton"
/>
) : null
}
</div>
<div className="col-md-5">
Expand Down
51 changes: 0 additions & 51 deletions src/components/Connexion/Connexion.test.tsx

This file was deleted.

32 changes: 13 additions & 19 deletions src/components/Connexion/Connexion.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
'use client'

import { BuiltInProviderType } from 'next-auth/providers'
import { ClientSafeProvider, LiteralUnion, signIn } from 'next-auth/react'
import { ClientSafeProvider, signIn } from 'next-auth/react'
import { ReactElement } from 'react'

type ConnexionProps = Readonly<{
providers: Readonly<Record<LiteralUnion<BuiltInProviderType>, ClientSafeProvider>>
providers: Readonly<Record<'pasrel', ClientSafeProvider>>
styleDuBouton: 'bouton' | 'lien'
}>

export default function Connexion({ providers }: ConnexionProps): ReactElement {
export default function Connexion({ providers, styleDuBouton }: ConnexionProps): ReactElement {
const classe = styleDuBouton === 'bouton' ? 'btn btn--plain btn--primary' : 'nav-link'

return (
<div className="text-center">
{
Object.values(providers).map((provider): ReactElement => (
<div key={provider.name}>
<button
className="btn btn--plain btn--primary"
onClick={async () => signIn(provider.id)}
type="button"
>
Se connecter avec Plage
</button>
</div>
))
}
</div>
<button
className={classe}
onClick={async () => signIn(providers.pasrel.id)}
type="button"
>
Se connecter
</button>
)
}
37 changes: 28 additions & 9 deletions src/components/sharedComponents/EnTete.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as nextAuth from 'next-auth/react'

import EnTete from './EnTete'
import { ProfilAtih } from '../../authentification'
import { renderComponent } from '../../testShared'
import { renderComponent, spyPasrel } from '../../testShared'

describe('en-tête', () => {
describe('en étant connecté', () => {
Expand Down Expand Up @@ -64,21 +64,35 @@ describe('en-tête', () => {
})

describe('en étant déconnecté', () => {
it('quand j’affiche une page quelconque alors j’ai accès au lien de connexion', () => {
it('quand j’affiche une page quelconque alors je peux m’authentifier', () => {
// GIVEN
vi.spyOn(nextAuth, 'signIn').mockImplementationOnce(vi.fn())

renderComponent(
<EnTete
profil={jeSuiDeconnecte()}
providers={spyPasrel}
/>
)
const menuItems = screen.getAllByRole('listitem')
const boutonSeConnecter = within(menuItems[2]).getByRole('button', { name: 'Se connecter' })

// WHEN
renderComponent(<EnTete profil={jeSuiDeconnecte()} />)
fireEvent.click(boutonSeConnecter)

// THEN
const menuItems = screen.getAllByRole('listitem')
expect(menuItems).toHaveLength(3)

const lienSeConnecter = within(menuItems[2]).getByRole('link', { name: 'Se connecter' })
expect(lienSeConnecter).toHaveAttribute('href', '/connexion')
expect(nextAuth.signIn).toHaveBeenCalledWith('pasrel')
})

it('quand j’affiche une page quelconque alors je n’ai pas accès à la déconnexion', () => {
// WHEN
renderComponent(<EnTete profil={jeSuiDeconnecte()} />)
renderComponent(
<EnTete
profil={jeSuiDeconnecte()}
providers={spyPasrel}
/>
)

// THEN
const boutonSeDeconnecter = screen.queryByRole('button', { name: 'Se déconnecter' })
Expand All @@ -87,7 +101,12 @@ describe('en-tête', () => {

it('quand j’affiche une page quelconque alors je n’ai pas accès au lien de mes inventaires', () => {
// WHEN
renderComponent(<EnTete profil={jeSuiDeconnecte()} />)
renderComponent(
<EnTete
profil={jeSuiDeconnecte()}
providers={spyPasrel}
/>
)

// THEN
const lienInventaires = screen.queryByRole('link', { name: 'Inventaires' })
Expand Down
Loading

0 comments on commit e21365d

Please sign in to comment.