diff --git a/lib/api/archiveHandler.ts b/lib/api/archiveHandler.ts index c4b5c5e..a32498f 100644 --- a/lib/api/archiveHandler.ts +++ b/lib/api/archiveHandler.ts @@ -7,10 +7,9 @@ import { JSDOM } from "jsdom"; import DOMPurify from "dompurify"; import { Collection, Link, User } from "@prisma/client"; import validateUrlSize from "./validateUrlSize"; -import removeFile from "./storage/removeFile"; -import Jimp from "jimp"; import createFolder from "./storage/createFolder"; import generatePreview from "./generatePreview"; +import { removeFiles } from "./manageLinkFiles"; type LinksAndCollectionAndOwner = Link & { collection: Collection & { @@ -52,6 +51,14 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) { ); }); + createFolder({ + filePath: `archives/preview/${link.collectionId}`, + }); + + createFolder({ + filePath: `archives/${link.collectionId}`, + }); + try { await Promise.race([ (async () => { @@ -163,10 +170,6 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) { return metaTag ? (metaTag as any).content : null; }); - createFolder({ - filePath: `archives/preview/${link.collectionId}`, - }); - if (ogImageUrl) { console.log("Found og:image URL:", ogImageUrl); @@ -296,14 +299,7 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) { }, }); else { - removeFile({ filePath: `archives/${link.collectionId}/${link.id}.png` }); - removeFile({ filePath: `archives/${link.collectionId}/${link.id}.pdf` }); - removeFile({ - filePath: `archives/${link.collectionId}/${link.id}_readability.json`, - }); - removeFile({ - filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`, - }); + await removeFiles(link.id, link.collectionId); } await browser.close(); diff --git a/lib/api/controllers/links/bulk/deleteLinksById.ts b/lib/api/controllers/links/bulk/deleteLinksById.ts index 466db98..2db3896 100644 --- a/lib/api/controllers/links/bulk/deleteLinksById.ts +++ b/lib/api/controllers/links/bulk/deleteLinksById.ts @@ -2,6 +2,7 @@ import { prisma } from "@/lib/api/db"; import { UsersAndCollections } from "@prisma/client"; import getPermission from "@/lib/api/getPermission"; import removeFile from "@/lib/api/storage/removeFile"; +import { removeFiles } from "@/lib/api/manageLinkFiles"; export default async function deleteLinksById( userId: number, @@ -43,15 +44,7 @@ export default async function deleteLinksById( const linkId = linkIds[i]; const collectionIsAccessible = collectionIsAccessibleArray[i]; - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}.pdf`, - }); - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}.png`, - }); - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}_readability.json`, - }); + if (collectionIsAccessible) removeFiles(linkId, collectionIsAccessible.id); } return { response: deletedLinks, status: 200 }; diff --git a/lib/api/controllers/links/linkId/deleteLinkById.ts b/lib/api/controllers/links/linkId/deleteLinkById.ts index db68ee7..dba90cb 100644 --- a/lib/api/controllers/links/linkId/deleteLinkById.ts +++ b/lib/api/controllers/links/linkId/deleteLinkById.ts @@ -2,6 +2,7 @@ import { prisma } from "@/lib/api/db"; import { Link, UsersAndCollections } from "@prisma/client"; import getPermission from "@/lib/api/getPermission"; import removeFile from "@/lib/api/storage/removeFile"; +import { removeFiles } from "@/lib/api/manageLinkFiles"; export default async function deleteLink(userId: number, linkId: number) { if (!linkId) return { response: "Please choose a valid link.", status: 401 }; @@ -12,7 +13,10 @@ export default async function deleteLink(userId: number, linkId: number) { (e: UsersAndCollections) => e.userId === userId && e.canDelete ); - if (!(collectionIsAccessible?.ownerId === userId || memberHasAccess)) + if ( + !collectionIsAccessible || + !(collectionIsAccessible?.ownerId === userId || memberHasAccess) + ) return { response: "Collection is not accessible.", status: 401 }; const deleteLink: Link = await prisma.link.delete({ @@ -21,15 +25,7 @@ export default async function deleteLink(userId: number, linkId: number) { }, }); - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}.pdf`, - }); - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}.png`, - }); - removeFile({ - filePath: `archives/${collectionIsAccessible?.id}/${linkId}_readability.json`, - }); + removeFiles(linkId, collectionIsAccessible.id); return { response: deleteLink, status: 200 }; } diff --git a/lib/api/controllers/links/linkId/updateLinkById.ts b/lib/api/controllers/links/linkId/updateLinkById.ts index e6f7f0d..4a24f4a 100644 --- a/lib/api/controllers/links/linkId/updateLinkById.ts +++ b/lib/api/controllers/links/linkId/updateLinkById.ts @@ -2,7 +2,7 @@ import { prisma } from "@/lib/api/db"; import { LinkIncludingShortenedCollectionAndTags } from "@/types/global"; import { UsersAndCollections } from "@prisma/client"; import getPermission from "@/lib/api/getPermission"; -import moveFile from "@/lib/api/storage/moveFile"; +import { moveFiles } from "@/lib/api/manageLinkFiles"; export default async function updateLinkById( userId: number, @@ -146,20 +146,7 @@ export default async function updateLinkById( }); if (collectionIsAccessible?.id !== data.collection.id) { - await moveFile( - `archives/${collectionIsAccessible?.id}/${linkId}.pdf`, - `archives/${data.collection.id}/${linkId}.pdf` - ); - - await moveFile( - `archives/${collectionIsAccessible?.id}/${linkId}.png`, - `archives/${data.collection.id}/${linkId}.png` - ); - - await moveFile( - `archives/${collectionIsAccessible?.id}/${linkId}_readability.json`, - `archives/${data.collection.id}/${linkId}_readability.json` - ); + await moveFiles(linkId, collectionIsAccessible?.id, data.collection.id); } return { response: updatedLink, status: 200 }; diff --git a/lib/api/controllers/users/userId/deleteUserById.ts b/lib/api/controllers/users/userId/deleteUserById.ts index 2a5a083..976bd71 100644 --- a/lib/api/controllers/users/userId/deleteUserById.ts +++ b/lib/api/controllers/users/userId/deleteUserById.ts @@ -71,6 +71,10 @@ export default async function deleteUserById( // Delete archive folders removeFolder({ filePath: `archives/${collection.id}` }); + + await removeFolder({ + filePath: `archives/preview/${collection.id}`, + }); } // Delete collections after cleaning up related data diff --git a/lib/api/generatePreview.ts b/lib/api/generatePreview.ts index 3c2da0f..6e81630 100644 --- a/lib/api/generatePreview.ts +++ b/lib/api/generatePreview.ts @@ -1,6 +1,7 @@ import Jimp from "jimp"; import { prisma } from "./db"; import createFile from "./storage/createFile"; +import createFolder from "./storage/createFolder"; const generatePreview = async ( buffer: Buffer, diff --git a/lib/api/manageLinkFiles.ts b/lib/api/manageLinkFiles.ts new file mode 100644 index 0000000..7bacdab --- /dev/null +++ b/lib/api/manageLinkFiles.ts @@ -0,0 +1,61 @@ +import moveFile from "./storage/moveFile"; +import removeFile from "./storage/removeFile"; + +const removeFiles = async (linkId: number, collectionId: number) => { + // PDF + await removeFile({ + filePath: `archives/${collectionId}/${linkId}.pdf`, + }); + // Images + await removeFile({ + filePath: `archives/${collectionId}/${linkId}.png`, + }); + await removeFile({ + filePath: `archives/${collectionId}/${linkId}.jpeg`, + }); + await removeFile({ + filePath: `archives/${collectionId}/${linkId}.jpg`, + }); + // Preview + await removeFile({ + filePath: `archives/preview/${collectionId}/${linkId}.jpeg`, + }); + // Readability + await removeFile({ + filePath: `archives/${collectionId}/${linkId}_readability.json`, + }); +}; + +const moveFiles = async (linkId: number, from: number, to: number) => { + await moveFile( + `archives/${from}/${linkId}.pdf`, + `archives/${to}/${linkId}.pdf` + ); + + await moveFile( + `archives/${from}/${linkId}.png`, + `archives/${to}/${linkId}.png` + ); + + await moveFile( + `archives/${from}/${linkId}.jpeg`, + `archives/${to}/${linkId}.jpeg` + ); + + await moveFile( + `archives/${from}/${linkId}.jpg`, + `archives/${to}/${linkId}.jpg` + ); + + await moveFile( + `archives/preview/${from}/${linkId}.jpeg`, + `archives/preview/${to}/${linkId}.jpeg` + ); + + await moveFile( + `archives/${from}/${linkId}_readability.json`, + `archives/${to}/${linkId}_readability.json` + ); +}; + +export { removeFiles, moveFiles }; diff --git a/pages/api/v1/archives/[linkId].ts b/pages/api/v1/archives/[linkId].ts index 554d4b9..9a439ec 100644 --- a/pages/api/v1/archives/[linkId].ts +++ b/pages/api/v1/archives/[linkId].ts @@ -11,6 +11,7 @@ import fs from "fs"; import verifyToken from "@/lib/api/verifyToken"; import Jimp from "jimp"; import generatePreview from "@/lib/api/generatePreview"; +import createFolder from "@/lib/api/storage/createFolder"; export const config = { api: { @@ -127,11 +128,12 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) { }); if (linkStillExists && files.file[0].mimetype?.includes("image")) { - generatePreview( - fileBuffer, - collectionPermissions?.id as number, - linkId - ); + const collectionId = collectionPermissions?.id as number; + createFolder({ + filePath: `archives/preview/${collectionId}`, + }); + + generatePreview(fileBuffer, collectionId, linkId); } if (linkStillExists) { diff --git a/pages/api/v1/links/[id]/archive/index.ts b/pages/api/v1/links/[id]/archive/index.ts index 4693fac..78353bb 100644 --- a/pages/api/v1/links/[id]/archive/index.ts +++ b/pages/api/v1/links/[id]/archive/index.ts @@ -2,8 +2,8 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { prisma } from "@/lib/api/db"; import verifyUser from "@/lib/api/verifyUser"; import isValidUrl from "@/lib/shared/isValidUrl"; -import removeFile from "@/lib/api/storage/removeFile"; import { Collection, Link } from "@prisma/client"; +import { removeFiles } from "@/lib/api/manageLinkFiles"; const RE_ARCHIVE_LIMIT = Number(process.env.RE_ARCHIVE_LIMIT) || 5; @@ -80,16 +80,5 @@ const deleteArchivedFiles = async (link: Link & { collection: Collection }) => { }, }); - await removeFile({ - filePath: `archives/${link.collection.id}/${link.id}.pdf`, - }); - await removeFile({ - filePath: `archives/${link.collection.id}/${link.id}.png`, - }); - await removeFile({ - filePath: `archives/${link.collection.id}/${link.id}_readability.json`, - }); - await removeFile({ - filePath: `archives/preview/${link.collection.id}/${link.id}.png`, - }); + await removeFiles(link.id, link.collection.id); };