mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
chore: ajustement JWT
This commit is contained in:
@ -8,6 +8,9 @@ const nextConfig = {
|
||||
output: "standalone",
|
||||
experimental: {
|
||||
instrumentationHook: true,
|
||||
},
|
||||
images: {
|
||||
domains:['i.pravatar.cc'],
|
||||
},
|
||||
env: {
|
||||
NEXT_PUBLIC_APP_VERSION: pkg.version,
|
||||
|
||||
@ -4,6 +4,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import Sidebar from '@/components/Sidebar';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import {useTranslations} from 'next-intl';
|
||||
import Image from 'next/image';
|
||||
import {
|
||||
Users,
|
||||
Building,
|
||||
@ -94,7 +95,7 @@ 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">
|
||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||
<DropdownMenu
|
||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
||||
buttonContent={<Image src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" width={150} height={150} />}
|
||||
items={dropdownItems}
|
||||
buttonClassName=""
|
||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { SendHorizontal } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
const contacts = [
|
||||
{ id: 1, name: 'Facturation', profilePic: 'https://i.pravatar.cc/32' },
|
||||
@ -61,7 +62,7 @@ export default function MessageriePage() {
|
||||
className={`p-2 cursor-pointer ${selectedContact?.id === contact.id ? 'bg-gray-200' : ''}`}
|
||||
onClick={() => setSelectedContact(contact)}
|
||||
>
|
||||
<img src={contact.profilePic} alt={`${contact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" />
|
||||
<Image src={contact.profilePic} alt={`${contact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150}/>
|
||||
{contact.name}
|
||||
</div>
|
||||
))}
|
||||
@ -75,7 +76,7 @@ export default function MessageriePage() {
|
||||
style={{ borderRadius: message.isResponse ? '20px 20px 0 20px' : '20px 20px 20px 0', minWidth: '25%' }}
|
||||
>
|
||||
<div className="flex items-center mb-1">
|
||||
<img src={selectedContact.profilePic} alt={`${selectedContact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" />
|
||||
<img src={selectedContact.profilePic} alt={`${selectedContact.name}'s profile`} className="w-8 h-8 rounded-full inline-block mr-2" width={150} height={150} />
|
||||
<span className="text-xs text-gray-600">{selectedContact.name}</span>
|
||||
<span className="text-xs text-gray-400 ml-2">{new Date(message.date).toLocaleTimeString()}</span>
|
||||
</div>
|
||||
|
||||
@ -4,8 +4,8 @@ import logoImage from '@/img/logo_min.svg'; // Assurez-vous que le chemin vers l
|
||||
|
||||
const Logo = ({ className }) => {
|
||||
return (
|
||||
<div className={className}>
|
||||
<Image src={logoImage} alt="Logo" width={150} height={150} />
|
||||
<div className={`max-w-[150px] ${className}`}>
|
||||
<Image src={logoImage} alt="Logo" style={{ width: 'auto', height: 'auto'}} priority />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -5,23 +5,21 @@ import Loader from '@/components/Loader'; // Importez le composant Loader
|
||||
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
|
||||
|
||||
const ProtectedRoute = ({ children }) => {
|
||||
const { data: session, status } = useSession();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'loading') return; // Ne rien faire tant que le statut est "loading"
|
||||
if (!session) {
|
||||
// Rediriger vers la page de login si l'utilisateur n'est pas connecté
|
||||
const { data: session, status } = useSession({
|
||||
required: true,
|
||||
onUnauthenticated() {
|
||||
router.push(`${FE_USERS_LOGIN_URL}`);
|
||||
}
|
||||
}, [session, status, router]);
|
||||
});
|
||||
const router = useRouter();
|
||||
|
||||
if (status === 'loading' || !session) {
|
||||
return <Loader />; // Affichez un loader pendant le chargement ou si l'utilisateur n'est pas connecté
|
||||
// Ne vérifier que si le statut est définitif
|
||||
if (status === 'loading') {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
// Afficher les enfants seulement si l'utilisateur est connecté
|
||||
return children;
|
||||
// Autoriser l'affichage si authentifié
|
||||
return session ? children : null;
|
||||
};
|
||||
|
||||
export default ProtectedRoute;
|
||||
@ -1,31 +1,48 @@
|
||||
import { useState } from "react"
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
const useLocalStorage = (key, initialValue) => {
|
||||
const [state, setState] = useState(() => {
|
||||
// Initialize the state
|
||||
const [storedValue, setStoredValue] = useState(() => {
|
||||
try {
|
||||
const value = window.localStorage.getItem(key)
|
||||
// Check if the local storage already has any values,
|
||||
// otherwise initialize it with the passed initialValue
|
||||
return value ? JSON.parse(value) : initialValue
|
||||
if (typeof window !== 'undefined') {
|
||||
const item = window.localStorage.getItem(key);
|
||||
// Vérifier si l'item existe et n'est pas undefined
|
||||
return item !== null && item !== 'undefined'
|
||||
? JSON.parse(item)
|
||||
: initialValue;
|
||||
}
|
||||
return initialValue;
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error('Error reading from localStorage:', error);
|
||||
return initialValue;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const setValue = value => {
|
||||
useEffect(() => {
|
||||
try {
|
||||
// If the passed value is a callback function,
|
||||
// then call it with the existing state.
|
||||
const valueToStore = value instanceof Function ? value(state) : value
|
||||
window.localStorage.setItem(key, JSON.stringify(valueToStore))
|
||||
setState(value)
|
||||
// Vérifier si la valeur n'est pas undefined avant de la stocker
|
||||
if (typeof storedValue !== 'undefined') {
|
||||
window.localStorage.setItem(key, JSON.stringify(storedValue));
|
||||
} else {
|
||||
window.localStorage.removeItem(key);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error('Error writing to localStorage:', error);
|
||||
}
|
||||
}
|
||||
}, [key, storedValue]);
|
||||
|
||||
return [state, setValue]
|
||||
}
|
||||
const setValue = (value) => {
|
||||
try {
|
||||
// Permettre à la valeur d'être une fonction
|
||||
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
||||
setStoredValue(valueToStore);
|
||||
} catch (error) {
|
||||
console.error('Error updating localStorage value:', error);
|
||||
}
|
||||
};
|
||||
|
||||
export default useLocalStorage
|
||||
return [storedValue, setValue];
|
||||
};
|
||||
|
||||
export default useLocalStorage;
|
||||
@ -34,45 +34,69 @@ const options = {
|
||||
})
|
||||
],
|
||||
session: {
|
||||
strategy:"jwt",
|
||||
strategy: "jwt",
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 jours
|
||||
updateAge: 24 * 60 * 60, // 24 heures
|
||||
},
|
||||
cookies: {
|
||||
sessionToken: {
|
||||
name: 'n3wtschool_session_token',
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: process.env.NODE_ENV === 'production'
|
||||
}
|
||||
}
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
if (user) {
|
||||
token.token = user.token;
|
||||
token.refresh = user.refresh;
|
||||
token.tokenExpires = jwt_decode.decode(user.token).exp * 1000;
|
||||
async jwt({ token, user, trigger }) {
|
||||
// Si c'est la première connexion
|
||||
if (user) {
|
||||
return {
|
||||
...token,
|
||||
token: user.token,
|
||||
refresh: user.refresh,
|
||||
tokenExpires: jwt_decode.decode(user.token).exp * 1000
|
||||
};
|
||||
}
|
||||
// Vérifie si l'access token a expiré
|
||||
|
||||
// Vérifier si le token n'est pas expiré
|
||||
if (Date.now() < token.tokenExpires) {
|
||||
return token;
|
||||
}
|
||||
// Renouvelle le token expiré
|
||||
|
||||
// Token expiré, essayer de le rafraîchir
|
||||
try {
|
||||
const data = {refresh: token.refresh}
|
||||
const res = await refreshJWT(data);
|
||||
console.log(res);
|
||||
token.token = res.token;
|
||||
token.refresh = res.refresh;
|
||||
token.tokenExpires = jwt_decode.decode(res.token).exp * 1000;
|
||||
console.log("Token refreshed", token);
|
||||
return token;
|
||||
const response = await refreshJWT({ refresh: token.refresh });
|
||||
if (!response) {
|
||||
throw new Error('Failed to refresh token');
|
||||
}
|
||||
|
||||
return {
|
||||
...token,
|
||||
token: response.token,
|
||||
refresh: response.refresh,
|
||||
tokenExpires: jwt_decode.decode(response.token).exp * 1000
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du rafraîchissement du token", error);
|
||||
console.error("Refresh token failed:", error);
|
||||
return token;
|
||||
}
|
||||
},
|
||||
async session({ session, token }) {
|
||||
console.log("Session callback called", token);
|
||||
if (!token) {
|
||||
throw new Error('Token not found');
|
||||
}
|
||||
else{
|
||||
const decodedToken = jwt_decode.decode(token.token);
|
||||
const {user_id,email,droit} = decodedToken;
|
||||
session.user = {id:user_id,email,droit};
|
||||
return session;
|
||||
if (token) {
|
||||
const {user_id, droit, email} = jwt_decode.decode(token.token);
|
||||
session.user = {
|
||||
...session.user,
|
||||
token: token.token,
|
||||
refresh: token.refresh
|
||||
};
|
||||
session.user.user_id = user_id;
|
||||
session.user.droit = droit;
|
||||
session.user.email = email;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
|
||||
Reference in New Issue
Block a user