mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 07:03:25 +00:00
feat(wip): create models to access db data
This commit is contained in:
40
package-lock.json
generated
40
package-lock.json
generated
@@ -22,7 +22,8 @@
|
||||
"react-select": "^5.7.3",
|
||||
"sass": "^1.62.1",
|
||||
"sharp": "^0.32.1",
|
||||
"toastr": "^2.1.4"
|
||||
"toastr": "^2.1.4",
|
||||
"yup": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.2.4",
|
||||
@@ -6005,6 +6006,11 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/property-expr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
@@ -6811,6 +6817,11 @@
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tiny-case": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
||||
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
|
||||
},
|
||||
"node_modules/tiny-glob": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||
@@ -6848,6 +6859,11 @@
|
||||
"jquery": ">=1.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toposort": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
|
||||
@@ -7161,6 +7177,28 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/yup": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yup/-/yup-1.2.0.tgz",
|
||||
"integrity": "sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==",
|
||||
"dependencies": {
|
||||
"property-expr": "^2.0.5",
|
||||
"tiny-case": "^1.0.3",
|
||||
"toposort": "^2.0.2",
|
||||
"type-fest": "^2.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yup/node_modules/type-fest": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.21.4",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"react-select": "^5.7.3",
|
||||
"sass": "^1.62.1",
|
||||
"sharp": "^0.32.1",
|
||||
"toastr": "^2.1.4"
|
||||
"toastr": "^2.1.4",
|
||||
"yup": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.2.4",
|
||||
|
||||
17
src/lib/category/getUserCategories.ts
Normal file
17
src/lib/category/getUserCategories.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { User } from "@prisma/client";
|
||||
import prisma from "utils/prisma";
|
||||
|
||||
export default async function getUserCategories(user: User) {
|
||||
return await prisma.category.findMany({
|
||||
where: {
|
||||
authorId: user.id,
|
||||
},
|
||||
include: {
|
||||
links: {
|
||||
where: {
|
||||
authorId: user.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
14
src/lib/link/getUserLink.ts
Normal file
14
src/lib/link/getUserLink.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Link, User } from "@prisma/client";
|
||||
import prisma from "utils/prisma";
|
||||
|
||||
export default async function getUserLink(user: User, id: Link["id"]) {
|
||||
return await prisma.link.findFirst({
|
||||
where: {
|
||||
id,
|
||||
authorId: user.id,
|
||||
},
|
||||
include: {
|
||||
category: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
10
src/lib/link/getUserLinks.ts
Normal file
10
src/lib/link/getUserLinks.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { User } from "@prisma/client";
|
||||
import prisma from "utils/prisma";
|
||||
|
||||
export default async function getUserLinks(user: User) {
|
||||
return await prisma.link.findMany({
|
||||
where: {
|
||||
authorId: user.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
10
src/lib/user/getUserOrThrow.ts
Normal file
10
src/lib/user/getUserOrThrow.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Session } from "next-auth";
|
||||
import prisma from "utils/prisma";
|
||||
|
||||
export default async function getUserOrThrow(session: Session) {
|
||||
return await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
email: session?.user?.email,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -33,6 +33,7 @@ export const authOptions = {
|
||||
"[AUTH]",
|
||||
"User",
|
||||
profile.name,
|
||||
profile.sub,
|
||||
"attempt to log in with",
|
||||
accountParam.provider
|
||||
);
|
||||
|
||||
@@ -1,64 +1,40 @@
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "../auth/[...nextauth]";
|
||||
|
||||
import { checkMethodAllowedOrThrow } from "utils/api";
|
||||
import prisma from "utils/prisma";
|
||||
import { getSessionOrThrow } from "utils/session";
|
||||
|
||||
export default async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||
await checkMethodAllowedOrThrow(req, ["post"]);
|
||||
const session = await getSessionOrThrow(req, res);
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await getServerSession(req, res, authOptions); // je sais plus d'où ça vient
|
||||
console.log("session", session);
|
||||
const name = req.body?.name as string;
|
||||
|
||||
if (!name) {
|
||||
return res.status(400).send({ error: "Nom de catégorie manquant" });
|
||||
throw new Error("Categorie name missing");
|
||||
}
|
||||
|
||||
try {
|
||||
const category = await prisma.category.findFirst({
|
||||
where: { name },
|
||||
});
|
||||
|
||||
if (category) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ error: "Une catégorie avec ce nom existe déjà" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({
|
||||
error:
|
||||
"Une erreur est survenue lors de la création de la catégorie (category/create->findCategory)",
|
||||
});
|
||||
const category = await prisma.category.findFirst({
|
||||
where: { name },
|
||||
});
|
||||
if (category) {
|
||||
throw new Error("Category name already used");
|
||||
}
|
||||
|
||||
try {
|
||||
const { id: authorId } = await prisma.user.findFirst({
|
||||
where: {
|
||||
email: session.user.email,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
if (!authorId) {
|
||||
throw new Error("Unable to find user");
|
||||
}
|
||||
const { id: authorId } = await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
email: session.user.email,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
const category = await prisma.category.create({
|
||||
data: { name, authorId },
|
||||
});
|
||||
return res.status(200).send({
|
||||
success: "Catégorie créée avec succès",
|
||||
categoryId: category.id,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({
|
||||
error:
|
||||
"Une erreur est survenue lors de la création de la catégorie (category/create->createCategory)",
|
||||
});
|
||||
}
|
||||
const categoryCreated = await prisma.category.create({
|
||||
data: { name, authorId },
|
||||
});
|
||||
console.log("là");
|
||||
return res.status(200).send({
|
||||
success: "Category successfully created",
|
||||
categoryId: categoryCreated.id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
|
||||
import prisma from "utils/prisma";
|
||||
import { authOptions } from "../auth/[...nextauth]";
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await getServerSession(req, res, authOptions); // je sais plus d'où ça vient
|
||||
console.log("session", session);
|
||||
if (!session?.user) {
|
||||
return res.status(400).send({ error: "You must be connected" });
|
||||
}
|
||||
|
||||
const name = req.body?.name as string;
|
||||
const url = req.body?.url as string;
|
||||
const favorite = Boolean(req.body?.favorite) || false;
|
||||
@@ -57,12 +66,16 @@ export default async function handler(
|
||||
}
|
||||
|
||||
try {
|
||||
const { id: authorId } = await prisma.user.findFirstOrThrow({
|
||||
where: { email: session.user.email },
|
||||
});
|
||||
await prisma.link.create({
|
||||
data: {
|
||||
name,
|
||||
url,
|
||||
categoryId,
|
||||
favorite,
|
||||
authorId,
|
||||
},
|
||||
});
|
||||
return res
|
||||
|
||||
@@ -79,7 +79,7 @@ export async function getServerSideProps({ query }) {
|
||||
const { cid } = query;
|
||||
const categoryDB = await prisma.category.findFirst({
|
||||
where: { id: Number(cid) },
|
||||
include: { links: true },
|
||||
include: { links: true, author: true },
|
||||
});
|
||||
|
||||
if (!categoryDB) {
|
||||
|
||||
@@ -84,7 +84,7 @@ export async function getServerSideProps({ query }) {
|
||||
const { cid } = query;
|
||||
const categoryDB = await prisma.category.findFirst({
|
||||
where: { id: Number(cid) },
|
||||
include: { links: true },
|
||||
include: { links: true, author: true },
|
||||
});
|
||||
|
||||
if (!categoryDB) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Category, Link, SearchItem } from "types";
|
||||
import { BuildCategory } from "utils/front";
|
||||
import { pushStateVanilla } from "utils/link";
|
||||
import prisma from "utils/prisma";
|
||||
import { getSessionOrThrow } from "utils/session";
|
||||
|
||||
interface HomePageProps {
|
||||
categories: Category[];
|
||||
@@ -185,10 +186,27 @@ function Home(props: HomePageProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps({ query }) {
|
||||
export async function getServerSideProps({ req, res, query }) {
|
||||
const session = await getSessionOrThrow(req, res);
|
||||
const queryCategoryId = (query?.categoryId as string) || "";
|
||||
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
email: session.user.email,
|
||||
},
|
||||
});
|
||||
const categoriesDB = await prisma.category.findMany({
|
||||
include: { links: true },
|
||||
include: {
|
||||
links: {
|
||||
where: {
|
||||
authorId: user.id,
|
||||
},
|
||||
},
|
||||
author: true,
|
||||
},
|
||||
where: {
|
||||
authorId: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (categoriesDB.length === 0) {
|
||||
|
||||
@@ -111,7 +111,9 @@ CreateLink.authRequired = true;
|
||||
export default CreateLink;
|
||||
|
||||
export async function getServerSideProps() {
|
||||
const categoriesDB = await prisma.category.findMany();
|
||||
const categoriesDB = await prisma.category.findMany({
|
||||
include: { author: true },
|
||||
});
|
||||
const categories = categoriesDB.map((categoryDB) =>
|
||||
BuildCategory(categoryDB)
|
||||
);
|
||||
|
||||
@@ -11,15 +11,13 @@ import TextBox from "components/TextBox";
|
||||
|
||||
import useAutoFocus from "hooks/useAutoFocus";
|
||||
import { Category, Link } from "types";
|
||||
import {
|
||||
BuildCategory,
|
||||
BuildLink,
|
||||
HandleAxiosError,
|
||||
IsValidURL,
|
||||
} from "utils/front";
|
||||
import prisma from "utils/prisma";
|
||||
import { HandleAxiosError, IsValidURL } from "utils/front";
|
||||
|
||||
import getUserCategories from "lib/category/getUserCategories";
|
||||
import getUserLink from "lib/link/getUserLink";
|
||||
import getUserOrThrow from "lib/user/getUserOrThrow";
|
||||
import styles from "styles/create.module.scss";
|
||||
import { getSessionOrThrow } from "utils/session";
|
||||
|
||||
function EditLink({
|
||||
link,
|
||||
@@ -133,20 +131,15 @@ function EditLink({
|
||||
EditLink.authRequired = true;
|
||||
export default EditLink;
|
||||
|
||||
export async function getServerSideProps({ query }) {
|
||||
export async function getServerSideProps({ req, res, query }) {
|
||||
const { lid } = query;
|
||||
|
||||
const categoriesDB = await prisma.category.findMany();
|
||||
const categories = categoriesDB.map((categoryDB) =>
|
||||
BuildCategory(categoryDB)
|
||||
);
|
||||
const session = await getSessionOrThrow(req, res);
|
||||
const user = await getUserOrThrow(session);
|
||||
const categories = await getUserCategories(user);
|
||||
|
||||
const linkDB = await prisma.link.findFirst({
|
||||
where: { id: Number(lid) },
|
||||
include: { category: true },
|
||||
});
|
||||
|
||||
if (!linkDB) {
|
||||
const link = await getUserLink(user, Number(lid));
|
||||
if (!link) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/",
|
||||
@@ -154,10 +147,6 @@ export async function getServerSideProps({ query }) {
|
||||
};
|
||||
}
|
||||
|
||||
const link = BuildLink(linkDB, {
|
||||
categoryId: linkDB.categoryId,
|
||||
categoryName: linkDB.category.name,
|
||||
});
|
||||
return {
|
||||
props: {
|
||||
link: JSON.parse(JSON.stringify(link)),
|
||||
|
||||
@@ -98,7 +98,7 @@ export async function getServerSideProps({ query }) {
|
||||
const { lid } = query;
|
||||
const linkDB = await prisma.link.findFirst({
|
||||
where: { id: Number(lid) },
|
||||
include: { category: true },
|
||||
include: { category: true, author: true },
|
||||
});
|
||||
|
||||
if (!linkDB) {
|
||||
|
||||
8
src/types.d.ts
vendored
8
src/types.d.ts
vendored
@@ -1,9 +1,12 @@
|
||||
import { User } from "@prisma/client";
|
||||
|
||||
export interface Category {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
links: Link[];
|
||||
nextCategoryId: number;
|
||||
authorId: User["id"];
|
||||
author: User;
|
||||
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
@@ -20,7 +23,8 @@ export interface Link {
|
||||
name: string;
|
||||
};
|
||||
|
||||
nextLinkId: number;
|
||||
authorId: User["id"];
|
||||
author: User;
|
||||
favorite: boolean;
|
||||
|
||||
createdAt: Date;
|
||||
|
||||
12
src/utils/api.ts
Normal file
12
src/utils/api.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NextApiRequest } from "next";
|
||||
|
||||
export function checkMethodAllowedOrThrow(
|
||||
req: NextApiRequest,
|
||||
methods: Array<RequestInit["method"]>
|
||||
) {
|
||||
const isMethodAllowed = methods.includes(req.method.toLowerCase());
|
||||
if (!isMethodAllowed) {
|
||||
throw new Error(`Method ${req.method} not allowed`);
|
||||
}
|
||||
return isMethodAllowed;
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import { Category, Link } from "types";
|
||||
export function BuildCategory({
|
||||
id,
|
||||
name,
|
||||
nextCategoryId,
|
||||
authorId,
|
||||
author,
|
||||
links = [],
|
||||
createdAt,
|
||||
updatedAt,
|
||||
@@ -16,14 +17,15 @@ export function BuildCategory({
|
||||
links: links.map((link) =>
|
||||
BuildLink(link, { categoryId: id, categoryName: name })
|
||||
),
|
||||
nextCategoryId,
|
||||
authorId,
|
||||
author,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
export function BuildLink(
|
||||
{ id, name, url, nextLinkId, favorite, createdAt, updatedAt },
|
||||
{ id, name, url, authorId, author, favorite, createdAt, updatedAt },
|
||||
{ categoryId, categoryName }
|
||||
): Link {
|
||||
return {
|
||||
@@ -34,7 +36,8 @@ export function BuildLink(
|
||||
id: categoryId,
|
||||
name: categoryName,
|
||||
},
|
||||
nextLinkId,
|
||||
authorId,
|
||||
author,
|
||||
favorite,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
|
||||
17
src/utils/session.ts
Normal file
17
src/utils/session.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
|
||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
||||
|
||||
export async function getSessionOrThrow(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await getServerSession(req, res, authOptions);
|
||||
|
||||
if (!session) {
|
||||
throw new Error("You must be connected");
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
Reference in New Issue
Block a user