29 lines
1.7 KiB
TypeScript
29 lines
1.7 KiB
TypeScript
import { json } from '@sveltejs/kit';
|
|
import type { RequestHandler } from './$types';
|
|
import { session, synchronize } from '$lib/server/application';
|
|
import { protectMutation } from '$lib/server/http';
|
|
import { capabilityDisabledReason, capabilityEnabled } from '$lib/server/release-gate';
|
|
import { configuration } from '$lib/server/config';
|
|
import { hashSecret } from '$lib/server/security';
|
|
import { SESSION_COOKIE } from '$lib/server/application';
|
|
export const POST: RequestHandler = async (event) => {
|
|
const config = configuration();
|
|
// Bound origin/session work by the existing anonymous IP bucket first. The
|
|
// normal authenticated user-keyed limiter is restored after resolution.
|
|
protectMutation(event, `sync:${event.getClientAddress()}`, 6);
|
|
if (!capabilityEnabled('asset_sync', config.capabilityAllowlist)) {
|
|
return json({ error: capabilityDisabledReason('asset_sync') }, { status: 503 });
|
|
}
|
|
const current = await session(event);
|
|
if (current) protectMutation(event, `sync:${current.userId}`, 6);
|
|
if (!current) return json({ error: 'Connect an EVE character first.' }, { status: 401 });
|
|
try {
|
|
const cookie = event.cookies.get(SESSION_COOKIE);
|
|
if (!cookie) return json({ error: 'Connect an EVE character first.' }, { status: 401 });
|
|
const result = await synchronize(current.userId, hashSecret(cookie));
|
|
const failures = result.skipped.filter((entry) => entry.reason !== 'authorization_required');
|
|
const status = result.queued > 0 ? 202 : failures.some((entry) => entry.reason === 'queue_full') ? 429 : failures.length > 0 ? 503 : 200;
|
|
return json(result, { status });
|
|
} catch { return json({ error: 'Synchronization unavailable. Check backend configuration and try again.' }, { status: 503 }); }
|
|
};
|