From 966136dab6a1ab7c27f1532d6a01d481ccf92fe9 Mon Sep 17 00:00:00 2001 From: daniel31x13 Date: Wed, 25 Oct 2023 15:42:36 -0400 Subject: [PATCH 01/33] created migration script [WIP] --- .../users/userId/deleteUserById.ts | 2 +- lib/api/migration/migrateToV2.js | 83 +++++++++++++++++++ .../migration.sql | 13 +++ prisma/schema.prisma | 5 +- 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 lib/api/migration/migrateToV2.js create mode 100644 prisma/migrations/20231025123038_added_pathname_to_files/migration.sql diff --git a/lib/api/controllers/users/userId/deleteUserById.ts b/lib/api/controllers/users/userId/deleteUserById.ts index 731e877..0641525 100644 --- a/lib/api/controllers/users/userId/deleteUserById.ts +++ b/lib/api/controllers/users/userId/deleteUserById.ts @@ -59,7 +59,7 @@ export default async function deleteUserById( where: { collectionId: collection.id }, }); - // Delete archive folders associated with collections + // Delete archive folders removeFolder({ filePath: `archives/${collection.id}` }); } diff --git a/lib/api/migration/migrateToV2.js b/lib/api/migration/migrateToV2.js new file mode 100644 index 0000000..aeb07fb --- /dev/null +++ b/lib/api/migration/migrateToV2.js @@ -0,0 +1,83 @@ +const { PrismaClient } = require("@prisma/client"); +const axios = require("axios"); +const { existsSync } = require("fs"); + +const prisma = new PrismaClient(); + +const STORAGE_FOLDER = process.env.STORAGE_FOLDER || "data"; + +async function checkFileExistence(path) { + try { + if (existsSync(path)) { + return true; + } else return false; + } catch (err) { + console.log(err); + } +} + +// Avatars +async function migrateAvatars() { + const users = await prisma.user.findMany(); + + for (let user of users) { + const path = STORAGE_FOLDER + `/uploads/avatar/${user.id}.jpg`; + + const res = await checkFileExistence(path); + + if (res) { + // await prisma.user.update({ + // where: { id: user.id }, + // data: { image: "avatar/" + user.id }, + // }); + console.log(`Updated avatar for user ${user.id}`); + } else { + console.log(`No avatar found for user ${user.id}`); + } + } + + const links = await prisma.link.findMany(); + + // Screenshots + for (let link of links) { + const path = + STORAGE_FOLDER + `/archives/${link.collectionId}/${link.id}.pdf`; + + const res = await checkFileExistence(path); + + if (res) { + // await prisma.user.update({ + // where: { id: user.id }, + // data: { image: "avatar/" + user.id }, + // }); + console.log(`Updated capture for link ${link.id}`); + } else { + console.log(`No capture found for link ${link.id}`); + } + } + + // PDFs + for (let link of links) { + const path = + STORAGE_FOLDER + `/archives/${link.collectionId}/${link.id}.png`; + + const res = await checkFileExistence(path); + + if (res) { + // await prisma.user.update({ + // where: { id: user.id }, + // data: { image: "avatar/" + user.id }, + // }); + console.log(`Updated capture for link ${link.id}`); + } else { + console.log(`No capture found for link ${link.id}`); + } + } + + await prisma.$disconnect(); +} + +migrateAvatars().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/prisma/migrations/20231025123038_added_pathname_to_files/migration.sql b/prisma/migrations/20231025123038_added_pathname_to_files/migration.sql new file mode 100644 index 0000000..65fa41a --- /dev/null +++ b/prisma/migrations/20231025123038_added_pathname_to_files/migration.sql @@ -0,0 +1,13 @@ +/* + Warnings: + + - You are about to drop the column `image` on the `User` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Link" ADD COLUMN "pdfPath" TEXT, +ADD COLUMN "screenshotPath" TEXT; + +-- AlterTable +ALTER TABLE "User" DROP COLUMN "image", +ADD COLUMN "imagePath" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ab67eb6..e417a4f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -42,7 +42,7 @@ model User { email String? @unique emailVerified DateTime? - image String? + imagePath String? accounts Account[] sessions Session[] @@ -122,6 +122,9 @@ model Link { collectionId Int tags Tag[] + screenshotPath String? + pdfPath String? + createdAt DateTime @default(now()) } From 788fc56caf6bea85150f7114405ef4bfa60de557 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:23:38 +0000 Subject: [PATCH 02/33] Bump crypto-js from 4.1.1 to 4.2.0 Bumps [crypto-js](https://github.com/brix/crypto-js) from 4.1.1 to 4.2.0. - [Commits](https://github.com/brix/crypto-js/compare/4.1.1...4.2.0) --- updated-dependencies: - dependency-name: crypto-js dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 93867e6..c84eddc 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "axios": "^1.5.1", "bcrypt": "^5.1.0", "colorthief": "^2.4.0", - "crypto-js": "^4.1.1", + "crypto-js": "^4.2.0", "csstype": "^3.1.2", "eslint": "8.46.0", "eslint-config-next": "13.4.9", diff --git a/yarn.lock b/yarn.lock index bb2f10a..ddbf62f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2097,10 +2097,10 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypto-js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" - integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== cssesc@^3.0.0: version "3.0.0" From ea8673783503dff0f0a74e71568bc51f41c38fde Mon Sep 17 00:00:00 2001 From: daniel31x13 Date: Thu, 26 Oct 2023 18:49:46 -0400 Subject: [PATCH 03/33] bugs fixed --- components/FilterSearchDropdown.tsx | 8 +- components/Modal/Link/AddOrEditLink.tsx | 2 + lib/api/controllers/migration/exportData.ts | 2 +- lib/api/migration/migrateToV2.js | 107 ++++++++++++++------ pages/api/v1/getToken.ts | 2 + pages/collections/index.tsx | 2 +- pages/settings/delete.tsx | 3 +- 7 files changed, 88 insertions(+), 38 deletions(-) diff --git a/components/FilterSearchDropdown.tsx b/components/FilterSearchDropdown.tsx index 2c835ab..181febb 100644 --- a/components/FilterSearchDropdown.tsx +++ b/components/FilterSearchDropdown.tsx @@ -1,12 +1,16 @@ import React, { SetStateAction } from "react"; import ClickAwayHandler from "./ClickAwayHandler"; import Checkbox from "./Checkbox"; -import { LinkSearchFilter } from "@/types/global"; type Props = { setFilterDropdown: (value: SetStateAction) => void; setSearchFilter: Function; - searchFilter: LinkSearchFilter; + searchFilter: { + name: boolean; + url: boolean; + description: boolean; + tags: boolean; + }; }; export default function FilterSearchDropdown({ diff --git a/components/Modal/Link/AddOrEditLink.tsx b/components/Modal/Link/AddOrEditLink.tsx index dcdf422..201b3d0 100644 --- a/components/Modal/Link/AddOrEditLink.tsx +++ b/components/Modal/Link/AddOrEditLink.tsx @@ -46,6 +46,8 @@ export default function AddOrEditLink({ url: "", description: "", tags: [], + screenshotPath: "", + pdfPath: "", collection: { name: "", ownerId: data?.user.id as number, diff --git a/lib/api/controllers/migration/exportData.ts b/lib/api/controllers/migration/exportData.ts index 49a25b4..2776d85 100644 --- a/lib/api/controllers/migration/exportData.ts +++ b/lib/api/controllers/migration/exportData.ts @@ -18,7 +18,7 @@ export default async function exportData(userId: number) { if (!user) return { response: "User not found.", status: 404 }; - const { password, id, image, ...userData } = user; + const { password, id, ...userData } = user; function redactIds(obj: any) { if (Array.isArray(obj)) { diff --git a/lib/api/migration/migrateToV2.js b/lib/api/migration/migrateToV2.js index aeb07fb..29c7e17 100644 --- a/lib/api/migration/migrateToV2.js +++ b/lib/api/migration/migrateToV2.js @@ -1,83 +1,124 @@ +const { S3 } = require("@aws-sdk/client-s3"); const { PrismaClient } = require("@prisma/client"); const axios = require("axios"); const { existsSync } = require("fs"); +const util = require("util"); const prisma = new PrismaClient(); const STORAGE_FOLDER = process.env.STORAGE_FOLDER || "data"; +const s3Client = + process.env.SPACES_ENDPOINT && + process.env.SPACES_REGION && + process.env.SPACES_KEY && + process.env.SPACES_SECRET + ? new S3({ + forcePathStyle: false, + endpoint: process.env.SPACES_ENDPOINT, + region: process.env.SPACES_REGION, + credentials: { + accessKeyId: process.env.SPACES_KEY, + secretAccessKey: process.env.SPACES_SECRET, + }, + }) + : undefined; + async function checkFileExistence(path) { - try { - if (existsSync(path)) { - return true; - } else return false; - } catch (err) { - console.log(err); + if (s3Client) { + const bucketParams = { + Bucket: process.env.BUCKET_NAME, + Key: path, + }; + + console.log(path); + try { + const headObjectAsync = util.promisify( + s3Client.headObject.bind(s3Client) + ); + + try { + await headObjectAsync(bucketParams); + return true; + } catch (err) { + return false; + } + } catch (err) { + console.log("Error:", err); + + return false; + } + } else { + try { + if (existsSync(STORAGE_FOLDER + "/" + path)) { + return true; + } else return false; + } catch (err) { + console.log(err); + } } } // Avatars -async function migrateAvatars() { +async function migrateToV2() { const users = await prisma.user.findMany(); for (let user of users) { - const path = STORAGE_FOLDER + `/uploads/avatar/${user.id}.jpg`; + const path = `uploads/avatar/${user.id}.jpg`; const res = await checkFileExistence(path); if (res) { - // await prisma.user.update({ - // where: { id: user.id }, - // data: { image: "avatar/" + user.id }, - // }); - console.log(`Updated avatar for user ${user.id}`); + await prisma.user.update({ + where: { id: user.id }, + data: { imagePath: path }, + }); + console.log(`Updated avatar for avatar ${user.id}`); } else { - console.log(`No avatar found for user ${user.id}`); + console.log(`No avatar found for avatar ${user.id}`); } } const links = await prisma.link.findMany(); - // Screenshots + // PDFs for (let link of links) { - const path = - STORAGE_FOLDER + `/archives/${link.collectionId}/${link.id}.pdf`; + const path = `archives/${link.collectionId}/${link.id}.pdf`; const res = await checkFileExistence(path); if (res) { - // await prisma.user.update({ - // where: { id: user.id }, - // data: { image: "avatar/" + user.id }, - // }); - console.log(`Updated capture for link ${link.id}`); + await prisma.link.update({ + where: { id: link.id }, + data: { pdfPath: path }, + }); + console.log(`Updated capture for pdf ${link.id}`); } else { - console.log(`No capture found for link ${link.id}`); + console.log(`No capture found for pdf ${link.id}`); } } - // PDFs + // Screenshots for (let link of links) { - const path = - STORAGE_FOLDER + `/archives/${link.collectionId}/${link.id}.png`; + const path = `archives/${link.collectionId}/${link.id}.png`; const res = await checkFileExistence(path); if (res) { - // await prisma.user.update({ - // where: { id: user.id }, - // data: { image: "avatar/" + user.id }, - // }); - console.log(`Updated capture for link ${link.id}`); + await prisma.link.update({ + where: { id: link.id }, + data: { screenshotPath: path }, + }); + console.log(`Updated capture for screenshot ${link.id}`); } else { - console.log(`No capture found for link ${link.id}`); + console.log(`No capture found for screenshot ${link.id}`); } } await prisma.$disconnect(); } -migrateAvatars().catch((e) => { +migrateToV2().catch((e) => { console.error(e); process.exit(1); }); diff --git a/pages/api/v1/getToken.ts b/pages/api/v1/getToken.ts index c767075..e51c4bb 100644 --- a/pages/api/v1/getToken.ts +++ b/pages/api/v1/getToken.ts @@ -14,3 +14,5 @@ // } // res.end(); // }; + +export {}; diff --git a/pages/collections/index.tsx b/pages/collections/index.tsx index 0df0588..1f81285 100644 --- a/pages/collections/index.tsx +++ b/pages/collections/index.tsx @@ -154,7 +154,7 @@ export default function Collections() {

- Shared collections you're a member of + Shared collections you're a member of

diff --git a/pages/settings/delete.tsx b/pages/settings/delete.tsx index e072ab1..6a293af 100644 --- a/pages/settings/delete.tsx +++ b/pages/settings/delete.tsx @@ -119,7 +119,8 @@ export default function Password() {

- More information (the more details, the more helpful it'd be) + More information (the more details, the more helpful it'd + be)