import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { VAModel, LoggedModel, WorkTrackModel } from "../../../models/vaModel.js"; // function to close open work tracks and create logout async function closePreviousSession(vaId, lastLog) { try { const currentTime = new Date(); // Find all open work tracks for this VA and project (where to is not set or totalTime is 0) const openWorkTracks = await WorkTrackModel.find({ vaId, logId: lastLog._id, $or: [ { to: { $exists: false } }, { totalTime: 0 }, { to: null } ] }); // console.log(`Found ${openWorkTracks.length} open work tracks to close`); // Close all open work tracks for (const workTrack of openWorkTracks) { const fromTime = new Date(workTrack.from); const totalTimeMs = currentTime - fromTime; // Update the work track with end time and total time workTrack.to = currentTime; workTrack.totalTime = totalTimeMs; await workTrack.save(); // console.log(`Closed work track ${workTrack._id} with duration: ${totalTimeMs}ms`); } // Create a logout log entry const logoutLog = await LoggedModel.create({ loggedType: "LOGOUT", vaId, vaEmail: lastLog.vaEmail, // Use email from previous log projectId: lastLog.projectId, time: currentTime // Use same timestamp for consistent logging }); // console.log(`Created logout log: ${logoutLog._id}`); return { closedWorkTracks: openWorkTracks.length, logoutLogId: logoutLog._id }; } catch (error) { console.error("Error closing previous session:", error); throw error; } } // Login VA async function va_login_callback(req, res) { try { // const payload = req.body ? JSON.parse(req.body) : {}; const payload = req.body || {}; const { userDetails } = payload; if (!userDetails || !userDetails.email || !userDetails.password) { return res.status(400).json({ success: false, message: "Please provide email and password" }); } // Find user by email const user = await VAModel.findOne({ "userDetails.email": userDetails.email }); if (!user) { return res.status(404).json({ success: false, message: "Invalid credentials" }); } // const saltRounds = 10; // const hashedPassword = await bcrypt.hash(userDetails.password, saltRounds); // Compare password with stored hash const isMatch = await bcrypt.compare( userDetails.password, user.userDetails.password ); if (!isMatch) { return res.status(401).json({ success: false, message: "Invalid password" }); } // also on main login when user try to login into app then logout project and workModel track then allow login on same timestamp // Check if VA has any active sessions (LOGIN without LOGOUT) const activeSessions = await LoggedModel.find({ vaId: user._id }).sort({ time: -1 }); let closeResult = []; if (activeSessions.length > 0) { // Get the latest login to check if there's no corresponding logout const latestLog = activeSessions[0]; closeResult = await closePreviousSession(user._id, latestLog); } // Generate JWT accessToken with 24h expiry const accessToken = jwt.sign( { id: user._id, email: user.userDetails.email, name: user.userDetails.firstName, }, process.env.JWT_SECRET_ACCESS_TOKEN || "DocTrackerSecretKey", // { expiresIn: "24h" } ); // Generate JWT refreshToken with 24h expiry const refreshToken = jwt.sign( { id: user._id, email: user.userDetails.email, name: user.userDetails.firstName, }, process.env.JWT_SECRET_REFRESH_TOKEN || "DocTrackerSecretKeyRefreshToken", // { expiresIn: "30d" } ); await VAModel.updateOne({ "userDetails.email": userDetails.email }, { $set: { accessToken, refreshToken } }) let responseData = []; if (closeResult) { responseData = { success: true, message: "Login Successfull", accessToken, refreshToken, user: { id: user._id, name: user.userDetails.firstName, email: user.userDetails.email, }, previousSession: { closedWorkTracks: closeResult.closedWorkTracks, logoutLogId: closeResult.logoutLogId } } } else { responseData = { success: true, message: "Login Successfull", accessToken, refreshToken, user: { id: user._id, name: user.userDetails.firstName, email: user.userDetails.email, } } } // Return accessToken and user info return res.status(200).json(responseData); } catch (error) { console.error("va_register error:", error); return res.status(500).json({ success: false, message: "Internal Server Error" }); } } // Helper function to format session duration function formatSessionDuration(loginTime) { const now = new Date(); const login = new Date(loginTime); const durationMs = now - login; const hours = Math.floor(durationMs / (1000 * 60 * 60)); const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((durationMs % (1000 * 60)) / 1000); return `${hours}h ${minutes}m ${seconds}s`; } export { va_login_callback };