473 lines
12 KiB
JavaScript
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);
|
||
|
|
}
|
||
|
|
};
|