85 lines
2.6 KiB
React
85 lines
2.6 KiB
React
import { createContext, useContext, useEffect, useState } from 'react';
|
|
import { api } from '../api.js';
|
|
|
|
const AuthCtx = createContext(null);
|
|
|
|
export function AuthProvider({ children }) {
|
|
const [token, setToken] = useState(() => localStorage.getItem('cl_token'));
|
|
const [user, setUser] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
if (!token) { setLoading(false); return; }
|
|
api.get('/auth/me')
|
|
.then(({ user }) => setUser(user))
|
|
.catch(() => logout())
|
|
.finally(() => setLoading(false));
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [token]);
|
|
|
|
const login = async (email, password, deviceToken) => {
|
|
const body = { email, password, ...(deviceToken ? { deviceToken } : {}) };
|
|
const r = await api.post('/auth/login', body);
|
|
if (r.requires2FA) {
|
|
// Authentification incomplète — retourne les infos pour la page Login
|
|
return { requires2FA: true, sessionToken: r.sessionToken, email: r.email };
|
|
}
|
|
localStorage.setItem('cl_token', r.token);
|
|
setToken(r.token);
|
|
setUser(r.user);
|
|
return r.user;
|
|
};
|
|
|
|
// Appelé par Login après validation du code 2FA
|
|
const completeLogin = (token, userData) => {
|
|
localStorage.setItem('cl_token', token);
|
|
setToken(token);
|
|
setUser(userData);
|
|
};
|
|
|
|
const register = async (email, password, displayName) => {
|
|
const r = await api.post('/auth/register', { email, password, displayName });
|
|
if (r.requiresVerification) {
|
|
// Compte créé mais email non vérifié — pas de connexion automatique
|
|
return { requiresVerification: true, email: r.email };
|
|
}
|
|
localStorage.setItem('cl_token', r.token);
|
|
setToken(r.token);
|
|
setUser(r.user);
|
|
return r.user;
|
|
};
|
|
|
|
const logout = () => {
|
|
localStorage.removeItem('cl_token');
|
|
localStorage.removeItem('cl_investisseur_id');
|
|
setToken(null);
|
|
setUser(null);
|
|
};
|
|
|
|
const updateUser = async (payload) => {
|
|
const r = await api.put('/auth/me', payload);
|
|
setUser(r.user);
|
|
// If backend issued a fresh token (email changed), persist it
|
|
if (r.token) {
|
|
localStorage.setItem('cl_token', r.token);
|
|
setToken(r.token);
|
|
}
|
|
return r.user;
|
|
};
|
|
|
|
const deleteAccount = async (password) => {
|
|
await api.del('/auth/me', { password });
|
|
logout();
|
|
};
|
|
|
|
const isAdmin = user?.role === 'admin';
|
|
|
|
return (
|
|
<AuthCtx.Provider value={{ token, user, loading, login, completeLogin, register, logout, updateUser, deleteAccount, isAdmin }}>
|
|
{children}
|
|
</AuthCtx.Provider>
|
|
);
|
|
}
|
|
|
|
export const useAuth = () => useContext(AuthCtx);
|