Exocore-Backend / dist /auth /forgot.js
ChoruYt's picture
Upload 38 files
a21d6a5 verified
Raw
History Blame Contribute Delete
4.53 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = forgotHandler;
const drive_1 = require("../services/drive");
const mailer_1 = require("../services/mailer");
const validate_1 = require("../utils/validate");
// Dedupe rapid duplicate "send OTP" requests for the same email so we don't
// overwrite a freshly-issued OTP with another one before the user can use it.
const recentSends = new Map();
const SEND_COOLDOWN_MS = 15_000;
async function forgotHandler(req, res) {
try {
const params = { ...req.query, ...req.body };
const email = params.email;
const requestType = params.req;
const otp = params.otp;
const newPass = params.newPass;
if (!email)
return res.status(400).json({ success: false, message: "Email is required" });
if (requestType === "now") {
// Respond immediately to avoid the Replit edge proxy ~30s timeout.
// Drive lookup + email delivery happens in the background.
res.status(200).json({
success: true,
message: "If the email is registered, a reset code has been sent.",
account: { email },
});
const key = String(email).toLowerCase();
const last = recentSends.get(key) || 0;
const now = Date.now();
if (now - last < SEND_COOLDOWN_MS) {
console.log(`[forgot] cooldown hit for ${key}, skipping duplicate send`);
return;
}
recentSends.set(key, now);
(async () => {
try {
const users = await (0, drive_1.getAllUsers)();
const found = users.find(u => (u.email || "").toLowerCase() === String(email).toLowerCase());
if (!found) {
console.warn(`[forgot] no account found for ${email}`);
return;
}
const folderId = await (0, drive_1.getUserFolder)(found.username);
if (!folderId) {
console.warn(`[forgot] no folder for ${found.username}`);
return;
}
const fresh = await (0, drive_1.readUserDb)(folderId);
if (!fresh) {
console.warn(`[forgot] missing user db for ${found.username}`);
return;
}
const newOtp = Math.floor(100000 + Math.random() * 900000).toString();
fresh.verifyOtp = newOtp;
await (0, drive_1.writeUserDb)(folderId, fresh);
await (0, mailer_1.sendResetOtp)(fresh.email, newOtp, fresh.nickname);
console.log(`[forgot] reset OTP delivered to ${fresh.email}`);
}
catch (err) {
console.error("[forgot] background failed:", err?.message || err);
}
})();
return;
}
const users = await (0, drive_1.getAllUsers)();
const found = users.find(u => (u.email || "").toLowerCase() === String(email).toLowerCase());
if (!found)
return res.status(404).json({ success: false, message: "No account found with this email" });
const folderId = await (0, drive_1.getUserFolder)(found.username);
if (!folderId)
return res.status(404).json({ success: false, message: "User folder not found" });
if (otp && newPass) {
const passCheck = (0, validate_1.validatePassword)(newPass);
if (!passCheck.ok)
return res.status(400).json({ success: false, message: passCheck.message });
const fresh = (await (0, drive_1.readUserDb)(folderId));
if (fresh.verifyOtp !== otp) {
return res.status(400).json({ success: false, message: "Invalid OTP code" });
}
fresh.pass = newPass;
fresh.verifyOtp = null;
await (0, drive_1.writeUserDb)(folderId, fresh);
return res.status(200).json({ success: true, message: "Password updated" });
}
return res.status(400).json({ success: false, message: "Provide req=now to request a code, or otp and newPass to reset" });
}
catch (err) {
console.error("[forgot] error:", err);
return res.status(500).json({ success: false, message: "Internal Server Error" });
}
}