mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-08 22:53:25 +00:00
feat(wip): add support for multi user in instance
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
29
src/_middleware.ts
Normal 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,
|
||||
],
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user