check file size in server action
All checks were successful
deploy / build-and-deploy (/testvaro, /opt/website-test, website-test) (push) Successful in 21s
deploy / build-and-deploy (/varo, /opt/website, website) (push) Successful in 13s

This commit is contained in:
2025-06-21 21:54:01 +02:00
parent eb39cae44c
commit 94e9e83e93
4 changed files with 20 additions and 8 deletions

View File

@ -3,11 +3,12 @@ import { Session } from '@util/session.ts';
import { Permissions } from '@util/permissions.ts'; import { Permissions } from '@util/permissions.ts';
import { db } from '@db/database.ts'; import { db } from '@db/database.ts';
import { z } from 'astro:schema'; import { z } from 'astro:schema';
import { UPLOAD_PATH } from 'astro:env/server'; import { MAX_UPLOAD_BYTES, UPLOAD_PATH } from 'astro:env/server';
import fs from 'node:fs'; import fs from 'node:fs';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import path from 'node:path'; import path from 'node:path';
import { sendWebhook, WebhookAction } from '@util/webhook.ts'; import { sendWebhook, WebhookAction } from '@util/webhook.ts';
import { allowedImageTypes, allowedVideoTypes } from '@util/media.ts';
export const report = { export const report = {
submitReport: defineAction({ submitReport: defineAction({
@ -15,9 +16,22 @@ export const report = {
urlHash: z.string(), urlHash: z.string(),
reason: z.string(), reason: z.string(),
body: z.string(), body: z.string(),
files: z.array(z.instanceof(File)).nullable() files: z
.array(
z
.instanceof(File)
.refine((f) => [...allowedImageTypes, ...allowedVideoTypes].findIndex((v) => v === f.type) !== -1)
)
.nullable()
}), }),
handler: async (input) => { handler: async (input) => {
const fileSize = input.files?.reduce((prev, curr) => prev + curr.size, 0);
if (fileSize && fileSize > MAX_UPLOAD_BYTES) {
throw new ActionError({
code: 'BAD_REQUEST'
});
}
const report = await db.getReportByUrlHash({ urlHash: input.urlHash }); const report = await db.getReportByUrlHash({ urlHash: input.urlHash });
if (!report) { if (!report) {
throw new ActionError({ throw new ActionError({

View File

@ -38,8 +38,7 @@
{ key: 'report.status?.status', label: 'Bearbeitungsstatus' } { key: 'report.status?.status', label: 'Bearbeitungsstatus' }
]} ]}
onClick={(report) => (activeReport = report)} onClick={(report) => (activeReport = report)}
> />
</DataTable>
{#key activeReport} {#key activeReport}
<BottomBar {strikeReasons} report={activeReport} /> <BottomBar {strikeReasons} report={activeReport} />

View File

@ -1,15 +1,12 @@
<script lang="ts"> <script lang="ts">
import { popupState } from '@components/popup/Popup.ts'; import { popupState } from '@components/popup/Popup.ts';
import { allowedImageTypes, allowedVideoTypes } from '@util/media.ts';
// bindings // bindings
let containerElem: HTMLDivElement; let containerElem: HTMLDivElement;
let hiddenFileInputElem: HTMLInputElement; let hiddenFileInputElem: HTMLInputElement;
let previewDialogElem: HTMLDialogElement; let previewDialogElem: HTMLDialogElement;
// consts
const allowedImageTypes = ['image/png', 'image/jpeg', 'image/webp', 'image/avif'];
const allowedVideoTypes = ['video/mp4', 'video/webm'];
// types // types
interface Props { interface Props {
maxFilesBytes: number; maxFilesBytes: number;

2
src/util/media.ts Normal file
View File

@ -0,0 +1,2 @@
export const allowedImageTypes = ['image/png', 'image/jpeg', 'image/webp', 'image/avif'];
export const allowedVideoTypes = ['video/mp4', 'video/webm'];