77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import type { RequestHandler } from '@sveltejs/kit';
|
|
import { setBeatLeaderSessionFromSetCookieHeaders } from '$lib/server/beatleaderAuth';
|
|
|
|
/**
|
|
* Session-based login mimicking beatleader-website signin with login/password.
|
|
* Proxies credentials to BeatLeader and captures Set-Cookie, storing them as a session for server-side authenticated calls.
|
|
*
|
|
* Supported body formats:
|
|
* - application/json: { login: string, password: string, action?: 'login' | 'signup' }
|
|
* - multipart/form-data or application/x-www-form-urlencoded with fields: login, password, action
|
|
*/
|
|
export const POST: RequestHandler = async ({ request, cookies, fetch }) => {
|
|
let login = '';
|
|
let password = '';
|
|
let action = 'login';
|
|
|
|
const contentType = request.headers.get('content-type') || '';
|
|
if (contentType.includes('application/json')) {
|
|
const body = (await request.json()) as any;
|
|
login = String(body.login ?? '').trim();
|
|
password = String(body.password ?? '').trim();
|
|
if (body.action) action = String(body.action);
|
|
} else {
|
|
const form = await request.formData();
|
|
login = String(form.get('login') ?? '').trim();
|
|
password = String(form.get('password') ?? '').trim();
|
|
action = String(form.get('action') ?? 'login');
|
|
}
|
|
|
|
if (!login || !password) {
|
|
return new Response(JSON.stringify({ error: 'login and password are required' }), {
|
|
status: 400,
|
|
headers: { 'content-type': 'application/json' }
|
|
});
|
|
}
|
|
|
|
const fd = new FormData();
|
|
fd.set('action', action);
|
|
fd.set('login', login);
|
|
fd.set('password', password);
|
|
|
|
// Proxy to BeatLeader website login endpoint
|
|
const blRes = await fetch('https://api.beatleader.com/signinoculus', {
|
|
method: 'POST',
|
|
body: fd,
|
|
// Do not send our cookies to third-party; we're simply capturing upstream cookies from response
|
|
redirect: 'manual'
|
|
});
|
|
|
|
// In website, successful response is empty text; otherwise contains an error message
|
|
const text = await blRes.text();
|
|
|
|
// Capture Set-Cookie headers regardless of body
|
|
try {
|
|
const setCookieHeaders = (blRes.headers as any).getSetCookie?.() ?? blRes.headers.get('set-cookie')?.split(',') ?? [];
|
|
setBeatLeaderSessionFromSetCookieHeaders(cookies, Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders]);
|
|
} catch {}
|
|
|
|
if (!blRes.ok) {
|
|
return new Response(JSON.stringify({ error: text || `BeatLeader returned ${blRes.status}` }), {
|
|
status: 400,
|
|
headers: { 'content-type': 'application/json' }
|
|
});
|
|
}
|
|
|
|
if (text && text.length > 0) {
|
|
return new Response(JSON.stringify({ error: text }), {
|
|
status: 401,
|
|
headers: { 'content-type': 'application/json' }
|
|
});
|
|
}
|
|
|
|
return new Response(JSON.stringify({ ok: true }), { headers: { 'content-type': 'application/json' } });
|
|
};
|
|
|
|
|