64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
|
|
const BASE = '/api/experience';
|
||
|
|
|
||
|
|
async function request(method: string, path: string, body?: unknown): Promise<Response> {
|
||
|
|
const res = await fetch(`${BASE}${path}`, {
|
||
|
|
method,
|
||
|
|
headers: body ? { 'Content-Type': 'application/json' } : undefined,
|
||
|
|
body: body ? JSON.stringify(body) : undefined,
|
||
|
|
credentials: 'same-origin',
|
||
|
|
});
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function initInteraction(): Promise<void> {
|
||
|
|
const res = await request('PUT', '', { interactionEvent: 'SignIn' });
|
||
|
|
if (!res.ok) {
|
||
|
|
const err = await res.json().catch(() => ({}));
|
||
|
|
throw new Error(err.message || `Failed to initialize sign-in (${res.status})`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function verifyPassword(
|
||
|
|
username: string,
|
||
|
|
password: string
|
||
|
|
): Promise<string> {
|
||
|
|
const res = await request('POST', '/verification/password', {
|
||
|
|
identifier: { type: 'username', value: username },
|
||
|
|
password,
|
||
|
|
});
|
||
|
|
if (!res.ok) {
|
||
|
|
const err = await res.json().catch(() => ({}));
|
||
|
|
if (res.status === 422) {
|
||
|
|
throw new Error('Invalid username or password');
|
||
|
|
}
|
||
|
|
throw new Error(err.message || `Authentication failed (${res.status})`);
|
||
|
|
}
|
||
|
|
const data = await res.json();
|
||
|
|
return data.verificationId;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function identifyUser(verificationId: string): Promise<void> {
|
||
|
|
const res = await request('POST', '/identification', { verificationId });
|
||
|
|
if (!res.ok) {
|
||
|
|
const err = await res.json().catch(() => ({}));
|
||
|
|
throw new Error(err.message || `Identification failed (${res.status})`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function submitInteraction(): Promise<string> {
|
||
|
|
const res = await request('POST', '/submit');
|
||
|
|
if (!res.ok) {
|
||
|
|
const err = await res.json().catch(() => ({}));
|
||
|
|
throw new Error(err.message || `Submit failed (${res.status})`);
|
||
|
|
}
|
||
|
|
const data = await res.json();
|
||
|
|
return data.redirectTo;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function signIn(username: string, password: string): Promise<string> {
|
||
|
|
await initInteraction();
|
||
|
|
const verificationId = await verifyPassword(username, password);
|
||
|
|
await identifyUser(verificationId);
|
||
|
|
return submitInteraction();
|
||
|
|
}
|