This commit is contained in:
daniel31x13 2023-11-07 08:03:35 -05:00
parent 6f5245cbc4
commit cb5b1751c0
7 changed files with 243 additions and 248 deletions

View File

@ -60,51 +60,47 @@ export default function Dropdown({
} }
}, [points, dropdownHeight]); }, [points, dropdownHeight]);
return ( return !points || pos ? (
(!points || pos) && ( <ClickAwayHandler
<ClickAwayHandler onMount={(e) => {
onMount={(e) => { setDropdownHeight(e.height);
setDropdownHeight(e.height); setDropdownWidth(e.width);
setDropdownWidth(e.width); }}
}} style={
style={ points
points ? {
? { position: "fixed",
position: "fixed", top: `${pos?.y}px`,
top: `${pos?.y}px`, left: `${pos?.x}px`,
left: `${pos?.x}px`, }
} : undefined
: undefined }
} onClickOutside={onClickOutside}
onClickOutside={onClickOutside} className={`${
className={`${ className || ""
className || "" } py-1 shadow-md border border-sky-100 dark:border-neutral-700 bg-gray-50 dark:bg-neutral-800 rounded-md flex flex-col z-20`}
} py-1 shadow-md border border-sky-100 dark:border-neutral-700 bg-gray-50 dark:bg-neutral-800 rounded-md flex flex-col z-20`} >
> {items.map((e, i) => {
{items.map((e, i) => { const inner = e && (
const inner = e && ( <div className="cursor-pointer rounded-md">
<div className="cursor-pointer rounded-md"> <div className="flex items-center gap-2 py-1 px-2 hover:bg-slate-200 dark:hover:bg-neutral-700 duration-100">
<div className="flex items-center gap-2 py-1 px-2 hover:bg-slate-200 dark:hover:bg-neutral-700 duration-100"> <p className="text-black dark:text-white select-none">{e.name}</p>
<p className="text-black dark:text-white select-none">
{e.name}
</p>
</div>
</div> </div>
); </div>
);
return e && e.href ? ( return e && e.href ? (
<Link key={i} href={e.href}> <Link key={i} href={e.href}>
{inner}
</Link>
) : (
e && (
<div key={i} onClick={e.onClick}>
{inner} {inner}
</Link> </div>
) : ( )
e && ( );
<div key={i} onClick={e.onClick}> })}
{inner} </ClickAwayHandler>
</div> ) : null;
)
);
})}
</ClickAwayHandler>
)
);
} }

View File

