| |
| |
| |
| |
|
|
| import { apiClient } from './client' |
| import type { |
| LoginRequest, |
| RegisterRequest, |
| AuthResponse, |
| CurrentUserResponse, |
| SendVerifyCodeRequest, |
| SendVerifyCodeResponse, |
| PublicSettings, |
| TotpLoginResponse, |
| TotpLogin2FARequest |
| } from '@/types' |
|
|
| |
| |
| |
| export type LoginResponse = AuthResponse | TotpLoginResponse |
|
|
| |
| |
| |
| export function isTotp2FARequired(response: LoginResponse): response is TotpLoginResponse { |
| return 'requires_2fa' in response && response.requires_2fa === true |
| } |
|
|
| |
| |
| |
| export function setAuthToken(token: string): void { |
| localStorage.setItem('auth_token', token) |
| } |
|
|
| |
| |
| |
| export function setRefreshToken(token: string): void { |
| localStorage.setItem('refresh_token', token) |
| } |
|
|
| |
| |
| |
| |
| export function setTokenExpiresAt(expiresIn: number): void { |
| const expiresAt = Date.now() + expiresIn * 1000 |
| localStorage.setItem('token_expires_at', String(expiresAt)) |
| } |
|
|
| |
| |
| |
| export function getAuthToken(): string | null { |
| return localStorage.getItem('auth_token') |
| } |
|
|
| |
| |
| |
| export function getRefreshToken(): string | null { |
| return localStorage.getItem('refresh_token') |
| } |
|
|
| |
| |
| |
| export function getTokenExpiresAt(): number | null { |
| const value = localStorage.getItem('token_expires_at') |
| return value ? parseInt(value, 10) : null |
| } |
|
|
| |
| |
| |
| export function clearAuthToken(): void { |
| localStorage.removeItem('auth_token') |
| localStorage.removeItem('refresh_token') |
| localStorage.removeItem('auth_user') |
| localStorage.removeItem('token_expires_at') |
| } |
|
|
| |
| |
| |
| |
| |
| export async function login(credentials: LoginRequest): Promise<LoginResponse> { |
| const { data } = await apiClient.post<LoginResponse>('/auth/login', credentials) |
|
|
| |
| if (!isTotp2FARequired(data)) { |
| setAuthToken(data.access_token) |
| if (data.refresh_token) { |
| setRefreshToken(data.refresh_token) |
| } |
| if (data.expires_in) { |
| setTokenExpiresAt(data.expires_in) |
| } |
| localStorage.setItem('auth_user', JSON.stringify(data.user)) |
| } |
|
|
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function login2FA(request: TotpLogin2FARequest): Promise<AuthResponse> { |
| const { data } = await apiClient.post<AuthResponse>('/auth/login/2fa', request) |
|
|
| |
| setAuthToken(data.access_token) |
| if (data.refresh_token) { |
| setRefreshToken(data.refresh_token) |
| } |
| if (data.expires_in) { |
| setTokenExpiresAt(data.expires_in) |
| } |
| localStorage.setItem('auth_user', JSON.stringify(data.user)) |
|
|
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function register(userData: RegisterRequest): Promise<AuthResponse> { |
| const { data } = await apiClient.post<AuthResponse>('/auth/register', userData) |
|
|
| |
| setAuthToken(data.access_token) |
| if (data.refresh_token) { |
| setRefreshToken(data.refresh_token) |
| } |
| if (data.expires_in) { |
| setTokenExpiresAt(data.expires_in) |
| } |
| localStorage.setItem('auth_user', JSON.stringify(data.user)) |
|
|
| return data |
| } |
|
|
| |
| |
| |
| |
| export async function getCurrentUser() { |
| return apiClient.get<CurrentUserResponse>('/auth/me') |
| } |
|
|
| |
| |
| |
| |
| |
| export async function logout(): Promise<void> { |
| const refreshToken = getRefreshToken() |
|
|
| |
| if (refreshToken) { |
| try { |
| await apiClient.post('/auth/logout', { refresh_token: refreshToken }) |
| } catch { |
| |
| } |
| } |
|
|
| clearAuthToken() |
| } |
|
|
| |
| |
| |
| export interface RefreshTokenResponse { |
| access_token: string |
| refresh_token: string |
| expires_in: number |
| token_type: string |
| } |
|
|
| |
| |
| |
| |
| export async function refreshToken(): Promise<RefreshTokenResponse> { |
| const currentRefreshToken = getRefreshToken() |
| if (!currentRefreshToken) { |
| throw new Error('No refresh token available') |
| } |
|
|
| const { data } = await apiClient.post<RefreshTokenResponse>('/auth/refresh', { |
| refresh_token: currentRefreshToken |
| }) |
|
|
| |
| setAuthToken(data.access_token) |
| setRefreshToken(data.refresh_token) |
| setTokenExpiresAt(data.expires_in) |
|
|
| return data |
| } |
|
|
| |
| |
| |
| |
| export async function revokeAllSessions(): Promise<{ message: string }> { |
| const { data } = await apiClient.post<{ message: string }>('/auth/revoke-all-sessions') |
| return data |
| } |
|
|
| |
| |
| |
| |
| export function isAuthenticated(): boolean { |
| return getAuthToken() !== null |
| } |
|
|
| |
| |
| |
| |
| export async function getPublicSettings(): Promise<PublicSettings> { |
| const { data } = await apiClient.get<PublicSettings>('/settings/public') |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function sendVerifyCode( |
| request: SendVerifyCodeRequest |
| ): Promise<SendVerifyCodeResponse> { |
| const { data } = await apiClient.post<SendVerifyCodeResponse>('/auth/send-verify-code', request) |
| return data |
| } |
|
|
| |
| |
| |
| export interface ValidatePromoCodeResponse { |
| valid: boolean |
| bonus_amount?: number |
| error_code?: string |
| message?: string |
| } |
|
|
| |
| |
| |
| |
| |
| export async function validatePromoCode(code: string): Promise<ValidatePromoCodeResponse> { |
| const { data } = await apiClient.post<ValidatePromoCodeResponse>('/auth/validate-promo-code', { code }) |
| return data |
| } |
|
|
| |
| |
| |
| export interface ValidateInvitationCodeResponse { |
| valid: boolean |
| error_code?: string |
| } |
|
|
| |
| |
| |
| |
| |
| export async function validateInvitationCode(code: string): Promise<ValidateInvitationCodeResponse> { |
| const { data } = await apiClient.post<ValidateInvitationCodeResponse>('/auth/validate-invitation-code', { code }) |
| return data |
| } |
|
|
| |
| |
| |
| export interface ForgotPasswordRequest { |
| email: string |
| turnstile_token?: string |
| } |
|
|
| |
| |
| |
| export interface ForgotPasswordResponse { |
| message: string |
| } |
|
|
| |
| |
| |
| |
| |
| export async function forgotPassword(request: ForgotPasswordRequest): Promise<ForgotPasswordResponse> { |
| const { data } = await apiClient.post<ForgotPasswordResponse>('/auth/forgot-password', request) |
| return data |
| } |
|
|
| |
| |
| |
| export interface ResetPasswordRequest { |
| email: string |
| token: string |
| new_password: string |
| } |
|
|
| |
| |
| |
| export interface ResetPasswordResponse { |
| message: string |
| } |
|
|
| |
| |
| |
| |
| |
| export async function resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse> { |
| const { data } = await apiClient.post<ResetPasswordResponse>('/auth/reset-password', request) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function completeLinuxDoOAuthRegistration( |
| pendingOAuthToken: string, |
| invitationCode: string |
| ): Promise<{ access_token: string; refresh_token: string; expires_in: number; token_type: string }> { |
| const { data } = await apiClient.post<{ |
| access_token: string |
| refresh_token: string |
| expires_in: number |
| token_type: string |
| }>('/auth/oauth/linuxdo/complete-registration', { |
| pending_oauth_token: pendingOAuthToken, |
| invitation_code: invitationCode |
| }) |
| return data |
| } |
|
|
| export const authAPI = { |
| login, |
| login2FA, |
| isTotp2FARequired, |
| register, |
| getCurrentUser, |
| logout, |
| isAuthenticated, |
| setAuthToken, |
| setRefreshToken, |
| setTokenExpiresAt, |
| getAuthToken, |
| getRefreshToken, |
| getTokenExpiresAt, |
| clearAuthToken, |
| getPublicSettings, |
| sendVerifyCode, |
| validatePromoCode, |
| validateInvitationCode, |
| forgotPassword, |
| resetPassword, |
| refreshToken, |
| revokeAllSessions, |
| completeLinuxDoOAuthRegistration |
| } |
|
|
| export default authAPI |
|
|