memowake-front/contexts/auth-context.tsx
2025-08-05 23:12:42 +08:00

147 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { clearCredentials, selectCurrentToken, selectCurrentUser, setCredentials } from '@/features/auth/authSlice';
import { EVENT_TYPES, eventEmitter } from '@/lib/event-util';
import { fetchApi, refreshAuthToken } from '@/lib/server-api-util';
import { store } from '@/store';
import { User } from '@/types/user';
import * as SecureStore from 'expo-secure-store';
import React, { createContext, ReactNode, useContext, useEffect } from 'react';
import { Platform } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
interface AuthContextType {
user: User | null;
login: (user: User, jwt: string) => void;
logout: () => void;
jwt: string | null;
isGuester: () => Promise<boolean>;
isFormalUser: (userMessage: User | null) => boolean;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const dispatch = useDispatch();
const user = useSelector(selectCurrentUser);
const jwt = useSelector(selectCurrentToken);
useEffect(() => {
// 检查 Redux store 中是否已有 token
const refreshTokenAction = async () => {
let token = store.getState().auth.token;
if (Platform.OS === 'web') {
token = localStorage.getItem('token') || "";
} else {
const storedToken = await SecureStore.getItemAsync('token');
token = storedToken || "";
}
if (token) {
// 验证当前 token 是否有效
fetchApi('/user/identity-check', {}, false)
.catch(async (error) => {
// console.error("JWT validation failed, attempting to refresh token...");
try {
// 尝试刷新 token
await refreshAuthToken("Token expired");
// console.log("Token refreshed successfully");
// Token 刷新成功,不需要做其他操作
} catch (refreshError) {
// 刷新 token 失败,才进行登出操作
// console.error("Token refresh failed, logging out", refreshError);
logout();
}
});
} else {
try {
// 尝试刷新 token
await refreshAuthToken("Token expired");
// console.log("Token refreshed successfully");
// Token 刷新成功,不需要做其他操作
} catch (refreshError) {
// 刷新 token 失败,才进行登出操作
// console.error("Token refresh failed, logging out", refreshError);
// 只有在确实需要登出时才调用logout()
// 如果是首次启动应用没有token是正常的不需要登出
}
}
}
refreshTokenAction();
}, [dispatch]);
const login = (newUser: User, newJwt: string) => {
// 更新 Redux store
dispatch(setCredentials({
user: newUser,
token: newJwt
}));
// 判断运行环境是web则存在localstorage或者expo-secure-store中
if (Platform.OS === 'web') {
localStorage.setItem('user', JSON.stringify(newUser));
localStorage.setItem('token', newJwt);
} else {
SecureStore.setItemAsync('user', JSON.stringify(newUser));
SecureStore.setItemAsync('token', newJwt);
}
// 触发事件通知
eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, newUser);
};
const logout = () => {
// 清除 Redux store 中的认证信息
dispatch(clearCredentials());
if (Platform.OS === 'web') {
localStorage.setItem('user', "");
localStorage.setItem('token', "");
} else {
SecureStore.setItemAsync('user', "");
SecureStore.setItemAsync('token', "");
}
// 触发事件通知
eventEmitter.emit(EVENT_TYPES.USER_INFO_UPDATED, null);
};
// 判断是否是游客身份
const isGuester = async () => {
// 调用接口判断是否是游客
try {
await fetchApi(`/iam/identity-check`, {
method: 'POST',
}, false);
user?.email === ""
return false
} catch (error) {
return true;
}
}
// 判断是否是正式用户 手机号注册和email注册都为正式用户
const isFormalUser = (userMessage: User | null) => {
if (userMessage?.account) {
if (userMessage?.account?.includes("@")) {
return true
} else if (/^1[3-9]\d{9}$/.test(userMessage?.account)) {
return true
} else {
return false
}
}
// 没有用户信息
return false
}
return (
<AuthContext.Provider value={{ user, login, logout, jwt, isGuester, isFormalUser }}>
{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;
};