Первоначальная версия VidConf

This commit is contained in:
2026-07-23 01:04:01 +03:00
commit 896455381a
335 changed files with 61527 additions and 0 deletions

81
frontend/src/api/auth.ts Normal file
View File

@@ -0,0 +1,81 @@
/**
* API-функции аутентификации.
*/
import { apiRequest } from '@/api/client'
export interface RegisterPayload {
email: string
name_user: string
password: string
/** Выбранная команда — только если выбор команды включён в настройках инстанса. */
team_id?: string | null
}
/** Команда, доступная для выбора на экране регистрации. */
export interface RegistrationTeamOption {
id: string
name: string
}
/** Параметры экрана регистрации — зависят от настройки инстанса `registration_team_choice`. */
export interface RegistrationOptions {
team_choice_enabled: boolean
teams: RegistrationTeamOption[]
/** Эталонный домен почты при включённой верификации, иначе `null`. */
email_domain: string | null
}
export interface CurrentUser {
id: string
email: string
name_user: string
role: string
/** URL загруженного аватара, `null` — показывается заглушка с инициалами (см. `Avatar`). */
avatar_url: string | null
team_id: string | null
team_name: string | null
}
export interface TokenResponse {
access_token: string
token_type: string
}
/** Регистрация нового пользователя. 409 — если email уже занят. */
export async function register(payload: RegisterPayload): Promise<void> {
await apiRequest('/auth/register', { method: 'POST', body: payload, skipAuthRefresh: true })
}
/**
* Параметры экрана регистрации — публичный эндпоинт, доступен без авторизации.
* Если выбор команды отключён в настройках инстанса, `teams` пуст.
*/
export async function getRegistrationOptions(): Promise<RegistrationOptions> {
return apiRequest<RegistrationOptions>('/auth/registration-options', { skipAuthRefresh: true })
}
/** Подтверждение почты по токену из письма. 400 — если ссылка просрочена/недействительна. */
export async function verifyEmail(token: string): Promise<void> {
await apiRequest('/auth/verify-email', { method: 'POST', body: { token }, skipAuthRefresh: true })
}
/**
* Вход по логину/паролю. Backend ждёт OAuth2-form-data (username=email).
* Refresh-токен приходит httpOnly cookie — тело ответа содержит только access.
*/
export async function login(email: string, password: string): Promise<TokenResponse> {
const form = new URLSearchParams()
form.set('username', email)
form.set('password', password)
return apiRequest<TokenResponse>('/auth/token', { method: 'POST', body: form, skipAuthRefresh: true })
}
/** Явный выход — инвалидирует refresh-сессию на backend. */
export async function logout(): Promise<void> {
await apiRequest('/auth/logout', { method: 'POST' })
}
/** Текущий пользователь по access-токену. */
export async function getMe(): Promise<CurrentUser> {
return apiRequest<CurrentUser>('/users/me')
}