mirror of
https://github.com/Kevsl/crypto-exchange-api.git
synced 2026-02-07 10:56:12 +01:00
testing all features
This commit is contained in:
21
src/auth/auth.controller.ts
Normal file
21
src/auth/auth.controller.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthLoginDto, AuthRegisterDto } from './dto';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@ApiTags('auth')
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private authService: AuthService) {}
|
||||
|
||||
@Post('signup')
|
||||
signup(@Body() dto: AuthRegisterDto) {
|
||||
return this.authService.signup(dto);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('signin')
|
||||
signin(@Body() dto: AuthLoginDto) {
|
||||
return this.authService.signin(dto);
|
||||
}
|
||||
}
|
||||
12
src/auth/auth.module.ts
Normal file
12
src/auth/auth.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
import { JwtStrategy } from './strategy';
|
||||
|
||||
@Module({
|
||||
imports: [JwtModule.register({})],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService, JwtStrategy],
|
||||
})
|
||||
export class AuthModule {}
|
||||
92
src/auth/auth.service.ts
Normal file
92
src/auth/auth.service.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { ForbiddenException, Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { AuthLoginDto, AuthRegisterDto } from './dto';
|
||||
import * as argon from 'argon2';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private jwt: JwtService,
|
||||
private config: ConfigService,
|
||||
) {}
|
||||
|
||||
async signup(dto: AuthRegisterDto) {
|
||||
const hash = await argon.hash(dto.password);
|
||||
const promoCode = await this.prisma.promoCode.findFirst({
|
||||
where: {
|
||||
name: dto.promoCode,
|
||||
},
|
||||
});
|
||||
|
||||
const userRole = await this.prisma.role.findFirst({
|
||||
where: {
|
||||
name: 'user',
|
||||
},
|
||||
});
|
||||
let balance = 1000;
|
||||
if (promoCode && promoCode.value) {
|
||||
balance = promoCode.value;
|
||||
}
|
||||
try {
|
||||
const user = await this.prisma.user.create({
|
||||
data: {
|
||||
firstName: dto.firstName,
|
||||
lastName: dto.lastName,
|
||||
pseudo: dto.pseudo,
|
||||
city: dto.city,
|
||||
email: dto.email,
|
||||
hash,
|
||||
roleId: userRole.id,
|
||||
isActive: true,
|
||||
dollarAvailables: balance,
|
||||
},
|
||||
});
|
||||
|
||||
return this.signToken(user.id, user.email);
|
||||
} catch (error) {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
if (error.code === 'P2002') {
|
||||
throw new ForbiddenException('Credentials taken');
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async signin(dto: AuthLoginDto) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: {
|
||||
email: dto.email,
|
||||
},
|
||||
});
|
||||
if (!user) throw new ForbiddenException('Credentials incorrect');
|
||||
|
||||
const pwMatches = await argon.verify(user.hash, dto.password);
|
||||
if (!pwMatches) throw new ForbiddenException('Credentials incorrect');
|
||||
|
||||
return this.signToken(user.id, user.email);
|
||||
}
|
||||
|
||||
async signToken(
|
||||
userId: string,
|
||||
email: string,
|
||||
): Promise<{ access_token: string }> {
|
||||
const payload = {
|
||||
sub: userId,
|
||||
email: email,
|
||||
};
|
||||
const secret = this.config.get('JWT_SECRET');
|
||||
const token = await this.jwt.signAsync(payload, {
|
||||
expiresIn: '30d',
|
||||
secret: secret,
|
||||
});
|
||||
|
||||
return {
|
||||
access_token: token,
|
||||
};
|
||||
}
|
||||
}
|
||||
11
src/auth/decorator/get-user.decorator.ts
Normal file
11
src/auth/decorator/get-user.decorator.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
|
||||
export const GetUser = createParamDecorator(
|
||||
(data: string | undefined, ctx: ExecutionContext) => {
|
||||
const request: Express.Request = ctx.switchToHttp().getRequest();
|
||||
if (data) {
|
||||
return request.user[data];
|
||||
}
|
||||
return request.user;
|
||||
},
|
||||
);
|
||||
1
src/auth/decorator/index.ts
Normal file
1
src/auth/decorator/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './get-user.decorator';
|
||||
13
src/auth/dto/auth.login.dto.ts
Normal file
13
src/auth/dto/auth.login.dto.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
export class AuthLoginDto {
|
||||
@IsEmail()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ type: String, description: 'email' })
|
||||
email: string;
|
||||
|
||||
@ApiProperty({ type: String, description: 'password' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
password: string;
|
||||
}
|
||||
65
src/auth/dto/auth.register.dto.ts
Normal file
65
src/auth/dto/auth.register.dto.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
export class AuthRegisterDto {
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'FirstName',
|
||||
example: 'Thomas',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
firstName: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'Last Name',
|
||||
example: 'Anderson',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
lastName: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'Pseudo',
|
||||
example: 'Néo',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
pseudo: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'User city',
|
||||
example: 'Aix les bains',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
city: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'email',
|
||||
example: 'neo@matrix.fr',
|
||||
})
|
||||
@IsEmail()
|
||||
@IsNotEmpty()
|
||||
email: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'password',
|
||||
example: 'AAaa11&&&&',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
password: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
description: 'promoCode',
|
||||
example: 'FILOU20',
|
||||
})
|
||||
@IsOptional()
|
||||
promoCode: string;
|
||||
}
|
||||
2
src/auth/dto/index.ts
Normal file
2
src/auth/dto/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './auth.register.dto';
|
||||
export * from './auth.login.dto';
|
||||
1
src/auth/guard/index.ts
Normal file
1
src/auth/guard/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './jwt.guard';
|
||||
7
src/auth/guard/jwt.guard.ts
Normal file
7
src/auth/guard/jwt.guard.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
export class JwtGuard extends AuthGuard('jwt') {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
1
src/auth/strategy/index.ts
Normal file
1
src/auth/strategy/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './jwt.strategy';
|
||||
28
src/auth/strategy/jwt.strategy.ts
Normal file
28
src/auth/strategy/jwt.strategy.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
constructor(
|
||||
config: ConfigService,
|
||||
private prisma: PrismaService,
|
||||
) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: config.get('JWT_SECRET'),
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: { sub: string; email: string }) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: {
|
||||
id: payload.sub,
|
||||
},
|
||||
});
|
||||
delete user.hash;
|
||||
return user;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user