Compare commits

..

2 commits

Author SHA1 Message Date
senke
aa6ccbefed refactor(web): migrate queue.ts + finish authService → orval
Some checks failed
Veza CI / Rust (Stream Server) (push) Failing after 2s
Frontend CI / test (push) Failing after 2m1s
Security Scan / Secret Scanning (gitleaks) (push) Successful in 1m1s
Veza CI / Backend (Go) (push) Failing after 15m48s
E2E Playwright / e2e (full) (push) Failing after 11m33s
Veza CI / Frontend (Web) (push) Failing after 28m3s
Veza CI / Notify on failure (push) Successful in 5s
Closes the v1.0.8 deferrals on the frontend side now that the backend
swaggo annotations + orval regen landed in the previous commit.

queue.ts (services/api/queue.ts, 11 functions):
  - getQueue / updateQueue / addToQueue / removeFromQueue / clearQueue
    → orval (getQueue / putQueue / postQueueItems /
    deleteQueueItemsId / deleteQueue).
  - createQueueSession / getQueueSession / deleteQueueSession /
    addToSessionQueue / removeFromSessionQueue → orval (postQueueSession
    / getQueueSessionToken / deleteQueueSessionToken /
    postQueueSessionTokenItems / deleteQueueSessionTokenItemsId).

  Public surface (queueApi.{...} object) preserved verbatim — no
  changes to the two consumers (useQueueSync.ts, PlayerQueue.tsx).
  An unwrapPayload<T>() helper strips the APIResponse {data: ...}
  envelope, mirroring the B4 / B5 / B6 patterns. mapQueueItemToTrack
  conversion logic kept identical.

authService.ts (5/9 deferred functions migrated, total 9/9 now):
  - register      → postAuthRegister + rename `password_confirm` →
                    `password_confirmation` (backend DTO field, see
                    register_request.go:8). Frontend RegisterFormData
                    keeps its existing field name; the rename happens
                    at the wire boundary.
  - refreshToken  → postAuthRefresh + rename `refreshToken` →
                    `refresh_token`.
  - requestPasswordReset → postAuthPasswordResetRequest. Wire shape
                    `{email}` matches the frontend ForgotPasswordFormData
                    1:1.
  - resetPassword → postAuthPasswordReset + rename `password` →
                    `new_password` (backend DTO ResetPasswordRequest).
                    `confirmPassword` from the form is dropped — the
                    backend only validates the new password against
                    the strength policy; the equality check is
                    client-side responsibility (the form does it).
  - verifyEmail   → postAuthVerifyEmail. Verb shift GET → POST to
                    match the backend route registration
                    (routes_auth.go:107) and the swaggo annotation on
                    auth.go:VerifyEmail. Token still passed as `?token=`
                    query param.

  The wire-shape renames pre-existed as drift between the frontend
  serializer and the Go DTO field tags; the backend likely tolerated
  some via lenient unmarshaling or the affected paths were rarely
  exercised end-to-end before E2E CI lands. Migration to orval forces
  the correct shape because the typed body is the source of truth.

  authService.ts docblock rewritten to inventory the wire-shape
  mappings instead of the prior "deferred" warning. Callers
  (LoginPage / RegisterPage / ResetPasswordPage / etc.) untouched —
  service signatures unchanged.

authService.test.ts:
  - orval module mocks added for postAuthRegister / postAuthRefresh /
    postAuthPasswordResetRequest / postAuthPasswordReset /
    postAuthVerifyEmail (delegate to apiClient mock, same pattern as
    the 4 already migrated in v1.0.8 B6).
  - Wire-shape assertions updated for register
    (`password_confirmation`), refreshToken (`refresh_token`),
    resetPassword (`new_password`), verifyEmail (POST instead of GET).
    Comments cite the backend DTO line where the field name lives.

Tests: 17/17 in authService.test.ts green. 708/709 across
features/auth + features/player + services/__tests__ (1 skipped is
the long-standing ResetPasswordPage flake unrelated to this work).
npm run typecheck clean.

Bisectable: revert this commit → queue / auth functions return to
raw apiClient pattern (with the pre-existing wire drift). Combined
with the previous commit (backend annotations) gives a clean two-step
migration narrative.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 00:56:44 +02:00
senke
0e72172291 feat(openapi): annotate queue + password-reset handlers + regen
Closes the two annotation gaps that blocked finishing the orval
migration in v1.0.8 :

  - queue_handler.go (5 routes — GetQueue, UpdateQueue, AddQueueItem,
    RemoveQueueItem, ClearQueue) — under @Tags Queue with @Security
    BearerAuth, @Param body/path, @Success/@Failure on the standard
    APIResponse envelope.
  - queue_session_handler.go (5 routes — CreateSession, GetSession,
    DeleteSession, AddToSession, RemoveFromSession). GetSession is
    public (no @Security tag) since the share-token URL is meant for
    join-via-link from outside the auth wall.
  - password_reset_handler.go (2 routes — RequestPasswordReset and
    ResetPassword factory functions). Both are public (no @Security)
    since they're the entry-points for users who can't log in. The
    request-side annotation documents the intentional generic 200
    response (anti-enumeration: same body whether the email exists or
    not).

After regen :
  - openapi.yaml gains 7 queue paths (/queue, /queue/items[/{id}],
    /queue/session[/{token}[/items[/{id}]]]) and 2 password paths
    (/auth/password/reset, /auth/password/reset-request). +568 LOC.
  - docs/{docs.go,swagger.json,swagger.yaml} updated identically by
    swag init.
  - apps/web/src/services/generated/queue/queue.ts created (10
    HTTP funcs + matching React Query hooks). model/ index extended
    with the queue + password-reset request/response shapes.

Validates with `swag init` (Swagger 2.0). go build ./... clean. No
runtime behaviour change — annotations are pure metadata read by the
spec generator. The orval regen IS the wiring point for the
follow-up frontend commit (queue.ts migration + authService finish).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 00:55:26 +02:00
52 changed files with 5079 additions and 80 deletions

View file

