refactored/cleaned up API + added support for renaming tags

This commit is contained in:
daniel31x13
2023-10-23 00:28:39 -04:00
parent 24cced9dba
commit ed24685aaf
48 changed files with 603 additions and 305 deletions
-79
View File
@@ -1,79 +0,0 @@
import { prisma } from "@/lib/api/db";
import type { NextApiRequest, NextApiResponse } from "next";
import bcrypt from "bcrypt";
const emailEnabled =
process.env.EMAIL_FROM && process.env.EMAIL_SERVER ? true : false;
interface Data {
response: string | object;
}
interface User {
name: string;
username?: string;
email?: string;
password: string;
}
export default async function Index(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
if (process.env.NEXT_PUBLIC_DISABLE_REGISTRATION === "true") {
return res.status(400).json({ response: "Registration is disabled." });
}
const body: User = req.body;
const checkHasEmptyFields = emailEnabled
? !body.password || !body.name || !body.email
: !body.username || !body.password || !body.name;
if (checkHasEmptyFields)
return res
.status(400)
.json({ response: "Please fill out all the fields." });
const checkUsername = RegExp("^[a-z0-9_-]{3,31}$");
if (!emailEnabled && !checkUsername.test(body.username?.toLowerCase() || ""))
return res.status(400).json({
response:
"Username has to be between 3-30 characters, no spaces and special characters are allowed.",
});
const checkIfUserExists = await prisma.user.findFirst({
where: emailEnabled
? {
email: body.email?.toLowerCase(),
emailVerified: { not: null },
}
: {
username: (body.username as string).toLowerCase(),
},
});
if (!checkIfUserExists) {
const saltRounds = 10;
const hashedPassword = bcrypt.hashSync(body.password, saltRounds);
await prisma.user.create({
data: {
name: body.name,
username: emailEnabled
? undefined
: (body.username as string).toLowerCase(),
email: emailEnabled ? body.email?.toLowerCase() : undefined,
password: hashedPassword,
},
});
return res.status(201).json({ response: "User successfully created." });
} else if (checkIfUserExists) {
return res
.status(400)
.json({ response: "Username and/or Email already exists." });
}
}
-39
View File
@@ -1,39 +0,0 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import getUsers from "@/lib/api/controllers/users/getUsers";
import updateUser from "@/lib/api/controllers/users/updateUser";
export default async function users(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
if (!session?.user.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
const lookupUsername = (req.query.username as string) || undefined;
const lookupId = Number(req.query.id) || undefined;
const isSelf =
session.user.username === lookupUsername || session.user.id === lookupId
? true
: false;
if (req.method === "GET") {
const users = await getUsers({
params: {
lookupUsername,
lookupId,
},
isSelf,
username: session.user.username,
});
return res.status(users.status).json({ response: users.response });
} else if (req.method === "PUT") {
const updated = await updateUser(req.body, session.user);
return res.status(updated.status).json({ response: updated.response });
}
}
@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getPermission from "@/lib/api/getPermission";
import readFile from "@/lib/api/storage/readFile";
@@ -21,10 +21,10 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
const collectionIsAccessible = await getPermission(
session.user.id,
Number(collectionId)
);
const collectionIsAccessible = await getPermission({
userId: session.user.id,
collectionId: Number(collectionId),
});
if (!collectionIsAccessible)
return res
@@ -88,8 +88,7 @@ export const authOptions: AuthOptions = {
return session;
},
// Using the `...rest` parameter to be able to narrow down the type based on `trigger`
async jwt({ token, trigger, session, user }) {
async jwt({ token, trigger, user }) {
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
const NEXT_PUBLIC_TRIAL_PERIOD_DAYS =
@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import { prisma } from "@/lib/api/db";
import readFile from "@/lib/api/storage/readFile";
+35
View File
@@ -0,0 +1,35 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import updateCollectionById from "@/lib/api/controllers/collections/collectionId/updateCollectionById";
import deleteCollectionById from "@/lib/api/controllers/collections/collectionId/deleteCollectionById";
export default async function collections(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getServerSession(req, res, authOptions);
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
if (req.method === "PUT") {
const updated = await updateCollectionById(
session.user.id,
Number(req.query.id) as number,
req.body
);
return res.status(updated.status).json({ response: updated.response });
} else if (req.method === "DELETE") {
const deleted = await deleteCollectionById(
session.user.id,
Number(req.query.id) as number
);
return res.status(deleted.status).json({ response: deleted.response });
}
}
@@ -1,10 +1,8 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getCollections from "@/lib/api/controllers/collections/getCollections";
import postCollection from "@/lib/api/controllers/collections/postCollection";
import updateCollection from "@/lib/api/controllers/collections/updateCollection";
import deleteCollection from "@/lib/api/controllers/collections/deleteCollection";
export default async function collections(
req: NextApiRequest,
@@ -30,11 +28,5 @@ export default async function collections(
return res
.status(newCollection.status)
.json({ response: newCollection.response });
} else if (req.method === "PUT") {
const updated = await updateCollection(req.body, session.user.id);
return res.status(updated.status).json({ response: updated.response });
} else if (req.method === "DELETE") {
const deleted = await deleteCollection(req.body, session.user.id);
return res.status(deleted.status).json({ response: deleted.response });
}
}
+16
View File
@@ -0,0 +1,16 @@
// For future...
// import { getToken } from "next-auth/jwt";
// export default async (req, res) => {
// // If you don't have NEXTAUTH_SECRET set, you will have to pass your secret as `secret` to `getToken`
// console.log({ req });
// const token = await getToken({ req, raw: true });
// if (token) {
// // Signed in
// console.log("JSON Web Token", JSON.stringify(token, null, 2));
// } else {
// // Not Signed in
// res.status(401);
// }
// res.end();
// };
+33
View File
@@ -0,0 +1,33 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import deleteLinkById from "@/lib/api/controllers/links/linkId/deleteLinkById";
import updateLinkById from "@/lib/api/controllers/links/linkId/updateLinkById";
export default async function links(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
if (req.method === "PUT") {
const updated = await updateLinkById(
session.user.id,
Number(req.query.id),
req.body
);
return res.status(updated.status).json({
response: updated.response,
});
} else if (req.method === "DELETE") {
const deleted = await deleteLinkById(session.user.id, Number(req.query.id));
return res.status(deleted.status).json({
response: deleted.response,
});
}
}
@@ -1,10 +1,8 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getLinks from "@/lib/api/controllers/links/getLinks";
import postLink from "@/lib/api/controllers/links/postLink";
import deleteLink from "@/lib/api/controllers/links/deleteLink";
import updateLink from "@/lib/api/controllers/links/updateLink";
export default async function links(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
@@ -25,15 +23,5 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) {
return res.status(newlink.status).json({
response: newlink.response,
});
} else if (req.method === "PUT") {
const updated = await updateLink(req.body, session.user.id);
return res.status(updated.status).json({
response: updated.response,
});
} else if (req.method === "DELETE") {
const deleted = await deleteLink(req.body, session.user.id);
return res.status(deleted.status).json({
response: deleted.response,
});
}
}
@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import exportData from "@/lib/api/controllers/migration/exportData";
import importFromHTMLFile from "@/lib/api/controllers/migration/importFromHTMLFile";
import importFromLinkwarden from "@/lib/api/controllers/migration/importFromLinkwarden";
@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import paymentCheckout from "@/lib/api/paymentCheckout";
import { Plan } from "@/types/global";
+23
View File
@@ -0,0 +1,23 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import updateTag from "@/lib/api/controllers/tags/tagId/updeteTagById";
export default async function tags(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
if (!session?.user?.username) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
const tagId = Number(req.query.id);
if (req.method === "PUT") {
const tags = await updateTag(session.user.id, tagId, req.body);
return res.status(tags.status).json({ response: tags.response });
}
}
@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getTags from "@/lib/api/controllers/tags/getTags";
export default async function tags(req: NextApiRequest, res: NextApiResponse) {
+40
View File
@@ -0,0 +1,40 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getUserById from "@/lib/api/controllers/users/userId/getUserById";
import getPublicUserById from "@/lib/api/controllers/users/userId/getPublicUserById";
import updateUserById from "@/lib/api/controllers/users/userId/updateUserById";
export default async function users(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
const userId = session?.user.id;
const username = session?.user.username;
const lookupId = req.query.id as string;
const isSelf =
userId === Number(lookupId) || username === lookupId ? true : false;
// Check if "lookupId" is the user "id" or their "username"
const isId = lookupId.split("").every((e) => Number.isInteger(parseInt(e)));
if (req.method === "GET" && !isSelf) {
const users = await getPublicUserById(lookupId, isId, username);
return res.status(users.status).json({ response: users.response });
}
if (!userId) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});
if (req.method === "GET") {
const users = await getUserById(session.user.id);
return res.status(users.status).json({ response: users.response });
} else if (req.method === "PUT") {
const updated = await updateUserById(session.user, req.body);
return res.status(updated.status).json({ response: updated.response });
}
}
+9
View File
@@ -0,0 +1,9 @@
import type { NextApiRequest, NextApiResponse } from "next";
import postUser from "@/lib/api/controllers/users/postUser";
export default async function users(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "POST") {
const response = await postUser(req, res);
return response;
}
}