@ -7,94 +7,97 @@ export default async function importFromHTMLFile(
userId: number, userId: number,
rawData: string rawData: string
) { ) {
try { const dom = new JSDOM(rawData);
const dom = new JSDOM(rawData); const document = dom.window.document;
const document = dom.window.document;
const folders = document.querySelectorAll("H3"); const folders = document.querySelectorAll("H3");
// @ts-ignore await prisma
for (const folder of folders) { .$transaction(
const findCollection = await prisma.user.findUnique({ async () => {
where: { // @ts-ignore
id: userId, for (const folder of folders) {
}, const findCollection = await prisma.user.findUnique({
select: {
collections: {
where: { where: {
name: folder.textContent.trim(), id: userId,
}, },
}, select: {
}, collections: {
}); where: {
name: folder.textContent.trim(),
},
},
},
});
const checkIfCollectionExists = findCollection?.collections[0]; const checkIfCollectionExists = findCollection?.collections[0];
let collectionId = findCollection?.collections[0]?.id; let collectionId = findCollection?.collections[0]?.id;
if (!checkIfCollectionExists || !collectionId) { if (!checkIfCollectionExists || !collectionId) {
const newCollection = await prisma.collection.create({ const newCollection = await prisma.collection.create({
data: { data: {
name: folder.textContent.trim(), name: folder.textContent.trim(),
description: "", description: "",
color: "#0ea5e9", color: "#0ea5e9",
isPublic: false, isPublic: false,
ownerId: userId, ownerId: userId,
}, },
}); });
createFolder({ filePath: `archives/${newCollection.id}` }); createFolder({ filePath: `archives/${newCollection.id}` });
collectionId = newCollection.id; collectionId = newCollection.id;
} }
createFolder({ filePath: `archives/${collectionId}` }); createFolder({ filePath: `archives/${collectionId}` });
const bookmarks = folder.nextElementSibling.querySelectorAll("A"); const bookmarks = folder.nextElementSibling.querySelectorAll("A");
for (const bookmark of bookmarks) { for (const bookmark of bookmarks) {
await prisma.link.create({ await prisma.link.create({
data: { data: {
name: bookmark.textContent.trim(), name: bookmark.textContent.trim(),
url: bookmark.getAttribute("HREF"), url: bookmark.getAttribute("HREF"),
tags: bookmark.getAttribute("TAGS") tags: bookmark.getAttribute("TAGS")
? { ? {
connectOrCreate: bookmark connectOrCreate: bookmark
.getAttribute("TAGS") .getAttribute("TAGS")
.split(",") .split(",")
.map((tag: string) => .map((tag: string) =>
tag tag
? { ? {
where: { where: {
name_ownerId: { name_ownerId: {
name: tag.trim(), name: tag.trim(),
ownerId: userId, ownerId: userId,
}, },
},
create: {
name: tag.trim(),
owner: {
connect: {
id: userId,
}, },
}, create: {
}, name: tag.trim(),
} owner: {
: undefined connect: {
), id: userId,
} },
: undefined, },
description: bookmark.getAttribute("DESCRIPTION") },
? bookmark.getAttribute("DESCRIPTION") }
: "", : undefined
collectionId: collectionId, ),
createdAt: new Date(), }
}, : undefined,
}); description: bookmark.getAttribute("DESCRIPTION")
} ? bookmark.getAttribute("DESCRIPTION")
} : "",
} catch (err) { collectionId: collectionId,
console.log(err); createdAt: new Date(),
} },
});
}
}
},
{ timeout: 30000 }
)
.catch((err) => console.log(err));
return { response: "Success.", status: 200 }; return { response: "Success.", status: 200 };
} }

View File

@ -5,87 +5,88 @@ import createFolder from "@/lib/api/storage/createFolder";
export default async function getData(userId: number, rawData: string) { export default async function getData(userId: number, rawData: string) {
const data: Backup = JSON.parse(rawData); const data: Backup = JSON.parse(rawData);
console.log(typeof data); await prisma
.$transaction(
async () => {
// Import collections
for (const e of data.collections) {
e.name = e.name.trim();
// Import collections const findCollection = await prisma.user.findUnique({
try {
for (const e of data.collections) {
e.name = e.name.trim();
const findCollection = await prisma.user.findUnique({
where: {
id: userId,
},
select: {
collections: {
where: { where: {
name: e.name, id: userId,
}, },
}, select: {
}, collections: {
});
const checkIfCollectionExists = findCollection?.collections[0];
let collectionId = findCollection?.collections[0]?.id;
if (!checkIfCollectionExists) {
const newCollection = await prisma.collection.create({
data: {
owner: {
connect: {
id: userId,
},
},
name: e.name,
description: e.description,
color: e.color,
},
});
createFolder({ filePath: `archives/${newCollection.id}` });
collectionId = newCollection.id;
}
// Import Links
for (const link of e.links) {
const newLink = await prisma.link.create({
data: {
url: link.url,
name: link.name,
description: link.description,
collection: {
connect: {
id: collectionId,
},
},
// Import Tags
tags: {
connectOrCreate: link.tags.map((tag) => ({
where: { where: {
name_ownerId: { name: e.name,
name: tag.name.trim(),
ownerId: userId,
},
}, },
create: { },
name: tag.name.trim(),
owner: {
connect: {
id: userId,
},
},
},
})),
}, },
}, });
});
} const checkIfCollectionExists = findCollection?.collections[0];
}
} catch (err) { let collectionId = findCollection?.collections[0]?.id;
console.log(err);
} if (!checkIfCollectionExists) {
const newCollection = await prisma.collection.create({
data: {
owner: {
connect: {
id: userId,
},
},
name: e.name,
description: e.description,
color: e.color,
},
});
createFolder({ filePath: `archives/${newCollection.id}` });
collectionId = newCollection.id;
}
// Import Links
for (const link of e.links) {
const newLink = await prisma.link.create({
data: {
url: link.url,
name: link.name,
description: link.description,
collection: {
connect: {
id: collectionId,
},
},
// Import Tags
tags: {
connectOrCreate: link.tags.map((tag) => ({
where: {
name_ownerId: {
name: tag.name.trim(),
ownerId: userId,
},
},
create: {
name: tag.name.trim(),
owner: {
connect: {
id: userId,
},
},
},
})),
},
},
});
}
}
},
{ timeout: 30000 }
)
.catch((err) => console.log(err));
return { response: "Success.", status: 200 }; return { response: "Success.", status: 200 };
} }

