API authentifiée

This commit is contained in:
2024-12-07 13:06:15 +01:00
parent 376c297eda
commit 45a1cebcf9
23 changed files with 783 additions and 41 deletions

View File

@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing'
import { AuthController } from './auth.controller'
import { AuthService } from './auth.service'
describe('AuthController', () => {
let controller: AuthController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AuthController],
providers: [AuthService],
}).compile()
controller = module.get<AuthController>(AuthController)
})
it('should be defined', () => {
expect(controller).toBeDefined()
})
})

View File

@ -0,0 +1,17 @@
import { Body, Controller, Post } from '@nestjs/common'
import { AuthService } from './auth.service'
import { ApiOkResponse, ApiTags } from '@nestjs/swagger'
import { AuthEntity } from './entity/auth.entity'
import { LoginDto } from './dto/login.dto'
@Controller('auth')
@ApiTags('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('login')
@ApiOkResponse({ type: AuthEntity })
login(@Body() { name, password }: LoginDto) {
return this.authService.login(name, password)
}
}

View File

@ -0,0 +1,26 @@
import { Module } from '@nestjs/common'
import { AuthService } from './auth.service'
import { AuthController } from './auth.controller'
import { PrismaModule } from 'src/prisma/prisma.module'
import { PassportModule } from '@nestjs/passport'
import { JwtModule } from '@nestjs/jwt'
import { env } from 'process'
import { UsersModule } from 'src/users/users.module'
import { JwtStrategy } from './jwt.strategy'
export const JWT_SECRET = env.JWT_SECRET
@Module({
imports: [
PrismaModule,
PassportModule,
JwtModule.register({
secret: JWT_SECRET,
signOptions: { expiresIn: '5m' },
}),
UsersModule,
],
controllers: [AuthController],
providers: [AuthService, JwtStrategy],
})
export class AuthModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing'
import { AuthService } from './auth.service'
describe('AuthService', () => {
let service: AuthService
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile()
service = module.get<AuthService>(AuthService)
})
it('should be defined', () => {
expect(service).toBeDefined()
})
})

View File

@ -0,0 +1,27 @@
import { Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common'
import { PrismaService } from './../prisma/prisma.service'
import { JwtService } from '@nestjs/jwt'
import { AuthEntity } from './entity/auth.entity'
import * as bcrypt from 'bcrypt'
@Injectable()
export class AuthService {
constructor(private prisma: PrismaService, private jwtService: JwtService) {}
async login(name: string, password: string): Promise<AuthEntity> {
const user = await this.prisma.user.findUnique({ where: { name: name } })
if (!user) {
throw new NotFoundException(`Aucun⋅e utilisateur⋅rice avec pour nom ${name}`)
}
const isPasswordValid = await bcrypt.compare(password, user.password)
if (!isPasswordValid) {
throw new UnauthorizedException('Mot de passe incorrect')
}
return {
accessToken: this.jwtService.sign({ userId: user.id }),
}
}
}

View File

@ -0,0 +1,14 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsNotEmpty, IsString, MinLength } from 'class-validator'
export class LoginDto {
@IsString()
@IsNotEmpty()
@ApiProperty()
name: string
@IsString()
@IsNotEmpty()
@ApiProperty()
password: string
}

View File

@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger'
export class AuthEntity {
@ApiProperty()
accessToken: string
}

View File

@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

View File

@ -0,0 +1,23 @@
import { Injectable, UnauthorizedException } from '@nestjs/common'
import { PassportStrategy } from '@nestjs/passport'
import { ExtractJwt, Strategy } from 'passport-jwt'
import { JWT_SECRET } from './auth.module'
import { UsersService } from 'src/users/users.service'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private usersService: UsersService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: JWT_SECRET,
})
}
async validate(payload: { userId: number }) {
const user = await this.usersService.findOne(payload.userId)
if (!user) {
throw new UnauthorizedException()
}
return user
}
}