mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
refactor: Creation d'un provider et d'un systeme de middleware
This commit is contained in:
@ -1,2 +1,4 @@
|
|||||||
NEXT_PUBLIC_API_URL=http://localhost:8080
|
NEXT_PUBLIC_API_URL=http://localhost:8080
|
||||||
NEXT_PUBLIC_USE_FAKE_DATA='false'
|
NEXT_PUBLIC_USE_FAKE_DATA='false'
|
||||||
|
AUTH_SECRET='false'
|
||||||
|
NEXTAUTH_URL=http://localhost:3000
|
||||||
@ -15,7 +15,7 @@ replace_value() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
printenv | grep NEXT_PUBLIC_ | while read -r line ; do
|
printenv | while read -r line ; do
|
||||||
key=$(echo $line | cut -d "=" -f1)
|
key=$(echo $line | cut -d "=" -f1)
|
||||||
value=$(echo $line | cut -d "=" -f2)
|
value=$(echo $line | cut -d "=" -f2)
|
||||||
|
|
||||||
|
|||||||
@ -10,13 +10,19 @@ const nextConfig = {
|
|||||||
instrumentationHook: true,
|
instrumentationHook: true,
|
||||||
},
|
},
|
||||||
images: {
|
images: {
|
||||||
domains:['i.pravatar.cc'],
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "www.gravatar.com",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
NEXT_PUBLIC_APP_VERSION: pkg.version,
|
NEXT_PUBLIC_APP_VERSION: pkg.version,
|
||||||
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080",
|
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080",
|
||||||
NEXT_PUBLIC_USE_FAKE_DATA: process.env.NEXT_PUBLIC_USE_FAKE_DATA || 'false',
|
NEXT_PUBLIC_USE_FAKE_DATA: process.env.NEXT_PUBLIC_USE_FAKE_DATA || 'false',
|
||||||
|
AUTH_SECRET: process.env.AUTH_SECRET || 'false',
|
||||||
|
NEXTAUTH_URL: process.env.NEXTAUTH_URL || "http://localhost:3000",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
NEXT_PUBLIC_API_URL=_NEXT_PUBLIC_API_URL_
|
NEXT_PUBLIC_API_URL=_NEXT_PUBLIC_API_URL_
|
||||||
NEXT_PUBLIC_USE_FAKE_DATA=_NEXT_PUBLIC_USE_FAKE_DATA_
|
NEXT_PUBLIC_USE_FAKE_DATA=_NEXT_PUBLIC_USE_FAKE_DATA_
|
||||||
|
AUTH_SECRET=_AUTH_SECRET_
|
||||||
|
NEXTAUTH_URL=_NEXTAUTH_URL_
|
||||||
@ -26,10 +26,11 @@ import {
|
|||||||
FE_ADMIN_SETTINGS_URL
|
FE_ADMIN_SETTINGS_URL
|
||||||
} from '@/utils/Url';
|
} from '@/utils/Url';
|
||||||
|
|
||||||
import { disconnect } from '@/app/actions/authAction';
|
import { disconnect, getUser } from '@/app/actions/authAction';
|
||||||
|
import { useSession } from 'next-auth/react';
|
||||||
import { fetchEstablishment } from '@/app/actions/schoolAction';
|
import { fetchEstablishment } from '@/app/actions/schoolAction';
|
||||||
import ProtectedRoute from '@/components/ProtectedRoute';
|
import ProtectedRoute from '@/components/ProtectedRoute';
|
||||||
import { SessionProvider } from 'next-auth/react';
|
import { getGravatarUrl } from '@/utils/gravatar';
|
||||||
|
|
||||||
export default function Layout({
|
export default function Layout({
|
||||||
children,
|
children,
|
||||||
@ -48,6 +49,8 @@ export default function Layout({
|
|||||||
const [establishment, setEstablishment] = useState(null);
|
const [establishment, setEstablishment] = useState(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
const { data: session } = useSession();
|
||||||
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const currentPage = pathname.split('/').pop();
|
const currentPage = pathname.split('/').pop();
|
||||||
@ -84,8 +87,18 @@ export default function Layout({
|
|||||||
.finally(() => setIsLoading(false));
|
.finally(() => setIsLoading(false));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
if (session) { // Vérifier que la session existe
|
||||||
|
const userData = await getUser();
|
||||||
|
setUser(userData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUser();
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SessionProvider>
|
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<div className="flex min-h-screen bg-gray-50">
|
<div className="flex min-h-screen bg-gray-50">
|
||||||
@ -95,7 +108,15 @@ export default function Layout({
|
|||||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
buttonContent={<Image src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" width={150} height={150} />}
|
buttonContent={
|
||||||
|
<Image
|
||||||
|
src={getGravatarUrl(user?.email)}
|
||||||
|
alt="Profile"
|
||||||
|
className="w-8 h-8 rounded-full cursor-pointer"
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
/>
|
||||||
|
}
|
||||||
items={dropdownItems}
|
items={dropdownItems}
|
||||||
buttonClassName=""
|
buttonClassName=""
|
||||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||||
@ -126,7 +147,6 @@ export default function Layout({
|
|||||||
onCancel={() => setIsPopupVisible(false)}
|
onCancel={() => setIsPopupVisible(false)}
|
||||||
/>
|
/>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
</SessionProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_URL
|
|||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { fetchMessages } from '@/app/actions/messagerieAction';
|
import { fetchMessages } from '@/app/actions/messagerieAction';
|
||||||
import ProtectedRoute from '@/components/ProtectedRoute';
|
import ProtectedRoute from '@/components/ProtectedRoute';
|
||||||
import { SessionProvider } from 'next-auth/react';
|
|
||||||
import { disconnect } from '@/app/actions/authAction';
|
import { disconnect } from '@/app/actions/authAction';
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
|
|
||||||
@ -55,7 +54,6 @@ export default function Layout({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SessionProvider>
|
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<div className="flex flex-col min-h-screen bg-gray-50">
|
<div className="flex flex-col min-h-screen bg-gray-50">
|
||||||
{/* Entête */}
|
{/* Entête */}
|
||||||
@ -111,7 +109,6 @@ export default function Layout({
|
|||||||
onCancel={() => setIsPopupVisible(false)}
|
onCancel={() => setIsPopupVisible(false)}
|
||||||
/>
|
/>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
</SessionProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,12 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
import { SendHorizontal } from 'lucide-react';
|
import { SendHorizontal } from 'lucide-react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
import { getGravatarUrl } from '@/utils/gravatar';
|
||||||
|
|
||||||
const contacts = [
|
const contacts = [
|
||||||
{ id: 1, name: 'Facturation', profilePic: 'https://i.pravatar.cc/32' },
|
{ id: 1, name: 'Facturation', profilePic: getGravatarUrl('facturation@n3wtschool.com') },
|
||||||
{ id: 2, name: 'Enseignant 1', profilePic: 'https://i.pravatar.cc/32' },
|
{ id: 2, name: 'Enseignant 1', profilePic: getGravatarUrl('enseignant@n3wtschool.com') },
|
||||||
{ id: 3, name: 'Contact', profilePic: 'https://i.pravatar.cc/32' },
|
{ id: 3, name: 'Contact', profilePic: getGravatarUrl('contact@n3wtschool.com') },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function MessageriePage() {
|
export default function MessageriePage() {
|
||||||
|
|||||||
@ -161,3 +161,27 @@ export const getResetPassword = (uuid) => {
|
|||||||
},
|
},
|
||||||
}).then(requestResponseHandler);
|
}).then(requestResponseHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère les informations de l'utilisateur connecté depuis la session
|
||||||
|
* @returns {Promise} Les données de l'utilisateur
|
||||||
|
*/
|
||||||
|
export const getUser = async () => {
|
||||||
|
try {
|
||||||
|
const session = await getSession();
|
||||||
|
|
||||||
|
if (!session || !session.user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: session.user.user_id,
|
||||||
|
email: session.user.email,
|
||||||
|
role: session.user.droit
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting user from session:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { getMessages } from 'next-intl/server';
|
import { getMessages } from 'next-intl/server';
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import Providers from '@/components/Providers'
|
||||||
import { CsrfProvider } from '@/context/CsrfContext';
|
|
||||||
import "@/css/tailwind.css";
|
import "@/css/tailwind.css";
|
||||||
|
import { headers } from 'next/headers';
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: "N3WT-SCHOOL",
|
title: "N3WT-SCHOOL",
|
||||||
@ -22,17 +22,16 @@ export const metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function RootLayout({ children, params }) {
|
export default async function RootLayout({ children, params }) {
|
||||||
const { locale } = params;
|
const headersList = headers();
|
||||||
const messages = await getMessages(locale); // Passez le locale ici
|
const locale = headersList.get('x-locale') || 'fr';
|
||||||
|
const messages = await getMessages(locale);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={locale}>
|
<html lang={locale}>
|
||||||
<body>
|
<body>
|
||||||
<CsrfProvider>
|
<Providers messages={messages} locale={locale} session={params.session}>
|
||||||
<NextIntlClientProvider messages={messages} locale={locale}> {/* Passez le locale ici */}
|
|
||||||
{children}
|
{children}
|
||||||
</NextIntlClientProvider>
|
</Providers>
|
||||||
</CsrfProvider>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
21
Front-End/src/components/Providers.js
Normal file
21
Front-End/src/components/Providers.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
import { CsrfProvider } from '@/context/CsrfContext'
|
||||||
|
import { NextIntlClientProvider } from 'next-intl'
|
||||||
|
|
||||||
|
export default function Providers({ children, messages, locale, session }) {
|
||||||
|
if (!locale) {
|
||||||
|
console.error('Locale non définie dans Providers');
|
||||||
|
locale = 'fr'; // Valeur par défaut
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
<CsrfProvider>
|
||||||
|
<NextIntlClientProvider messages={messages} locale={locale}>
|
||||||
|
{children}
|
||||||
|
</NextIntlClientProvider>
|
||||||
|
</CsrfProvider>
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -8,8 +8,12 @@ const CsrfContext = createContext();
|
|||||||
|
|
||||||
export const CsrfProvider = ({ children }) => {
|
export const CsrfProvider = ({ children }) => {
|
||||||
const [csrfToken, setCsrfTokenState] = useState('');
|
const [csrfToken, setCsrfTokenState] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Éviter les appels multiples si le token existe déjà
|
||||||
|
if (csrfToken) return;
|
||||||
|
|
||||||
fetch(`${BE_AUTH_CSRF_URL}`, {
|
fetch(`${BE_AUTH_CSRF_URL}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
credentials: 'include' // Inclut les cookies dans la requête
|
credentials: 'include' // Inclut les cookies dans la requête
|
||||||
@ -24,16 +28,23 @@ export const CsrfProvider = ({ children }) => {
|
|||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error fetching CSRF token:', error);
|
console.error('Error fetching CSRF token:', error);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []); // Dépendance vide pour n'exécuter qu'une seule fois
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CsrfContext.Provider value={csrfToken}>
|
<CsrfContext.Provider value={csrfToken}>
|
||||||
{children}
|
{!isLoading && children}
|
||||||
</CsrfContext.Provider>
|
</CsrfContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCsrfToken = () => {
|
export const useCsrfToken = () => {
|
||||||
return useContext(CsrfContext);
|
const context = useContext(CsrfContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useCsrfToken must be used within a CsrfProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
};
|
};
|
||||||
12
Front-End/src/hooks/useLocale.js
Normal file
12
Front-End/src/hooks/useLocale.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { headers } from 'next/headers';
|
||||||
|
|
||||||
|
export function useLocale() {
|
||||||
|
try {
|
||||||
|
const headersList = headers();
|
||||||
|
return headersList.get('x-locale') || 'fr';
|
||||||
|
} catch {
|
||||||
|
return 'fr';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
export async function register() {
|
export async function register() {
|
||||||
|
if (process.env.NEXT_RUNTIME === 'nodejs' && process.env.NODE_ENV === 'production') {
|
||||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
||||||
await require('pino')
|
await require('pino')
|
||||||
await require('next-logger')
|
await require('next-logger')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,5 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { stackMiddlewares } from "@/middlewares/stackHandler";
|
||||||
import createMiddleware from 'next-intl/middleware';
|
import { withLocale } from "@/middlewares/withLocale";
|
||||||
import { routing } from '@/i18n/routing';
|
|
||||||
const middleware = createMiddleware(routing);
|
|
||||||
|
|
||||||
export default function handler(req) {
|
const middlewares = [withLocale];
|
||||||
const { pathname, search } = req.nextUrl;
|
export default stackMiddlewares(middlewares);
|
||||||
const locale = pathname.split('/')[1]; // Obtenez la locale actuelle
|
|
||||||
|
|
||||||
// Vérifiez si la route ne contient pas de locale
|
|
||||||
if (!pathname.startsWith('/fr') && !pathname.startsWith('/en')) {
|
|
||||||
// Redirigez vers la locale par défaut (fr) avec les paramètres de recherche
|
|
||||||
|
|
||||||
console.log('Redirecting to /fr');
|
|
||||||
return NextResponse.redirect(new URL(`/fr${pathname}${search}`, req.url));
|
|
||||||
}
|
|
||||||
|
|
||||||
return middleware(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const config = {
|
|
||||||
// Match only internationalized pathnames
|
|
||||||
matcher: ['/', '/(fr|en)/:path*','/((?!api|_next|favicon.ico|favicon.svg).*)'],
|
|
||||||
};
|
|
||||||
20
Front-End/src/middlewares/stackHandler.js
Normal file
20
Front-End/src/middlewares/stackHandler.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export function stackMiddlewares(functions = []) {
|
||||||
|
return async (request, event) => {
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
const next = async (req, evt) => {
|
||||||
|
const current = functions[index];
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (current) {
|
||||||
|
return current(next)(req, evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.next();
|
||||||
|
};
|
||||||
|
|
||||||
|
return next(request, event);
|
||||||
|
};
|
||||||
|
}
|
||||||
42
Front-End/src/middlewares/withLocale.js
Normal file
42
Front-End/src/middlewares/withLocale.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import createIntlMiddleware from 'next-intl/middleware';
|
||||||
|
import { routing } from '@/i18n/routing';
|
||||||
|
|
||||||
|
const withLocale = (next) => {
|
||||||
|
const intlMiddleware = createIntlMiddleware(routing);
|
||||||
|
|
||||||
|
return async (request, event) => {
|
||||||
|
const { pathname, search } = request.nextUrl;
|
||||||
|
|
||||||
|
// Ignorer les ressources statiques et API routes
|
||||||
|
if (pathname.startsWith('/_next') || pathname.startsWith('/api') || pathname.includes('.')) {
|
||||||
|
return next(request, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Déterminer la locale
|
||||||
|
let locale = 'fr';
|
||||||
|
if (pathname.startsWith('/fr') || pathname.startsWith('/en')) {
|
||||||
|
locale = pathname.split('/')[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si pas de locale dans l'URL, rediriger vers /fr
|
||||||
|
if (!pathname.startsWith('/fr') && !pathname.startsWith('/en')) {
|
||||||
|
return NextResponse.redirect(new URL(`/fr${pathname}${search}`, request.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appliquer le middleware next-intl
|
||||||
|
const response = await intlMiddleware(request, event);
|
||||||
|
if (response) {
|
||||||
|
// Ajouter la locale aux headers
|
||||||
|
response.headers.set('x-locale', locale);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextResponse = await next(request, event);
|
||||||
|
// Ajouter la locale aux headers même pour les réponses suivantes
|
||||||
|
nextResponse.headers.set('x-locale', locale);
|
||||||
|
return nextResponse;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export { withLocale };
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import NextAuth from 'next-auth';
|
import NextAuth from 'next-auth';
|
||||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||||
import { getJWT, refreshJWT } from '@/app/actions/authAction';
|
import { getJWT, refreshJWT } from '@/app/actions/authAction';
|
||||||
|
import jwt_decode from 'jsonwebtoken';
|
||||||
import jwt_decode from 'jsonwebtoken'; // Changed import
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
secret: process.env.AUTH_SECRET,
|
||||||
providers: [
|
providers: [
|
||||||
CredentialsProvider({
|
CredentialsProvider({
|
||||||
name: 'Credentials',
|
name: 'Credentials',
|
||||||
@ -50,9 +50,9 @@ const options = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async jwt({ token, user, trigger }) {
|
async jwt({ token, user }) {
|
||||||
// Si c'est la première connexion
|
// Si c'est la première connexion
|
||||||
if (user) {
|
if (user && user?.token) {
|
||||||
return {
|
return {
|
||||||
...token,
|
...token,
|
||||||
token: user.token,
|
token: user.token,
|
||||||
@ -69,23 +69,24 @@ const options = {
|
|||||||
// Token expiré, essayer de le rafraîchir
|
// Token expiré, essayer de le rafraîchir
|
||||||
try {
|
try {
|
||||||
const response = await refreshJWT({ refresh: token.refresh });
|
const response = await refreshJWT({ refresh: token.refresh });
|
||||||
if (!response) {
|
if (response && response?.token) {
|
||||||
throw new Error('Failed to refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...token,
|
...token,
|
||||||
token: response.token,
|
token: response.token,
|
||||||
refresh: response.refresh,
|
refresh: response.refresh,
|
||||||
tokenExpires: jwt_decode.decode(response.token).exp * 1000
|
tokenExpires: jwt_decode.decode(response.token).exp * 1000
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new Error('Failed to refresh token');
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Refresh token failed:", error);
|
console.error("Refresh token failed:", error);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
if (token) {
|
if (token && token?.token) {
|
||||||
const {user_id, droit, email} = jwt_decode.decode(token.token);
|
const {user_id, droit, email} = jwt_decode.decode(token.token);
|
||||||
session.user = {
|
session.user = {
|
||||||
...session.user,
|
...session.user,
|
||||||
|
|||||||
11
Front-End/src/utils/gravatar.js
Normal file
11
Front-End/src/utils/gravatar.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
export function getGravatarUrl(email, size = 32) {
|
||||||
|
if(email === undefined || typeof email !== 'string') {
|
||||||
|
return 'https://www.gravatar.com/avatar/';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const hash = crypto.createHash('md5').update(email.toLowerCase().trim()).digest('hex');
|
||||||
|
return `https://www.gravatar.com/avatar/${hash}?s=${size}&d=identicon`;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user