mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
63cd906cfc
- Merge all files inside openflare-server to the repository root directory. - Relocate agent, relay, and flared subprojects from internal/ to internal/apps/. - Combine docker-compose files and update build context paths to root. - Update GitHub workflows and Dockerfiles to refer to new directories and package names. - Rewrite Go package imports across all files. - Resolve database renew test race condition and clean up docs.
136 lines
4.2 KiB
TypeScript
136 lines
4.2 KiB
TypeScript
import type {InternalAxiosRequestConfig} from 'axios';
|
||
import {BaseService} from '@/lib/services/core';
|
||
import type {
|
||
AuthSource,
|
||
ChangePasswordRequest,
|
||
ExternalAccountBinding,
|
||
LoginRequest,
|
||
OAuthAuthorizeResponse,
|
||
OAuthCallbackRequest,
|
||
OAuthCallbackResult,
|
||
OAuthLoginUrlResponse,
|
||
RegisterRequest,
|
||
UpdateProfileRequest,
|
||
User,
|
||
} from './types';
|
||
|
||
/**
|
||
* 认证服务
|
||
* 处理 OAuth 认证、用户信息获取、登出等
|
||
*/
|
||
export class AuthService extends BaseService {
|
||
protected static readonly basePath = '/api/v1';
|
||
|
||
/**
|
||
* 获取 OAuth 登录 URL
|
||
* @returns OAuth 授权 URL
|
||
* @throws {ApiErrorBase} 当获取失败时
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const url = await AuthService.getLoginUrl();
|
||
* window.location.href = url; // 重定向到 OAuth 授权页面
|
||
* ```
|
||
*/
|
||
static async getLoginUrl(): Promise<OAuthLoginUrlResponse> {
|
||
return this.get<OAuthLoginUrlResponse>('/oauth/login');
|
||
}
|
||
|
||
static async getAuthSources(): Promise<AuthSource[]> {
|
||
return this.get<AuthSource[]>('/oauth/sources');
|
||
}
|
||
|
||
static async getAuthorizeUrl(source: string, purpose: 'login' | 'bind' = 'login'): Promise<OAuthAuthorizeResponse> {
|
||
return this.get<OAuthAuthorizeResponse>(`/oauth/${encodeURIComponent(source)}/authorize?purpose=${purpose}`);
|
||
}
|
||
|
||
/**
|
||
* 处理 OAuth 回调
|
||
* @param request - OAuth 回调参数(state 和 code)
|
||
* @throws {ApiErrorBase} 当回调处理失败时
|
||
* @throws {ValidationError} 当 state 无效时
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* // 在回调页面获取 URL 参数
|
||
* const params = new URLSearchParams(window.location.search);
|
||
* const state = params.get('state');
|
||
* const code = params.get('code');
|
||
*
|
||
* if (state && code) {
|
||
* await AuthService.handleCallback({ state, code });
|
||
* // 登录成功,跳转到首页
|
||
* router.push('/home');
|
||
* }
|
||
* ```
|
||
*/
|
||
static async handleCallback(request: OAuthCallbackRequest): Promise<OAuthCallbackResult> {
|
||
return this.post<OAuthCallbackResult>('/oauth/callback', request);
|
||
}
|
||
|
||
/**
|
||
* 获取当前登录用户信息
|
||
* @returns 用户信息
|
||
* @throws {UnauthorizedError} 当未登录时
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* try {
|
||
* const user = await AuthService.getUserInfo();
|
||
* console.log('当前用户:', user.username);
|
||
* } catch (error) {
|
||
* if (error instanceof UnauthorizedError) {
|
||
* // 跳转到登录页
|
||
* router.push('/login');
|
||
* }
|
||
* }
|
||
* ```
|
||
*/
|
||
static async getUserInfo(): Promise<User> {
|
||
return this.get<User>('/user-info');
|
||
}
|
||
|
||
/**
|
||
* 用户登出
|
||
* @throws {ApiErrorBase} 当登出失败时
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* await AuthService.logout();
|
||
* // 清除本地状态
|
||
* router.push('/login');
|
||
* ```
|
||
*/
|
||
static async logout(): Promise<void> {
|
||
await this.get<void>('/oauth/logout');
|
||
}
|
||
|
||
static async login(request: LoginRequest, headers?: Record<string, string>): Promise<User> {
|
||
return this.post<User>('/user/login', request, headers ? ({ headers } as unknown as InternalAxiosRequestConfig) : undefined);
|
||
}
|
||
|
||
static async register(request: RegisterRequest, headers?: Record<string, string>): Promise<User> {
|
||
return this.post<User>('/user/register', request, headers ? ({ headers } as unknown as InternalAxiosRequestConfig) : undefined);
|
||
}
|
||
|
||
static async sendEmailCode(email: string, scene: 'register' | 'login', headers?: Record<string, string>): Promise<void> {
|
||
return this.post<void>('/user/send-email-code', { email, scene }, headers ? ({ headers } as unknown as InternalAxiosRequestConfig) : undefined);
|
||
}
|
||
|
||
static async changePassword(request: ChangePasswordRequest): Promise<void> {
|
||
return this.post<void>('/user/change-password', request);
|
||
}
|
||
|
||
static async updateProfile(request: UpdateProfileRequest): Promise<User> {
|
||
return this.put<User>('/user/profile', request);
|
||
}
|
||
|
||
static async getExternalAccountBindings(): Promise<ExternalAccountBinding[]> {
|
||
return this.get<ExternalAccountBinding[]>('/oauth/external-accounts');
|
||
}
|
||
|
||
static async deleteExternalAccountBinding(id: string): Promise<void> {
|
||
return this.post<void>(`/oauth/external-accounts/${encodeURIComponent(id)}/delete`);
|
||
}
|
||
}
|