This commit is contained in:
2026-03-23 02:09:14 +01:00
parent 705329d3c2
commit d8d46ed8e9
61 changed files with 6054 additions and 3116 deletions

View File

@@ -19,16 +19,14 @@ async function parseError(res, text) {
}
function redirectToLogin() {
if (
!location.hash.startsWith('#/login') &&
!location.hash.startsWith('#/bootstrap')
) {
location.hash = '#/login';
const p = location.pathname;
if (p !== '/login.html' && p !== '/bootstrap.html') {
location.href = '/login.html';
}
}
/** Geschützte REST-API liegt unter /api (Root-URLs bleiben für die SPA frei). */
function apiUrl(path) {
export function apiUrl(path) {
if (path.startsWith('/auth/')) return path;
return `/api${path.startsWith('/') ? path : `/${path}`}`;
}
@@ -105,6 +103,23 @@ export async function apiDelete(path) {
return apiRequest('DELETE', path);
}
/** multipart/form-data (kein Content-Type setzen — Boundary setzt der Browser) */
export async function apiPostForm(path, formData) {
const url = apiUrl(path);
const res = await fetch(url, {
method: 'POST',
credentials: 'include',
body: formData,
});
const text = await res.text();
if (res.status === 401) {
onUnauthorized(path);
throw authRedirectError();
}
if (!res.ok) throw new Error(await parseError(res, text));
return parseJsonBody(text);
}
/** Öffentlich: keine Session nötig, kein Redirect bei 401 */
export async function authFetchStatus() {
const res = await fetch('/auth/status', { credentials: 'include' });