datasquirel/package-shared/functions/api/users/api-send-email-code.ts

176 lines
5.4 KiB
TypeScript
Raw Normal View History

2025-01-10 19:10:28 +00:00
import varDatabaseDbHandler from "../../backend/varDatabaseDbHandler";
import nodemailer, { SendMailOptions } from "nodemailer";
import http from "http";
import getAuthCookieNames from "../../backend/cookies/get-auth-cookie-names";
import encrypt from "../../dsql/encrypt";
import serializeCookies from "../../../utils/serialize-cookies";
import { SendOneTimeCodeEmailResponse } from "../../../types";
type Param = {
email: string;
database: string;
email_login_field?: string;
mail_domain?: string;
mail_port?: number;
sender?: string;
mail_username?: string;
mail_password?: string;
html: string;
useLocal?: boolean;
response?: http.ServerResponse & { [s: string]: any };
extraCookies?: import("../../../../package-shared/types").CookieObject[];
};
2024-12-06 10:31:24 +00:00
/**
* # Send Email Login Code
*/
2025-01-10 19:10:28 +00:00
export default async function apiSendEmailCode({
2024-12-06 10:31:24 +00:00
email,
database,
email_login_field,
mail_domain,
mail_port,
sender,
mail_username,
mail_password,
html,
2024-12-06 11:55:03 +00:00
useLocal,
2024-12-10 14:10:32 +00:00
response,
2024-12-11 03:45:29 +00:00
extraCookies,
2025-01-10 19:10:28 +00:00
}: Param): Promise<SendOneTimeCodeEmailResponse> {
2024-12-06 10:31:24 +00:00
if (email?.match(/ /)) {
return {
success: false,
msg: "Invalid Email/Password format",
};
}
2024-12-10 14:10:32 +00:00
const createdAt = Date.now();
2024-12-06 10:31:24 +00:00
2024-12-06 11:55:03 +00:00
const foundUserQuery = `SELECT * FROM users WHERE email = ?`;
const foundUserValues = [email];
2024-12-08 08:58:57 +00:00
let foundUser = await varDatabaseDbHandler({
queryString: foundUserQuery,
queryValuesArray: foundUserValues,
database,
useLocal,
});
2024-12-06 10:31:24 +00:00
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (!foundUser || !foundUser[0]) {
return {
success: false,
msg: "No user found",
};
}
function generateCode() {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let code = "";
for (let i = 0; i < 8; i++) {
code += chars[Math.floor(Math.random() * chars.length)];
}
return code;
}
2024-12-10 14:10:32 +00:00
if (foundUser?.[0] && email_login_field) {
2024-12-06 10:31:24 +00:00
const tempCode = generateCode();
let transporter = nodemailer.createTransport({
host: mail_domain || process.env.DSQL_MAIL_HOST,
2025-01-10 19:10:28 +00:00
port: mail_port
? mail_port
: process.env.DSQL_MAIL_PORT
? Number(process.env.DSQL_MAIL_PORT)
: 465,
2024-12-06 10:31:24 +00:00
secure: true,
auth: {
user: mail_username || process.env.DSQL_MAIL_EMAIL,
pass: mail_password || process.env.DSQL_MAIL_PASSWORD,
},
});
2025-01-10 19:10:28 +00:00
let mailObject: SendMailOptions = {};
2024-12-06 10:31:24 +00:00
mailObject["from"] = `"Datasquirel SSO" <${
sender || "support@datasquirel.com"
}>`;
mailObject["sender"] = sender || "support@datasquirel.com";
mailObject["to"] = email;
mailObject["subject"] = "One Time Login Code";
mailObject["html"] = html.replace(/{{code}}/, tempCode);
const info = await transporter.sendMail(mailObject);
if (!info?.accepted) throw new Error("Mail not Sent!");
2024-12-06 11:55:03 +00:00
const setTempCodeQuery = `UPDATE users SET ${email_login_field} = ? WHERE email = ?`;
2024-12-10 14:10:32 +00:00
const setTempCodeValues = [tempCode + `-${createdAt}`, email];
2024-12-06 10:31:24 +00:00
2024-12-08 08:58:57 +00:00
let setTempCode = await varDatabaseDbHandler({
queryString: setTempCodeQuery,
queryValuesArray: setTempCodeValues,
database: database,
useLocal,
});
2024-12-06 10:31:24 +00:00
2024-12-10 14:10:32 +00:00
/** @type {import("../../../types").SendOneTimeCodeEmailResponse} */
2025-01-10 19:10:28 +00:00
const resObject: import("../../../types").SendOneTimeCodeEmailResponse =
{
success: true,
code: tempCode,
email: email,
createdAt,
msg: "Success",
};
2024-12-10 14:10:32 +00:00
if (response) {
2024-12-11 03:45:29 +00:00
const cookieKeyNames = getAuthCookieNames();
const oneTimeCodeCookieName = cookieKeyNames.oneTimeCodeName;
2024-12-10 14:10:32 +00:00
const encryptedPayload = encrypt({
data: JSON.stringify(resObject),
});
2024-12-11 03:45:29 +00:00
if (!encryptedPayload) {
throw new Error(
"apiSendEmailCode Error: Failed to encrypt payload"
);
}
/** @type {import("../../../../package-shared/types").CookieObject} */
2025-01-10 19:10:28 +00:00
const oneTimeCookieObject: import("../../../../package-shared/types").CookieObject =
{
name: oneTimeCodeCookieName,
value: encryptedPayload,
sameSite: "Strict",
path: "/",
httpOnly: true,
secure: true,
};
2024-12-11 03:45:29 +00:00
/** @type {import("../../../../package-shared/types").CookieObject[]} */
2025-01-10 19:10:28 +00:00
const cookiesObjectArray: import("../../../../package-shared/types").CookieObject[] =
extraCookies
? [...extraCookies, oneTimeCookieObject]
: [oneTimeCookieObject];
2024-12-11 03:45:29 +00:00
const serializedCookies = serializeCookies({
cookies: cookiesObjectArray,
});
response.setHeader("Set-Cookie", serializedCookies);
2024-12-10 14:10:32 +00:00
}
return resObject;
} else {
return {
success: false,
msg: "Invalid Email/Password format",
};
}
2025-01-10 19:10:28 +00:00
}