v3: allow users to edit dump thumbnail, fixed some linter errors in the frontend
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 41s

This commit is contained in:
khannurien
2026-06-21 15:41:40 +00:00
parent 57cf55cc48
commit cf988ae608
27 changed files with 431 additions and 121 deletions

View File

@@ -13,6 +13,8 @@ import {
import { authMiddleware } from "../middleware/auth.ts";
import { parseOptionalAuth } from "../lib/auth.ts";
import { parsePagination } from "../lib/pagination.ts";
import { validateImageUpload } from "../lib/upload.ts";
import { THUMBNAILS_DIR } from "../config.ts";
import {
createFileDump,
createUrlDump,
@@ -20,7 +22,9 @@ import {
getDump,
listDumps,
refreshDumpMetadata,
removeDumpThumbnail,
replaceFileDump,
setDumpThumbnail,
updateDump,
} from "../services/dump-service.ts";
import { getDumpVoters } from "../services/vote-service.ts";
@@ -175,6 +179,66 @@ router.put("/:dumpId", authMiddleware, async (ctx) => {
ctx.response.body = responseBody;
});
router.put("/:dumpId/thumbnail", authMiddleware, async (ctx) => {
const dumpId = ctx.params.dumpId;
const userId = ctx.state.user?.userId;
const dump = getDump(dumpId, userId);
if (userId !== dump.userId) {
throw new APIException(
APIErrorCode.UNAUTHORIZED,
403,
"Not authorized to update dump",
);
}
const formData = await ctx.request.body.formData();
const file = formData.get("file");
if (!(file instanceof File)) {
throw new APIException(
APIErrorCode.VALIDATION_ERROR,
400,
"Missing file field",
);
}
const data = new Uint8Array(await file.arrayBuffer());
const mime = validateImageUpload(data);
// DB update first (resolves slug → id), then file write.
const updatedDump = setDumpThumbnail(dump.id, mime);
const filePath = `${THUMBNAILS_DIR}/${dump.id}-custom`;
await Deno.mkdir(THUMBNAILS_DIR, { recursive: true });
try {
await Deno.writeFile(filePath, data);
} catch (err) {
await Deno.remove(filePath).catch(() => {});
throw err;
}
const responseBody: APIResponse<Dump> = { success: true, data: updatedDump };
ctx.response.body = responseBody;
});
router.delete("/:dumpId/thumbnail", authMiddleware, async (ctx) => {
const dumpId = ctx.params.dumpId;
const userId = ctx.state.user?.userId;
const dump = getDump(dumpId, userId);
if (userId !== dump.userId) {
throw new APIException(
APIErrorCode.UNAUTHORIZED,
403,
"Not authorized to update dump",
);
}
const updatedDump = await removeDumpThumbnail(dump.id);
const responseBody: APIResponse<Dump> = { success: true, data: updatedDump };
ctx.response.body = responseBody;
});
router.post("/:dumpId/refresh-metadata", authMiddleware, async (ctx) => {
const dumpId = ctx.params.dumpId;
const userId = ctx.state.user?.userId;