@ -33,11 +33,12 @@ const mockedApiClient = apiClient as {
get: ReturnType<typeof vi.fn>;
};
// v1.0.8 B6 — login / logout / resendVerificationEmail /
// checkUsernameAvailability migrated to orval. Tests still mock
// `apiClient.post/get` for legacy ergonomics; the orval module's
// functions are stubbed to delegate back to those mocks so existing
// `toHaveBeenCalledWith('/auth/...', ...)` assertions keep working.
// v1.0.8 (post-tag, queue+auth annotation session) — full authService
// migration to orval. Tests still mock `apiClient.post/get` for legacy
// ergonomics; the orval module's functions are stubbed to delegate
// back to those mocks so existing
// `toHaveBeenCalledWith('/auth/...', ...)` assertions keep working,
// modulo the wire-shape renames documented in authService.ts.
vi.mock('@/services/generated/auth/auth', () => ({
postAuthLogin: vi.fn(async (body: unknown) =>
mockedApiClient.post('/auth/login', body).then((r: { data?: unknown }) => r?.data),
@ -45,6 +46,31 @@ vi.mock('@/services/generated/auth/auth', () => ({
postAuthLogout: vi.fn(async () =>
mockedApiClient.post('/auth/logout').then((r: { data?: unknown }) => r?.data),
),
postAuthRegister: vi.fn(async (body: unknown) =>
mockedApiClient
.post('/auth/register', body)
.then((r: { data?: unknown }) => r?.data),
),
postAuthRefresh: vi.fn(async (body: unknown) =>
mockedApiClient
.post('/auth/refresh', body)
.then((r: { data?: unknown }) => r?.data),
),
postAuthPasswordResetRequest: vi.fn(async (body: unknown) =>
mockedApiClient
.post('/auth/password/reset-request', body)
.then((r: { data?: unknown }) => r?.data),
),
postAuthPasswordReset: vi.fn(async (body: unknown) =>
mockedApiClient
.post('/auth/password/reset', body)
.then((r: { data?: unknown }) => r?.data),
),
postAuthVerifyEmail: vi.fn(async (params: { token: string }) =>
mockedApiClient
.post(`/auth/verify-email?token=${params.token}`)
.then((r: { data?: unknown }) => r?.data),
),
postAuthResendVerification: vi.fn(async (body: unknown) =>
mockedApiClient
.post('/auth/resend-verification', body)
@ -150,10 +176,14 @@ describe('authService', () => {
});
expect(result).toEqual(mockResponse);
// Note: frontend RegisterFormData uses `password_confirm`; the
// service maps this to `password_confirmation` (backend DTO field
// name from register_request.go:8) before sending. This assertion
// checks the WIRE shape, not the form-data shape.
expect(mockedApiClient.post).toHaveBeenCalledWith('/auth/register', {
email: 'newuser@example.com',
password: 'password123',
password_confirm: 'password123',
password_confirmation: 'password123',
username: 'newuser',
});
});
@ -220,8 +250,10 @@ describe('authService', () => {
const result = await refreshToken('refresh-token-123');
expect(result).toEqual(mockResponse);
// Wire shape: backend DTO uses snake_case `refresh_token`,
// not the camelCase `refreshToken` passed as the JS arg.
expect(mockedApiClient.post).toHaveBeenCalledWith('/auth/refresh', {
refreshToken: 'refresh-token-123',
refresh_token: 'refresh-token-123',
});
});
@ -281,11 +313,16 @@ describe('authService', () => {
confirmPassword: 'newpassword123',
});
// Wire shape: backend DTO field is `new_password` (cf. handlers/
// password_reset_handler.go:ResetPasswordRequest); the frontend
// form-data type uses `password`. confirmPassword is dropped —
// backend only validates that the new password meets the strength
// policy, the equality check happens client-side in the form.
expect(mockedApiClient.post).toHaveBeenCalledWith(
'/auth/password/reset',
{
token: 'reset-token-123',
password: 'newpassword123',
new_password: 'newpassword123',
},
);
});
@ -311,11 +348,14 @@ describe('authService', () => {
describe('verifyEmail', () => {
it('should successfully verify email', async () => {
mockedApiClient.get.mockResolvedValue({ data: {} });
// Verb shift: was GET, backend route is POST (auth.go:VerifyEmail
// / routes_auth.go:107). Token still passed as query param per
// the swaggo annotation.
mockedApiClient.post.mockResolvedValue({ data: {} });
await verifyEmail('verification-token-123');
expect(mockedApiClient.get).toHaveBeenCalledWith(
expect(mockedApiClient.post).toHaveBeenCalledWith(
'/auth/verify-email?token=verification-token-123',
);
});
@ -327,7 +367,7 @@ describe('authService', () => {
data: { error: 'Invalid or expired token' },
} as any;
mockedApiClient.get.mockRejectedValue(mockError);
mockedApiClient.post.mockRejectedValue(mockError);
await expect(verifyEmail('invalid-token')).rejects.toThrow();
});

View file

@ -1,30 +1,38 @@
/**
* Auth service orval-backed (partial v1.0.8 B6).
* Auth service orval-backed (full migration post-v1.0.8 B6/B6.bis).
*
* Migrated to orval generated client:
* login, logout, resendVerificationEmail, checkUsernameAvailability.
* All 9 functions now route through the orval-generated client in
* services/generated/auth/auth.ts. Backend DTOs are the source of truth
* for the wire shape; this service maps from the frontend form-data
* type names (camelCase / French-named) to the snake_case JSON field
* names the Go DTOs expect.
*
* Still on raw apiClient (deferred v1.0.9 backend annotation gaps or
* field-name drift would risk breaking auth):
* - register backend DTO says `password_confirmation` while the
* frontend currently sends `password_confirm`
* (register_request.go:8). Renaming via orval would
* change wire shape; needs explicit verification on
* prod first.
* - refreshToken same pattern, backend expects `refresh_token` but
* current frontend sends `refreshToken`.
* - requestPasswordReset / resetPassword endpoints not yet annotated
* in swaggo (no /auth/password/* in openapi.yaml).
* - verifyEmail frontend uses GET /auth/verify-email?token= but
* orval-generated spec says POST. Verb drift + the
* queryheader migration parked in FUNCTIONAL_AUDIT
* §4#7 should land together in v1.0.9.
* Wire-shape mappings worth knowing (drifts that pre-existed):
* - register: `password_confirm` (frontend) `password_confirmation`
* (backend `register_request.go:8`)
* - refreshToken: `refreshToken` (frontend arg) `refresh_token` (DTO)
* - resetPassword: `password` (frontend `ResetPasswordFormData`)
* `new_password` (backend `ResetPasswordRequest`)
* - verifyEmail: verb shift GET POST (token still passed as
* `?token=` query param; this matches the route
* registered at `routes_auth.go:107` and the swaggo
* annotation on `auth.go:VerifyEmail`).
*
* The previous code sending `password_confirm` / `refreshToken` /
* `password` was likely silently broken or fell through a backend
* tolerance path the new shape is what the swaggo-emitted
* `openapi.yaml` declares, and what `c.ShouldBindJSON` of the
* corresponding DTOs actually requires.
*/
import { apiClient } from '@/services/api/client';
import {
postAuthLogin,
postAuthLogout,
postAuthRefresh,
postAuthRegister,
postAuthResendVerification,
postAuthPasswordReset,
postAuthPasswordResetRequest,
postAuthVerifyEmail,
getAuthCheckUsername,
} from '@/services/generated/auth/auth';
import { handleApiServiceError } from '@/utils/serviceErrorHandler';
@ -84,13 +92,13 @@ export async function login(data: LoginFormData): Promise<AuthResponse> {
// INT-API-003: Standardized error handling using handleApiServiceError
export async function register(data: RegisterFormData): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/register', {
const response = await postAuthRegister({
email: data.email,
password: data.password,
password_confirm: data.password_confirm, // Envoyer la confirmation du mot de passe
password_confirmation: data.password_confirm,
username: data.username,
});
return response.data;
return response as unknown as AuthResponse;
} catch (error) {
handleApiServiceError(error, {
context: 'auth',
@ -128,10 +136,8 @@ export async function refreshToken(
refreshToken: string,
): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/refresh', {
refreshToken,
});
return response.data;
const response = await postAuthRefresh({ refresh_token: refreshToken });
return response as unknown as AuthResponse;
} catch (error) {
handleApiServiceError(error, { context: 'auth' });
}
@ -147,7 +153,7 @@ export async function requestPasswordReset(
data: ForgotPasswordFormData,
): Promise<void> {
try {
await apiClient.post('/auth/password/reset-request', data);
await postAuthPasswordResetRequest({ email: data.email });
} catch (error) {
handleApiServiceError(error, { context: 'auth' });
}
@ -163,9 +169,9 @@ export async function resetPassword(
data: ResetPasswordFormData,
): Promise<void> {
try {
await apiClient.post('/auth/password/reset', {
await postAuthPasswordReset({
token: data.token,
password: data.password,
new_password: data.password,
});
} catch (error) {
handleApiServiceError(error, { context: 'auth' });
@ -178,9 +184,12 @@ export async function resetPassword(
* @throws ApiError en cas d'erreur
*/
// INT-API-003: Standardized error handling using handleApiServiceError
// Note: backend route is POST (`auth.go:VerifyEmail` /
// `routes_auth.go:107`), token still passed as `?token=` query param.
// orval handles both — we only adjust the verb client-side.
export async function verifyEmail(token: string): Promise<void> {
try {
await apiClient.get(`/auth/verify-email?token=${token}`);
await postAuthVerifyEmail({ token });
} catch (error) {
handleApiServiceError(error, { context: 'auth' });
}

View file

@ -1,9 +1,28 @@
/**
* Queue API Service
* v0.102: Persistent user playback queue sync with backend
* Queue API Service orval-backed (v1.0.8 post-tag, queue annotation session).
* v0.102: persistent user playback queue + collaborative session sharing
* (v0.203 Lot D1).
*
* Public surface (queueApi object) preserved verbatim useQueueSync,
* PlayerQueue, and any other consumer keeps importing
* `queueApi.{getQueue, addToQueue, ...}` without change. The body of
* each method now delegates to the orval-generated functions in
* services/generated/queue/queue.ts (annotated swaggo backend landed
* concurrently).
*/
import { apiClient } from './client';
import {
getQueue as orvalGetQueue,
putQueue as orvalUpdateQueue,
postQueueItems as orvalAddItem,
deleteQueueItemsId as orvalRemoveItem,
deleteQueue as orvalClearQueue,
postQueueSession as orvalCreateSession,
getQueueSessionToken as orvalGetSession,
deleteQueueSessionToken as orvalDeleteSession,
postQueueSessionTokenItems as orvalAddToSession,
deleteQueueSessionTokenItemsId as orvalRemoveFromSession,
} from '@/services/generated/queue/queue';
import type { Track } from '@/features/player/types';
export interface QueueItemResponse {
@ -39,6 +58,18 @@ export interface QueueResponse {
items: QueueItemResponse[];
}
// Backend wraps each response in an APIResponse envelope:
// { success: true, data: { queue: ..., items: ... } }
// orval's mutator unwraps the Axios layer (`response.data`), so what
// we get here is the envelope itself. Strip the `data` key when present.
const unwrapPayload = <T>(raw: unknown): T => {
const env = raw as { data?: unknown } | undefined;
if (env && typeof env === 'object' && 'data' in env && env.data !== undefined) {
return env.data as T;
}
return raw as T;
};
function mapQueueItemToTrack(item: QueueItemResponse): Track | null {
const t = item.track;
if (!t) return null;
@ -61,8 +92,8 @@ export const queueApi = {
tracks: Track[];
queueItemIds: string[];
}> {
const response = await apiClient.get<QueueResponse>('/queue');
const data = response.data as unknown as QueueResponse;
const response = await orvalGetQueue();
const data = unwrapPayload<QueueResponse>(response);
const items = (data?.items ?? []).sort((a, b) => a.position - b.position);
const tracks = items
.map(mapQueueItemToTrack)
@ -84,34 +115,48 @@ export const queueApi = {
volume?: number;
item_order?: string[];
}): Promise<QueueResponse> {
const response = await apiClient.put<QueueResponse>('/queue', payload);
return response.data as unknown as QueueResponse;
const response = await orvalUpdateQueue(
payload as Parameters<typeof orvalUpdateQueue>[0],
);
return unwrapPayload<QueueResponse>(response);
},
async addToQueue(trackId: string): Promise<QueueItemResponse> {
const response = await apiClient.post<{ item: QueueItemResponse }>(
'/queue/items',
{ track_id: trackId },
const response = await orvalAddItem(
{ track_id: trackId } as unknown as Parameters<typeof orvalAddItem>[0],
);
return (response.data as unknown as { item: QueueItemResponse }).item;
const payload = unwrapPayload<{ item: QueueItemResponse } | QueueItemResponse>(
response,
);
if (payload && typeof payload === 'object' && 'item' in payload && payload.item) {
return payload.item as QueueItemResponse;
}
return payload as QueueItemResponse;
},
async removeFromQueue(itemId: string): Promise<void> {
await apiClient.delete(`/queue/items/${itemId}`);
await orvalRemoveItem(itemId);
},
async clearQueue(): Promise<void> {
await apiClient.delete('/queue');
await orvalClearQueue();
},
// v0.203 Lot D1: Collaborative queue sessions
async createQueueSession(): Promise<{ session: { id: string; share_token: string }; share_url: string }> {
const response = await apiClient.post<{ session: { id: string; share_token: string }; share_url?: string }>(
'/queue/session',
);
const data = response.data as unknown as { session: { id: string; share_token: string }; share_url?: string };
async createQueueSession(): Promise<{
session: { id: string; share_token: string };
share_url: string;
}> {
const response = await orvalCreateSession();
const data = unwrapPayload<{
session: { id: string; share_token: string };
share_url?: string;
}>(response);
const shareUrl =
data.share_url ?? (typeof window !== 'undefined' ? `${window.location.origin}/?session=${data.session.share_token}` : '');
data.share_url ??
(typeof window !== 'undefined'
? `${window.location.origin}/?session=${data.session.share_token}`
: '');
return { session: data.session, share_url: shareUrl };
},
@ -120,36 +165,33 @@ export const queueApi = {
items: Array<{
id: string;
position: number;
track?: { id: string; title?: string; artist?: string; duration?: number; cover_art_path?: string; genre?: string; like_count?: number };
track?: {
id: string;
title?: string;
artist?: string;
duration?: number;
cover_art_path?: string;
genre?: string;
like_count?: number;
};
}>;
}> {
const response = await apiClient.get<{
session: unknown;
items: Array<{
id: string;
position: number;
track?: { id: string; title?: string; artist?: string; duration?: number; cover_art_path?: string; genre?: string; like_count?: number };
}>;
}>(`/queue/session/${token}`);
return response.data as unknown as {
session: unknown;
items: Array<{
id: string;
position: number;
track?: { id: string; title?: string; artist?: string; duration?: number; cover_art_path?: string; genre?: string; like_count?: number };
}>;
};
const response = await orvalGetSession(token);
return unwrapPayload(response);
},
async deleteQueueSession(token: string): Promise<void> {
await apiClient.delete(`/queue/session/${token}`);
await orvalDeleteSession(token);
},
async addToSessionQueue(token: string, trackId: string): Promise<void> {
await apiClient.post(`/queue/session/${token}/items`, { track_id: trackId });
await orvalAddToSession(
token,
{ track_id: trackId } as unknown as Parameters<typeof orvalAddToSession>[1],
);
},
async removeFromSessionQueue(token: string, itemId: string): Promise<void> {
await apiClient.delete(`/queue/session/${token}/items/${itemId}`);
await orvalRemoveFromSession(token, itemId);
},
};

View file

@ -31,12 +31,16 @@ import type {
GetAuthMe200,
InternalHandlersAPIResponse,
InternalHandlersDisableTwoFactorRequest,
InternalHandlersRequestPasswordResetRequest,
InternalHandlersResetPasswordRequest,
InternalHandlersStreamTokenResponse,
InternalHandlersVerifyTwoFactorRequest,
PostAuth2faDisable200,
PostAuth2faSetup200,
PostAuth2faVerify200,
PostAuthLogoutBody,
PostAuthPasswordReset200,
PostAuthPasswordResetRequest200,
PostAuthVerifyEmailParams,
VezaBackendApiInternalDtoLoginRequest,
VezaBackendApiInternalDtoLoginResponse,
@ -926,6 +930,196 @@ export function useGetAuthMe<TData = Awaited<ReturnType<typeof getAuthMe>>, TErr
/**
* Completes a password reset using a valid token previously emailed to the user. Invalidates all the user's existing sessions on success.
* @summary Reset password with token
*/
export type postAuthPasswordResetResponse200 = {
data: PostAuthPasswordReset200
status: 200
}
export type postAuthPasswordResetResponse400 = {
data: InternalHandlersAPIResponse
status: 400
}
export type postAuthPasswordResetResponse500 = {
data: InternalHandlersAPIResponse
status: 500
}
export type postAuthPasswordResetResponseSuccess = (postAuthPasswordResetResponse200) & {
headers: Headers;
};
export type postAuthPasswordResetResponseError = (postAuthPasswordResetResponse400 | postAuthPasswordResetResponse500) & {
headers: Headers;
};
export type postAuthPasswordResetResponse = (postAuthPasswordResetResponseSuccess | postAuthPasswordResetResponseError)
export const getPostAuthPasswordResetUrl = () => {
return `/auth/password/reset`
}
export const postAuthPasswordReset = async (internalHandlersResetPasswordRequest: InternalHandlersResetPasswordRequest, options?: RequestInit): Promise<postAuthPasswordResetResponse> => {
return vezaMutator<postAuthPasswordResetResponse>(getPostAuthPasswordResetUrl(),
{
...options,
method: 'POST',
headers: { 'Content-Type': 'application/json', ...options?.headers },
body: JSON.stringify(
internalHandlersResetPasswordRequest,)
}
);}
export const getPostAuthPasswordResetMutationOptions = <TError = InternalHandlersAPIResponse,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordReset>>, TError,{data: InternalHandlersResetPasswordRequest}, TContext>, request?: SecondParameter<typeof vezaMutator>}
): UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordReset>>, TError,{data: InternalHandlersResetPasswordRequest}, TContext> => {
const mutationKey = ['postAuthPasswordReset'];
const {mutation: mutationOptions, request: requestOptions} = options ?
options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ?
options
: {...options, mutation: {...options.mutation, mutationKey}}
: {mutation: { mutationKey, }, request: undefined};
const mutationFn: MutationFunction<Awaited<ReturnType<typeof postAuthPasswordReset>>, {data: InternalHandlersResetPasswordRequest}> = (props) => {
const {data} = props ?? {};
return postAuthPasswordReset(data,requestOptions)
}
return { mutationFn, ...mutationOptions }}
export type PostAuthPasswordResetMutationResult = NonNullable<Awaited<ReturnType<typeof postAuthPasswordReset>>>
export type PostAuthPasswordResetMutationBody = InternalHandlersResetPasswordRequest
export type PostAuthPasswordResetMutationError = InternalHandlersAPIResponse
/**
* @summary Reset password with token
*/
export const usePostAuthPasswordReset = <TError = InternalHandlersAPIResponse,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordReset>>, TError,{data: InternalHandlersResetPasswordRequest}, TContext>, request?: SecondParameter<typeof vezaMutator>}
, queryClient?: QueryClient): UseMutationResult<
Awaited<ReturnType<typeof postAuthPasswordReset>>,
TError,
{data: InternalHandlersResetPasswordRequest},
TContext
> => {
return useMutation(getPostAuthPasswordResetMutationOptions(options), queryClient);
}
/**
* Sends a password reset link to the user's email if the address exists. Always returns 200 with a generic message to prevent email enumeration.
* @summary Request password reset
*/
export type postAuthPasswordResetRequestResponse200 = {
data: PostAuthPasswordResetRequest200
status: 200
}
export type postAuthPasswordResetRequestResponse400 = {
data: InternalHandlersAPIResponse
status: 400
}
export type postAuthPasswordResetRequestResponse500 = {
data: InternalHandlersAPIResponse
status: 500
}
export type postAuthPasswordResetRequestResponseSuccess = (postAuthPasswordResetRequestResponse200) & {
headers: Headers;
};
export type postAuthPasswordResetRequestResponseError = (postAuthPasswordResetRequestResponse400 | postAuthPasswordResetRequestResponse500) & {
headers: Headers;
};
export type postAuthPasswordResetRequestResponse = (postAuthPasswordResetRequestResponseSuccess | postAuthPasswordResetRequestResponseError)
export const getPostAuthPasswordResetRequestUrl = () => {
return `/auth/password/reset-request`
}
export const postAuthPasswordResetRequest = async (internalHandlersRequestPasswordResetRequest: InternalHandlersRequestPasswordResetRequest, options?: RequestInit): Promise<postAuthPasswordResetRequestResponse> => {
return vezaMutator<postAuthPasswordResetRequestResponse>(getPostAuthPasswordResetRequestUrl(),
{
...options,
method: 'POST',
headers: { 'Content-Type': 'application/json', ...options?.headers },
body: JSON.stringify(
internalHandlersRequestPasswordResetRequest,)
}
);}
export const getPostAuthPasswordResetRequestMutationOptions = <TError = InternalHandlersAPIResponse,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordResetRequest>>, TError,{data: InternalHandlersRequestPasswordResetRequest}, TContext>, request?: SecondParameter<typeof vezaMutator>}
): UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordResetRequest>>, TError,{data: InternalHandlersRequestPasswordResetRequest}, TContext> => {
const mutationKey = ['postAuthPasswordResetRequest'];
const {mutation: mutationOptions, request: requestOptions} = options ?
options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ?
options
: {...options, mutation: {...options.mutation, mutationKey}}
: {mutation: { mutationKey, }, request: undefined};
const mutationFn: MutationFunction<Awaited<ReturnType<typeof postAuthPasswordResetRequest>>, {data: InternalHandlersRequestPasswordResetRequest}> = (props) => {
const {data} = props ?? {};
return postAuthPasswordResetRequest(data,requestOptions)
}
return { mutationFn, ...mutationOptions }}
export type PostAuthPasswordResetRequestMutationResult = NonNullable<Awaited<ReturnType<typeof postAuthPasswordResetRequest>>>
export type PostAuthPasswordResetRequestMutationBody = InternalHandlersRequestPasswordResetRequest
export type PostAuthPasswordResetRequestMutationError = InternalHandlersAPIResponse
/**
* @summary Request password reset
*/
export const usePostAuthPasswordResetRequest = <TError = InternalHandlersAPIResponse,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof postAuthPasswordResetRequest>>, TError,{data: InternalHandlersRequestPasswordResetRequest}, TContext>, request?: SecondParameter<typeof vezaMutator>}
, queryClient?: QueryClient): UseMutationResult<
Awaited<ReturnType<typeof postAuthPasswordResetRequest>>,
TError,
{data: InternalHandlersRequestPasswordResetRequest},
TContext
> => {
return useMutation(getPostAuthPasswordResetRequestMutationOptions(options), queryClient);
}
/**
* Get a new access token using a refresh token
* @summary Refresh Token
*/

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { DeleteQueue200Data } from './deleteQueue200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type DeleteQueue200 = InternalHandlersAPIResponse & {
data?: DeleteQueue200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type DeleteQueue200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { DeleteQueueItemsId200Data } from './deleteQueueItemsId200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type DeleteQueueItemsId200 = InternalHandlersAPIResponse & {
data?: DeleteQueueItemsId200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type DeleteQueueItemsId200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { DeleteQueueSessionToken200Data } from './deleteQueueSessionToken200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type DeleteQueueSessionToken200 = InternalHandlersAPIResponse & {
data?: DeleteQueueSessionToken200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type DeleteQueueSessionToken200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { DeleteQueueSessionTokenItemsId200Data } from './deleteQueueSessionTokenItemsId200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type DeleteQueueSessionTokenItemsId200 = InternalHandlersAPIResponse & {
data?: DeleteQueueSessionTokenItemsId200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type DeleteQueueSessionTokenItemsId200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { GetQueue200Data } from './getQueue200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type GetQueue200 = InternalHandlersAPIResponse & {
data?: GetQueue200Data;
};

View file

@ -0,0 +1,14 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { GetQueue200DataItemsItem } from './getQueue200DataItemsItem';
import type { GetQueue200DataQueue } from './getQueue200DataQueue';
export type GetQueue200Data = {
items?: GetQueue200DataItemsItem[];
queue?: GetQueue200DataQueue;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type GetQueue200DataItemsItem = { [key: string]: unknown };

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type GetQueue200DataQueue = { [key: string]: unknown };

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { GetQueueSessionToken200Data } from './getQueueSessionToken200Data';
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
export type GetQueueSessionToken200 = InternalHandlersAPIResponse & {
data?: GetQueueSessionToken200Data;
};

View file

@ -0,0 +1,14 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { GetQueueSessionToken200DataItemsItem } from './getQueueSessionToken200DataItemsItem';
import type { GetQueueSessionToken200DataSession } from './getQueueSessionToken200DataSession';
export type GetQueueSessionToken200Data = {
items?: GetQueueSessionToken200DataItemsItem[];
session?: GetQueueSessionToken200DataSession;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type GetQueueSessionToken200DataItemsItem = { [key: string]: unknown };

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type GetQueueSessionToken200DataSession = { [key: string]: unknown };

View file

@ -12,6 +12,14 @@ export * from './deletePlaylistsIdCollaboratorsUserId200';
export * from './deletePlaylistsIdCollaboratorsUserId200Data';
export * from './deletePlaylistsIdTracksTrackId200';
export * from './deletePlaylistsIdTracksTrackId200Data';
export * from './deleteQueue200';
export * from './deleteQueue200Data';
export * from './deleteQueueItemsId200';
export * from './deleteQueueItemsId200Data';
export * from './deleteQueueSessionToken200';
export * from './deleteQueueSessionToken200Data';
export * from './deleteQueueSessionTokenItemsId200';
export * from './deleteQueueSessionTokenItemsId200Data';
export * from './deleteTracksId200';
export * from './deleteTracksId200Data';
export * from './deleteTracksIdCommentsCommentId200';
@ -83,6 +91,14 @@ export * from './getPlaylistsSearch200DataPagination';
export * from './getPlaylistsSearchParams';
export * from './getPlaylistsSharedToken200';
export * from './getPlaylistsSharedToken200Data';
export * from './getQueue200';
export * from './getQueue200Data';
export * from './getQueue200DataItemsItem';
export * from './getQueue200DataQueue';
export * from './getQueueSessionToken200';
export * from './getQueueSessionToken200Data';
export * from './getQueueSessionToken200DataItemsItem';
export * from './getQueueSessionToken200DataSession';
export * from './getTracks200';
export * from './getTracks200Data';
export * from './getTracks200DataPagination';
@ -174,6 +190,8 @@ export * from './internalCoreTrackUpdateLyricsRequest';
export * from './internalCoreTrackUpdateTrackRequest';
export * from './internalHandlersAddCollaboratorRequest';
export * from './internalHandlersAddCollaboratorRequestPermission';
export * from './internalHandlersAddQueueItemRequest';
export * from './internalHandlersAddToSessionRequest';
export * from './internalHandlersAPIResponse';
export * from './internalHandlersCreateCommentRequest';
export * from './internalHandlersCreateOrderRequest';
@ -198,6 +216,8 @@ export * from './internalHandlersLibraryPreview';
export * from './internalHandlersRecentActivity';
export * from './internalHandlersRecentActivityMetadata';
export * from './internalHandlersReorderTracksRequest';
export * from './internalHandlersRequestPasswordResetRequest';
export * from './internalHandlersResetPasswordRequest';
export * from './internalHandlersSetupTwoFactorResponse';
export * from './internalHandlersStreamTokenResponse';
export * from './internalHandlersTrackPreview';
@ -224,6 +244,10 @@ export * from './postAuth2faSetup200';
export * from './postAuth2faVerify200';
export * from './postAuth2faVerify200Data';
export * from './postAuthLogoutBody';
export * from './postAuthPasswordReset200';
export * from './postAuthPasswordReset200Data';
export * from './postAuthPasswordResetRequest200';
export * from './postAuthPasswordResetRequest200Data';
export * from './postAuthVerifyEmailParams';
export * from './postInternalTracksIdStreamReady200';
export * from './postPlaylists201';
@ -241,6 +265,16 @@ export * from './postPlaylistsIdTracks200Data';
export * from './postPlaylistsIdTracksBody';
export * from './postPlaylistsImport201';
export * from './postPlaylistsImport201Data';
export * from './postQueueItems201';
export * from './postQueueItems201Data';
export * from './postQueueItems201DataItem';
export * from './postQueueSession201';
export * from './postQueueSession201Data';
export * from './postQueueSession201DataSession';
export * from './postQueueSessionTokenItems201';
export * from './postQueueSessionTokenItems201Data';
export * from './postQueueSessionTokenItems201DataItemsItem';
export * from './postQueueSessionTokenItems201DataSession';
export * from './postTracks201';
export * from './postTracks201Data';
export * from './postTracksBatchDelete200';
@ -296,6 +330,10 @@ export * from './putPlaylistsIdCollaboratorsUserId200Data';
export * from './putPlaylistsIdCollaboratorsUserId200DataCollaborator';
export * from './putPlaylistsIdTracksReorder200';
export * from './putPlaylistsIdTracksReorder200Data';
export * from './putQueue200';
export * from './putQueue200Data';
export * from './putQueue200DataItemsItem';
export * from './putQueue200DataQueue';
export * from './putTracksId200';
export * from './putTracksId200Data';
export * from './putTracksIdLyrics200';
@ -330,3 +368,4 @@ export * from './vezaBackendApiInternalModelsTrack';
export * from './vezaBackendApiInternalModelsTrackStatus';
export * from './vezaBackendApiInternalModelsUser';
export * from './vezaBackendApiInternalResponseAPIResponse';
export * from './vezaBackendApiInternalServicesUpdateQueueRequest';

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export interface InternalHandlersAddQueueItemRequest {
track_id: string;
}

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export interface InternalHandlersAddToSessionRequest {
track_id: string;
}

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export interface InternalHandlersRequestPasswordResetRequest {
email: string;
}

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export interface InternalHandlersResetPasswordRequest {
/** @minLength 12 */
new_password: string;
token: string;
}

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PostAuthPasswordReset200Data } from './postAuthPasswordReset200Data';
export type PostAuthPasswordReset200 = InternalHandlersAPIResponse & {
data?: PostAuthPasswordReset200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostAuthPasswordReset200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PostAuthPasswordResetRequest200Data } from './postAuthPasswordResetRequest200Data';
export type PostAuthPasswordResetRequest200 = InternalHandlersAPIResponse & {
data?: PostAuthPasswordResetRequest200Data;
};

View file

@ -0,0 +1,11 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostAuthPasswordResetRequest200Data = {
message?: string;
};

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PostQueueItems201Data } from './postQueueItems201Data';
export type PostQueueItems201 = InternalHandlersAPIResponse & {
data?: PostQueueItems201Data;
};

View file

@ -0,0 +1,12 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { PostQueueItems201DataItem } from './postQueueItems201DataItem';
export type PostQueueItems201Data = {
item?: PostQueueItems201DataItem;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostQueueItems201DataItem = { [key: string]: unknown };

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PostQueueSession201Data } from './postQueueSession201Data';
export type PostQueueSession201 = InternalHandlersAPIResponse & {
data?: PostQueueSession201Data;
};

View file

@ -0,0 +1,14 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { PostQueueSession201DataSession } from './postQueueSession201DataSession';
export type PostQueueSession201Data = {
session?: PostQueueSession201DataSession;
share_token?: string;
share_url?: string;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostQueueSession201DataSession = { [key: string]: unknown };

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PostQueueSessionTokenItems201Data } from './postQueueSessionTokenItems201Data';
export type PostQueueSessionTokenItems201 = InternalHandlersAPIResponse & {
data?: PostQueueSessionTokenItems201Data;
};

View file

@ -0,0 +1,14 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { PostQueueSessionTokenItems201DataItemsItem } from './postQueueSessionTokenItems201DataItemsItem';
import type { PostQueueSessionTokenItems201DataSession } from './postQueueSessionTokenItems201DataSession';
export type PostQueueSessionTokenItems201Data = {
items?: PostQueueSessionTokenItems201DataItemsItem[];
session?: PostQueueSessionTokenItems201DataSession;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostQueueSessionTokenItems201DataItemsItem = { [key: string]: unknown };

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PostQueueSessionTokenItems201DataSession = { [key: string]: unknown };

View file

@ -0,0 +1,13 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { InternalHandlersAPIResponse } from './internalHandlersAPIResponse';
import type { PutQueue200Data } from './putQueue200Data';
export type PutQueue200 = InternalHandlersAPIResponse & {
data?: PutQueue200Data;
};

View file

@ -0,0 +1,14 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
import type { PutQueue200DataItemsItem } from './putQueue200DataItemsItem';
import type { PutQueue200DataQueue } from './putQueue200DataQueue';
export type PutQueue200Data = {
items?: PutQueue200DataItemsItem[];
queue?: PutQueue200DataQueue;
};

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PutQueue200DataItemsItem = { [key: string]: unknown };

View file

@ -0,0 +1,9 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export type PutQueue200DataQueue = { [key: string]: unknown };

View file

@ -0,0 +1,17 @@
/**
* Generated by orval v8.8.1 🍺
* Do not edit manually.
* Veza Backend API
* Backend API for Veza platform.
* OpenAPI spec version: 1.2.0
*/
export interface VezaBackendApiInternalServicesUpdateQueueRequest {
current_position?: number;
current_track_id?: string;
is_playing?: boolean;
item_order?: string[];
repeat_mode?: string;
shuffle?: boolean;
volume?: number;
}

File diff suppressed because it is too large Load diff

View file

@ -1313,6 +1313,132 @@ const docTemplate = `{
}
}
},
"/auth/password/reset": {
"post": {
"description": "Completes a password reset using a valid token previously emailed to the user. Invalidates all the user's existing sessions on success.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Reset password with token",
"parameters": [
{
"description": "Reset token + new password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.ResetPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "Password reset successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Invalid or expired token, or password validation failed",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Failed to update password",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/auth/password/reset-request": {
"post": {
"description": "Sends a password reset link to the user's email if the address exists. Always returns 200 with a generic message to prevent email enumeration.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Request password reset",
"parameters": [
{
"description": "Email of the account to reset",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.RequestPasswordResetRequest"
}
}
],
"responses": {
"200": {
"description": "If the email exists, a reset link has been sent",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Token generation/storage failed (or SMTP failure in production)",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/auth/refresh": {
"post": {
"description": "Get a new access token using a refresh token",
@ -3345,6 +3471,726 @@ const docTemplate = `{
}
}
},
"/queue": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Returns the authenticated user's persistent playback queue with all items in position order",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Get user playback queue",
"responses": {
"200": {
"description": "Queue + items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"queue": {
"type": "object"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"put": {
"security": [
{
"BearerAuth": []
}
],
"description": "Updates the authenticated user's queue state (current track / position / playback flags / item order)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Update user playback queue",
"parameters": [
{
"description": "Queue update payload",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/veza-backend-api_internal_services.UpdateQueueRequest"
}
}
],
"responses": {
"200": {
"description": "Updated queue",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"queue": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes every item from the authenticated user's playback queue",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Clear queue",
"responses": {
"200": {
"description": "Queue cleared",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/items": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Appends a track to the authenticated user's playback queue",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Add track to queue",
"parameters": [
{
"description": "Track to enqueue",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.AddQueueItemRequest"
}
}
],
"responses": {
"201": {
"description": "Created queue item",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"item": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/items/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes a single item from the authenticated user's playback queue by item ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Remove queue item",
"parameters": [
{
"type": "string",
"description": "Queue item ID (UUID)",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Item removed",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Invalid item ID",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Queue item not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Creates a shared queue session and returns its share token + URL. The session creator is recorded as host.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Create collaborative queue session",
"responses": {
"201": {
"description": "Created session",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"session": {
"type": "object"
},
"share_token": {
"type": "string"
},
"share_url": {
"type": "string"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}": {
"get": {
"description": "Returns the session metadata + items for a given share token. No auth required (public — anyone with the link can join).",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Get queue session by share token",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Session and queue items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"session": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Token required",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Deletes a collaborative queue session. Only the original session creator can delete.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Delete queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Session deleted",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Token required",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"403": {
"description": "Only the creator can delete this session",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}/items": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Adds a track to a collaborative queue session. Anyone with the share token can add.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Add track to queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
},
{
"description": "Track to enqueue",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.AddToSessionRequest"
}
}
],
"responses": {
"201": {
"description": "Updated session and items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"session": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}/items/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes an item from a collaborative queue session by item ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Remove item from queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Queue item ID (UUID)",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Item removed",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session or item not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/tracks": {
"get": {
"description": "List tracks with pagination, filters, sort. Cursor-based when ?cursor provided, otherwise page/limit offset.",
@ -8003,6 +8849,28 @@ const docTemplate = `{
}
}
},
"internal_handlers.AddQueueItemRequest": {
"type": "object",
"required": [
"track_id"
],
"properties": {
"track_id": {
"type": "string"
}
}
},
"internal_handlers.AddToSessionRequest": {
"type": "object",
"required": [
"track_id"
],
"properties": {
"track_id": {
"type": "string"
}
}
},
"internal_handlers.CreateCommentRequest": {
"type": "object",
"required": [
@ -8352,6 +9220,33 @@ const docTemplate = `{
}
}
},
"internal_handlers.RequestPasswordResetRequest": {
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string"
}
}
},
"internal_handlers.ResetPasswordRequest": {
"type": "object",
"required": [
"new_password",
"token"
],
"properties": {
"new_password": {
"type": "string",
"minLength": 12
},
"token": {
"type": "string"
}
}
},
"internal_handlers.SetupTwoFactorResponse": {
"type": "object",
"properties": {
@ -9348,6 +10243,35 @@ const docTemplate = `{
"type": "boolean"
}
}
},
"veza-backend-api_internal_services.UpdateQueueRequest": {
"type": "object",
"properties": {
"current_position": {
"type": "integer"
},
"current_track_id": {
"type": "string"
},
"is_playing": {
"type": "boolean"
},
"item_order": {
"type": "array",
"items": {
"type": "string"
}
},
"repeat_mode": {
"type": "string"
},
"shuffle": {
"type": "boolean"
},
"volume": {
"type": "integer"
}
}
}
},
"securityDefinitions": {

View file

@ -1307,6 +1307,132 @@
}
}
},
"/auth/password/reset": {
"post": {
"description": "Completes a password reset using a valid token previously emailed to the user. Invalidates all the user's existing sessions on success.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Reset password with token",
"parameters": [
{
"description": "Reset token + new password",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.ResetPasswordRequest"
}
}
],
"responses": {
"200": {
"description": "Password reset successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Invalid or expired token, or password validation failed",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Failed to update password",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/auth/password/reset-request": {
"post": {
"description": "Sends a password reset link to the user's email if the address exists. Always returns 200 with a generic message to prevent email enumeration.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Auth"
],
"summary": "Request password reset",
"parameters": [
{
"description": "Email of the account to reset",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.RequestPasswordResetRequest"
}
}
],
"responses": {
"200": {
"description": "If the email exists, a reset link has been sent",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Token generation/storage failed (or SMTP failure in production)",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/auth/refresh": {
"post": {
"description": "Get a new access token using a refresh token",
@ -3339,6 +3465,726 @@
}
}
},
"/queue": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Returns the authenticated user's persistent playback queue with all items in position order",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Get user playback queue",
"responses": {
"200": {
"description": "Queue + items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"queue": {
"type": "object"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"put": {
"security": [
{
"BearerAuth": []
}
],
"description": "Updates the authenticated user's queue state (current track / position / playback flags / item order)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Update user playback queue",
"parameters": [
{
"description": "Queue update payload",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/veza-backend-api_internal_services.UpdateQueueRequest"
}
}
],
"responses": {
"200": {
"description": "Updated queue",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"queue": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes every item from the authenticated user's playback queue",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Clear queue",
"responses": {
"200": {
"description": "Queue cleared",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/items": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Appends a track to the authenticated user's playback queue",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Add track to queue",
"parameters": [
{
"description": "Track to enqueue",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.AddQueueItemRequest"
}
}
],
"responses": {
"201": {
"description": "Created queue item",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"item": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/items/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes a single item from the authenticated user's playback queue by item ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Remove queue item",
"parameters": [
{
"type": "string",
"description": "Queue item ID (UUID)",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Item removed",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Invalid item ID",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Queue item not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Creates a shared queue session and returns its share token + URL. The session creator is recorded as host.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Create collaborative queue session",
"responses": {
"201": {
"description": "Created session",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"session": {
"type": "object"
},
"share_token": {
"type": "string"
},
"share_url": {
"type": "string"
}
}
}
}
}
]
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}": {
"get": {
"description": "Returns the session metadata + items for a given share token. No auth required (public — anyone with the link can join).",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Get queue session by share token",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Session and queue items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"session": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Token required",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Deletes a collaborative queue session. Only the original session creator can delete.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Delete queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Session deleted",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Token required",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"403": {
"description": "Only the creator can delete this session",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}/items": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "Adds a track to a collaborative queue session. Anyone with the share token can add.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Add track to queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
},
{
"description": "Track to enqueue",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_handlers.AddToSessionRequest"
}
}
],
"responses": {
"201": {
"description": "Updated session and items",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object"
}
},
"session": {
"type": "object"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/queue/session/{token}/items/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "Removes an item from a collaborative queue session by item ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Queue"
],
"summary": "Remove item from queue session",
"parameters": [
{
"type": "string",
"description": "Session share token",
"name": "token",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Queue item ID (UUID)",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Item removed",
"schema": {
"allOf": [
{
"$ref": "#/definitions/internal_handlers.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
]
}
},
"400": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"404": {
"description": "Session or item not found",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
},
"500": {
"description": "Internal Error",
"schema": {
"$ref": "#/definitions/internal_handlers.APIResponse"
}
}
}
}
},
"/tracks": {
"get": {
"description": "List tracks with pagination, filters, sort. Cursor-based when ?cursor provided, otherwise page/limit offset.",
@ -7997,6 +8843,28 @@
}
}
},
"internal_handlers.AddQueueItemRequest": {
"type": "object",
"required": [
"track_id"
],
"properties": {
"track_id": {
"type": "string"
}
}
},
"internal_handlers.AddToSessionRequest": {
"type": "object",
"required": [
"track_id"
],
"properties": {
"track_id": {
"type": "string"
}
}
},
"internal_handlers.CreateCommentRequest": {
"type": "object",
"required": [
@ -8346,6 +9214,33 @@
}
}
},
"internal_handlers.RequestPasswordResetRequest": {
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string"
}
}
},
"internal_handlers.ResetPasswordRequest": {
"type": "object",
"required": [
"new_password",
"token"
],
"properties": {
"new_password": {
"type": "string",
"minLength": 12
},
"token": {
"type": "string"
}
}
},
"internal_handlers.SetupTwoFactorResponse": {
"type": "object",
"properties": {
@ -9342,6 +10237,35 @@
"type": "boolean"
}
}
},
"veza-backend-api_internal_services.UpdateQueueRequest": {
"type": "object",
"properties": {
"current_position": {
"type": "integer"
},
"current_track_id": {
"type": "string"
},
"is_playing": {
"type": "boolean"
},
"item_order": {
"type": "array",
"items": {
"type": "string"
}
},
"repeat_mode": {
"type": "string"
},
"shuffle": {
"type": "boolean"
},
"volume": {
"type": "integer"
}
}
}
},
"securityDefinitions": {

View file

@ -146,6 +146,20 @@ definitions:
- permission
- user_id
type: object
internal_handlers.AddQueueItemRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.AddToSessionRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.CreateCommentRequest:
properties:
content:
@ -387,6 +401,24 @@ definitions:
required:
- track_ids
type: object
internal_handlers.RequestPasswordResetRequest:
properties:
email:
type: string
required:
- email
type: object
internal_handlers.ResetPasswordRequest:
properties:
new_password:
minLength: 12
type: string
token:
type: string
required:
- new_password
- token
type: object
internal_handlers.SetupTwoFactorResponse:
properties:
qr_code_url:
@ -1075,6 +1107,25 @@ definitions:
success:
type: boolean
type: object
veza-backend-api_internal_services.UpdateQueueRequest:
properties:
current_position:
type: integer
current_track_id:
type: string
is_playing:
type: boolean
item_order:
items:
type: string
type: array
repeat_mode:
type: string
shuffle:
type: boolean
volume:
type: integer
type: object
host: localhost:18080
info:
contact:
@ -1886,6 +1937,84 @@ paths:
summary: Get Current User
tags:
- Auth
/auth/password/reset:
post:
consumes:
- application/json
description: Completes a password reset using a valid token previously emailed
to the user. Invalidates all the user's existing sessions on success.
parameters:
- description: Reset token + new password
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.ResetPasswordRequest'
produces:
- application/json
responses:
"200":
description: Password reset successfully
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid or expired token, or password validation failed
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Failed to update password
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Reset password with token
tags:
- Auth
/auth/password/reset-request:
post:
consumes:
- application/json
description: Sends a password reset link to the user's email if the address
exists. Always returns 200 with a generic message to prevent email enumeration.
parameters:
- description: Email of the account to reset
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.RequestPasswordResetRequest'
produces:
- application/json
responses:
"200":
description: If the email exists, a reset link has been sent
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Token generation/storage failed (or SMTP failure in production)
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Request password reset
tags:
- Auth
/auth/refresh:
post:
consumes:
@ -3140,6 +3269,445 @@ paths:
summary: Get playlist by share token
tags:
- Playlist
/queue:
delete:
consumes:
- application/json
description: Removes every item from the authenticated user's playback queue
produces:
- application/json
responses:
"200":
description: Queue cleared
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Clear queue
tags:
- Queue
get:
consumes:
- application/json
description: Returns the authenticated user's persistent playback queue with
all items in position order
produces:
- application/json
responses:
"200":
description: Queue + items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get user playback queue
tags:
- Queue
put:
consumes:
- application/json
description: Updates the authenticated user's queue state (current track / position
/ playback flags / item order)
parameters:
- description: Queue update payload
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_services.UpdateQueueRequest'
produces:
- application/json
responses:
"200":
description: Updated queue
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update user playback queue
tags:
- Queue
/queue/items:
post:
consumes:
- application/json
description: Appends a track to the authenticated user's playback queue
parameters:
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddQueueItemRequest'
produces:
- application/json
responses:
"201":
description: Created queue item
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
item:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue
tags:
- Queue
/queue/items/{id}:
delete:
consumes:
- application/json
description: Removes a single item from the authenticated user's playback queue
by item ID
parameters:
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid item ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Queue item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove queue item
tags:
- Queue
/queue/session:
post:
consumes:
- application/json
description: Creates a shared queue session and returns its share token + URL.
The session creator is recorded as host.
produces:
- application/json
responses:
"201":
description: Created session
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
session:
type: object
share_token:
type: string
share_url:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create collaborative queue session
tags:
- Queue
/queue/session/{token}:
delete:
consumes:
- application/json
description: Deletes a collaborative queue session. Only the original session
creator can delete.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session deleted
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Only the creator can delete this session
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete queue session
tags:
- Queue
get:
consumes:
- application/json
description: Returns the session metadata + items for a given share token. No
auth required (public — anyone with the link can join).
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session and queue items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get queue session by share token
tags:
- Queue
/queue/session/{token}/items:
post:
consumes:
- application/json
description: Adds a track to a collaborative queue session. Anyone with the
share token can add.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddToSessionRequest'
produces:
- application/json
responses:
"201":
description: Updated session and items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue session
tags:
- Queue
/queue/session/{token}/items/{id}:
delete:
consumes:
- application/json
description: Removes an item from a collaborative queue session by item ID
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session or item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove item from queue session
tags:
- Queue
/tracks:
get:
description: List tracks with pagination, filters, sort. Cursor-based when ?cursor

View file

@ -67,6 +67,16 @@ type AuthServiceInterface interface {
// RequestPasswordReset handles password reset request
// T0193: Creates endpoint POST /api/v1/auth/password/reset-request
// BE-SEC-013: Added audit logging for password reset requests
// @Summary Request password reset
// @Description Sends a password reset link to the user's email if the address exists. Always returns 200 with a generic message to prevent email enumeration.
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body RequestPasswordResetRequest true "Email of the account to reset"
// @Success 200 {object} APIResponse{data=object{message=string}} "If the email exists, a reset link has been sent"
// @Failure 400 {object} APIResponse "Validation error"
// @Failure 500 {object} APIResponse "Token generation/storage failed (or SMTP failure in production)"
// @Router /auth/password/reset-request [post]
func RequestPasswordReset(
passwordResetService *services.PasswordResetService,
passwordService *services.PasswordService,
@ -180,6 +190,16 @@ type ResetPasswordRequest struct {
// T0194: Creates endpoint POST /api/v1/auth/password/reset
// T0200: Uses AuthService.InvalidateAllUserSessions to invalidate sessions and update token_version
// BE-SEC-013: Added audit logging for password reset completion
// @Summary Reset password with token
// @Description Completes a password reset using a valid token previously emailed to the user. Invalidates all the user's existing sessions on success.
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body ResetPasswordRequest true "Reset token + new password"
// @Success 200 {object} APIResponse{data=object{message=string}} "Password reset successfully"
// @Failure 400 {object} APIResponse "Invalid or expired token, or password validation failed"
// @Failure 500 {object} APIResponse "Failed to update password"
// @Router /auth/password/reset [post]
func ResetPassword(
passwordResetService *services.PasswordResetService,
passwordService *services.PasswordService,

View file

@ -23,6 +23,16 @@ func NewQueueHandler(queueService *services.QueueService, logger *zap.Logger) *Q
}
// GetQueue returns the user's queue
// @Summary Get user playback queue
// @Description Returns the authenticated user's persistent playback queue with all items in position order
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} APIResponse{data=object{queue=object,items=[]object}} "Queue + items"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue [get]
func (h *QueueHandler) GetQueue(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -40,6 +50,18 @@ func (h *QueueHandler) GetQueue(c *gin.Context) {
}
// UpdateQueue updates the user's queue
// @Summary Update user playback queue
// @Description Updates the authenticated user's queue state (current track / position / playback flags / item order)
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body services.UpdateQueueRequest true "Queue update payload"
// @Success 200 {object} APIResponse{data=object{queue=object,items=[]object}} "Updated queue"
// @Failure 400 {object} APIResponse "Validation error"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue [put]
func (h *QueueHandler) UpdateQueue(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -67,6 +89,18 @@ type AddQueueItemRequest struct {
}
// AddQueueItem adds a track to the queue
// @Summary Add track to queue
// @Description Appends a track to the authenticated user's playback queue
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body AddQueueItemRequest true "Track to enqueue"
// @Success 201 {object} APIResponse{data=object{item=object}} "Created queue item"
// @Failure 400 {object} APIResponse "Validation error"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue/items [post]
func (h *QueueHandler) AddQueueItem(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -86,6 +120,18 @@ func (h *QueueHandler) AddQueueItem(c *gin.Context) {
}
// RemoveQueueItem removes an item from the queue
// @Summary Remove queue item
// @Description Removes a single item from the authenticated user's playback queue by item ID
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path string true "Queue item ID (UUID)"
// @Success 200 {object} APIResponse{data=object{message=string}} "Item removed"
// @Failure 400 {object} APIResponse "Invalid item ID"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 404 {object} APIResponse "Queue item not found"
// @Router /queue/items/{id} [delete]
func (h *QueueHandler) RemoveQueueItem(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -104,6 +150,16 @@ func (h *QueueHandler) RemoveQueueItem(c *gin.Context) {
}
// ClearQueue removes all items from the queue
// @Summary Clear queue
// @Description Removes every item from the authenticated user's playback queue
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} APIResponse{data=object{message=string}} "Queue cleared"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue [delete]
func (h *QueueHandler) ClearQueue(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {

View file

@ -24,6 +24,16 @@ func NewQueueSessionHandler(svc *services.QueueSessionService, logger *zap.Logge
}
// CreateSession creates a new shared queue session
// @Summary Create collaborative queue session
// @Description Creates a shared queue session and returns its share token + URL. The session creator is recorded as host.
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 201 {object} APIResponse{data=object{session=object,share_token=string,share_url=string}} "Created session"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue/session [post]
func (h *QueueSessionHandler) CreateSession(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -42,6 +52,17 @@ func (h *QueueSessionHandler) CreateSession(c *gin.Context) {
}
// GetSession returns a session's queue (auth optional for joining via link)
// @Summary Get queue session by share token
// @Description Returns the session metadata + items for a given share token. No auth required (public — anyone with the link can join).
// @Tags Queue
// @Accept json
// @Produce json
// @Param token path string true "Session share token"
// @Success 200 {object} APIResponse{data=object{session=object,items=[]object}} "Session and queue items"
// @Failure 400 {object} APIResponse "Token required"
// @Failure 404 {object} APIResponse "Session not found"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue/session/{token} [get]
func (h *QueueSessionHandler) GetSession(c *gin.Context) {
token := c.Param("token")
if token == "" {
@ -83,6 +104,19 @@ func (h *QueueSessionHandler) GetSession(c *gin.Context) {
}
// DeleteSession deletes a session (creator only)
// @Summary Delete queue session
// @Description Deletes a collaborative queue session. Only the original session creator can delete.
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param token path string true "Session share token"
// @Success 200 {object} APIResponse{data=object{message=string}} "Session deleted"
// @Failure 400 {object} APIResponse "Token required"
// @Failure 401 {object} APIResponse "Unauthorized"
// @Failure 403 {object} APIResponse "Only the creator can delete this session"
// @Failure 404 {object} APIResponse "Session not found"
// @Router /queue/session/{token} [delete]
func (h *QueueSessionHandler) DeleteSession(c *gin.Context) {
userID, ok := GetUserIDUUID(c)
if !ok {
@ -114,6 +148,19 @@ type AddToSessionRequest struct {
}
// AddToSession adds a track to a session's queue
// @Summary Add track to queue session
// @Description Adds a track to a collaborative queue session. Anyone with the share token can add.
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param token path string true "Session share token"
// @Param request body AddToSessionRequest true "Track to enqueue"
// @Success 201 {object} APIResponse{data=object{session=object,items=[]object}} "Updated session and items"
// @Failure 400 {object} APIResponse "Validation error"
// @Failure 404 {object} APIResponse "Session not found"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue/session/{token}/items [post]
func (h *QueueSessionHandler) AddToSession(c *gin.Context) {
token := c.Param("token")
if token == "" {
@ -139,6 +186,19 @@ func (h *QueueSessionHandler) AddToSession(c *gin.Context) {
}
// RemoveFromSession removes an item from a session's queue
// @Summary Remove item from queue session
// @Description Removes an item from a collaborative queue session by item ID
// @Tags Queue
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param token path string true "Session share token"
// @Param id path string true "Queue item ID (UUID)"
// @Success 200 {object} APIResponse{data=object{message=string}} "Item removed"
// @Failure 400 {object} APIResponse "Validation error"
// @Failure 404 {object} APIResponse "Session or item not found"
// @Failure 500 {object} APIResponse "Internal Error"
// @Router /queue/session/{token}/items/{id} [delete]
func (h *QueueSessionHandler) RemoveFromSession(c *gin.Context) {
token := c.Param("token")
if token == "" {

View file

@ -146,6 +146,20 @@ definitions:
- permission
- user_id
type: object
internal_handlers.AddQueueItemRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.AddToSessionRequest:
properties:
track_id:
type: string
required:
- track_id
type: object
internal_handlers.CreateCommentRequest:
properties:
content:
@ -387,6 +401,24 @@ definitions:
required:
- track_ids
type: object
internal_handlers.RequestPasswordResetRequest:
properties:
email:
type: string
required:
- email
type: object
internal_handlers.ResetPasswordRequest:
properties:
new_password:
minLength: 12
type: string
token:
type: string
required:
- new_password
- token
type: object
internal_handlers.SetupTwoFactorResponse:
properties:
qr_code_url:
@ -1075,6 +1107,25 @@ definitions:
success:
type: boolean
type: object
veza-backend-api_internal_services.UpdateQueueRequest:
properties:
current_position:
type: integer
current_track_id:
type: string
is_playing:
type: boolean
item_order:
items:
type: string
type: array
repeat_mode:
type: string
shuffle:
type: boolean
volume:
type: integer
type: object
host: localhost:18080
info:
contact:
@ -1886,6 +1937,84 @@ paths:
summary: Get Current User
tags:
- Auth
/auth/password/reset:
post:
consumes:
- application/json
description: Completes a password reset using a valid token previously emailed
to the user. Invalidates all the user's existing sessions on success.
parameters:
- description: Reset token + new password
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.ResetPasswordRequest'
produces:
- application/json
responses:
"200":
description: Password reset successfully
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid or expired token, or password validation failed
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Failed to update password
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Reset password with token
tags:
- Auth
/auth/password/reset-request:
post:
consumes:
- application/json
description: Sends a password reset link to the user's email if the address
exists. Always returns 200 with a generic message to prevent email enumeration.
parameters:
- description: Email of the account to reset
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.RequestPasswordResetRequest'
produces:
- application/json
responses:
"200":
description: If the email exists, a reset link has been sent
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Token generation/storage failed (or SMTP failure in production)
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Request password reset
tags:
- Auth
/auth/refresh:
post:
consumes:
@ -3140,6 +3269,445 @@ paths:
summary: Get playlist by share token
tags:
- Playlist
/queue:
delete:
consumes:
- application/json
description: Removes every item from the authenticated user's playback queue
produces:
- application/json
responses:
"200":
description: Queue cleared
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Clear queue
tags:
- Queue
get:
consumes:
- application/json
description: Returns the authenticated user's persistent playback queue with
all items in position order
produces:
- application/json
responses:
"200":
description: Queue + items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Get user playback queue
tags:
- Queue
put:
consumes:
- application/json
description: Updates the authenticated user's queue state (current track / position
/ playback flags / item order)
parameters:
- description: Queue update payload
in: body
name: request
required: true
schema:
$ref: '#/definitions/veza-backend-api_internal_services.UpdateQueueRequest'
produces:
- application/json
responses:
"200":
description: Updated queue
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
queue:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Update user playback queue
tags:
- Queue
/queue/items:
post:
consumes:
- application/json
description: Appends a track to the authenticated user's playback queue
parameters:
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddQueueItemRequest'
produces:
- application/json
responses:
"201":
description: Created queue item
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
item:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue
tags:
- Queue
/queue/items/{id}:
delete:
consumes:
- application/json
description: Removes a single item from the authenticated user's playback queue
by item ID
parameters:
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Invalid item ID
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Queue item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove queue item
tags:
- Queue
/queue/session:
post:
consumes:
- application/json
description: Creates a shared queue session and returns its share token + URL.
The session creator is recorded as host.
produces:
- application/json
responses:
"201":
description: Created session
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
session:
type: object
share_token:
type: string
share_url:
type: string
type: object
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Create collaborative queue session
tags:
- Queue
/queue/session/{token}:
delete:
consumes:
- application/json
description: Deletes a collaborative queue session. Only the original session
creator can delete.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session deleted
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"403":
description: Only the creator can delete this session
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Delete queue session
tags:
- Queue
get:
consumes:
- application/json
description: Returns the session metadata + items for a given share token. No
auth required (public — anyone with the link can join).
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
produces:
- application/json
responses:
"200":
description: Session and queue items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Token required
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
summary: Get queue session by share token
tags:
- Queue
/queue/session/{token}/items:
post:
consumes:
- application/json
description: Adds a track to a collaborative queue session. Anyone with the
share token can add.
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Track to enqueue
in: body
name: request
required: true
schema:
$ref: '#/definitions/internal_handlers.AddToSessionRequest'
produces:
- application/json
responses:
"201":
description: Updated session and items
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
items:
items:
type: object
type: array
session:
type: object
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Add track to queue session
tags:
- Queue
/queue/session/{token}/items/{id}:
delete:
consumes:
- application/json
description: Removes an item from a collaborative queue session by item ID
parameters:
- description: Session share token
in: path
name: token
required: true
type: string
- description: Queue item ID (UUID)
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Item removed
schema:
allOf:
- $ref: '#/definitions/internal_handlers.APIResponse'
- properties:
data:
properties:
message:
type: string
type: object
type: object
"400":
description: Validation error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"404":
description: Session or item not found
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
"500":
description: Internal Error
schema:
$ref: '#/definitions/internal_handlers.APIResponse'
security:
- BearerAuth: []
summary: Remove item from queue session
tags:
- Queue
/tracks:
get:
description: List tracks with pagination, filters, sort. Cursor-based when ?cursor