This commit is contained in:
ryan
2026-06-07 19:47:24 +08:00
parent 48d414e197
commit 360a26f109
60 changed files with 10063 additions and 637 deletions
+38 -35
View File
@@ -1,7 +1,13 @@
import { BaseService } from '../core/base.service';
import {BaseService} from '../core/base.service';
import type {
OAuthLoginUrlResponse,
AuthSource,
ExternalAccountBinding,
LoginRequest,
OAuthAuthorizeResponse,
OAuthCallbackRequest,
OAuthCallbackResult,
OAuthLoginUrlResponse,
RegisterRequest,
User,
} from './types';
@@ -10,13 +16,13 @@ import type {
* 处理 OAuth 认证、用户信息获取、登出等
*/
export class AuthService extends BaseService {
protected static readonly basePath = '/api/v1/oauth';
protected static readonly basePath = '/api/v1';
/**
* 获取 OAuth 登录 URL
* @returns OAuth 授权 URL
* @throws {ApiErrorBase} 当获取失败时
*
*
* @example
* ```typescript
* const url = await AuthService.getLoginUrl();
@@ -24,7 +30,15 @@ export class AuthService extends BaseService {
* ```
*/
static async getLoginUrl(): Promise<OAuthLoginUrlResponse> {
return this.get<OAuthLoginUrlResponse>('/login');
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}`);
}
/**
@@ -32,14 +46,14 @@ export class AuthService extends BaseService {
* @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 });
* // 登录成功,跳转到首页
@@ -47,15 +61,15 @@ export class AuthService extends BaseService {
* }
* ```
*/
static async handleCallback(request: OAuthCallbackRequest): Promise<void> {
return this.post<void>('/callback', request);
static async handleCallback(request: OAuthCallbackRequest): Promise<OAuthCallbackResult> {
return this.post<OAuthCallbackResult>('/oauth/callback', request);
}
/**
* 获取当前登录用户信息
* @returns 用户信息
* @throws {UnauthorizedError} 当未登录时
*
*
* @example
* ```typescript
* try {
@@ -76,7 +90,7 @@ export class AuthService extends BaseService {
/**
* 用户登出
* @throws {ApiErrorBase} 当登出失败时
*
*
* @example
* ```typescript
* await AuthService.logout();
@@ -85,33 +99,22 @@ export class AuthService extends BaseService {
* ```
*/
static async logout(): Promise<void> {
await this.get<void>('/logout');
await this.get<void>('/oauth/logout');
}
/**
* 发起登录流程
* 直接获取登录 URL 并重定向
*
* @example
* ```typescript
* // 在登录按钮点击时调用
* await AuthService.initiateLogin();
* ```
*/
static async initiateLogin(): Promise<void> {
if (typeof window !== 'undefined') {
const params = new URLSearchParams(window.location.search);
const callbackUrl = params.get('callbackUrl');
static async login(request: LoginRequest): Promise<User> {
return this.post<User>('/user/login', request);
}
if (callbackUrl) {
sessionStorage.setItem('redirect_after_login', callbackUrl);
}
}
static async register(request: RegisterRequest): Promise<User> {
return this.post<User>('/user/register', request);
}
const url = await this.getLoginUrl();
if (typeof window !== 'undefined' && url) {
window.location.href = url;
}
static async getExternalAccountBindings(): Promise<ExternalAccountBinding[]> {
return this.get<ExternalAccountBinding[]>('/oauth/external-accounts');
}
static async deleteExternalAccountBinding(id: string): Promise<void> {
return this.delete<void>(`/oauth/external-accounts/${encodeURIComponent(id)}/delete`);
}
}
+6 -1
View File
@@ -31,5 +31,10 @@ export type {
User,
OAuthLoginUrlResponse,
OAuthCallbackRequest,
LoginRequest,
RegisterRequest,
OAuthAuthorizeResponse,
OAuthCallbackResult,
AuthSource,
ExternalAccountBinding,
} from './types';
+41
View File
@@ -81,3 +81,44 @@ export interface OAuthCallbackRequest {
/** 授权码 */
code: string;
}
export interface LoginRequest {
username: string;
password: string;
}
export interface RegisterRequest {
username: string;
password: string;
nickname?: string;
}
export interface OAuthAuthorizeResponse {
authorize_url: string;
}
export interface OAuthCallbackResult {
status: 'logged_in' | 'bound';
user?: User;
}
export interface AuthSource {
id: string;
name: string;
type: 'oidc';
display_name: string;
is_active: boolean;
icon_url: string;
client_secret_configured: boolean;
}
export interface ExternalAccountBinding {
id: string;
auth_source_id: string;
auth_source_name: string;
auth_source_type: string;
auth_source_label: string;
external_username: string;
email: string;
created_at: string;
}