From 7ec69a67e702345c994947987b70ff94ae9107d1 Mon Sep 17 00:00:00 2001 From: hosseintaromi Date: Fri, 18 Jul 2025 13:06:09 +0330 Subject: [PATCH] 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 --- src/contexts/AuthContext.tsx | 101 +++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx index f35d01d..6379163 100644 --- a/src/contexts/AuthContext.tsx +++ b/src/contexts/AuthContext.tsx @@ -1,18 +1,20 @@ 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 { - login: (email: string, password: string) => Promise; logout: () => void; - hasPermission: (permission: number) => boolean; + hasPermission: (permissionId: number) => boolean; + hasPermissionByTitle: (title: string) => boolean; + restoreSession: () => void; } const AuthContext = createContext(undefined); 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: '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 => { switch (action.type) { @@ -20,22 +22,28 @@ const authReducer = (state: AuthState, action: AuthAction): AuthState => { return { isAuthenticated: true, user: action.payload.user, - permissions: action.payload.user.permissions, + permissions: action.payload.permissions, + allPermissions: action.payload.allPermissions, token: action.payload.token, + refreshToken: action.payload.refreshToken, }; case 'LOGOUT': return { isAuthenticated: false, user: null, permissions: [], + allPermissions: [], token: null, + refreshToken: null, }; case 'RESTORE_SESSION': return { isAuthenticated: true, user: action.payload.user, - permissions: action.payload.user.permissions, + permissions: action.payload.permissions, + allPermissions: action.payload.allPermissions, token: action.payload.token, + refreshToken: action.payload.refreshToken, }; default: return state; @@ -46,77 +54,76 @@ const initialState: AuthState = { isAuthenticated: false, user: null, permissions: [], + allPermissions: [], token: null, + refreshToken: null, }; export const AuthProvider = ({ children }: { children: React.ReactNode }) => { const [state, dispatch] = useReducer(authReducer, initialState); - useEffect(() => { + const restoreSession = () => { const token = localStorage.getItem('admin_token'); + const refreshToken = localStorage.getItem('admin_refresh_token'); 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 { const user = JSON.parse(userStr); - dispatch({ type: 'RESTORE_SESSION', payload: { user, token } }); - } catch (error) { - localStorage.removeItem('admin_token'); - localStorage.removeItem('admin_user'); - } - } - }, []); - - const login = async (email: string, password: string): Promise => { - 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)); + const permissions = JSON.parse(permissionsStr); + const allPermissions = allPermissionsStr ? JSON.parse(allPermissionsStr) : []; dispatch({ - type: 'LOGIN_SUCCESS', - payload: { user: mockUser, token: mockToken } + type: 'RESTORE_SESSION', + payload: { + user, + permissions, + allPermissions, + token, + refreshToken: refreshToken || '' + } }); - - return true; + } catch (error) { + 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 = () => { localStorage.removeItem('admin_token'); + localStorage.removeItem('admin_refresh_token'); localStorage.removeItem('admin_user'); + localStorage.removeItem('admin_permissions'); + localStorage.removeItem('admin_all_permissions'); dispatch({ type: 'LOGOUT' }); + toast.success('خروج موفقیت‌آمیز بود'); }; - const hasPermission = (permission: number): boolean => { - return state.permissions.includes(permission); + const hasPermission = (permissionId: number): boolean => { + return state.permissions.some(permission => permission.id === permissionId); + }; + + const hasPermissionByTitle = (title: string): boolean => { + return state.permissions.some(permission => permission.title === title); }; return ( {children}