import { Request, Response } from "express"; import User, { IUser } from "../../models/user"; import { randomBytes } from "crypto"; import moment = require("moment"); import LoginToken from "../../models/login_token"; import promiseMiddleware from "../../helper/promiseMiddleware"; import TwoFactor, { TFATypes, TFANames } from "../../models/twofactor"; import * as crypto from "crypto"; import Logging from "@hibas123/nodelogging"; const Login = promiseMiddleware(async (req: Request, res: Response) => { let type = req.query.type; if (type === "username") { let { username, uid } = req.query; let user = await User.findOne( username ? { username: username.toLowerCase() } : { uid: uid } ); if (!user) { res.json({ error: req.__("User not found") }); } else { res.json({ salt: user.salt, uid: user.uid }); } return; } else if (type === "password") { const sendToken = async (user: IUser, tfa?: any[]) => { let ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; let client = { ip: Array.isArray(ip) ? ip[0] : ip, browser: req.headers["user-agent"], }; let token_str = randomBytes(16).toString("hex"); let tfa_exp = moment().add(5, "minutes").toDate(); let token_exp = moment().add(6, "months").toDate(); let token = LoginToken.new({ token: token_str, valid: true, validTill: tfa ? tfa_exp : token_exp, user: user._id, validated: tfa ? false : true, ...client, }); await LoginToken.save(token); let special_str = randomBytes(24).toString("hex"); let special_exp = moment().add(30, "minutes").toDate(); let special = LoginToken.new({ token: special_str, valid: true, validTill: tfa ? tfa_exp : special_exp, special: true, user: user._id, validated: tfa ? false : true, ...client, }); await LoginToken.save(special); res.json({ login: { token: token_str, expires: token.validTill.toUTCString() }, special: { token: special_str, expires: special.validTill.toUTCString(), }, tfa, }); }; let { username, password, uid, date } = req.body; let user = await User.findOne( username ? { username: username.toLowerCase() } : { uid: uid } ); if (!user) { res.json({ error: req.__("User not found") }); } else { let upw = user.password; if (date) { if ( !moment(date).isBetween( moment().subtract(1, "minute"), moment().add(1, "minute") ) ) { res.json({ error: req.__( "Invalid timestamp. Please check your devices time!" ), }); return; } else { upw = crypto .createHash("sha512") .update(upw + date.toString()) .digest("hex"); } } if (upw !== password) { res.json({ error: req.__("Password or username wrong") }); } else { let twofactor = await TwoFactor.find({ user: user._id, valid: true, }); let expired = twofactor.filter((e) => e.expires ? moment().isAfter(moment(e.expires)) : false ); await Promise.all( expired.map((e) => { e.valid = false; return TwoFactor.save(e); }) ); twofactor = twofactor.filter((e) => e.valid); if (twofactor && twofactor.length > 0) { let tfa = twofactor.map((e) => { return { id: e._id, name: e.name || TFANames.get(e.type), type: e.type, }; }); await sendToken(user, tfa); } else { await sendToken(user); } } } } else { res.json({ error: req.__("Invalid type!") }); } }); export default Login;