Add AuthService for user registration and login

Implement user signup and signin functionality with password hashing, role assignment, and JWT token generation. Integrate promo code for initial balance adjustment, and handle unique credential errors.
This commit is contained in:
Mathis H (Avnyr) 2024-10-31 11:49:03 +01:00
parent 747b4357f9
commit cfcc998271
Signed by: Mathis
GPG Key ID: DD9E0666A747D126

110
src/auth/auth.service.ts Normal file
View File

@ -0,0 +1,110 @@
import { ForbiddenException, Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { AuthLoginDto, AuthRegisterDto } from './dto';
import * as argon from 'argon2';
import { Prisma, User } from '@prisma/client';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AuthService {
private readonly initialBalance = 1000;
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.getPromoCode(dto.promoCode);
const userRole = await this.getUserRole('user');
const balance = this.calculateBalance(promoCode);
try {
const user = await this.createUser(dto, hash, userRole.id, balance);
return this.signToken(user);
} catch (error) {
this.handleSignupError(error);
}
}
private async getPromoCode(promoCode: string) {
return this.prisma.promoCode.findFirst({
where: {name: promoCode},
});
}
private async getUserRole(roleName: string) {
return this.prisma.role.findFirst({
where: {name: roleName},
});
}
private calculateBalance(promoCode: any) {
let balance = this.initialBalance;
if (promoCode && promoCode.value) {
balance += promoCode.value;
}
return balance;
}
private async createUser(dto: AuthRegisterDto, hash: string, roleId: string, balance: number) {
return this.prisma.user.create({
data: {
firstName: dto.firstName,
lastName: dto.lastName,
pseudo: dto.pseudo,
city: dto.city,
email: dto.email,
hash,
age: dto.age,
roleId,
isActive: true,
dollarAvailables: balance,
},
});
}
private handleSignupError(error: any) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
throw new ForbiddenException('Credentials taken');
}
}
throw error;
}
async signin(dto: AuthLoginDto) {
const userDatas = await this.prisma.user.findUnique({
where: { email: dto.email },
include: {
UserHasCrypto: { include: { Crypto: true } },
Role: true,
},
});
if (!userDatas) throw new ForbiddenException('Credentials incorrect');
const pwMatches = await argon.verify(userDatas.hash, dto.password);
if (!pwMatches) throw new ForbiddenException('Credentials incorrect');
return this.signToken(userDatas);
}
async signToken(user: any): Promise<{ access_token: string; user: User }> {
const payload = { sub: user.id, email: user.email };
user.hash = null;
const secret = this.config.get('JWT_SECRET');
const token = await this.jwt.signAsync(payload, {
expiresIn: '30d',
secret: secret,
});
return {
access_token: token,
user,
};
}
}