One-Time Password Generation Using speakeasy, Nest.js And MongoDB
·
import {
Controller,
Post,
Req,
UseGuards,
Get,
Body,
BadRequestException,
Param,
NotFoundException,
} from "@nestjs/common";
import { JwtAuthGuard } from "./auth.guard";
import { LoggedInToken } from "../users/objects/login-user.dto";
import { AuthService } from "./auth.service";
import * as speakeasy from "speakeasy";
import { optSecret } from "../common/constants/config";
import {
UNKNOWN_PARAM,
EMAIL_NOT_FOUND,
OTP_ERROR,
EXISTS,
OTP_NOT_EXPIRED,
NEW_PASSWORD_AND_CONFIRM_NEW_PASSWORD_ERROR,
OTP_TIME_OUT,
TOKEN_ALREADY_USED,
EMAIL_ERROR,
BLOCKED_ACCOUNT_ERROR,
} from "../common/constants/string";
import { plainToClass } from "class-transformer";
import { success } from "../common/base/httpResponse.interface";
import { UserDto } from "../users/objects/create-user.dto";
import { OtpEmail, UserCycloanAccountBlockedEmail } from "../users/objects/user.registered.email";
import {
ForgetPasswordOtpEmail,
PasswordChangedAlert,
} from "../users/objects/user.registered.email";
import { EmailService } from "../email/email.service";
import { OtpService } from "./otp/otp.service";
import { RequestUser } from "../common/utils/controller.decorator";
import { UsersService } from "../users/users.service";
import { EmailDto } from "../email/objects/email.dto";
import { OtpDto } from "./otp/otp.dto";
import { InjectModel } from "@nestjs/mongoose";
import { IOtp, Otp } from "./otp/otp.schema";
import { Model } from "mongoose";
import { ForgotPasswordOtpService } from "./forgot-password-otp/forgot-password-otp.service";
import { ForgotPasswordOtp } from "./forgot-password-otp/forgot-password-otp.schema";
import { ForgotPasswordOtpDto } from "./forgot-password-otp/forgot-password-otp.dto";
import { OtpIncorrectService } from "./otpIncorrect/otpIncorrect.service";
import { OtpIncorrect } from "./otpIncorrect/otpIncorrect.schema";
import { BlockedAccountService } from "./blockedAccounts/blockedAccounts.service";
import { IBlockedAccount } from "./blockedAccounts/blockedAccounts.schema";
import { OTP_RETRY_LIMIT, Status, ROLES_ACCESS_ACTION, BLOCKED_ACCOUNT_TYPE } from "../common/constants/enum";
import { RolesService } from "../roles/roles.service";
import { OtpIncorrectForgotPasswordService } from "./otpIncorrectForgotPassword/otpIncorrectForgotPassword.service";
import { OtpIncorrectForgotPassword } from "./otpIncorrectForgotPassword/otpIncorrectForgotPassword.schema";
//@UseGuards(JwtAuthGuard)
@Controller("auth/refresh")
export class AuthController {
constructor(
private authService: AuthService,
private emailService: EmailService,
private usersService: UsersService,
private otpService: OtpService,
private forgotPasswordOtpService: ForgotPasswordOtpService,
@InjectModel("Otp") private readonly otpModel: Model,
@InjectModel("ForgotPasswordOtp")
private readonly forgotPasswordotpModel: Model,
private readonly otpIncorrectService: OtpIncorrectService,
@InjectModel("OtpIncorrect") private readonly otpIncorrectModel: Model,
private readonly blockedAccountService: BlockedAccountService,
@InjectModel("BlockedAccount") private readonly blockedAccountModel: Model,
private rolesservice: RolesService,
private otpIncorrectForgotPasswordService: OtpIncorrectForgotPasswordService,
@InjectModel("OtpIncorrectForgotPassword") private readonly otpIncorrectForgotPasswordModel: Model,
) {}
@UseGuards(JwtAuthGuard)
@Post()
public async refresh(@Req() req): Promise {
return this.authService.createJwtPayLoad(req.user);
}
//Api For generating a secret and storing it in config.ts
@Get("secret")
async getSecret() {
const secret = speakeasy.generateSecret({ length: 20 });
return secret;
}
//Api For generating a 6 digit token using the secret
@Post("generate")
async getOtp(
@Req() req,
@Body() body: { email: string; firstName: string; lastName: string }
//@RequestUser() user
) {
debugger;
let email = body.email;
let firstName = body.firstName;
let lastName = body.lastName;
var token = speakeasy.totp({
secret: optSecret,
encoding: "base32",
});
let userToAttempt: any = await this.usersService.findOneByEmail(body.email);
//Check for existing users
if (!userToAttempt) {
let _blocked: any = await this.blockedAccountService.findOneByQuery({email: email, type: BLOCKED_ACCOUNT_TYPE.USER_REGISTRATION})
if(_blocked !== null){
throw new BadRequestException(BLOCKED_ACCOUNT_ERROR(email))
}
let query = { email: email };
let _otp: any = await this.otpService.findOneByQuery(query);
let currentTime: number = Date.now();
if (_otp) {
let k: any = await this.otpModel
.find({ email: email })
.sort({ updatedTime: -1 })
.limit(1);
if (k !== undefined) {
let diff = (currentTime - k[0].expiry) / 1000;
let updateTime: number = Date.now();
let createDto: any = {
token: token,
email: email,
firstName: firstName,
lastName: lastName,
expiry: updateTime + 15 * 60 * 1000,
};
if (diff > 0) {
let _otp: any = await this.otpService.create(createDto);
let _data =
"Otp sent to registered email " +
body.email +
" " +
"token:" +
token;
await this.emailService.sendEmail(
new OtpEmail(
new EmailDto({
to: body.email,
metaData: { email, token, firstName, lastName },
})
)
);
return success(_data);
} else {
let errorData = "Otp sent yet to expire in" + diff + "seconds";
throw new BadRequestException(OTP_NOT_EXPIRED(errorData));
}
}
}
//For users requesting for the first time
let updateTime: number = Date.now();
let createDto: any = {
token: token,
email: email,
expiry: updateTime + 15 * 60 * 1000,
};
let _otp1: any = await this.otpService.create(createDto);
await this.emailService.sendEmail(
new OtpEmail(
new EmailDto({
to: body.email,
metaData: { email, token, firstName, lastName },
})
)
);
let _data1 =
"Otp sent to registered email " + body.email + " " + "token:" + token;
return success(_data1);
}
throw new BadRequestException(EXISTS, "User exists");
}
}
更多推荐

所有评论(0)