Minor refactoring on the attachment api route

This commit is contained in:
Andreas 2024-06-23 23:02:33 +02:00
parent de220ae02a
commit ac8bdb73c8

View File

@ -8,41 +8,48 @@ import { UUID, randomUUID } from "crypto";
import { mkdir, mkdirSync, writeFile } from "fs"; import { mkdir, mkdirSync, writeFile } from "fs";
import { where } from "@sequelize/core"; import { where } from "@sequelize/core";
async function writeFilesToFS(uuid: UUID, files: any[]): Promise<{ success: boolean, filePaths: string[] }> {
async function writeFilesToBucket(uuid: UUID, files: any[]) { type FileArrayEntryWithPromise = {
name: string;
type FileArrayEntry = {
name:string;
content: Promise<ReadableStreamReadResult<Uint8Array>> | ReadableStreamReadResult<Uint8Array> content: Promise<ReadableStreamReadResult<Uint8Array>> | ReadableStreamReadResult<Uint8Array>
} }
type FileArrayEntry = {
name: string;
content: ReadableStreamReadResult<Uint8Array>
};
const fileArray:FileArrayEntry[] = await Promise.all(files.map((file: File) => { // Resolve promises
const fileArray: FileArrayEntryWithPromise[] = await Promise.all(files.map((file: File) => {
return { 'name': (() => file.name)(), 'content': file.stream().getReader().read() }; return { 'name': (() => file.name)(), 'content': file.stream().getReader().read() };
})); }));
let finalFileArray: { name: string, content: ReadableStreamReadResult<Uint8Array> }[] = await (async () => {
let finalFileArray: FileArrayEntry[] = await (
async () => {
for (let file in fileArray) { for (let file in fileArray) {
fileArray[file].content = await fileArray[file].content fileArray[file].content = await fileArray[file].content
} }
return [...fileArray as { name: string, content: ReadableStreamReadResult<Uint8Array> }[]] return [...fileArray as FileArrayEntry[]]
})(); })();
mkdirSync(`./bucket/${uuid}/`) // Make Bucket Directory
mkdirSync(`./bucket/${uuid}/`, { recursive: true })
// Write files to filesystem
for (let file in finalFileArray) { for (let file in finalFileArray) {
writeFile( writeFile(`./bucket/${uuid}/${finalFileArray[file].name}`
`./bucket/${uuid}/${finalFileArray[file].name}`, , Buffer.from(finalFileArray[file].content.value as Uint8Array)
Buffer.from(finalFileArray[file].content.value as Uint8Array), , (e) => { console.log(e) });
(e) => { console.log(e) } }
); return {
const attachment = await Attachment.create( success: true,
{ bucket_id: uuid, filename: finalFileArray[file].name }, filePaths: finalFileArray.map((e) => e.name)
{ include: Attachment.associations.bucket }
);
console.log(attachment);
} }
} }
async function addToPost(postid: number): Promise<Bucket> { async function addToNewBucketForPost(postid: number): Promise<Bucket> {
Post.sync(); Post.sync();
const post = await Post.findOne({ where: { id: postid } }); const post = await Post.findOne({ where: { id: postid } });
@ -50,7 +57,7 @@ async function addToPost(postid: number): Promise<Bucket> {
const bucket = await post.createBucket({ id: randomUUID() }); const bucket = await post.createBucket({ id: randomUUID() });
return bucket; return bucket;
} }
async function addToBucket(bucketid: number): Promise<Bucket> { async function addToExistingBucket(bucketid: number): Promise<Bucket> {
const bucket = await Bucket.findOne({ const bucket = await Bucket.findOne({
where: { id: bucketid }, include: { association: Bucket.associations.posts } where: { id: bucketid }, include: { association: Bucket.associations.posts }
}); });
@ -92,10 +99,11 @@ async function tryCreateAttachment(request: Request) {
// Sanity check the auth and associated user for authorization // Sanity check the auth and associated user for authorization
if (!auth || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error" }); if (!auth
if (!auth.user.id) throw new APIError({ status: 500, responseText: "Missing user id" }); || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error" });
if (!auth.user.perms || !auth.user.perms.isAdmin) if (!auth.user.id) throw new APIError({ status: 401, responseText: "Missing user id" });
throw new APIError({ status: 401, responseText: `Unauthorized ${JSON.stringify(auth.user)}` }); if (!auth.user.perms
|| !auth.user.perms.isAdmin) throw new APIError({ status: 401, responseText: `Unauthorized` });
// Handle incomplete data or other problems // Handle incomplete data or other problems
if (!files) throw new APIError({ status: 500, responseText: "Missing file" }); if (!files) throw new APIError({ status: 500, responseText: "Missing file" });
if (!formData) throw new APIError({ status: 500, responseText: "Empty request body" }); if (!formData) throw new APIError({ status: 500, responseText: "Empty request body" });
@ -103,23 +111,40 @@ async function tryCreateAttachment(request: Request) {
if (!(typeof requestData == "string")) throw new APIError({ status: 500, responseText: "Malformed request data" }); if (!(typeof requestData == "string")) throw new APIError({ status: 500, responseText: "Malformed request data" });
// Parse JSON
const data = JSON.parse(requestData); const data = JSON.parse(requestData);
let bucket:Bucket = (data.postid && !data.bucketid) ? await addToPost(data.postid) : await addToBucket(data.bucketid) // Get or create bucket
writeFilesToBucket(bucket.id, files); const bucket: Bucket = (data.postid && !data.bucketid)
? await addToNewBucketForPost(data.postid)
: await addToExistingBucket(data.bucketid);
// Write files to bucket and store as attachments in DB
const writeResult = await writeFilesToFS(bucket.id, files);
// Handle failure
if (!writeResult.success) throw new APIError({ status: 500, responseText: "Error writing files to Bucket" });
const bucket2 = await Bucket.findOne({ // Write attachments to db
const attachments = ((writeResult).filePaths.map(async (fp) => {
return (await Attachment.create(
{
bucket_id: bucket.id,
filename: fp
},
{ include: Attachment.associations.bucket }
));
}))
attachments;
return new Response(
JSON.stringify({
bucket: await Bucket.findOne({
where: { id: bucket.id }, where: { id: bucket.id },
include: [Bucket.associations.posts, Bucket.associations.attachments] include: [Bucket.associations.posts, Bucket.associations.attachments]
}); })
}),
{ status: 200 }
return new Response(JSON.stringify({ );
bucket: bucket2
}), { status: 200 });
} }
export async function tryFetchAttachments(request: Request) { export async function tryFetchAttachments(request: Request) {