"use server"; import { APIError, attemptAPIAction } from "@/util"; import { sequelize, Bucket, Auth, Post, PostTag, Tag, User, dbSync, } from "@/models"; import { cookies } from "next/headers"; import { Attachment } from "@/models"; import { addToExistingBucket, addToNewBucketForPost, writeFilesToFS, } from "@/app/lib/actions/entityManagement/attachment/attachmentActions"; import { Attributes } from "@sequelize/core"; import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies"; export async function tryCreateAttachment(request: Request) { // Make sure the DB is ready await dbSync; // Prepare data const formData = await request.formData(); const requestData: string | Object | undefined = formData .get("data") ?.valueOf(); const files: FormDataEntryValue[] = formData.getAll("files"); const authCkie: RequestCookie | undefined = await cookies().get("auth"); // Sanity check auth cookie if (!authCkie || !authCkie.value) throw new APIError({ status: 500, responseText: "missing auth cookie", }); // Get JSON from the Cookie const cookieJSON: string = authCkie.value; const authObject:Attributes = JSON.parse(cookieJSON); // Fetch User Auth from thse database const auth = await Auth.findOne({ include: [ { model: User.withScope(["withPerms"]), attributes: { exclude: ["username", "password", "updatedAt", "createdAt"], }, }, ], where: { token: authObject.token }, }); // Sanity check the auth and associated user for authorization if (!auth || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error", }); if (!auth.user.id) throw new APIError({ status: 401, responseText: "Missing user id" }); if (!auth.user.perms || !auth.user.perms.isAdmin) throw new APIError({ status: 401, responseText: `Unauthorized` }); // Handle incomplete data or other problems if (!files) throw new APIError({ status: 500, responseText: "Missing file" }); if (!formData) throw new APIError({ status: 500, responseText: "Empty request body" }); if (!requestData) throw new APIError({ status: 500, responseText: "Missing request data", }); if (!(typeof requestData == "string")) throw new APIError({ status: 500, responseText: "Malformed request data", }); // Parse JSON const data = JSON.parse(requestData); // Get or create bucket 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", }); // 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 }, include: [ Bucket.associations.posts, Bucket.associations.attachments, ], }), }), { status: 200 } ); } export async function tryFetchAttachments(request: Request) { await Post.sync(); const foundPosts = await Post.findAll({ include: [ { association: Post.associations.user, attributes: { exclude: ["password", "createdAt", "updatedAt"] }, }, { association: Post.associations.postTags, }, ], }); return new Response(JSON.stringify(foundPosts), { status: 200 }); } export async function GET(request: Request) { return await attemptAPIAction(tryFetchAttachments, request); } export async function POST(request: Request) { return await attemptAPIAction(tryCreateAttachment, request); }