-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Varkoff/04-authentication
03: Add Shadcn-UI and Tailwind CSS + Add authentication
- Loading branch information
Showing
48 changed files
with
2,056 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
backend/prisma/migrations/20240414130439_init_prisma/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
-- CreateTable | ||
CREATE TABLE "User" ( | ||
"id" TEXT NOT NULL, | ||
"email" TEXT NOT NULL, | ||
"name" TEXT, | ||
"password" TEXT NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "User_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Session" ( | ||
"id" TEXT NOT NULL, | ||
"userId" TEXT NOT NULL, | ||
"ipAddress" TEXT, | ||
"userAgent" TEXT, | ||
"sessionToken" TEXT NOT NULL, | ||
|
||
CONSTRAINT "Session_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Please do not edit this file manually | ||
# It should be added in your version-control system (i.e. Git) | ||
provider = "postgresql" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// This is your Prisma schema file, | ||
// learn more about it in the docs: https://pris.ly/d/prisma-schema | ||
|
||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? | ||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init | ||
|
||
generator client { | ||
provider = "prisma-client-js" | ||
} | ||
|
||
datasource db { | ||
provider = "postgresql" | ||
url = env("DATABASE_URL") | ||
} | ||
|
||
model User { | ||
id String @id @default(cuid()) | ||
email String @unique | ||
name String? | ||
password String | ||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
sessions Session[] | ||
} | ||
|
||
model Session { | ||
id String @id @default(cuid()) | ||
userId String | ||
user User @relation(fields: [userId], references: [id]) | ||
ipAddress String? | ||
userAgent String? | ||
sessionToken String @unique | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { AppController } from './app.controller'; | ||
import { AppService } from './app.service'; | ||
import { AuthController } from './auth/auth.controller'; | ||
import { AuthModule } from './auth/auth.module'; | ||
import { PrismaService } from './prisma/prisma.service'; | ||
import { RemixController } from './remix/remix.controller'; | ||
import { RemixService } from './remix/remix.service'; | ||
|
||
@Module({ | ||
imports: [], | ||
controllers: [AppController, RemixController], | ||
providers: [AppService, RemixService], | ||
imports: [AuthModule], | ||
controllers: [AuthController, RemixController], | ||
providers: [PrismaService, RemixService], | ||
}) | ||
export class AppModule {} | ||
export class AppModule { } |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Controller, Get, Next, Post, Redirect, Req, Res, UseGuards } from '@nestjs/common'; | ||
import { NextFunction, Request, Response } from 'express'; | ||
import { LocalAuthGuard } from './local-auth.guard'; | ||
|
||
@Controller() | ||
export class AuthController { | ||
@UseGuards(LocalAuthGuard) | ||
@Get('/authenticate') | ||
@Redirect('/') | ||
async login(@Req() req: Request) { | ||
console.log({ requestUser: req.user }); | ||
// return req.user; | ||
} | ||
|
||
@Post('auth/logout') | ||
async logout( | ||
@Req() request: Express.Request, | ||
@Res() response: Response, | ||
@Next() next: NextFunction, | ||
) { | ||
// this will ensure that re-using the old session id | ||
// does not have a logged in user | ||
request.logOut(function (err) { | ||
if (err) { | ||
return next(err); | ||
} | ||
// Ensure the session is destroyed and the user is redirected. | ||
request.session.destroy(() => { | ||
response.clearCookie('connect.sid'); // The name of the cookie where express/connect stores its session_id | ||
response.redirect('/'); // Redirect to website after logout | ||
}); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { PassportModule } from '@nestjs/passport'; | ||
import { PrismaService } from '../prisma/prisma.service'; | ||
import { AuthService } from './auth.service'; | ||
import { CookieSerializer } from './cookie-serializer'; | ||
import { LocalAuthGuard } from './local-auth.guard'; | ||
import { LocalStrategy } from './local.strategy'; | ||
|
||
@Module({ | ||
imports: [ | ||
PassportModule.register({ | ||
defaultStrategy: 'local', | ||
property: 'user', | ||
session: true | ||
}) | ||
], | ||
controllers: [], | ||
providers: [LocalStrategy, LocalAuthGuard, CookieSerializer, PrismaService, AuthService], | ||
exports: [AuthService] | ||
}) | ||
export class AuthModule { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { createId } from '@paralleldrive/cuid2'; | ||
import { compare, hash } from 'bcryptjs'; | ||
import { PrismaService } from '../prisma/prisma.service'; | ||
const PASSWORD_SALT = 10; | ||
|
||
@Injectable() | ||
export class AuthService { | ||
constructor(private readonly prisma: PrismaService) { } | ||
|
||
public readonly checkIfUserExists = async ({ | ||
email, | ||
password, | ||
withPassword, | ||
}: { | ||
email: string; | ||
withPassword: boolean; | ||
password: string; | ||
}) => { | ||
// Renvoie true si l'utilisateur n'existe pas | ||
// Renvoie false si l'utilisateur existe | ||
// 1. Vérifier que l'utilisateur existe sur l'email | ||
// 2. Si withPassword est activé, on vérifie que son mot de passe | ||
// est bien défini. | ||
const existingUser = await this.prisma.user.findUnique({ | ||
where: { | ||
email, | ||
}, | ||
select: { | ||
id: true, | ||
name: true, | ||
email: true, | ||
password: true, | ||
}, | ||
}); | ||
if (!existingUser) { | ||
return { | ||
message: "L'email est invalide", | ||
error: true, | ||
}; | ||
} | ||
|
||
if (withPassword) { | ||
// Rajouter une logique de validation par mot de passez | ||
const isPasswordValid = await compare(password, existingUser.password); | ||
|
||
if (!isPasswordValid) { | ||
return { | ||
message: "Le mot de passe est invalide", | ||
error: true, | ||
}; | ||
} | ||
} | ||
return { | ||
message: "L'utilisateur existe.", | ||
error: false, | ||
}; | ||
}; | ||
|
||
public readonly createUser = async ({ | ||
email, | ||
name, | ||
password, | ||
}: { | ||
email: string; | ||
name: string; | ||
password: string; | ||
}) => { | ||
const hashedPassword = await hash(password, PASSWORD_SALT); | ||
return await this.prisma.user.create({ | ||
data: { | ||
email: email.toLowerCase(), | ||
password: hashedPassword, | ||
name, | ||
}, | ||
select: { | ||
id: true, | ||
name: true, | ||
email: true, | ||
}, | ||
}); | ||
}; | ||
|
||
public readonly authenticateUser = async ({ | ||
email, | ||
}: { | ||
email: string; | ||
}) => { | ||
return await this.prisma.session.create({ | ||
data: { | ||
user: { | ||
connect: { | ||
}, | ||
}, | ||
sessionToken: createId() | ||
}, | ||
select: { | ||
sessionToken: true | ||
} | ||
}) | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
import { Injectable } from '@nestjs/common'; | ||
import { PassportSerializer } from '@nestjs/passport'; | ||
|
||
@Injectable() | ||
export class CookieSerializer extends PassportSerializer { | ||
deserializeUser(payload: any, done: Function) { | ||
// console.log('deserializeUser', { payload }); | ||
done(null, payload); | ||
} | ||
serializeUser(user: any, done: Function) { | ||
// console.log('serializeUser', { user }); | ||
done(null, user); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common'; | ||
import { Request, Response } from 'express'; | ||
import { RedirectException } from './redirected-error.exception'; | ||
|
||
@Catch(HttpException) | ||
export class HttpExceptionFilter implements ExceptionFilter { | ||
catch(exception: HttpException, host: ArgumentsHost) { | ||
const ctx = host.switchToHttp(); | ||
const response = ctx.getResponse<Response>(); | ||
const request = ctx.getRequest<Request>(); | ||
const status = exception.getStatus(); | ||
|
||
if (exception instanceof RedirectException) { | ||
const { redirectUrl, message } = exception | ||
return response.redirect(302, `${redirectUrl}?error=${message}`) | ||
} | ||
|
||
response | ||
.status(status) | ||
.json({ | ||
statusCode: status, | ||
timestamp: new Date().toISOString(), | ||
path: request.url, | ||
}); | ||
} | ||
} |
Oops, something went wrong.