This commit is contained in:
+172
-137
@@ -1,163 +1,198 @@
|
||||
import React, { createContext, useContext, useState, useEffect, type ReactNode } from 'react';
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import {
|
||||
getToken, setToken as storeToken, removeToken,
|
||||
getAdminToken, setAdminToken as storeAdminToken, removeAdminToken,
|
||||
setUsername, removeUsername,
|
||||
setAdminUsername, removeAdminUsername,
|
||||
setRole as storeRole, getRole, removeRole,
|
||||
clearAllAuth,
|
||||
} from './tokenStorage';
|
||||
import { extractUsernameFromToken, extractRoleFromToken, isTokenExpired } from './jwtUtils';
|
||||
getToken,
|
||||
setToken as storeToken,
|
||||
removeToken,
|
||||
getAdminToken,
|
||||
setAdminToken as storeAdminToken,
|
||||
removeAdminToken,
|
||||
setUsername,
|
||||
removeUsername,
|
||||
setAdminUsername,
|
||||
removeAdminUsername,
|
||||
setRole as storeRole,
|
||||
getRole,
|
||||
removeRole,
|
||||
clearAllAuth,
|
||||
} from "./tokenStorage";
|
||||
import {
|
||||
extractUsernameFromToken,
|
||||
extractRoleFromToken,
|
||||
isTokenExpired,
|
||||
} from "./jwtUtils";
|
||||
|
||||
export type UserRole = 'client' | 'admin' | 'cabine' | 'livreur' | null;
|
||||
export type UserRole = "client" | "admin" | "cabine" | "livreur" | null;
|
||||
|
||||
interface AuthState {
|
||||
token: string | null;
|
||||
username: string | null;
|
||||
role: UserRole;
|
||||
isLoading: boolean;
|
||||
isAuthenticated: boolean;
|
||||
mustChangePassword: boolean;
|
||||
token: string | null;
|
||||
username: string | null;
|
||||
role: UserRole;
|
||||
isLoading: boolean;
|
||||
isAuthenticated: boolean;
|
||||
mustChangePassword: boolean;
|
||||
}
|
||||
|
||||
interface AuthContextType extends AuthState {
|
||||
loginClient: (token: string, mustChangePassword?: boolean) => Promise<void>;
|
||||
loginAdmin: (token: string, role: 'admin' | 'cabine' | 'livreur') => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
setMustChangePassword: (value: boolean) => void;
|
||||
loginClient: (token: string, mustChangePassword?: boolean) => Promise<void>;
|
||||
loginAdmin: (
|
||||
token: string,
|
||||
role: "admin" | "cabine" | "livreur",
|
||||
) => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
setMustChangePassword: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
|
||||
export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
const [state, setState] = useState<AuthState>({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: true,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
const [state, setState] = useState<AuthState>({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: true,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
|
||||
// Restore session on mount
|
||||
useEffect(() => {
|
||||
const restore = async () => {
|
||||
try {
|
||||
const savedRole = await getRole();
|
||||
useEffect(() => {
|
||||
const restore = async () => {
|
||||
try {
|
||||
const savedRole = await getRole();
|
||||
|
||||
if (savedRole === 'client') {
|
||||
const token = await getToken();
|
||||
if (token && !isTokenExpired(token)) {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role: 'client',
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (savedRole === 'admin' || savedRole === 'cabine' || savedRole === 'livreur') {
|
||||
const token = await getAdminToken();
|
||||
if (token && !isTokenExpired(token)) {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role: savedRole as UserRole,
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (savedRole === "client") {
|
||||
const token = await getToken();
|
||||
if (token && !isTokenExpired(token)) {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role: "client",
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (
|
||||
savedRole === "admin" ||
|
||||
savedRole === "cabine" ||
|
||||
savedRole === "livreur"
|
||||
) {
|
||||
const token = await getAdminToken();
|
||||
if (token && !isTokenExpired(token)) {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role: savedRole as UserRole,
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No valid session
|
||||
await clearAllAuth();
|
||||
// No valid session
|
||||
await clearAllAuth();
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
} catch {
|
||||
await clearAllAuth();
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
restore();
|
||||
}, []);
|
||||
|
||||
const loginClient = async (token: string, mustChangePassword = false) => {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
await storeToken(token);
|
||||
if (uname) await setUsername(uname);
|
||||
await storeRole("client");
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
token,
|
||||
username: uname,
|
||||
role: "client",
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword,
|
||||
});
|
||||
} catch {
|
||||
await clearAllAuth();
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
restore();
|
||||
}, []);
|
||||
const setMustChangePassword = (value: boolean) => {
|
||||
setState((prev) => ({ ...prev, mustChangePassword: value }));
|
||||
};
|
||||
|
||||
const loginClient = async (token: string, mustChangePassword = false) => {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
await storeToken(token);
|
||||
if (uname) await setUsername(uname);
|
||||
await storeRole('client');
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role: 'client',
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword,
|
||||
});
|
||||
};
|
||||
const loginAdmin = async (
|
||||
token: string,
|
||||
role: "admin" | "cabine" | "livreur",
|
||||
) => {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
await storeAdminToken(token);
|
||||
if (uname) await setAdminUsername(uname);
|
||||
await storeRole(role);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role,
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
};
|
||||
|
||||
const setMustChangePassword = (value: boolean) => {
|
||||
setState(prev => ({ ...prev, mustChangePassword: value }));
|
||||
};
|
||||
const logout = async () => {
|
||||
await clearAllAuth();
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
};
|
||||
|
||||
const loginAdmin = async (token: string, role: 'admin' | 'cabine' | 'livreur') => {
|
||||
const uname = extractUsernameFromToken(token);
|
||||
await storeAdminToken(token);
|
||||
if (uname) await setAdminUsername(uname);
|
||||
await storeRole(role);
|
||||
setState({
|
||||
token,
|
||||
username: uname,
|
||||
role,
|
||||
isLoading: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
await clearAllAuth();
|
||||
setState({
|
||||
token: null,
|
||||
username: null,
|
||||
role: null,
|
||||
isLoading: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ ...state, loginClient, loginAdmin, logout, setMustChangePassword }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
...state,
|
||||
loginClient,
|
||||
loginAdmin,
|
||||
logout,
|
||||
setMustChangePassword,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error('useAuth must be used within an AuthProvider');
|
||||
}
|
||||
return context;
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth must be used within an AuthProvider");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user