updated route + bug fixed
This commit is contained in:
parent
bd16136946
commit
0c6911aaf0
|
@ -1,4 +1,7 @@
|
|||
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
|
||||
import {
|
||||
ArchivedFormat,
|
||||
LinkIncludingShortenedCollectionAndTags,
|
||||
} from "@/types/global";
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
@ -65,15 +68,16 @@ export default function PreservedFormats() {
|
|||
} else toast.error(data.response);
|
||||
};
|
||||
|
||||
const handleDownload = (format: "png" | "pdf") => {
|
||||
const path = `/api/v1/archives/${link?.collection.id}/${link?.id}.${format}`;
|
||||
const handleDownload = (format: ArchivedFormat) => {
|
||||
const path = `/api/v1/archives/${link?.id}?format=${format}`;
|
||||
fetch(path)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
// Create a temporary link and click it to trigger the download
|
||||
const link = document.createElement("a");
|
||||
link.href = path;
|
||||
link.download = format === "pdf" ? "PDF" : "Screenshot";
|
||||
link.download =
|
||||
format === ArchivedFormat.screenshot ? "Screenshot" : "PDF";
|
||||
link.click();
|
||||
} else {
|
||||
console.error("Failed to download file");
|
||||
|
@ -98,7 +102,7 @@ export default function PreservedFormats() {
|
|||
|
||||
<div className="flex text-black dark:text-white gap-1">
|
||||
<div
|
||||
onClick={() => handleDownload("png")}
|
||||
onClick={() => handleDownload(ArchivedFormat.screenshot)}
|
||||
className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
|
@ -108,7 +112,7 @@ export default function PreservedFormats() {
|
|||
</div>
|
||||
|
||||
<Link
|
||||
href={`/api/v1/archives/${link.collectionId}/${link.id}.png`}
|
||||
href={`/api/v1/archives/${link?.id}?format=${ArchivedFormat.screenshot}`}
|
||||
target="_blank"
|
||||
className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md"
|
||||
>
|
||||
|
@ -133,7 +137,7 @@ export default function PreservedFormats() {
|
|||
|
||||
<div className="flex text-black dark:text-white gap-1">
|
||||
<div
|
||||
onClick={() => handleDownload("pdf")}
|
||||
onClick={() => handleDownload(ArchivedFormat.pdf)}
|
||||
className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
|
@ -143,7 +147,7 @@ export default function PreservedFormats() {
|
|||
</div>
|
||||
|
||||
<Link
|
||||
href={`/api/v1/archives/${link.collectionId}/${link.id}.pdf`}
|
||||
href={`/api/v1/archives/${link?.id}?format=${ArchivedFormat.pdf}`}
|
||||
target="_blank"
|
||||
className="cursor-pointer hover:opacity-60 duration-100 p-2 rounded-md"
|
||||
>
|
||||
|
|
|
@ -10,14 +10,10 @@ export default async function deleteCollection(
|
|||
if (!collectionId)
|
||||
return { response: "Please choose a valid collection.", status: 401 };
|
||||
|
||||
const collectionIsAccessible = (await getPermission({
|
||||
const collectionIsAccessible = await getPermission({
|
||||
userId,
|
||||
collectionId,
|
||||
})) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
});
|
||||
|
||||
const memberHasAccess = collectionIsAccessible?.members.some(
|
||||
(e: UsersAndCollections) => e.userId === userId
|
||||
|
|
|
@ -11,14 +11,10 @@ export default async function updateCollection(
|
|||
if (!collectionId)
|
||||
return { response: "Please choose a valid collection.", status: 401 };
|
||||
|
||||
const collectionIsAccessible = (await getPermission({
|
||||
const collectionIsAccessible = await getPermission({
|
||||
userId,
|
||||
collectionId,
|
||||
})) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
});
|
||||
|
||||
if (!(collectionIsAccessible?.ownerId === userId))
|
||||
return { response: "Collection is not accessible.", status: 401 };
|
||||
|
|
|
@ -6,11 +6,7 @@ import removeFile from "@/lib/api/storage/removeFile";
|
|||
export default async function deleteLink(userId: number, linkId: number) {
|
||||
if (!linkId) return { response: "Please choose a valid link.", status: 401 };
|
||||
|
||||
const collectionIsAccessible = (await getPermission({ userId, linkId })) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
const collectionIsAccessible = await getPermission({ userId, linkId });
|
||||
|
||||
const memberHasAccess = collectionIsAccessible?.members.some(
|
||||
(e: UsersAndCollections) => e.userId === userId && e.canDelete
|
||||
|
|
|
@ -9,11 +9,7 @@ export default async function getLinkById(userId: number, linkId: number) {
|
|||
status: 401,
|
||||
};
|
||||
|
||||
const collectionIsAccessible = (await getPermission({ userId, linkId })) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
const collectionIsAccessible = await getPermission({ userId, linkId });
|
||||
|
||||
const memberHasAccess = collectionIsAccessible?.members.some(
|
||||
(e: UsersAndCollections) => e.userId === userId
|
||||
|
|
|
@ -15,11 +15,7 @@ export default async function updateLinkById(
|
|||
status: 401,
|
||||
};
|
||||
|
||||
const collectionIsAccessible = (await getPermission({ userId, linkId })) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
const collectionIsAccessible = await getPermission({ userId, linkId });
|
||||
|
||||
const memberHasAccess = collectionIsAccessible?.members.some(
|
||||
(e: UsersAndCollections) => e.userId === userId && e.canUpdate
|
||||
|
|
|
@ -2,7 +2,7 @@ import { prisma } from "@/lib/api/db";
|
|||
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
|
||||
import getTitle from "@/lib/api/getTitle";
|
||||
import archive from "@/lib/api/archive";
|
||||
import { Collection, UsersAndCollections } from "@prisma/client";
|
||||
import { UsersAndCollections } from "@prisma/client";
|
||||
import getPermission from "@/lib/api/getPermission";
|
||||
import createFolder from "@/lib/api/storage/createFolder";
|
||||
|
||||
|
@ -27,14 +27,10 @@ export default async function postLink(
|
|||
link.collection.name = link.collection.name.trim();
|
||||
|
||||
if (link.collection.id) {
|
||||
const collectionIsAccessible = (await getPermission({
|
||||
const collectionIsAccessible = await getPermission({
|
||||
userId,
|
||||
collectionId: link.collection.id,
|
||||
})) as
|
||||
| (Collection & {
|
||||
members: UsersAndCollections[];
|
||||
})
|
||||
| null;
|
||||
});
|
||||
|
||||
const memberHasAccess = collectionIsAccessible?.members.some(
|
||||
(e: UsersAndCollections) => e.userId === userId && e.canCreate
|
||||
|
|
|
@ -1,35 +1,24 @@
|
|||
import { prisma } from "@/lib/api/db";
|
||||
|
||||
type Props = {
|
||||
userId?: number;
|
||||
userId: number;
|
||||
collectionId?: number;
|
||||
linkId?: number;
|
||||
isPublic?: boolean;
|
||||
};
|
||||
|
||||
export default async function getPermission({
|
||||
userId,
|
||||
collectionId,
|
||||
linkId,
|
||||
isPublic,
|
||||
}: Props) {
|
||||
if (linkId) {
|
||||
const check = await prisma.collection.findFirst({
|
||||
where: {
|
||||
[isPublic ? "OR" : "AND"]: [
|
||||
{
|
||||
id: collectionId,
|
||||
OR: [{ ownerId: userId }, { members: { some: { userId } } }],
|
||||
links: {
|
||||
some: {
|
||||
id: linkId,
|
||||
},
|
||||
},
|
||||
links: {
|
||||
some: {
|
||||
id: linkId,
|
||||
},
|
||||
{
|
||||
isPublic: isPublic ? true : undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
include: { members: true },
|
||||
});
|
||||
|
@ -38,15 +27,8 @@ export default async function getPermission({
|
|||
} else if (collectionId) {
|
||||
const check = await prisma.collection.findFirst({
|
||||
where: {
|
||||
[isPublic ? "OR" : "AND"]: [
|
||||
{
|
||||
id: collectionId,
|
||||
OR: [{ ownerId: userId }, { members: { some: { userId } } }],
|
||||
},
|
||||
{
|
||||
isPublic: isPublic ? true : undefined,
|
||||
},
|
||||
],
|
||||
id: collectionId,
|
||||
OR: [{ ownerId: userId }, { members: { some: { userId } } }],
|
||||
},
|
||||
include: { members: true },
|
||||
});
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import getPermission from "@/lib/api/getPermission";
|
||||
import readFile from "@/lib/api/storage/readFile";
|
||||
import { getToken } from "next-auth/jwt";
|
||||
|
||||
export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (!req.query.params)
|
||||
return res.status(401).json({ response: "Invalid parameters." });
|
||||
|
||||
const token = await getToken({ req });
|
||||
const userId = token?.id;
|
||||
|
||||
const collectionId = req.query.params[0];
|
||||
const linkId = req.query.params[1];
|
||||
|
||||
const collectionIsAccessible = await getPermission({
|
||||
userId,
|
||||
collectionId: Number(collectionId),
|
||||
});
|
||||
|
||||
if (!collectionIsAccessible)
|
||||
return res
|
||||
.status(401)
|
||||
.json({ response: "You don't have access to this collection." });
|
||||
|
||||
const { file, contentType, status } = await readFile(
|
||||
`archives/${collectionId}/${linkId}`
|
||||
);
|
||||
res.setHeader("Content-Type", contentType).status(status as number);
|
||||
|
||||
return res.send(file);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import readFile from "@/lib/api/storage/readFile";
|
||||
import { getToken } from "next-auth/jwt";
|
||||
import { prisma } from "@/lib/api/db";
|
||||
import { ArchivedFormat } from "@/types/global";
|
||||
|
||||
export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||
const linkId = Number(req.query.linkId);
|
||||
const format = Number(req.query.format);
|
||||
|
||||
let suffix;
|
||||
|
||||
if (format === ArchivedFormat.screenshot) suffix = ".png";
|
||||
else if (format === ArchivedFormat.pdf) suffix = ".pdf";
|
||||
else if (format === ArchivedFormat.readability) suffix = "_readability.json";
|
||||
|
||||
if (!linkId || !suffix)
|
||||
return res.status(401).json({ response: "Invalid parameters." });
|
||||
|
||||
const token = await getToken({ req });
|
||||
const userId = token?.id;
|
||||
|
||||
const collectionIsAccessible = await prisma.collection.findFirst({
|
||||
where: {
|
||||
links: {
|
||||
some: {
|
||||
id: linkId,
|
||||
},
|
||||
},
|
||||
OR: [
|
||||
{ ownerId: userId || -1 },
|
||||
{ members: { some: { userId: userId || -1 } } },
|
||||
{ isPublic: true },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (!collectionIsAccessible)
|
||||
return res
|
||||
.status(401)
|
||||
.json({ response: "You don't have access to this collection." });
|
||||
|
||||
const { file, contentType, status } = await readFile(
|
||||
`archives/${collectionIsAccessible.id}/${linkId + suffix}`
|
||||
);
|
||||
res.setHeader("Content-Type", contentType).status(status as number);
|
||||
|
||||
return res.send(file);
|
||||
}
|
|
@ -3,7 +3,10 @@ import React, { useEffect, useState } from "react";
|
|||
import Link from "next/link";
|
||||
import useLinkStore from "@/store/links";
|
||||
import { useRouter } from "next/router";
|
||||
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
|
||||
import {
|
||||
ArchivedFormat,
|
||||
LinkIncludingShortenedCollectionAndTags,
|
||||
} from "@/types/global";
|
||||
import Image from "next/image";
|
||||
import ColorThief, { RGBColor } from "colorthief";
|
||||
import { useTheme } from "next-themes";
|
||||
|
@ -63,7 +66,9 @@ export default function Index() {
|
|||
link?.readabilityPath &&
|
||||
link?.readabilityPath !== "pending"
|
||||
) {
|
||||
const response = await fetch(`/api/v1/${link?.readabilityPath}`);
|
||||
const response = await fetch(
|
||||
`/api/v1/archives/${link?.id}?format=${ArchivedFormat.readability}`
|
||||
);
|
||||
|
||||
const data = await response?.json();
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@ import React, { useEffect, useState } from "react";
|
|||
import Link from "next/link";
|
||||
import useLinkStore from "@/store/links";
|
||||
import { useRouter } from "next/router";
|
||||
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
|
||||
import {
|
||||
ArchivedFormat,
|
||||
LinkIncludingShortenedCollectionAndTags,
|
||||
} from "@/types/global";
|
||||
import Image from "next/image";
|
||||
import ColorThief, { RGBColor } from "colorthief";
|
||||
import { useTheme } from "next-themes";
|
||||
|
@ -64,7 +67,9 @@ export default function Index() {
|
|||
link?.readabilityPath &&
|
||||
link?.readabilityPath !== "pending"
|
||||
) {
|
||||
const response = await fetch(`/api/v1/${link?.readabilityPath}`);
|
||||
const response = await fetch(
|
||||
`/api/v1/archives/${link?.id}?format=${ArchivedFormat.readability}`
|
||||
);
|
||||
|
||||
const data = await response?.json();
|
||||
|
||||
|
|
|
@ -115,3 +115,9 @@ export type DeleteUserBody = {
|
|||
feedback?: Stripe.SubscriptionCancelParams.CancellationDetails.Feedback;
|
||||
};
|
||||
};
|
||||
|
||||
export enum ArchivedFormat {
|
||||
screenshot,
|
||||
pdf,
|
||||
readability,
|
||||
}
|
||||
|
|
Ŝarĝante…
Reference in New Issue