refactor(auth): update AuthContext for new API structure

- Remove login logic from context (moved to custom hook)
- Add restoreSession functionality
- Update state management for new auth response structure
- Add permission checking by ID and title
- Manage access_token and refresh_token separately
This commit is contained in:
hosseintaromi 2025-07-18 13:06:09 +03:30
parent d45f588fa7
commit 7ec69a67e7
1 changed files with 54 additions and 47 deletions

View File

@ -1,18 +1,20 @@
import { createContext, useContext, useReducer, useEffect } from 'react'; import { createContext, useContext, useReducer, useEffect } from 'react';
import { AuthState, User } from '../types'; import { AuthState, AdminUser, Permission } from '../types/auth';
import toast from 'react-hot-toast';
interface AuthContextType extends AuthState { interface AuthContextType extends AuthState {
login: (email: string, password: string) => Promise<boolean>;
logout: () => void; logout: () => void;
hasPermission: (permission: number) => boolean; hasPermission: (permissionId: number) => boolean;
hasPermissionByTitle: (title: string) => boolean;
restoreSession: () => void;
} }
const AuthContext = createContext<AuthContextType | undefined>(undefined); const AuthContext = createContext<AuthContextType | undefined>(undefined);
type AuthAction = type AuthAction =
| { type: 'LOGIN_SUCCESS'; payload: { user: User; token: string } } | { type: 'LOGIN_SUCCESS'; payload: { user: AdminUser; permissions: Permission[]; allPermissions: Permission[]; token: string; refreshToken: string } }
| { type: 'LOGOUT' } | { type: 'LOGOUT' }
| { type: 'RESTORE_SESSION'; payload: { user: User; token: string } }; | { type: 'RESTORE_SESSION'; payload: { user: AdminUser; permissions: Permission[]; allPermissions: Permission[]; token: string; refreshToken: string } };
const authReducer = (state: AuthState, action: AuthAction): AuthState => { const authReducer = (state: AuthState, action: AuthAction): AuthState => {
switch (action.type) { switch (action.type) {
@ -20,22 +22,28 @@ const authReducer = (state: AuthState, action: AuthAction): AuthState => {
return { return {
isAuthenticated: true, isAuthenticated: true,
user: action.payload.user, user: action.payload.user,
permissions: action.payload.user.permissions, permissions: action.payload.permissions,
allPermissions: action.payload.allPermissions,
token: action.payload.token, token: action.payload.token,
refreshToken: action.payload.refreshToken,
}; };
case 'LOGOUT': case 'LOGOUT':
return { return {
isAuthenticated: false, isAuthenticated: false,
user: null, user: null,
permissions: [], permissions: [],
allPermissions: [],
token: null, token: null,
refreshToken: null,
}; };
case 'RESTORE_SESSION': case 'RESTORE_SESSION':
return { return {
isAuthenticated: true, isAuthenticated: true,
user: action.payload.user, user: action.payload.user,
permissions: action.payload.user.permissions, permissions: action.payload.permissions,
allPermissions: action.payload.allPermissions,
token: action.payload.token, token: action.payload.token,
refreshToken: action.payload.refreshToken,
}; };
default: default:
return state; return state;
@ -46,77 +54,76 @@ const initialState: AuthState = {
isAuthenticated: false, isAuthenticated: false,
user: null, user: null,
permissions: [], permissions: [],
allPermissions: [],
token: null, token: null,
refreshToken: null,
}; };
export const AuthProvider = ({ children }: { children: React.ReactNode }) => { export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [state, dispatch] = useReducer(authReducer, initialState); const [state, dispatch] = useReducer(authReducer, initialState);
useEffect(() => { const restoreSession = () => {
const token = localStorage.getItem('admin_token'); const token = localStorage.getItem('admin_token');
const refreshToken = localStorage.getItem('admin_refresh_token');
const userStr = localStorage.getItem('admin_user'); const userStr = localStorage.getItem('admin_user');
const permissionsStr = localStorage.getItem('admin_permissions');
const allPermissionsStr = localStorage.getItem('admin_all_permissions');
if (token && userStr) { if (token && userStr && permissionsStr) {
try { try {
const user = JSON.parse(userStr); const user = JSON.parse(userStr);
dispatch({ type: 'RESTORE_SESSION', payload: { user, token } }); const permissions = JSON.parse(permissionsStr);
} catch (error) { const allPermissions = allPermissionsStr ? JSON.parse(allPermissionsStr) : [];
localStorage.removeItem('admin_token');
localStorage.removeItem('admin_user');
}
}
}, []);
const login = async (email: string, password: string): Promise<boolean> => {
try {
const mockUser: User = {
id: '1',
name: 'مدیر کل',
email: email,
role: 'admin',
permissions: [1, 2, 3, 4, 5, 10, 15, 20, 22, 25, 30],
status: 'active',
createdAt: new Date().toISOString(),
lastLogin: new Date().toISOString(),
};
const mockToken = 'mock-jwt-token-' + Date.now();
if (email === 'admin@test.com' && password === 'admin123') {
localStorage.setItem('admin_token', mockToken);
localStorage.setItem('admin_user', JSON.stringify(mockUser));
dispatch({ dispatch({
type: 'LOGIN_SUCCESS', type: 'RESTORE_SESSION',
payload: { user: mockUser, token: mockToken } payload: {
user,
permissions,
allPermissions,
token,
refreshToken: refreshToken || ''
}
}); });
} catch (error) {
return true; localStorage.removeItem('admin_token');
localStorage.removeItem('admin_refresh_token');
localStorage.removeItem('admin_user');
localStorage.removeItem('admin_permissions');
localStorage.removeItem('admin_all_permissions');
} }
return false;
} catch (error) {
console.error('Login error:', error);
return false;
} }
}; };
useEffect(() => {
restoreSession();
}, []);
const logout = () => { const logout = () => {
localStorage.removeItem('admin_token'); localStorage.removeItem('admin_token');
localStorage.removeItem('admin_refresh_token');
localStorage.removeItem('admin_user'); localStorage.removeItem('admin_user');
localStorage.removeItem('admin_permissions');
localStorage.removeItem('admin_all_permissions');
dispatch({ type: 'LOGOUT' }); dispatch({ type: 'LOGOUT' });
toast.success('خروج موفقیت‌آمیز بود');
}; };
const hasPermission = (permission: number): boolean => { const hasPermission = (permissionId: number): boolean => {
return state.permissions.includes(permission); return state.permissions.some(permission => permission.id === permissionId);
};
const hasPermissionByTitle = (title: string): boolean => {
return state.permissions.some(permission => permission.title === title);
}; };
return ( return (
<AuthContext.Provider value={{ <AuthContext.Provider value={{
...state, ...state,
login,
logout, logout,
hasPermission, hasPermission,
hasPermissionByTitle,
restoreSession,
}}> }}>
{children} {children}
</AuthContext.Provider> </AuthContext.Provider>