nest-project/src/users/users.service.ts

76 lines
2.5 KiB
TypeScript

import { Inject, Injectable, UnauthorizedException } from '@nestjs/common'
import * as bcrypt from 'bcrypt'
import { PrismaService } from 'nestjs-prisma'
import { JwtService } from '@nestjs/jwt'
import { securityConfig, type SecurityConfig } from 'src/common/configs'
import { CreateUserDto } from 'src/users/dto/create-user.dto'
import { EmailScene } from 'src/email/dto/email.dto'
import { EmailService } from 'src/email/email.service'
import { ResetPassword } from './dto/reset-password.dto'
import { Token, TokenPayload } from './dto/token.dto'
import { VerifyEmail } from 'src/email/email-verify.decorator'
@Injectable()
export class UsersService {
constructor(
private jwtService: JwtService,
private prismaService: PrismaService,
private emailService: EmailService,
@Inject(securityConfig.KEY) private secureConfig: SecurityConfig,
) {}
@VerifyEmail(EmailScene.register)
async registerByEmail(userToCreate: CreateUserDto) {
const { email, username, password } = userToCreate
const hashedPassword = await bcrypt.hash(
password,
this.secureConfig.bcryptSaltOrRound,
)
const user = await this.prismaService.user.create({
data: { username, email, password: hashedPassword },
})
return this.generateTokens({ userId: user.id })
}
async loginByEmail(email: string, password: string) {
const user = await this.prismaService.user.findUniqueOrThrow({
where: { email },
})
const passwordValid = await bcrypt.compare(password, user.password)
if (!passwordValid) {
throw new UnauthorizedException('Invalid password')
}
return this.generateTokens({ userId: user.id })
}
@VerifyEmail(EmailScene.forgetPassword)
async resetPasswordByEmail(data: ResetPassword) {
const { password } = data
const hashedPassword = await bcrypt.hash(
password,
this.secureConfig.bcryptSaltOrRound,
)
const user = await this.prismaService.user.update({
where: { id: data.userId },
data: { password: hashedPassword },
})
return this.generateTokens({ userId: user.id })
}
private generateTokens(payload: TokenPayload): Token {
const accessToken = this.jwtService.sign(payload, {
secret: this.secureConfig.jwt_access_secret,
expiresIn: this.secureConfig.expiresIn,
})
const refreshToken = this.jwtService.sign(payload, {
secret: this.secureConfig.jwt_refresh_secret,
expiresIn: this.secureConfig.refreshIn,
})
return { accessToken, refreshToken, ...payload }
}
}