import response from "../../response.js"; import models from "../../models/index.js"; import bcrypt from "bcrypt"; import fs from "fs"; import path from "path"; import { clearFileBuffers, saveFileToDisk, } from "../../middlewares/User/uploadUser.js"; export const getUsers = async (req, res) => { try { const users = await models.User.findAll({ attributes: { exclude: ["PASSWORD"], include: [ [ models.Sequelize.literal( `COALESCE(\`teachers\`.\`NIP\`, \`students\`.\`NISN\`)` ), "NIP/NISN", ], ], }, include: [ { model: models.Teacher, as: "teachers", attributes: [], }, { model: models.Student, as: "students", attributes: [], }, ], }); response(200, users, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving users data!", res); } }; export const getAdmins = async (req, res) => { try { const admins = await models.User.findAll({ where: { ROLE: "admin", }, attributes: { exclude: ["PASSWORD"], }, }); response(200, admins, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving admin data!", res); } }; export const getTeachers = async (req, res) => { try { const teachers = await models.User.findAll({ where: { ROLE: "teacher", }, attributes: ["ID", "NAME_USERS", "EMAIL", "ROLE"], include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], }, ], raw: true, nest: true, }); const formattedTeachers = teachers.map((teacher) => ({ ID: teacher.ID, NAME_USERS: teacher.NAME_USERS, EMAIL: teacher.EMAIL, NISN: teacher.teachers.NIP, ROLE: teacher.ROLE, })); response(200, formattedTeachers, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving teacher data!", res); } }; export const getStudents = async (req, res) => { try { const students = await models.User.findAll({ where: { ROLE: "student", }, attributes: ["ID", "NAME_USERS", "EMAIL", "ROLE"], include: [ { model: models.Student, as: "students", attributes: ["NISN"], }, ], raw: true, nest: true, }); const formattedStudents = students.map((student) => ({ ID: student.ID, NAME_USERS: student.NAME_USERS, EMAIL: student.EMAIL, NISN: student.students.NISN, ROLE: student.ROLE, })); response(200, formattedStudents, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving student data!", res); } }; export const getUserById = async (req, res) => { try { const { id } = req.params; const user = await models.User.findByPk(id, { attributes: { exclude: ["PASSWORD"], }, include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], }, { model: models.Student, as: "students", attributes: ["NISN"], }, ], }); if (!user) { return response(404, null, "User not found", res); } let additionalField = null; if (user.ROLE === "teacher") { additionalField = { NIP: user.teachers.NIP }; } else if (user.ROLE === "student") { additionalField = { NISN: user.students.NISN }; } const responseObject = { ID: user.ID, NAME_USERS: user.NAME_USERS, EMAIL: user.EMAIL, ROLE: user.ROLE, ...additionalField, }; response(200, responseObject, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving user data!", res); } }; export const getUserByName = async (req, res) => { try { const { name } = req.params; const user = await models.User.findOne({ where: { NAME_USERS: name }, attributes: { exclude: ["PASSWORD"], }, include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], }, { model: models.Student, as: "students", attributes: ["NISN"], }, ], }); if (!user) { return response(404, null, "User not found", res); } let additionalField = null; if (user.ROLE === "teacher" ) { additionalField = { NIP: user.teachers.NIP }; } else if (user.ROLE === "student") { additionalField = { NISN: user.students.NISN }; } const responseObject = { ID: user.ID, NAME_USERS: user.NAME_USERS, EMAIL: user.EMAIL, ROLE: user.ROLE, ...additionalField, }; return response(200, responseObject, "Success", res); } catch (error) { console.log(error); return response(500, null, "Error retrieving user data!", res); } }; export const updateUserById = async (req, res) => { const transaction = await models.db.transaction(); const { picture } = req.filesToSave || {}; try { const { id } = req.params; const { name, email, nip, nisn } = req.body; const user = await models.User.findByPk(id, { include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], }, { model: models.Student, as: "students", attributes: ["NISN"], }, ], transaction, }); if (!user) { clearFileBuffers({ picture }); await transaction.rollback(); return response(404, null, "User not found", res); } if (user.ROLE === "teacher" && nisn) { clearFileBuffers({ picture }); await transaction.rollback(); return response(400, null, "Role is teacher, but NISN is provided", res); } if (user.ROLE === "student" && nip) { clearFileBuffers({ picture }); await transaction.rollback(); return response(400, null, "Role is student, but NIP is provided", res); } if (email && email !== user.EMAIL) { const emailExists = await models.User.findOne({ where: { EMAIL: email }, transaction, }); if (emailExists) { clearFileBuffers({ picture }); await transaction.rollback(); return response(400, null, "Email already in use", res); } user.EMAIL = email; } user.NAME_USERS = name || user.NAME_USERS; if (user.ROLE === "teacher" && nip) { let teacher = await models.Teacher.findOne({ where: { ID: id }, transaction, }); if (teacher) { teacher.NIP = nip; await teacher.save({ transaction }); } else { teacher = await models.Teacher.create( { ID: id, NIP: nip }, { transaction } ); } } if (user.ROLE === "student" && nisn) { let student = await models.Student.findOne({ where: { ID: id }, transaction, }); if (student) { student.NISN = nisn; await student.save({ transaction }); } else { student = await models.Student.create( { ID: id, NISN: nisn }, { transaction } ); } } if (picture) { if (user.PICTURE) { const oldPicturePath = path.join("public/uploads/avatar", user.PICTURE); if (fs.existsSync(oldPicturePath)) { fs.unlinkSync(oldPicturePath); } } user.PICTURE = saveFileToDisk(picture, user.ID, user.NAME_USERS); } await user.save({ transaction }); await user.reload({ include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], }, { model: models.Student, as: "students", attributes: ["NISN"], }, ], transaction, }); await transaction.commit(); return response(200, user, "User updated successfully", res); } catch (error) { clearFileBuffers({ picture }); await transaction.rollback(); console.log(error); return response(500, null, "Internal Server Error", res); } }; export const updateUserPasswordById = async (req, res) => { try { const { id } = req.params; const { oldPassword, password, confirmPassword } = req.body; if (!oldPassword || !password || !confirmPassword) { return response(400, null, "All fields must be filled.", res); } if (password !== confirmPassword) { return response( 400, null, "New password and confirm password do not match.", res ); } const user = await models.User.findByPk(id); if (!user) { return response(404, null, "User not found.", res); } const isMatch = await bcrypt.compare(oldPassword, user.PASSWORD); if (!isMatch) { return response(400, null, "Incorrect old password.", res); } const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); user.PASSWORD = hashedPassword; await user.save(); response(200, null, "Password updated successfully.", res); } catch (error) { response(500, null, "Internal Server Error", res); } }; export const deleteUserById = async (req, res) => { const transaction = await models.db.transaction(); try { const { id } = req.params; const user = await models.User.findByPk(id, { transaction }); if (!user) { await transaction.rollback(); return response(404, null, "User not found", res); } if (user.ROLE === "teacher") { await models.Teacher.destroy({ where: { ID: id }, transaction }); } else if (user.ROLE === "student") { await models.Student.destroy({ where: { ID: id }, transaction }); } await user.destroy({ transaction }); await transaction.commit(); return response(200, null, "User deleted successfully", res); } catch (error) { await transaction.rollback(); console.log(error); return response(500, null, "Internal Server Error", res); } }; export const getMe = async (req, res) => { try { const user = req.user; // User object from verifyLoginUser middleware // Retrieve teacher or student details based on the user's role const userWithDetails = await models.User.findByPk(user.ID, { attributes: { exclude: ["PASSWORD"], // Exclude sensitive information }, include: [ { model: models.Teacher, as: "teachers", attributes: ["NIP"], // Include NIP for teacher }, { model: models.Student, as: "students", attributes: ["NISN"], // Include NISN for student }, ], }); if (!userWithDetails) { return response(404, null, "User not found", res); } // Determine additional field based on user role let additionalField = null; if (userWithDetails.ROLE === "teacher") { additionalField = { NIP: userWithDetails.teachers.NIP }; } else if (userWithDetails.ROLE === "student") { additionalField = { NISN: userWithDetails.students.NISN }; } // Construct the response object const responseObject = { ID: userWithDetails.ID, NAME_USERS: userWithDetails.NAME_USERS, EMAIL: userWithDetails.EMAIL, ROLE: userWithDetails.ROLE, ...additionalField, }; // Send the response response(200, responseObject, "Success", res); } catch (error) { console.error(error); response(500, null, "Error retrieving user data!", res); } };