minor bugfixes
This commit is contained in:
@@ -9,6 +9,7 @@ import { NextResponse } from 'next/server';
|
||||
import {
|
||||
maxRetentionSeconds,
|
||||
maxUploadBytes,
|
||||
publicBaseUrl,
|
||||
shareDir,
|
||||
uploadTtlSeconds,
|
||||
} from '@/src/lib/config.js';
|
||||
@@ -41,8 +42,49 @@ function requestPageHref(requestId, params = {}) {
|
||||
return serialized ? `/_request/${encodedId}?${serialized}` : `/_request/${encodedId}`;
|
||||
}
|
||||
|
||||
function redirectToRequest(request, requestId, params = {}) {
|
||||
return NextResponse.redirect(new URL(requestPageHref(requestId, params), request.url), { status: 303 });
|
||||
function redirectToRequest(requestId, params = {}) {
|
||||
return new NextResponse(null, {
|
||||
status: 303,
|
||||
headers: {
|
||||
location: requestPageHref(requestId, params),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function firstForwardedPart(value) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
return value.split(',')[0].trim();
|
||||
}
|
||||
|
||||
function requestOrigin(request) {
|
||||
const forwardedHost = firstForwardedPart(request.headers.get('x-forwarded-host'));
|
||||
const host = forwardedHost || request.headers.get('host') || '';
|
||||
if (!host) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const forwardedProto = firstForwardedPart(request.headers.get('x-forwarded-proto'));
|
||||
const proto = forwardedProto || (host.startsWith('localhost') || host.startsWith('127.0.0.1') ? 'http' : 'https');
|
||||
return `${proto}://${host}`;
|
||||
}
|
||||
|
||||
function resolvePublicOrigin(request) {
|
||||
if (publicBaseUrl) {
|
||||
return publicBaseUrl;
|
||||
}
|
||||
|
||||
const fromHeaders = requestOrigin(request);
|
||||
if (fromHeaders) {
|
||||
return fromHeaders;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(request.url).origin;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function toBase32(buffer) {
|
||||
@@ -119,7 +161,7 @@ export async function POST(request, { params }) {
|
||||
try {
|
||||
formData = await request.formData();
|
||||
} catch {
|
||||
return redirectToRequest(request, requestId, { error: 'Ungültige Formulardaten.' });
|
||||
return redirectToRequest(requestId, { error: 'Ungültige Formulardaten.' });
|
||||
}
|
||||
|
||||
const uploadRequest = await get(
|
||||
@@ -130,25 +172,25 @@ export async function POST(request, { params }) {
|
||||
);
|
||||
|
||||
if (!uploadRequest) {
|
||||
return redirectToRequest(request, requestId, { error: 'Anfrage nicht gefunden.' });
|
||||
return redirectToRequest(requestId, { error: 'Anfrage nicht gefunden.' });
|
||||
}
|
||||
|
||||
if (Number(uploadRequest.completed_at || 0) > 0) {
|
||||
return redirectToRequest(request, requestId, { success: 'Diese Anfrage wurde bereits erfüllt.' });
|
||||
return redirectToRequest(requestId, { success: 'Diese Anfrage wurde bereits erfüllt.' });
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
if (Number(uploadRequest.expires_at || 0) <= now) {
|
||||
return redirectToRequest(request, requestId, { error: 'Diese Anfrage ist bereits abgelaufen.' });
|
||||
return redirectToRequest(requestId, { error: 'Diese Anfrage ist bereits abgelaufen.' });
|
||||
}
|
||||
|
||||
const uploadedFile = uploadedFileFromForm(formData, 'file');
|
||||
if (!uploadedFile || Number(uploadedFile.size || 0) <= 0) {
|
||||
return redirectToRequest(request, requestId, { error: 'Keine Datei hochgeladen.' });
|
||||
return redirectToRequest(requestId, { error: 'Keine Datei hochgeladen.' });
|
||||
}
|
||||
|
||||
if (maxUploadBytes > 0 && Number(uploadedFile.size || 0) > maxUploadBytes) {
|
||||
return redirectToRequest(request, requestId, {
|
||||
return redirectToRequest(requestId, {
|
||||
error: `Datei überschreitet das Größenlimit (${maxUploadBytes} Bytes).`,
|
||||
});
|
||||
}
|
||||
@@ -171,7 +213,7 @@ export async function POST(request, { params }) {
|
||||
}
|
||||
|
||||
if (!storedName || !storedPath) {
|
||||
return redirectToRequest(request, requestId, { error: 'Upload-ID konnte nicht erzeugt werden.' });
|
||||
return redirectToRequest(requestId, { error: 'Upload-ID konnte nicht erzeugt werden.' });
|
||||
}
|
||||
|
||||
const uploadExpiry = Math.min(now + uploadTtlSeconds * 1000, now + maxRetentionSeconds * 1000);
|
||||
@@ -187,7 +229,7 @@ export async function POST(request, { params }) {
|
||||
);
|
||||
uploadId = insertResult.lastID;
|
||||
} catch {
|
||||
return redirectToRequest(request, requestId, { error: 'Upload fehlgeschlagen.' });
|
||||
return redirectToRequest(requestId, { error: 'Upload fehlgeschlagen.' });
|
||||
}
|
||||
|
||||
const updateResult = await run(
|
||||
@@ -206,7 +248,7 @@ export async function POST(request, { params }) {
|
||||
if (!updateResult || updateResult.changes < 1) {
|
||||
await run('DELETE FROM uploads WHERE id = ?', [uploadId]).catch(() => undefined);
|
||||
await fs.promises.rm(storedPath, { force: true }).catch(() => undefined);
|
||||
return redirectToRequest(request, requestId, { success: 'Diese Anfrage wurde bereits erfüllt.' });
|
||||
return redirectToRequest(requestId, { success: 'Diese Anfrage wurde bereits erfüllt.' });
|
||||
}
|
||||
|
||||
await logEvent(
|
||||
@@ -216,7 +258,7 @@ export async function POST(request, { params }) {
|
||||
await getRequestMeta()
|
||||
);
|
||||
|
||||
const baseUrl = new URL(request.url).origin;
|
||||
const baseUrl = resolvePublicOrigin(request);
|
||||
const downloadUrl = `${baseUrl}/_share/${encodeURIComponent(storedName)}`;
|
||||
|
||||
const mailResult = await sendUploadRequestCompletedMail({
|
||||
@@ -230,7 +272,7 @@ export async function POST(request, { params }) {
|
||||
|
||||
if (mailResult.ok) {
|
||||
await run('UPDATE upload_requests SET notification_sent_at = ? WHERE id = ?', [Date.now(), requestId]);
|
||||
return redirectToRequest(request, requestId, { success: 'Datei erfolgreich hochgeladen. Vielen Dank!' });
|
||||
return redirectToRequest(requestId, { success: 'Datei erfolgreich hochgeladen. Vielen Dank!' });
|
||||
}
|
||||
|
||||
await logEvent(
|
||||
@@ -240,7 +282,7 @@ export async function POST(request, { params }) {
|
||||
await getRequestMeta()
|
||||
);
|
||||
|
||||
return redirectToRequest(request, requestId, {
|
||||
return redirectToRequest(requestId, {
|
||||
success: 'Datei hochgeladen. Hinweis: E-Mail-Benachrichtigung konnte nicht gesendet werden.',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -107,8 +107,12 @@ function expectsHtml(request) {
|
||||
|
||||
function errorResponse(request, message, status = 400) {
|
||||
if (expectsHtml(request)) {
|
||||
const target = new URL(dashboardHref({ error: message }), request.url);
|
||||
return NextResponse.redirect(target, { status: 303 });
|
||||
return new NextResponse(null, {
|
||||
status: 303,
|
||||
headers: {
|
||||
location: dashboardHref({ error: message }),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: false, error: message }, { status });
|
||||
@@ -117,8 +121,12 @@ function errorResponse(request, message, status = 400) {
|
||||
function successResponse(request, message) {
|
||||
const redirectPath = dashboardHref({ success: message });
|
||||
if (expectsHtml(request)) {
|
||||
const target = new URL(redirectPath, request.url);
|
||||
return NextResponse.redirect(target, { status: 303 });
|
||||
return new NextResponse(null, {
|
||||
status: 303,
|
||||
headers: {
|
||||
location: redirectPath,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true, redirect: redirectPath });
|
||||
|
||||
@@ -5,15 +5,33 @@ function parseInteger(value, fallback) {
|
||||
return Number.isFinite(parsed) ? parsed : fallback;
|
||||
}
|
||||
|
||||
function normalizeBaseUrl(value) {
|
||||
const raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const withProtocol = raw.includes('://') ? raw : `https://${raw}`;
|
||||
|
||||
try {
|
||||
const parsed = new URL(withProtocol);
|
||||
return `${parsed.protocol}//${parsed.host}`;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export const managementBasePath = '/manage';
|
||||
export const dataDir = process.env.DATA_DIR || path.join(process.cwd(), 'data');
|
||||
export const dbPath = process.env.DB_PATH || path.join(dataDir, 'uploads.sqlite');
|
||||
export const shareDir = path.join(dataDir, '_share');
|
||||
export const serviceFqdn = String(process.env.SERVICE_FQDN || '').trim();
|
||||
export const adminHash = process.env.MANAGEMENT_ADMIN_HASH || '';
|
||||
export const uploadTtlSeconds = parseInteger(process.env.UPLOAD_TTL_SECONDS || '604800', 604800);
|
||||
export const maxRetentionSeconds = 90 * 24 * 60 * 60;
|
||||
export const maxUploadBytes = parseInteger(process.env.UPLOAD_MAX_BYTES || '0', 0);
|
||||
export const cookieSecure = process.env.COOKIE_SECURE === 'true';
|
||||
export const publicBaseUrl = normalizeBaseUrl(process.env.PUBLIC_BASE_URL || serviceFqdn);
|
||||
export const smtpHost = String(process.env.SMTP_HOST || '').trim();
|
||||
export const smtpPort = parseInteger(process.env.SMTP_PORT || '587', 587);
|
||||
export const smtpUser = String(process.env.SMTP_USER || '').trim();
|
||||
|
||||
Reference in New Issue
Block a user