mxivideo/src/services/pythonCliAuth.ts

317 lines
7.9 KiB
TypeScript

/**
* 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<UserProfile> {
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<UserProfile> {
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<boolean> {
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<void> {
this.token = null;
this.user = null;
this.clearStoredAuth();
}
/**
* 获取当前用户信息
*/
async getCurrentUser(): Promise<UserProfile | null> {
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<Pick<UserProfile, 'displayName' | 'avatarUrl'>>): Promise<void> {
// 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;