182 lines
6.2 KiB
JavaScript
182 lines
6.2 KiB
JavaScript
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 }; |