import { application } from "express"; import prisma from "../config/prismaConfig.js"; import { applicantDesignations, validatorDesignations, } from "../config/designations.js"; import bcrypt from "bcryptjs"; const dataRoot = async (req, res) => { try { const user = req.user; // Contains all user info (id, designation, department, etc.) const { id: profileId, email, designation, department, role } = user; if (applicantDesignations.includes(designation) && role === "applicant") { const applicant = await prisma.user.findUnique({ where: { profileId }, }); if (!applicant) { return res .status(404) .json({ message: "Applicant not found", data: null }); } delete applicant.password; return res.status(200).json({ message: "Applicant Authorized", user: applicant, role: "Applicant", }); } else if ( validatorDesignations.includes(designation) && role === "validator" ) { const validator = await prisma.user.findUnique({ where: { profileId }, }); if (!validator) { return res .status(404) .json({ message: "Validator not found", data: null }); } delete validator.password; return res.status(200).json({ message: "Validator Authorized", user: validator, role: "Validator", }); } else { return res .status(403) .json({ message: "Unauthorized access", data: null }); } } catch (error) { // Handle any errors that occur during the process console.error(error); return res .status(500) .json({ message: "Internal Server Error", data: null }); } }; const getApplicationsByStatus = async (req, res) => { try { const user = req.user; const userId = user.id; const take = parseInt(req.query.take) || 5; const skip = parseInt(req.query.skip) || 0; const status = req.params.status.toUpperCase(); // Expected: "PENDING", "ACCEPTED", or "REJECTED" const sortBy = req.query?.sortBy; const sortValue = req.query?.sortValue; const validStatuses = ["PENDING", "ACCEPTED", "REJECTED"]; if (!validStatuses.includes(status)) { return res.status(400).send("Invalid status"); } let applications, totalApplications; // Filter conditions for Student and Faculty if ( applicantDesignations.includes(user.designation) && user.role === "applicant" ) { const baseWhere = { applicantId: userId, ...(status === "PENDING" && { OR: [ { facultyValidation: "PENDING" }, { hodValidation: "PENDING" }, { hoiValidation: "PENDING" }, { vcValidation: "PENDING" }, { accountsValidation: "PENDING" }, ], }), ...(status === "ACCEPTED" && { AND: [ { OR: [ { facultyValidation: "ACCEPTED" }, { facultyValidation: null }, ], }, { OR: [{ hodValidation: "ACCEPTED" }, { hodValidation: null }] }, { OR: [{ hoiValidation: "ACCEPTED" }, { hoiValidation: null }] }, { OR: [{ vcValidation: "ACCEPTED" }, { vcValidation: null }] }, { OR: [ { accountsValidation: "ACCEPTED" }, { accountsValidation: null }, ], }, ], }), ...(status === "REJECTED" && { OR: [ { facultyValidation: "REJECTED" }, { hodValidation: "REJECTED" }, { hoiValidation: "REJECTED" }, { vcValidation: "REJECTED" }, { accountsValidation: "REJECTED" }, ], }), }; // Apply case-insensitive filter for search functionality if (sortBy && sortValue) { baseWhere[sortBy] = { contains: sortValue, mode: "insensitive", }; } // Count and fetch applications totalApplications = await prisma.application.count({ where: baseWhere }); applications = await prisma.application.findMany({ where: baseWhere, select: { applicationId: true, applicantName: true, formData: true, createdAt: true, }, take, skip, orderBy: { createdAt: "desc" }, }); // Filter conditions for Validators (Supervisor, HOD, HOI, FDCcoordinator) } else if ( validatorDesignations.includes(user.designation) && user.role === "validator" ) { const validationField = `${user.designation.toLowerCase()}Validation`; const baseWhere = { validators: { some: { profileId: userId } }, [validationField]: status, }; if (sortBy && sortValue) { baseWhere[sortBy] = { contains: sortValue, mode: "insensitive", }; } totalApplications = await prisma.application.count({ where: baseWhere, }); applications = await prisma.application.findMany({ where: baseWhere, select: { applicationId: true, applicantName: true, formData: true, createdAt: true, }, take, skip, orderBy: { createdAt: "desc" }, }); } else { // Unauthorized access for other user roles return res.status(403).send("Unauthorized"); } // Format response with selected fields const responseApplications = applications.map((application) => { const parsedFormData = JSON.parse(application.formData); return { applicationId: application.applicationId, applicantName: application.applicantName, formData: { eventName: parsedFormData.eventName, applicantDepartment: parsedFormData.applicantDepartment, }, createdAt: application.createdAt, }; }); return res.status(200).json({ message: `${status} Applications Fetched Successfully`, totalApplications, applications: responseApplications, }); } catch (error) { console.error(error); res.status(500).send(error.message); } }; const getApplicationData = async (req, res) => { try { const applicationId = req.params.applicationId; const user = req.user; // Fetch application data excluding proof fields const applicationFull = await prisma.application.findUnique({ where: { applicationId: applicationId, }, select: { applicationId: true, applicantId: true, applicantName: true, resubmission: true, formData: true, facultyValidation: true, hodValidation: true, hoiValidation: true, vcValidation: true, accountsValidation: true, rejectionFeedback: true, createdAt: true, applicant: { select: { designation: true, }, }, validators: { select: { profileId: true, }, }, }, }); if ( applicationFull?.applicantId !== user.id && !applicationFull.validators.some( (validator) => validator.profileId === user.id ) ) { return res.status(403).json({ message: "Unauthorized", data: null, }); } if (!applicationFull) { return res.status(404).json({ message: "Application not found", data: null, }); } let currentStatus; // Check if the user is an applicant or a validator if ( applicantDesignations.includes(user.designation) && user.role === "applicant" ) { if ( applicationFull.facultyValidation === "PENDING" || applicationFull.hodValidation === "PENDING" || applicationFull.hoiValidation === "PENDING" || applicationFull.vcValidation === "PENDING" || applicationFull.accountsValidation === "PENDING" ) { currentStatus = "PENDING"; } else if ( applicationFull.facultyValidation === "REJECTED" || applicationFull.supervisorValidation === "REJECTED" || applicationFull.hodValidation === "REJECTED" || applicationFull.hoiValidation === "REJECTED" || applicationFull.fdccoordinatorValidation === "REJECTED" ) { currentStatus = "REJECTED"; } else { currentStatus = "ACCEPTED"; } } else if ( validatorDesignations.includes(user.designation) && user.role === "validator" ) { const validationField = `${user.designation.toLowerCase()}Validation`; if (applicationFull[validationField] === "ACCEPTED") { currentStatus = "ACCEPTED"; } else if (applicationFull[validationField] === "REJECTED") { currentStatus = "REJECTED"; } else { currentStatus = "PENDING"; } } else { return res.status(403).json({ message: "Unauthorized", data: null, }); } // Respond with the full application data and current status const parsedApplicationFull = { ...applicationFull, formData: JSON.parse(applicationFull.formData), }; return res.status(200).json({ message: "Application data retrieved successfully", data: { ...parsedApplicationFull, currentStatus }, }); } catch (error) { console.error("Error retrieving application data:", error); return res.status(500).json({ message: "An error occurred while retrieving the application data", data: null, }); } }; const getFile = async (req, res) => { try { const { applicationId, fileName } = req.params; const user = req.user; const userId = user.id; const validFileNames = [ "proofOfTravel", "proofOfAccommodation", "proofOfAttendance", "expenseProof0", "expenseProof1", "expenseProof2", "expenseProof3", "expenseProof4", "expenseProof5", "expenseProof6", "expenseProof7", "expenseProof8", "expenseProof9", ]; if (!validFileNames.includes(fileName)) { return res.status(400).json({ error: "Invalid File request" }); } const fileSelection = { proofOfTravel: false, proofOfAccommodation: false, proofOfAttendance: false, expenseProof0: false, expenseProof1: false, expenseProof2: false, expenseProof3: false, expenseProof4: false, expenseProof5: false, expenseProof6: false, expenseProof7: false, expenseProof8: false, expenseProof9: false, }; if (validFileNames.includes(fileName)) { fileSelection[fileName] = true; } let myApplication, myFile; if ( applicantDesignations.includes(user.designation) && user.role === "applicant" ) { myApplication = await prisma.user.findUnique({ where: { profileId: userId, }, select: { appliedApplications: { where: { applicationId, }, select: fileSelection, }, }, }); myFile = myApplication?.appliedApplications[0]; } else if ( validatorDesignations.includes(user.designation) && user.role === "validator" ) { myApplication = await prisma.user.findUnique({ where: { profileId: userId, }, select: { toValidateApplications: { where: { applicationId, }, select: fileSelection, }, }, }); myFile = myApplication?.toValidateApplications[0]; } if (!myFile) { return res.status(404).json({ error: "File not found" }); } // Retrieve the file buffer dynamically based on the fileName const fileBuffer = myFile[fileName]; // If file buffer doesn't exist if (!fileBuffer) { return res.status(404).json({ error: "File content not found" }); } // Set response headers for PDF file download res.setHeader("Content-Type", "application/pdf"); res.setHeader( "Content-Disposition", `attachment; filename="${fileName}.pdf"` ); // Send the file buffer as a response return res.send(fileBuffer); } catch (error) { console.error("Error retrieving application data:", error); return res.status(500).json({ error: "An error occurred while retrieving the application data", }); } }; export { getApplicationData, getFile, dataRoot, getApplicationsByStatus, changePassword, }; const changePassword = async (req, res) => { try { const user = req.user; const { oldPassword, newPassword } = req.body; if (!user || !user.id) { return res.status(401).json({ message: "Unauthorized" }); } // Get the current user from DB to check password const dbUser = await prisma.user.findUnique({ where: { profileId: user.id }, }); if (!dbUser) { return res.status(404).json({ message: "User not found" }); } let isPasswordCorrect = false; // 1. Try bcrypt try { isPasswordCorrect = await bcrypt.compare(oldPassword, dbUser.password); } catch (err) { isPasswordCorrect = false; } // 2. Try plaintext (fallback) if (!isPasswordCorrect && dbUser.password === oldPassword) { isPasswordCorrect = true; } if (!isPasswordCorrect) { return res.status(400).json({ message: "Incorrect old password" }); } // Hash the new password const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(newPassword, salt); await prisma.user.update({ where: { profileId: user.id }, data: { password: hashedPassword }, }); return res.status(200).json({ message: "Password updated successfully" }); } catch (error) { console.error(error); return res.status(500).json({ message: "Internal Server Error" }); } };