finalized adding support for access tokens

This commit is contained in:
daniel31x13
2024-01-24 15:48:40 -05:00
parent 05563134b4
commit 5be194235c
18 changed files with 366 additions and 106 deletions
+3 -3
View File
@@ -1,6 +1,5 @@
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";
import verifyUser from "@/lib/api/verifyUser";
@@ -9,6 +8,7 @@ import { UsersAndCollections } from "@prisma/client";
import formidable from "formidable";
import createFile from "@/lib/api/storage/createFile";
import fs from "fs";
import verifyToken from "@/lib/api/verifyToken";
export const config = {
api: {
@@ -33,8 +33,8 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
return res.status(401).json({ response: "Invalid parameters." });
if (req.method === "GET") {
const token = await getToken({ req });
const userId = token?.id;
const token = await verifyToken({ req });
const userId = typeof token === "string" ? undefined : token?.id;
const collectionIsAccessible = await prisma.collection.findFirst({
where: {
+3 -3
View File
@@ -1,7 +1,7 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/api/db";
import readFile from "@/lib/api/storage/readFile";
import { getToken } from "next-auth/jwt";
import verifyToken from "@/lib/api/verifyToken";
export default async function Index(req: NextApiRequest, res: NextApiResponse) {
const queryId = Number(req.query.id);
@@ -12,8 +12,8 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
.status(401)
.send("Invalid parameters.");
const token = await getToken({ req });
const userId = token?.id;
const token = await verifyToken({ req });
const userId = typeof token === "string" ? undefined : token?.id;
if (req.method === "GET") {
const targetUser = await prisma.user.findUnique({
+3 -3
View File
@@ -1,10 +1,10 @@
import type { NextApiRequest, NextApiResponse } from "next";
import getPublicUser from "@/lib/api/controllers/public/users/getPublicUser";
import { getToken } from "next-auth/jwt";
import verifyToken from "@/lib/api/verifyToken";
export default async function users(req: NextApiRequest, res: NextApiResponse) {
const token = await getToken({ req });
const requestingId = token?.id;
const token = await verifyToken({ req });
const requestingId = typeof token === "string" ? undefined : token?.id;
const lookupId = req.query.id as string;
+8 -12
View File
@@ -2,26 +2,22 @@ import type { NextApiRequest, NextApiResponse } from "next";
import getUserById from "@/lib/api/controllers/users/userId/getUserById";
import updateUserById from "@/lib/api/controllers/users/userId/updateUserById";
import deleteUserById from "@/lib/api/controllers/users/userId/deleteUserById";
import { getToken } from "next-auth/jwt";
import { prisma } from "@/lib/api/db";
import verifySubscription from "@/lib/api/verifySubscription";
import verifyToken from "@/lib/api/verifyToken";
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
export default async function users(req: NextApiRequest, res: NextApiResponse) {
const token = await getToken({ req });
const token = await verifyToken({ req });
if (typeof token === "string") {
res.status(401).json({ response: token });
return null;
}
const userId = token?.id;
if (!userId) {
return res.status(401).json({ response: "You must be logged in." });
}
if (token.exp < Date.now() / 1000) {
return res
.status(401)
.json({ response: "Your session has expired, please log in again." });
}
if (userId !== Number(req.query.id))
return res.status(401).json({ response: "Permission denied." });
+80 -8
View File
@@ -1,13 +1,33 @@
import SettingsLayout from "@/layouts/SettingsLayout";
import React, { useState } from "react";
import NewKeyModal from "@/components/ModalContent/NewKeyModal";
import React, { useEffect, useState } from "react";
import NewTokenModal from "@/components/ModalContent/NewTokenModal";
import RevokeTokenModal from "@/components/ModalContent/RevokeTokenModal";
import { AccessToken } from "@prisma/client";
import useTokenStore from "@/store/tokens";
export default function Api() {
const [newKeyModal, setNewKeyModal] = useState(false);
export default function AccessTokens() {
const [newTokenModal, setNewTokenModal] = useState(false);
const [revokeTokenModal, setRevokeTokenModal] = useState(false);
const [selectedToken, setSelectedToken] = useState<AccessToken | null>(null);
const openRevokeModal = (token: AccessToken) => {
setSelectedToken(token);
setRevokeTokenModal(true);
};
const { setTokens, tokens } = useTokenStore();
useEffect(() => {
fetch("/api/v1/tokens")
.then((res) => res.json())
.then((data) => {
if (data.response) setTokens(data.response as AccessToken[]);
});
}, []);
return (
<SettingsLayout>
<p className="capitalize text-3xl font-thin inline">API Keys</p>
<p className="capitalize text-3xl font-thin inline">Access Tokens</p>
<div className="divider my-3"></div>
@@ -20,16 +40,68 @@ export default function Api() {
<button
className={`btn btn-accent dark:border-violet-400 text-white tracking-wider w-fit flex items-center gap-2`}
onClick={() => {
setNewKeyModal(true);
setNewTokenModal(true);
}}
>
New Access Token
</button>
{tokens.length > 0 ? (
<>
<div className="divider"></div>
<table className="table">
{/* head */}
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Created</th>
<th>Expires</th>
<th></th>
</tr>
</thead>
<tbody>
{tokens.map((token, i) => (
<React.Fragment key={i}>
<tr>
<th>{i + 1}</th>
<td>{token.name}</td>
<td>
{new Date(token.createdAt || "").toLocaleDateString()}
</td>
<td>
{new Date(token.expires || "").toLocaleDateString()}
</td>
<td>
<button
className="btn btn-sm btn-ghost btn-square hover:bg-red-500"
onClick={() => openRevokeModal(token as AccessToken)}
>
<i className="bi-x text-lg"></i>
</button>
</td>
</tr>
</React.Fragment>
))}
</tbody>
</table>
</>
) : undefined}
</div>
{newKeyModal ? (
<NewKeyModal onClose={() => setNewKeyModal(false)} />
{newTokenModal ? (
<NewTokenModal onClose={() => setNewTokenModal(false)} />
) : undefined}
{revokeTokenModal && selectedToken && (
<RevokeTokenModal
onClose={() => {
setRevokeTokenModal(false);
setSelectedToken(null);
}}
activeToken={selectedToken}
/>
)}
</SettingsLayout>
);
}