From 7e5d5efb094fd5f4f5937a7ccf9e85c0b08273ea Mon Sep 17 00:00:00 2001 From: Isaac Date: Sun, 8 Dec 2024 22:18:33 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=8A=20forgot=20password=20backend=20co?= =?UTF-8?q?mplete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20241206134721_init/migration.sql | 11 +++++ backend/prisma/schema.prisma | 10 ----- backend/src/index.ts | 8 ++-- backend/src/routes/OTP/OTPToken.ts | 40 ------------------- backend/src/routes/OTP/deleteExpired.ts | 16 -------- backend/src/routes/OTP/generateOTP.ts | 13 +----- backend/src/routes/OTP/sendEmail.ts | 4 +- backend/src/routes/OTP/verifyOTP.ts | 5 +-- backend/tests/otp.test.ts | 1 - 9 files changed, 18 insertions(+), 90 deletions(-) create mode 100644 backend/prisma/migrations/20241206134721_init/migration.sql delete mode 100644 backend/src/routes/OTP/deleteExpired.ts diff --git a/backend/prisma/migrations/20241206134721_init/migration.sql b/backend/prisma/migrations/20241206134721_init/migration.sql new file mode 100644 index 0000000..fefa79e --- /dev/null +++ b/backend/prisma/migrations/20241206134721_init/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the `OtpToken` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "OtpToken" DROP CONSTRAINT "OtpToken_userId_fkey"; + +-- DropTable +DROP TABLE "OtpToken"; diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 7627cd8..99ee565 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -30,7 +30,6 @@ model User { salt String dateJoined DateTime profilePicture String? - oneTimeToken OtpToken? } model Attendee { @@ -69,13 +68,4 @@ model Keyword { text String @unique attendees Attendee[] events Event[] -} - -model OtpToken { - id Int @id @default(autoincrement()) - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int @unique - token String - timeCreated DateTime - expiryTime DateTime } \ No newline at end of file diff --git a/backend/src/index.ts b/backend/src/index.ts index 6a333e1..41f4aab 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -9,7 +9,6 @@ import prisma from "./prisma"; import RedisStore from "connect-redis"; import { createClient } from "redis"; import { generateOTP } from "./routes/OTP/generateOTP"; -import { removeExpiredOTPs } from "./routes/OTP/deleteExpired"; import { verifyOTP } from "./routes/OTP/verifyOTP"; declare module "express-session" { @@ -57,9 +56,6 @@ app.use( }) ); -// OTP removing cron job -removeExpiredOTPs.start(); - app.get("/", (req: Request, res: Response) => { console.log("Hello, TypeScript with Express :)))!"); res.send("Hello, TypeScript with Express :)))!"); @@ -151,11 +147,13 @@ app.post("/auth/otp/verify", async(req: Request, res: Response) => { const hash = await redisClient.get(email); if(!hash) { - throw Error("One time code has expired."); + throw new Error("One time code is invalid or expired."); } await verifyOTP(token, hash); + await redisClient.del(email); + return res.status(200).json({message: "ok" }); } catch (error) { diff --git a/backend/src/routes/OTP/OTPToken.ts b/backend/src/routes/OTP/OTPToken.ts index 5b6aa8e..e10440c 100644 --- a/backend/src/routes/OTP/OTPToken.ts +++ b/backend/src/routes/OTP/OTPToken.ts @@ -17,44 +17,4 @@ export const getUserFromEmail = async (emailAddress: string) => { }); return result; -} - -export const deleteToken = async(userId: number) => { - const result = await prisma.otpToken.deleteMany({ - where: { - userId - } - }); - - return result; -} - -export const addTokenToDb = async(token: OTPToken) => { - const result = await prisma.otpToken.create({ - data: { - userId: token.user.id, - token: token.token, - timeCreated: token.timeCreated, - expiryTime: token.expiryTime - } - }); - return result; -} - -export const getTokenFromEmail = async(emailAddress: string) => { - const user = await getUserFromEmail(emailAddress); - if(!user) { - throw new Error(`User with email address ${emailAddress} not found.`) - } - const otpToken = await prisma.otpToken.findFirst({ - where: { - userId: user.id - } - }); - - if(!otpToken) { - throw new Error(`OTP Token for ${emailAddress} not found.`); - } - - return otpToken; } \ No newline at end of file diff --git a/backend/src/routes/OTP/deleteExpired.ts b/backend/src/routes/OTP/deleteExpired.ts deleted file mode 100644 index 85f7daf..0000000 --- a/backend/src/routes/OTP/deleteExpired.ts +++ /dev/null @@ -1,16 +0,0 @@ -import cron from 'node-cron'; -import prisma from '../../prisma'; - -export const removeExpiredOTPs = cron.schedule('* * * * *', async () => { - try { - await prisma.otpToken.deleteMany({ - where: { - expiryTime: { - lte: new Date(), - }, - }, - }); - } catch (error) { - console.error(error); - } - }); \ No newline at end of file diff --git a/backend/src/routes/OTP/generateOTP.ts b/backend/src/routes/OTP/generateOTP.ts index 719d553..1c8d474 100644 --- a/backend/src/routes/OTP/generateOTP.ts +++ b/backend/src/routes/OTP/generateOTP.ts @@ -1,8 +1,7 @@ import crypto from 'crypto'; import bcrypt from 'bcrypt'; -import { addTokenToDb, deleteToken, getUserFromEmail, OTPToken } from './OTPToken'; +import { getUserFromEmail } from './OTPToken'; import { sendEmail } from './sendEmail'; -import { RedisClientType, RedisModules } from 'redis'; export const generateOTP = async (emailAddress: string, salt_rounds: number) => { const user = await getUserFromEmail(emailAddress); @@ -11,21 +10,11 @@ export const generateOTP = async (emailAddress: string, salt_rounds: number) => throw new Error("User not found."); } - //await deleteToken(user.id); - const rand = crypto.randomBytes(4).readUint32BE(0); const sixDigits = (rand % 900000) + 100000; const otpCode = sixDigits.toString(); const hash = await bcrypt.hash(otpCode, salt_rounds); - // const token: OTPToken = { - // token: hash, - // timeCreated: new Date(), - // expiryTime: new Date(Date.now()+60000), - // }; - - //await addTokenToDb(token); - await sendEmail(emailAddress, user.username, otpCode); return hash; diff --git a/backend/src/routes/OTP/sendEmail.ts b/backend/src/routes/OTP/sendEmail.ts index 5b710c4..bc26203 100644 --- a/backend/src/routes/OTP/sendEmail.ts +++ b/backend/src/routes/OTP/sendEmail.ts @@ -16,7 +16,7 @@ export const sendEmail = async (emailAddress: string, userName: string, code: st throw new Error("invalid email key"); } - console.log(`emailing ${userName} at ${emailAddress} with otp ${code}.`); + //console.log(`emailing ${userName} at ${emailAddress} with otp ${code}.`); const senderDomain = "mg.pyrmds.app"; try { @@ -30,7 +30,7 @@ export const sendEmail = async (emailAddress: string, userName: string, code: st

Dear ${userName},

We have received a request from you to reset your password for Pyramids.

Your one time code is: ${code}.

-

Please note that this code will expire in 5 minutes.

+

Please note that this code will expire in 60 seconds.


Thank you.

` diff --git a/backend/src/routes/OTP/verifyOTP.ts b/backend/src/routes/OTP/verifyOTP.ts index 1265d93..9bc55f0 100644 --- a/backend/src/routes/OTP/verifyOTP.ts +++ b/backend/src/routes/OTP/verifyOTP.ts @@ -1,5 +1,3 @@ -import prisma from "../../prisma"; -import { getTokenFromEmail } from "./OTPToken"; import bcrypt from 'bcrypt'; export const verifyOTP = async (token: string, hash: string) => { @@ -10,5 +8,4 @@ export const verifyOTP = async (token: string, hash: string) => { } return verify; -} - +} \ No newline at end of file diff --git a/backend/tests/otp.test.ts b/backend/tests/otp.test.ts index f67e00e..ebcd0c7 100644 --- a/backend/tests/otp.test.ts +++ b/backend/tests/otp.test.ts @@ -3,7 +3,6 @@ import { expect, test, vi, describe } from "vitest"; // 👈🏻 Added the `vi` import request from "supertest"; import app from "../src/index"; import { createClient } from "redis"; -import { afterEach, beforeEach } from "node:test"; import prisma from "../src/prisma"; describe("Tests", () => {