55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import "server-only";
|
|
import SignInFormData from "../types/SignInFormData";
|
|
import db from "@/core/db";
|
|
import AuthError from "../error/AuthError";
|
|
import comparePassword from "../utils/comparePassword";
|
|
import { createJwtToken } from "../utils/createJwtToken";
|
|
|
|
/**
|
|
* Authenticates a user with email and password credentials.
|
|
*
|
|
* This function looks up the user in the database by email. If the user exists and the password matches
|
|
* the hashed password in the database, a JWT token is created and returned. If any step of this process fails,
|
|
* an `AuthError` with a specific error code and message is thrown.
|
|
*
|
|
* @param rawCredential - Contains the email and password provided by the user.
|
|
* @returns An object containing a JWT token if authentication is successful.
|
|
* @throws {AuthError} - Throws an `AuthError` with an appropriate error code and message for various failure scenarios.
|
|
*/
|
|
export default async function signIn(rawCredential: SignInFormData) {
|
|
const user = await db.user.findUnique({
|
|
where: { email: rawCredential.email },
|
|
});
|
|
|
|
if (!user)
|
|
throw new AuthError({
|
|
errorCode: "EMAIL_NOT_FOUND",
|
|
message: "Email or Password does not match",
|
|
});
|
|
|
|
//TODO: Add handle for empty password hash
|
|
// Ensure there is a password hash to compare against.
|
|
if (!user.passwordHash)
|
|
throw new AuthError({
|
|
errorCode: "EMPTY_USER_HASH",
|
|
message: "Something wrong. Please contact your administrator",
|
|
});
|
|
|
|
// Compare the provided password with the stored hash.
|
|
const isMatch = await comparePassword(
|
|
rawCredential.password,
|
|
user.passwordHash
|
|
);
|
|
|
|
// Create a JWT token upon successful authentication.
|
|
if (!isMatch)
|
|
throw new AuthError({
|
|
errorCode: "INVALID_CREDENTIALS",
|
|
message: "Email or Password does not match",
|
|
});
|
|
|
|
const token = createJwtToken({ id: user.id });
|
|
|
|
return { token };
|
|
}
|