View File

@ -32,56 +32,61 @@ export default async function deleteUserById(
} }
// Delete the user and all related data within a transaction // Delete the user and all related data within a transaction
await prisma.$transaction(async (prisma) => { await prisma
// Delete whitelisted users .$transaction(
await prisma.whitelistedUser.deleteMany({ async (prisma) => {
where: { userId }, // Delete whitelisted users
}); await prisma.whitelistedUser.deleteMany({
where: { userId },
});
// Delete links // Delete links
await prisma.link.deleteMany({ await prisma.link.deleteMany({
where: { collection: { ownerId: userId } }, where: { collection: { ownerId: userId } },
}); });
// Delete tags // Delete tags
await prisma.tag.deleteMany({ await prisma.tag.deleteMany({
where: { ownerId: userId }, where: { ownerId: userId },
}); });
// Find collections that the user owns // Find collections that the user owns
const collections = await prisma.collection.findMany({ const collections = await prisma.collection.findMany({
where: { ownerId: userId }, where: { ownerId: userId },
}); });
for (const collection of collections) { for (const collection of collections) {
// Delete related users and collections relations // Delete related users and collections relations
await prisma.usersAndCollections.deleteMany({ await prisma.usersAndCollections.deleteMany({
where: { collectionId: collection.id }, where: { collectionId: collection.id },
}); });
// Delete archive folders // Delete archive folders
await removeFolder({ filePath: `archives/${collection.id}` }); removeFolder({ filePath: `archives/${collection.id}` });
} }
// Delete collections after cleaning up related data // Delete collections after cleaning up related data
await prisma.collection.deleteMany({ await prisma.collection.deleteMany({
where: { ownerId: userId }, where: { ownerId: userId },
}); });
// Delete subscription // Delete subscription
if (process.env.STRIPE_SECRET_KEY) if (process.env.STRIPE_SECRET_KEY)
await prisma.subscription.delete({ await prisma.subscription.delete({
where: { userId }, where: { userId },
}); });
// Delete user's avatar // Delete user's avatar
await removeFile({ filePath: `uploads/avatar/${userId}.jpg` }); await removeFile({ filePath: `uploads/avatar/${userId}.jpg` });
// Finally, delete the user // Finally, delete the user
await prisma.user.delete({ await prisma.user.delete({
where: { id: userId }, where: { id: userId },
}); });
}); },
{ timeout: 20000 }
)
.catch((err) => console.log(err));
if (process.env.STRIPE_SECRET_KEY) { if (process.env.STRIPE_SECRET_KEY) {
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {

View File

@ -1,10 +0,0 @@
import { NextApiRequest, NextApiResponse } from "next";
import { getToken } from "next-auth/jwt";
export default async (req: NextApiRequest, res: NextApiResponse) => {
// if using `NEXTAUTH_SECRET` env variable, we detect it, and you won't actually need to `secret`
// const token = await getToken({ req })
// const token = await getToken({ req });
// console.log("JSON Web Token", token);
// res.end();
};

View File

@ -8,7 +8,7 @@ import verifyUser from "@/lib/api/verifyUser";
export const config = { export const config = {
api: { api: {
bodyParser: { bodyParser: {
sizeLimit: process.env.IMPORT_SIZE_LIMIT || "2mb", sizeLimit: `${process.env.IMPORT_SIZE_LIMIT || "5"}mb`,
}, },
}, },
}; };

View File

@ -29,7 +29,7 @@ export interface Member {
} }
export interface CollectionIncludingMembersAndLinkCount export interface CollectionIncludingMembersAndLinkCount
extends Omit<Collection, "id" | "createdAt" | "ownerId"> { extends Omit<Collection, "id" | "createdAt" | "ownerId" | "updatedAt"> {
id?: number; id?: number;
ownerId?: number; ownerId?: number;
createdAt?: string; createdAt?: string;