video-flow-b/lib/auth.ts

253 lines
5.7 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 { BASE_URL } from "@/api/constants";
// API配置
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || '';
// Token存储键
const TOKEN_KEY = 'X-EASE-ADMIN-TOKEN';
const USER_KEY = 'currentUser';
/**
* 登录用户
*/
export const loginUser = async (email: string, password: string) => {
try {
const response = await fetch(`${API_BASE_URL}/admin/login/signIn`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
userName: email,
password: password,
}),
});
const data = await response.json();
if (data.code === '200' && data.status === 200) {
// 保存token到本地存储
setToken(data.body.token);
// 保存用户信息
const user = {
id: data.body.userId,
name: data.body.userName,
email: email,
token: data.body.token,
};
setUser(user);
return user;
} else {
throw new Error(data.msg || '登录失败');
}
} catch (error) {
console.error('Login failed:', error);
throw error;
}
};
/**
* 鉴权检查
*/
export const checkAuth = async (): Promise<boolean> => {
const token = getToken();
if (!token) {
return false;
}
try {
const response = await fetch(`${API_BASE_URL}/admin/login/auth`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-EASE-ADMIN-TOKEN': token,
},
});
const data = await response.json();
if (data.code === '401' || data.status === 401) {
// Token无效清除本地存储
clearAuthData();
return false;
}
return data.code === '200' && data.status === 200;
} catch (error) {
console.error('Auth check failed:', error);
return false;
}
};
/**
* 获取token
*/
export const getToken = (): string | null => {
if (typeof window === 'undefined') return null;
return localStorage.getItem(TOKEN_KEY);
};
/**
* 设置token
*/
export const setToken = (token: string) => {
if (typeof window === 'undefined') return;
localStorage.setItem(TOKEN_KEY, token);
};
/**
* 获取当前用户
*/
export const getCurrentUser = () => {
if (typeof window === 'undefined') return null;
const userJson = localStorage.getItem(USER_KEY);
if (!userJson) return null;
try {
return JSON.parse(userJson);
} catch (error) {
console.error('Failed to parse user data from storage', error);
return null;
}
};
/**
* 设置用户信息
*/
export const setUser = (user: any) => {
if (typeof window === 'undefined') return;
localStorage.setItem(USER_KEY, JSON.stringify(user));
};
/**
* 清除认证数据
*/
export const clearAuthData = () => {
if (typeof window === 'undefined') return;
localStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(USER_KEY);
};
/**
* 用户登出
*/
export const logoutUser = () => {
clearAuthData();
window.location.href = '/login';
};
/**
* 检查是否已登录
*/
export const isAuthenticated = (): boolean => {
return !!getToken();
};
/**
* 创建带有token的请求头
*/
export const getAuthHeaders = () => {
const token = getToken();
return {
'Accept': 'application/json',
'Content-Type': 'application/json',
...(token && { 'X-EASE-ADMIN-TOKEN': token }),
};
};
/**
* 带有自动token处理的fetch封装
*/
export const authFetch = async (url: string, options: RequestInit = {}) => {
const token = getToken();
if (!token) {
throw new Error('No token available');
}
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-EASE-ADMIN-TOKEN': token,
...options.headers,
};
const response = await fetch(url, {
...options,
headers,
});
// 检查是否token过期
if (response.status === 401) {
const data = await response.json();
if (data.code === '401') {
// Token过期清除本地数据并重定向到登录页
clearAuthData();
window.location.href = '/login';
throw new Error('Token expired');
}
}
return response;
};
// Google OAuth相关函数保持不变
const GOOGLE_CLIENT_ID = '1016208801816-qtvcvki2jobmcin1g4e7u4sotr0p8g3u.apps.googleusercontent.com';
const GOOGLE_REDIRECT_URI = typeof window !== 'undefined'
? BASE_URL+'/users/oauth/callback'
: '';
/**
* Initiates Google OAuth authentication flow
*/
export const signInWithGoogle = () => {
const state = generateOAuthState();
const params = new URLSearchParams({
client_id: GOOGLE_CLIENT_ID,
redirect_uri: GOOGLE_REDIRECT_URI,
response_type: 'code',
scope: 'email profile',
prompt: 'select_account',
state: state,
});
// Redirect to Google's OAuth endpoint
window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
};
/**
* Generates and stores a state parameter for OAuth to prevent CSRF attacks
*/
export const generateOAuthState = () => {
if (typeof window === 'undefined') return '';
// Generate a random string for state
const state = Math.random().toString(36).substring(2, 15);
// Store the state in session storage to validate later
sessionStorage.setItem('oauthState', state);
return state;
};
/**
* Validates the state parameter returned from OAuth to prevent CSRF attacks
*/
export const validateOAuthState = (state: string): boolean => {
if (typeof window === 'undefined') return false;
const storedState = sessionStorage.getItem('oauthState');
// Clean up the stored state regardless of validity
sessionStorage.removeItem('oauthState');
// Validate that the returned state matches what we stored
return state === storedState;
};