import dbHandler from "../../backend/dbHandler"; import nodemailer, { SendMailOptions } from "nodemailer"; import getAuthCookieNames from "../../backend/cookies/get-auth-cookie-names"; import encrypt from "../../dsql/encrypt"; import serializeCookies from "../../../utils/serialize-cookies"; import { APIResponseObject, APISendEmailCodeFunctionParams, CookieObject, } from "../../../types"; import grabDbFullName from "../../../utils/grab-db-full-name"; /** * # Send Email Login Code */ export default async function apiSendEmailCode({ email, database, email_login_field, mail_domain, mail_port, sender, mail_username, mail_password, html, response, extraCookies, dbUserId, }: APISendEmailCodeFunctionParams): Promise { if (email?.match(/ /)) { return { success: false, msg: "Invalid Email/Password format", }; } const dbFullName = grabDbFullName({ dbName: database, userId: dbUserId }); const createdAt = Date.now(); const foundUserQuery = `SELECT * FROM users WHERE email = ?`; const foundUserValues = [email]; let foundUser = (await dbHandler({ query: foundUserQuery, values: foundUserValues, database: dbFullName, })) as any[]; 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; } if (foundUser?.[0] && email_login_field) { const tempCode = generateCode(); let transporter = nodemailer.createTransport({ host: mail_domain || process.env.DSQL_MAIL_HOST, port: mail_port ? mail_port : process.env.DSQL_MAIL_PORT ? Number(process.env.DSQL_MAIL_PORT) : 465, secure: true, auth: { user: mail_username || process.env.DSQL_MAIL_EMAIL, pass: mail_password || process.env.DSQL_MAIL_PASSWORD, }, }); let mailObject: SendMailOptions = {}; const finalSender = sender || process.env.DSQL_MAIL_EMAIL || "support@datasquirel.com"; mailObject["from"] = `"Datasquirel SSO" <${finalSender}>`; mailObject["sender"] = finalSender; 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!"); const setTempCodeQuery = `UPDATE users SET ${email_login_field} = ? WHERE email = ?`; const setTempCodeValues = [tempCode + `-${createdAt}`, email]; await dbHandler({ query: setTempCodeQuery, values: setTempCodeValues, database: dbFullName, }); const resObject: APIResponseObject = { success: true, code: tempCode, email: email, createdAt, msg: "Success", }; if (response) { const cookieKeyNames = getAuthCookieNames(); const oneTimeCodeCookieName = cookieKeyNames.oneTimeCodeName; const encryptedPayload = encrypt({ data: JSON.stringify(resObject), }); if (!encryptedPayload) { throw new Error( "apiSendEmailCode Error: Failed to encrypt payload" ); } const oneTimeCookieObject: CookieObject = { name: oneTimeCodeCookieName, value: encryptedPayload, sameSite: "Strict", path: "/", httpOnly: true, secure: true, }; const cookiesObjectArray: CookieObject[] = extraCookies ? [...extraCookies, oneTimeCookieObject] : [oneTimeCookieObject]; const serializedCookies = serializeCookies({ cookies: cookiesObjectArray, }); response.setHeader("Set-Cookie", serializedCookies); } return resObject; } else { return { success: false, msg: "Invalid Email/Password format", }; } }