backend_adaptive_learning/controllers/usersControllers/user.js
2024-09-13 20:03:35 +07:00

473 lines
12 KiB
JavaScript

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);
}
};