feat(wip): add support for multi user in instance

This commit is contained in:
Sonny
2023-05-30 01:17:50 +02:00
parent 7c4999830f
commit e7e7e0c950
8 changed files with 153 additions and 37 deletions

View File

@@ -0,0 +1,17 @@
/*
Warnings:
- You are about to drop the column `nextCategoryId` on the `category` table. All the data in the column will be lost.
- You are about to drop the column `nextLinkId` on the `link` table. All the data in the column will be lost.
- Added the required column `authorId` to the `category` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE `category` DROP COLUMN `nextCategoryId`,
ADD COLUMN `authorId` INTEGER NOT NULL;
-- AlterTable
ALTER TABLE `link` DROP COLUMN `nextLinkId`;
-- AddForeignKey
ALTER TABLE `category` ADD CONSTRAINT `category_authorId_fkey` FOREIGN KEY (`authorId`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@@ -0,0 +1,11 @@
/*
Warnings:
- Added the required column `authorId` to the `link` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE `link` ADD COLUMN `authorId` INTEGER NOT NULL;
-- AddForeignKey
ALTER TABLE `link` ADD CONSTRAINT `link_authorId_fkey` FOREIGN KEY (`authorId`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@@ -6,14 +6,19 @@ generator client {
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
provider = "mysql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
google_id String @unique
email String @unique
id Int @id @default(autoincrement())
google_id String @unique
email String @unique
categories Category[]
links Link[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -21,26 +26,33 @@ model User {
}
model Category {
id Int @id @default(autoincrement())
name String @unique @db.VarChar(255)
links Link[]
nextCategoryId Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id Int @id @default(autoincrement())
name String @unique @db.VarChar(255)
links Link[]
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("category")
}
model Link {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
url String @db.Text
id Int @id @default(autoincrement())
name String @db.VarChar(255)
url String @db.Text
category Category @relation(fields: [categoryId], references: [id])
categoryId Int
nextLinkId Int @default(0)
favorite Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
author User @relation(fields: [authorId], references: [id])
authorId Int
favorite Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("link")
}

29
src/_middleware.ts Normal file
View File

@@ -0,0 +1,29 @@
import PATHS from "constants/paths";
export { default } from "next-auth/middleware";
// WAIT: for fix - Next.js@13.4.4 seems to be broken
// cf: https://github.com/nextauthjs/next-auth/issues/7650
// (this file must renamed "middleware.ts")
export const config = {
matcher: [
PATHS.HOME,
PATHS.LINK.CREATE,
PATHS.LINK.EDIT,
PATHS.LINK.REMOVE,
PATHS.CATEGORY.CREATE,
PATHS.CATEGORY.EDIT,
PATHS.CATEGORY.REMOVE,
PATHS.API.CATEGORY.CREATE,
PATHS.API.CATEGORY.EDIT,
PATHS.API.CATEGORY.REMOVE,
PATHS.API.LINK.CREATE,
PATHS.API.LINK.EDIT,
PATHS.API.LINK.REMOVE,
],
};

View File

@@ -1,5 +1,6 @@
const PATHS = {
LOGIN: "/signin",
LOGOUT: "/signout",
HOME: "/",
CATEGORY: {
CREATE: "/category/create",
@@ -13,14 +14,14 @@ const PATHS = {
},
API: {
CATEGORY: {
CREATE: "/category/create",
EDIT: "/category/edit",
REMOVE: "/category/remove",
CREATE: "/api/category/create",
EDIT: "/api/category/edit",
REMOVE: "/api/category/remove",
},
LINK: {
CREATE: "/link/create",
EDIT: "/link/edit",
REMOVE: "/link/remove",
CREATE: "/api/link/create",
EDIT: "/api/link/edit",
REMOVE: "/api/link/remove",
},
},
NOT_FOUND: "/404",

View File

@@ -1,11 +1,12 @@
import { PrismaClient } from "@prisma/client";
import PATHS from "constants/paths";
import NextAuth from "next-auth";
import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
const prisma = new PrismaClient();
export default NextAuth({
// TODO: refactor auth
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
@@ -20,24 +21,33 @@ export default NextAuth({
}),
],
callbacks: {
async session({ session }) {
// check if stored in session still exist in db
await prisma.user.findFirstOrThrow({
where: { email: session.user.email },
});
return session;
},
async signIn({ account: accountParam, profile }) {
// TODO: Auth
console.log(
"Connexion via",
accountParam.provider,
accountParam.providerAccountId,
profile.email,
profile.name
"[AUTH]",
"User",
profile.name,
"attempt to log in with",
accountParam.provider
);
if (accountParam.provider !== "google") {
console.log("[AUTH]", "User", profile.name, "rejeced : bad provider");
return (
PATHS.LOGIN +
"?error=" +
encodeURI("Authentitifcation via Google requise")
);
}
const email = profile?.email;
if (email === "") {
console.log("[AUTH]", "User", profile.name, "rejeced : missing email");
return (
PATHS.LOGIN +
"?error=" +
@@ -48,6 +58,12 @@ export default NextAuth({
}
const googleId = profile?.sub;
if (googleId === "") {
console.log(
"[AUTH]",
"User",
profile.name,
"rejeced : missing google id"
);
return (
PATHS.LOGIN +
"?error=" +
@@ -74,6 +90,13 @@ export default NextAuth({
});
return true;
}
console.log(
"[AUTH]",
"User",
profile.name,
"rejeced : not authorized"
);
return (
PATHS.LOGIN +
"?error=" +
@@ -82,9 +105,11 @@ export default NextAuth({
)
);
} else {
console.log("[AUTH]", "User", profile.name, "success");
return true;
}
} catch (error) {
console.log("[AUTH]", "User", profile.name, "unhandled error");
console.error(error);
return (
PATHS.LOGIN +
@@ -97,8 +122,10 @@ export default NextAuth({
pages: {
signIn: PATHS.LOGIN,
error: PATHS.LOGIN,
signOut: PATHS.LOGOUT,
},
session: {
maxAge: 60 * 60 * 6, // Session de 6 heures
},
});
} as NextAuthOptions;
export default NextAuth(authOptions);

View File

@@ -1,10 +1,15 @@
import { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]";
import prisma from "utils/prisma";
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) {
@@ -30,8 +35,20 @@ export default async function handler(
}
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 category = await prisma.category.create({
data: { name },
data: { name, authorId },
});
return res.status(200).send({
success: "Catégorie créée avec succès",

View File

@@ -1,5 +1,6 @@
import { getServerSession } from "next-auth/next";
import { Provider } from "next-auth/providers";
import { getProviders, getSession, signIn } from "next-auth/react";
import { getProviders, signIn } from "next-auth/react";
import { NextSeo } from "next-seo";
import Link from "next/link";
@@ -7,6 +8,7 @@ import MessageManager from "components/MessageManager/MessageManager";
import PATHS from "constants/paths";
import styles from "styles/login.module.scss";
import { authOptions } from "./api/auth/[...nextauth]";
interface SignInProps {
providers: Provider[];
@@ -36,8 +38,8 @@ export default function SignIn({ providers }: SignInProps) {
);
}
export async function getServerSideProps(context) {
const session = await getSession(context);
export async function getServerSideProps({ req, res }) {
const session = await getServerSession(req, res, authOptions);
if (session) {
return {
redirect: {