Add files via upload
This commit is contained in:
parent
97ddf01ed1
commit
96e7123805
2 changed files with 32 additions and 27 deletions
|
|
@ -1,5 +1,3 @@
|
||||||
// src/pages/upload.tsx
|
|
||||||
|
|
||||||
import { Elysia, t } from "elysia";
|
import { Elysia, t } from "elysia";
|
||||||
import db from "../db/db";
|
import db from "../db/db";
|
||||||
import { WEBROOT, CLAMAV_URL } from "../helpers/env";
|
import { WEBROOT, CLAMAV_URL } from "../helpers/env";
|
||||||
|
|
@ -25,7 +23,7 @@ type ClamAvResponse = {
|
||||||
* Send a file to ClamAV REST API (benzino77/clamav-rest-api).
|
* Send a file to ClamAV REST API (benzino77/clamav-rest-api).
|
||||||
* Returns { infected: boolean, viruses: string[] } and logs everything.
|
* Returns { infected: boolean, viruses: string[] } and logs everything.
|
||||||
*/
|
*/
|
||||||
async function scanFileWithClamAV(file: any, fileName: string) {
|
async function scanFileWithClamAV(file: File, fileName: string) {
|
||||||
// 🔀 Respect toggle + CLAMAV_URL availability
|
// 🔀 Respect toggle + CLAMAV_URL availability
|
||||||
if (!isAntivirusEnabled()) {
|
if (!isAntivirusEnabled()) {
|
||||||
console.log(
|
console.log(
|
||||||
|
|
@ -48,21 +46,9 @@ async function scanFileWithClamAV(file: any, fileName: string) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const FormDataCtor = (globalThis as any).FormData as
|
|
||||||
| (new () => { append: (name: string, value: any, fileName?: string) => void })
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
if (!FormDataCtor) {
|
|
||||||
console.error("[ClamAV] FormData is not available in this runtime, skipping scan.");
|
|
||||||
return {
|
|
||||||
infected: false,
|
|
||||||
viruses: [] as string[],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[ClamAV] Scanning file:", fileName, "via", CLAMAV_URL);
|
console.log("[ClamAV] Scanning file:", fileName, "via", CLAMAV_URL);
|
||||||
|
|
||||||
const formData = new FormDataCtor();
|
const formData = new FormData();
|
||||||
formData.append("FILES", file, fileName);
|
formData.append("FILES", file, fileName);
|
||||||
|
|
||||||
let rawText = "";
|
let rawText = "";
|
||||||
|
|
@ -71,7 +57,7 @@ async function scanFileWithClamAV(file: any, fileName: string) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(CLAMAV_URL, {
|
const res = await fetch(CLAMAV_URL, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData as any,
|
body: formData,
|
||||||
});
|
});
|
||||||
|
|
||||||
status = res.status;
|
status = res.status;
|
||||||
|
|
@ -175,9 +161,16 @@ export const upload = new Elysia()
|
||||||
|
|
||||||
const infectedFiles: { name: string; viruses: string[] }[] = [];
|
const infectedFiles: { name: string; viruses: string[] }[] = [];
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files as File[]) {
|
||||||
const originalName = (file as any).name ?? "upload";
|
const originalName = file.name ?? "upload";
|
||||||
const sanitizedFileName = sanitize(originalName) || "file";
|
|
||||||
|
// Sanitize first; if result is empty, generate a unique fallback
|
||||||
|
const baseSanitized = sanitize(originalName);
|
||||||
|
const sanitizedFileName =
|
||||||
|
baseSanitized && baseSanitized.trim().length > 0
|
||||||
|
? baseSanitized
|
||||||
|
: `file_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"[Upload] Handling file:",
|
"[Upload] Handling file:",
|
||||||
originalName,
|
originalName,
|
||||||
|
|
@ -203,7 +196,7 @@ export const upload = new Elysia()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Only save if clean, with sanitized filename
|
// 2) Only save if clean, with sanitized (or unique-fallback) filename
|
||||||
const targetPath = `${userUploadsDir}${sanitizedFileName}`;
|
const targetPath = `${userUploadsDir}${sanitizedFileName}`;
|
||||||
console.log("[Upload] Saving clean file to:", targetPath);
|
console.log("[Upload] Saving clean file to:", targetPath);
|
||||||
await Bun.write(targetPath, file);
|
await Bun.write(targetPath, file);
|
||||||
|
|
@ -238,4 +231,3 @@ export const upload = new Elysia()
|
||||||
auth: true,
|
auth: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -536,8 +536,8 @@ export const user = new Elysia()
|
||||||
<table
|
<table
|
||||||
class={`
|
class={`
|
||||||
w-full table-auto rounded bg-neutral-900
|
w-full table-auto rounded bg-neutral-900
|
||||||
[&_th]:border-b [&_th]:border-neutral-800 [&_th]:p-2
|
|
||||||
[&_td]:border-b [&_td]:border-neutral-800 [&_td]:p-2
|
[&_td]:border-b [&_td]:border-neutral-800 [&_td]:p-2
|
||||||
|
[&_th]:border-b [&_th]:border-neutral-800 [&_th]:p-2
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
|
|
@ -566,7 +566,10 @@ export const user = new Elysia()
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="inline-flex items-center justify-center text-accent-400 hover:text-accent-300"
|
class={`
|
||||||
|
inline-flex items-center justify-center text-accent-400
|
||||||
|
hover:text-accent-500
|
||||||
|
`}
|
||||||
title="Edit user"
|
title="Edit user"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -598,7 +601,10 @@ export const user = new Elysia()
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="inline-flex items-center justify-center text-accent-400 hover:text-accent-300"
|
class={`
|
||||||
|
inline-flex items-center justify-center text-accent-400
|
||||||
|
hover:text-accent-500
|
||||||
|
`}
|
||||||
title="Delete user"
|
title="Delete user"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -671,6 +677,7 @@ export const user = new Elysia()
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields: string[] = [];
|
const fields: string[] = [];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const values: any[] = [];
|
const values: any[] = [];
|
||||||
|
|
||||||
if (body.email) {
|
if (body.email) {
|
||||||
|
|
@ -822,7 +829,13 @@ export const user = new Elysia()
|
||||||
it unchanged.
|
it unchanged.
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
<form method="post" action={`${WEBROOT}/account/edit-user`} class="flex flex-col gap-4">
|
<form
|
||||||
|
method="post"
|
||||||
|
action={`${WEBROOT}/account/edit-user`}
|
||||||
|
class={`
|
||||||
|
flex flex-col gap-4
|
||||||
|
`}
|
||||||
|
>
|
||||||
<input type="hidden" name="userId" value={String(targetUser.id)} />
|
<input type="hidden" name="userId" value={String(targetUser.id)} />
|
||||||
<fieldset class="mb-4 flex flex-col gap-4">
|
<fieldset class="mb-4 flex flex-col gap-4">
|
||||||
<label class="flex flex-col gap-1">
|
<label class="flex flex-col gap-1">
|
||||||
|
|
@ -931,6 +944,7 @@ export const user = new Elysia()
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields: string[] = [];
|
const fields: string[] = [];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const values: any[] = [];
|
const values: any[] = [];
|
||||||
|
|
||||||
if (role === "admin" || role === "user") {
|
if (role === "admin" || role === "user") {
|
||||||
|
|
@ -1038,4 +1052,3 @@ export const user = new Elysia()
|
||||||
cookie: "session",
|
cookie: "session",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue