super-fit-web-app / src / utils / planetscale / change-password.ts
change-password.ts
Raw
import { NextApiRequest, NextApiResponse } from "next"
import { db } from "@/db/PrismaClient";
import { TRPCError } from '@trpc/server';
import { getSession } from "@/utils/planetscale/session";
import argon2 from "argon2";
import crypto from "crypto";

export const changePassword = async (
  oldPassword: string,
  newPassword: string,
  req: NextApiRequest,
  res: NextApiResponse,
) => {
  const sessionResponse = await getSession(req, res)

  if (!sessionResponse.session_valid) {
    throw new TRPCError({
      code: 'FORBIDDEN',
      message: 'You must be logged in to change your password'
    })
  }

  const user = await db.user.findFirst({
    where: { email: sessionResponse.user.email }
  })

  if (!user) {
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: 'User not found'
    })
  }

  const salted_password = oldPassword + user.salt;

  const valid = await argon2.verify(user.hash, salted_password);

  if (!valid) {
    throw new TRPCError({
      code: 'UNAUTHORIZED',
      message: 'Invalid password',
    });
  }

  const salt: string = crypto.randomBytes(16).toString('hex');
  const hash: string = await argon2.hash(newPassword + salt);

  const newPasswordOnOldSalt = await argon2.hash(newPassword + user.salt);
  const oldHash: string = await argon2.hash(oldPassword + user.salt);

  if (oldHash == newPasswordOnOldSalt) {
    throw new TRPCError({
      code: 'BAD_REQUEST',
      message: 'New password cannot be the same as the old password',
    });
  }

  await db.user.update({
    where: { email: sessionResponse.user.email },
    data: {
      hash: hash,
      salt: salt
    }
  })

  return {
    success: true
  }
}