/** * Python CLI 认证服务 * 通过Rust调用Python CLI实现用户认证功能 */ import { invoke } from '@tauri-apps/api/core'; export interface LoginCredentials { email?: string; username?: string; password: string; } export interface RegisterCredentials { email: string; username: string; password: string; displayName?: string; } export interface UserProfile { id: string; username: string; displayName: string; email?: string; avatarUrl?: string; createTime: string; updateTime: string; lastLogin?: string; isActive: boolean; } export interface AuthResponse { success: boolean; message: string; data?: any; output?: string; error?: string; } export interface PythonCliAuthResponse { success: boolean; message: string; data?: { user?: UserProfile; token?: string; expires_at?: string; }; output?: string; error?: string; } class PythonCliAuth { private token: string | null = null; private user: UserProfile | null = null; constructor() { // 从localStorage恢复认证状态 this.loadStoredAuth(); } /** * 用户登录 */ async login(credentials: LoginCredentials): Promise { try { // 确定使用邮箱还是用户名登录 let username_or_email: string; if (credentials.email) { username_or_email = credentials.email; } else if (credentials.username) { username_or_email = credentials.username; } else { throw new Error('Email or username is required'); } const response: PythonCliAuthResponse = await invoke('python_cli_auth_login', { request: { username_or_email: username_or_email, password: credentials.password, json_output: true } }); console.log({ response }) if (!response.success) { throw new Error(response.error || response.message || 'Login failed'); } // 解析输出中的用户信息和token if (response.success && response.output) { // 尝试从输出中解析JSON const jsonMatch = response.output.match(/\{[\s\S]*\}/); if (jsonMatch) { try { const authData = JSON.parse(jsonMatch[0]); if (authData.success && authData.data?.user && authData.data?.token) { this.token = authData.data.token; this.user = { id: authData.data.user.id, username: authData.data.user.username, displayName: authData.data.user.display_name, email: authData.data.user.email, avatarUrl: authData.data.user.avatar_url, createTime: authData.data.user.created_at, updateTime: authData.data.user.updated_at, lastLogin: authData.data.user.last_login, isActive: authData.data.user.is_active }; // 保存到localStorage this.saveAuthToStorage(); return this.user; } } catch (parseError) { console.error('Failed to parse auth response JSON:', parseError); } } } throw new Error(response.error || response.message || 'Login failed'); } catch (error) { console.error('Login failed:', error); throw error; } } /** * 用户注册 */ async register(credentials: RegisterCredentials): Promise { try { const response: PythonCliAuthResponse = await invoke('python_cli_auth_register', { request: { username: credentials.username, email: credentials.email, password: credentials.password, display_name: credentials.displayName, } }); console.log({ response }) if (!response.success) { throw new Error(response.error || response.message || 'Registration failed'); } // 解析输出中的用户信息和token if (response.success && response.output) { // 尝试从输出中解析JSON const jsonMatch = response.output.match(/\{[\s\S]*\}/); if (jsonMatch) { try { const authData = JSON.parse(jsonMatch[0]); if (authData.success && authData.data?.user && authData.data?.token) { this.token = authData.data.token; this.user = { id: authData.data.user.id, username: authData.data.user.username, displayName: authData.data.user.display_name, email: authData.data.user.email, avatarUrl: authData.data.user.avatar_url, createTime: authData.data.user.created_at, updateTime: authData.data.user.updated_at, lastLogin: authData.data.user.last_login, isActive: authData.data.user.is_active }; // 保存到localStorage this.saveAuthToStorage(); return this.user; } } catch (parseError) { console.error('Failed to parse auth response JSON:', parseError); } } } throw new Error(response.error || response.message || 'Registration failed'); } catch (error) { console.error('Registration failed:', error); throw error; } } /** * 验证Token */ async verifyToken(token?: string): Promise { try { const tokenToVerify = token || this.token; if (!tokenToVerify) { return false; } const response: PythonCliAuthResponse = await invoke('python_cli_auth_verify', { request: { token: tokenToVerify, verbose: true } }); return response.success; } catch (error) { console.error('Token verification failed:', error); return false; } } /** * 用户登出 */ async logout(): Promise { this.token = null; this.user = null; this.clearStoredAuth(); } /** * 获取当前用户信息 */ async getCurrentUser(): Promise { if (!this.token) { return null; } try { // 验证当前token是否有效 const isValid = await this.verifyToken(); if (!isValid) { this.logout(); return null; } return this.user; } catch (error) { console.error('Failed to get current user:', error); this.logout(); return null; } } /** * 更新用户资料 */ async updateProfile(updates: Partial>): Promise { // TODO: 实现用户资料更新 console.log('Update profile:', updates); throw new Error('Profile update not implemented yet'); } /** * 检查是否已认证 */ isAuthenticated(): boolean { return this.token !== null && this.user !== null; } /** * 获取当前token */ getToken(): string | null { return this.token; } /** * 获取当前用户 */ getUser(): UserProfile | null { return this.user; } /** * 保存认证信息到localStorage */ private saveAuthToStorage(): void { if (this.token && this.user) { localStorage.setItem('auth_token', this.token); localStorage.setItem('auth_user', JSON.stringify(this.user)); } } /** * 从localStorage加载认证信息 */ private loadStoredAuth(): void { try { const token = localStorage.getItem('auth_token'); const userStr = localStorage.getItem('auth_user'); if (token && userStr) { this.token = token; this.user = JSON.parse(userStr); } } catch (error) { console.error('Failed to load stored auth:', error); this.clearStoredAuth(); } } /** * 清除存储的认证信息 */ private clearStoredAuth(): void { localStorage.removeItem('auth_token'); localStorage.removeItem('auth_user'); } } // 创建全局实例 export const pythonCliAuth = new PythonCliAuth(); // 导出默认实例 export default pythonCliAuth;