Files
vf_react/src/views/AgentChat/neuratalk/lib/auth.ts
2025-11-22 10:01:04 +08:00

128 lines
3.7 KiB
TypeScript

// lib/auth.ts - 简化版认证工具
// 用于在 Next.js 中获取主应用的登录信息
export interface User {
id: string;
username: string;
email: string;
subscription_tier: string;
avatar?: string;
}
export interface AuthInfo {
isAuthenticated: boolean;
user?: User;
canAccessChat?: boolean;
message?: string;
}
/**
* 客户端检查认证状态
* 直接调用 Flask 后端的 session 接口
*/
export async function checkAuth(): Promise<AuthInfo> {
try {
// 根据访问方式决定 API URL
const isProduction = typeof window !== 'undefined' && window.location.hostname === 'valuefrontier.cn';
const apiUrl = isProduction
? 'https://valuefrontier.cn' // 生产环境通过域名访问
: (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5001'); // 开发环境
console.log('Auth check - API URL:', apiUrl, 'isProduction:', isProduction);
// 调用主应用的 session 检查接口
const response = await fetch(`${apiUrl}/api/auth/session`, {
method: 'GET',
credentials: 'include', // 重要:携带 Cookie
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
// 对于同域请求,不需要额外的 CORS 配置
});
if (!response.ok) {
return { isAuthenticated: false };
}
const data = await response.json();
// 检查是否登录
if (!data.isAuthenticated || !data.user) {
return {
isAuthenticated: false,
message: '请先登录'
};
}
// 检查订阅权限 - 注意:后端返回的是 subscription_type 而不是 subscription_tier
const userType = data.user.subscription_type?.toLowerCase() || '';
const userTier = data.user.subscription_tier?.toLowerCase() || '';
const subscriptionLevel = userType || userTier; // 兼容两个字段
// 检查是否为付费用户
const canAccessChat =
['max', 'premium', 'pro', 'enterprise', 'vip', 'plus'].includes(subscriptionLevel) ||
data.user.is_subscription_active === true ||
data.user.subscription_status === 'active';
console.log('User subscription:', {
type: data.user.subscription_type,
tier: data.user.subscription_tier,
active: data.user.is_subscription_active,
status: data.user.subscription_status,
canAccess: canAccessChat
});
return {
isAuthenticated: true,
user: data.user,
canAccessChat,
message: canAccessChat ? undefined : '需要订阅才能使用 AI 助手功能'
};
} catch (error) {
console.error('Auth check failed:', error);
return {
isAuthenticated: false,
message: '认证服务暂时不可用'
};
}
}
/**
* 调用 MCP API
* 自动携带认证信息
*/
export async function callMCPApi(endpoint: string, options: RequestInit = {}) {
const url = `${process.env.NEXT_PUBLIC_API_URL}${endpoint}`;
const response = await fetch(url, {
...options,
credentials: 'include', // 携带 Cookie
headers: {
'Content-Type': 'application/json',
...options.headers,
},
});
if (response.status === 401) {
// 未登录,跳转到主应用登录页
window.location.href = `${process.env.NEXT_PUBLIC_MAIN_APP_URL}/auth/sign-in?redirect=/chat`;
throw new Error('Unauthorized');
}
if (response.status === 403) {
// 无权限,跳转到订阅页
window.location.href = `${process.env.NEXT_PUBLIC_MAIN_APP_URL}/subscription?feature=ai-chat`;
throw new Error('Subscription required');
}
return response;
}
/**
* 登出(跳转到主应用的登出接口)
*/
export function logout() {
window.location.href = `${process.env.NEXT_PUBLIC_MAIN_APP_URL}/api/auth/logout?redirect=/`;
}