Files
ostan-complain-api/src/modules/auth/auth.service.ts
T

114 lines
3.3 KiB
TypeScript

import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import type { ISmsConfigs } from 'src/config/sms.config';
import { SMS_CONFIG } from '../utils/constants';
import { SmsService } from '../utils/providers/sms.service';
import { OtpRepository } from './repositories/otp.repository';
import { OtpStatus } from './enums/otp-status.enum';
import { VerifyOtpDto } from './DTO/verify-otp.dto';
import { OTPMessages, UserMessages } from 'src/common/enums/messages.enum';
import { LoginCredentialDto } from './DTO/login-credential.dto';
import { UsersService } from 'src/modules/users/users.service';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import ms from 'ms';
import { OtpService } from './otp.service';
@Injectable()
export class AuthService {
constructor(
@Inject(SMS_CONFIG) private smsConfig: ISmsConfigs,
private readonly smsService: SmsService,
private readonly configService: ConfigService,
private readonly userService: UsersService,
private readonly jwtService: JwtService,
private readonly otpService: OtpService
) {}
async sendOTP(phone: string) {
const otp = await this.otpService.generate(phone);
try {
await this.smsService.sendSms({
Mobile: phone,
TemplateId: this.smsConfig.SMS_PATTERN_OTP,
Parameters: [
{
name: 'code',
value: otp,
},
],
});
return { otp };
} catch (error) {
if (this.configService.get('NODE_ENV') !== 'production') {
return { otp };
}
throw error;
}
}
async verifyOTP(dto: VerifyOtpDto) {
await this.otpService.verify(dto.phoneNumber, dto.code);
}
async checkLoginCredentials(credential: LoginCredentialDto): Promise<void> {
const { phoneNumber, password } = credential;
const user = await this.userService.findOneByPhoneOrFail(phoneNumber);
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
throw new BadRequestException(UserMessages.USER_PASSWORD_INVALID);
}
await this.sendOTP(phoneNumber);
}
async verifyOtpAndLogin(dto: VerifyOtpDto) {
await this.verifyOTP(dto);
const user = await this.userService.findUserWithRolesByPhoneOrFail(
dto.phoneNumber,
);
const roles = user.roles.map((r) => r.role);
const payload = {
id: user.id,
phone: user.phone,
roles,
};
const accessToken = await this.jwtService.signAsync(payload, {
secret: this.configService.getOrThrow<string>('JWT_ACCESS_SECRET'),
expiresIn: this.configService.getOrThrow<string>(
'JWT_ACCESS_EXPIRES',
) as ms.StringValue,
});
const refreshToken = await this.jwtService.signAsync(payload, {
secret: this.configService.getOrThrow<string>('JWT_REFRESH_SECRET'),
expiresIn: this.configService.getOrThrow<string>(
'JWT_REFRESH_EXPIRES',
) as ms.StringValue,
});
await this.userService.updateRefreshToken(user.id, refreshToken);
return {
user: {
userId: user.id,
username: user.firstName + ' ' + user.lastName,
userPhone: user.phone,
userEmail: user.email,
},
accessToken,
refreshToken,
};
}
}