160 lines
5.5 KiB
TypeScript
160 lines
5.5 KiB
TypeScript
import React, { createContext, useContext, useReducer, useEffect } from 'react';
|
|
import { AuthState, AdminUser, Permission, LoginRequest } from '../types/auth';
|
|
import toast from 'react-hot-toast';
|
|
|
|
interface AuthContextType {
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
user: AdminUser | null;
|
|
permissions: Permission[];
|
|
allPermissions: Permission[];
|
|
token: string | null;
|
|
refreshToken: string | null;
|
|
logout: () => void;
|
|
restoreSession: () => void;
|
|
hasPermission: (permissionId: number) => boolean;
|
|
hasPermissionByTitle: (title: string) => boolean;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
type AuthAction =
|
|
| { type: 'LOGIN'; payload: { user: AdminUser; permissions: Permission[]; allPermissions: Permission[]; token: string; refreshToken: string } }
|
|
| { type: 'LOGOUT' }
|
|
| { type: 'RESTORE_SESSION'; payload: { user: AdminUser; permissions: Permission[]; allPermissions: Permission[]; token: string; refreshToken: string } }
|
|
| { type: 'SET_LOADING'; payload: boolean };
|
|
|
|
const authReducer = (state: AuthState, action: AuthAction): AuthState => {
|
|
switch (action.type) {
|
|
case 'LOGIN':
|
|
case 'RESTORE_SESSION':
|
|
return {
|
|
...state,
|
|
isAuthenticated: true,
|
|
isLoading: false,
|
|
user: action.payload.user,
|
|
permissions: action.payload.permissions,
|
|
allPermissions: action.payload.allPermissions,
|
|
token: action.payload.token,
|
|
refreshToken: action.payload.refreshToken,
|
|
};
|
|
case 'LOGOUT':
|
|
return {
|
|
...state,
|
|
isAuthenticated: false,
|
|
isLoading: false,
|
|
user: null,
|
|
permissions: [],
|
|
allPermissions: [],
|
|
token: null,
|
|
refreshToken: null,
|
|
};
|
|
case 'SET_LOADING':
|
|
return {
|
|
...state,
|
|
isLoading: action.payload,
|
|
};
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
const initialState: AuthState = {
|
|
isAuthenticated: false,
|
|
isLoading: true,
|
|
user: null,
|
|
permissions: [],
|
|
allPermissions: [],
|
|
token: null,
|
|
refreshToken: null,
|
|
};
|
|
|
|
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|
const [state, dispatch] = useReducer(authReducer, initialState);
|
|
|
|
const restoreSession = () => {
|
|
dispatch({ type: 'SET_LOADING', payload: true });
|
|
|
|
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');
|
|
|
|
if (token && userStr && permissionsStr) {
|
|
try {
|
|
const user = JSON.parse(userStr);
|
|
const permissions = JSON.parse(permissionsStr);
|
|
|
|
dispatch({
|
|
type: 'RESTORE_SESSION',
|
|
payload: {
|
|
user,
|
|
permissions,
|
|
allPermissions: permissions,
|
|
token,
|
|
refreshToken: refreshToken || ''
|
|
}
|
|
});
|
|
} catch (error) {
|
|
localStorage.removeItem('admin_token');
|
|
localStorage.removeItem('admin_refresh_token');
|
|
localStorage.removeItem('admin_user');
|
|
localStorage.removeItem('admin_permissions');
|
|
dispatch({ type: 'SET_LOADING', payload: false });
|
|
}
|
|
} else {
|
|
dispatch({ type: 'SET_LOADING', payload: false });
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
restoreSession();
|
|
}, []);
|
|
|
|
const logout = () => {
|
|
localStorage.removeItem('admin_token');
|
|
localStorage.removeItem('admin_refresh_token');
|
|
localStorage.removeItem('admin_user');
|
|
localStorage.removeItem('admin_permissions');
|
|
dispatch({ type: 'LOGOUT' });
|
|
toast.success('خروج موفقیتآمیز بود');
|
|
};
|
|
|
|
const hasPermission = (permissionId: number): boolean => {
|
|
// اگر Super Admin (id=1) باشد، به همه چیز دسترسی دارد
|
|
const isSuperAdmin = state.permissions.some(permission => permission.id === 1);
|
|
if (isSuperAdmin) return true;
|
|
|
|
// در غیر اینصورت چک کن permission مورد نیاز را دارد یا نه
|
|
return state.permissions.some(permission => permission.id === permissionId);
|
|
};
|
|
|
|
const hasPermissionByTitle = (title: string): boolean => {
|
|
// اگر Super Admin (AdminAll) باشد، به همه چیز دسترسی دارد
|
|
const isSuperAdmin = state.permissions.some(permission => permission.title === "AdminAll");
|
|
if (isSuperAdmin) return true;
|
|
|
|
// در غیر اینصورت چک کن permission مورد نیاز را دارد یا نه
|
|
return state.permissions.some(permission => permission.title === title);
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={{
|
|
...state,
|
|
logout,
|
|
restoreSession,
|
|
hasPermission,
|
|
hasPermissionByTitle,
|
|
}}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useAuth = () => {
|
|
const context = useContext(AuthContext);
|
|
if (context === undefined) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
};
|