All files / src/utils otpHandler.ts

61.19% Statements 41/67
57.62% Branches 34/59
66.66% Functions 12/18
68.51% Lines 37/54

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58  7x                     7x         7x 7x           7x 9x 6x 9x   15x 6x     7x 21x   7x 7x 7x 7x 7x 7x 7x     3x 3x 3x 3x 18x 18x   3x 3x        
import bcrypt from 'bcryptjs';
import prisma from '@/services/prisma.service';
import { addTime } from './helpers';
import appConfig, { parseStrPeriod } from '@/config/app.config';
import crypto from 'crypto';

export class OTPHandler {
  static async generate(userId: string) {
    const digits = '0123456789';
    let otpValue = '';
    for (let i = 0; i < appConfig.mfa.otp.digits; i++) {
      const randomIndex = crypto.randomInt(0, digits.length);
      otpValue += digits[randomIndex];
    }

    const timePeriod = parseStrPeriod(appConfig.mfa.otp.expirationPeriod);
 
    await prisma.otps.create({
    E  data: {
        otp: bcrypt.hashSync(otpValue, 10),
        expiresAt: addTime(timePeriod.value, timePeriod.unit),
        user: {
          connect: {
            id: userId,
          },
        },
      },
    });

    return otpValue;
  }
 
  static async validateOTP(userId: string, otpValue: string) {
    const otpRecord = await prisma.otps.findUnique({
      where: {
        userId,
      },
    });
 
    if (!otpRecord) return false;
 
    if (otpRecord.expiresAt < new Date()) return false;
 
    const isValid = bcrypt.compareSync(otpValue, otpRecord.otp);
    if (!isValid) {
      return false;
    }
 
    await prisma.otps.delete({
      where: {
        id: otpRecord.id,
      },
    });
 
    return true;
  }
}