From 323e934cd764534e1737608d75eecc6c7591deb8 Mon Sep 17 00:00:00 2001 From: Lightemerald Date: Mon, 26 Feb 2024 16:07:09 +0100 Subject: [PATCH] Second part of backend rework - Improved consistency in routes - Fixed permission issues - Added new endpoints - Fixed some issues - SQL: Switched status to ENUM - SQL: Changed rooms table - SQL: Added unique constraints --- database.sql | 21 ++-- routes/companies.js | 45 ++++---- routes/doctors.js | 276 +++++++++++++++++++++++++++++++++++++++----- routes/hospitals.js | 166 ++++++++++++++++++-------- routes/patients.js | 85 ++++++++++---- routes/test.js | 2 +- routes/users.js | 9 +- 7 files changed, 470 insertions(+), 134 deletions(-) diff --git a/database.sql b/database.sql index 20f320e..9d4b4bd 100644 --- a/database.sql +++ b/database.sql @@ -43,7 +43,7 @@ CREATE TABLE users ( email_verified BOOLEAN NOT NULL DEFAULT FALSE, phone VARCHAR(32) DEFAULT 'None', phone_verified BOOLEAN NOT NULL DEFAULT FALSE, - PRIMARY KEY (id), + PRIMARY KEY (id) ) ENGINE=InnoDB; CREATE TABLE user_roles ( @@ -99,7 +99,7 @@ CREATE TABLE doctors ( email VARCHAR(255) NOT NULL, phone VARCHAR(20) NOT NULL, speciality VARCHAR(255) NOT NULL, - status VARCHAR(255) NOT NULL, + status ENUM('Available', 'Absent', 'Unavailable') NOT NULL, is_verified BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (id), CONSTRAINT dt_user_id @@ -107,7 +107,8 @@ CREATE TABLE doctors ( REFERENCES users(id) ON DELETE RESTRICT ON UPDATE CASCADE, - INDEX dt_user_id_idx (user_id) + INDEX dt_user_id_idx (user_id), + CONSTRAINT uc_doctor_user_id UNIQUE (user_id) ) ENGINE=InnoDB; CREATE TABLE patients ( @@ -118,7 +119,8 @@ CREATE TABLE patients ( address VARCHAR(255) NOT NULL, social_security_number VARCHAR(128) NOT NULL, insurance_number VARCHAR(128) NOT NULL, - PRIMARY KEY (id) + PRIMARY KEY (id), + CONSTRAINT uc_user_id UNIQUE (user_id) ) ENGINE=InnoDB; CREATE TABLE services ( @@ -126,7 +128,6 @@ CREATE TABLE services ( name VARCHAR(255) NOT NULL, description TEXT NOT NULL, price DECIMAL(10, 2) NOT NULL, - status VARCHAR(255) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; @@ -178,7 +179,11 @@ CREATE TABLE rooms ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, hospital_id INT UNSIGNED NOT NULL, name VARCHAR(255) NOT NULL, - PRIMARY KEY (id) + code VARCHAR(3) NOT NULL, + floor INT UNSIGNED NOT NULL, + room_number INT UNSIGNED NOT NULL, + room_type ENUM('General Ward', 'Private', 'Intensive Care Unit', 'Labor and Delivery', 'Operating', 'Recovery', 'Isolation', 'Emergency', 'Imaging', 'Procedure', 'Physical Therapy', 'Consultation') NOT NULL, + PRIMARY KEY (id), CONSTRAINT ch_hospital_id FOREIGN KEY (hospital_id) REFERENCES hospitals(id) @@ -213,8 +218,8 @@ CREATE TABLE appointments ( room_id INT UNSIGNED DEFAULT NULL, date DATE NOT NULL, time TIME NOT NULL, - status VARCHAR(255) NOT NULL, - PRIMARY KEY (id) + status ENUM('Confirmed', 'Completed', 'Absent', 'Cancelled by Patient', 'Cancelled by Doctor') NOT NULL, + PRIMARY KEY (id), CONSTRAINT ap_patient_id FOREIGN KEY (patient_id) REFERENCES patients(id) diff --git a/routes/companies.js b/routes/companies.js index 601e787..0ec296c 100644 --- a/routes/companies.js +++ b/routes/companies.js @@ -7,10 +7,9 @@ import { respondWithStatus, respondWithStatusJSON } from '../modules/requestHand const router = express.Router(); -router.get('/', verifyToken, checkBanned, checkPermissions('companies', 1), async (req, res) => { +router.get('/', verifyToken, checkBanned, checkPermissions('company', 1), async (req, res) => { try { const [rows] = await pool.execute('SELECT * FROM companies WHERE 1'); - if (rows.length === 0) return await respondWithStatus(res, 404, 'Companies not found'); return await respondWithStatusJSON(res, 200, rows); } @@ -20,7 +19,7 @@ router.get('/', verifyToken, checkBanned, checkPermissions('companies', 1), asyn } }); -router.post('/', verifyToken, checkBanned, checkPermissions('companies', 2), async (req, res) => { +router.post('/', verifyToken, checkBanned, checkPermissions('company', 2), async (req, res) => { const { name, code, logo } = req.body; if ([ name, code, logo ].every(Boolean)) { try { @@ -41,10 +40,9 @@ router.post('/', verifyToken, checkBanned, checkPermissions('companies', 2), asy } }); -router.get('/:companyId', verifyToken, checkBanned, checkPermissions('companies', 1), async (req, res) => { +router.get('/:companyId', verifyToken, checkBanned, checkPermissions('company', 1), async (req, res) => { try { - const id = req.params.companyId; - const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [req.params.companyId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Company not found'); return await respondWithStatusJSON(res, 200, rows[0]); } @@ -54,18 +52,16 @@ router.get('/:companyId', verifyToken, checkBanned, checkPermissions('companies' } }); -router.patch('/:companyId', verifyToken, checkBanned, checkPermissions('companies', 2), async (req, res) => { +router.patch('/:companyId', verifyToken, checkBanned, checkPermissions('company', 2), async (req, res) => { try { - const id = req.params.companyId; const { type, value } = req.body; - const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [req.params.companyId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Company not found'); const excludedKeys = ['id']; const fields = rows.map(row => Object.keys(row).filter(key => !excludedKeys.includes(key))); if (fields[0].includes(type)) { - const [result] = await pool.execute(`UPDATE companies SET ${type} = ? WHERE id = ?`, [value, id]); - + const [result] = await pool.execute(`UPDATE companies SET ${type} = ? WHERE id = ?`, [value, req.params.companyId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating companie'); return await respondWithStatus(res, 200, 'Company updated successfully'); } @@ -79,17 +75,16 @@ router.patch('/:companyId', verifyToken, checkBanned, checkPermissions('companie } }); -router.put('/:companyId', verifyToken, checkBanned, checkPermissions('companies', 2), async (req, res) => { - const id = req.params.companyId; +router.put('/:companyId', verifyToken, checkBanned, checkPermissions('company', 2), async (req, res) => { const { name, code, logo } = req.body; if ([name, code, logo].every(Boolean)) { try { - const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [req.params.companyId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Company not found'); const [result] = await pool.execute( 'UPDATE companies SET name = ?, code = ?, logo = ? WHERE id = ?', - [name, code, logo, id], + [name, code, logo, req.params.companyId], ); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating companie'); @@ -105,14 +100,12 @@ router.put('/:companyId', verifyToken, checkBanned, checkPermissions('companies' } }); -router.delete('/:companyId', verifyToken, checkBanned, checkPermissions('companies', 4), async (req, res) => { +router.delete('/:companyId', verifyToken, checkBanned, checkPermissions('company', 4), async (req, res) => { try { - const id = req.params.companyId; - const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM companies WHERE id = ? LIMIT 1', [req.params.companyId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Company not found'); - const [result] = await pool.execute('DELETE FROM companies WHERE id = ?', [id]); - + const [result] = await pool.execute('DELETE FROM companies WHERE id = ?', [req.params.companyId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing companie'); return await respondWithStatus(res, 200, 'Company removed successfully'); } @@ -123,7 +116,17 @@ router.delete('/:companyId', verifyToken, checkBanned, checkPermissions('compani }); // Hospital endpoints -// GET /:companyId/hospitals +router.get('/:companyId/hospitals', verifyToken, checkBanned, checkPermissions('company', 1), async (req, res) => { + try { + const [rows] = await pool.execute('SELECT * FROM hospitals WHERE company_id = ?', [req.params.companyId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Hospitals not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); export default router; \ No newline at end of file diff --git a/routes/doctors.js b/routes/doctors.js index fbbdca9..183d8b0 100644 --- a/routes/doctors.js +++ b/routes/doctors.js @@ -12,7 +12,7 @@ const router = express.Router(); * * @returns {Promise} A promise that resolves to an array of doctor objects. */ -router.get('/', verifyToken, checkBanned, checkPermissions('doctors', 1), async (req, res) => { +router.get('/', verifyToken, checkBanned, checkPermissions('doctor', 1), async (req, res) => { try { const [rows] = await pool.execute('SELECT * FROM doctors WHERE 1'); if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctors not found'); @@ -28,15 +28,16 @@ router.get('/', verifyToken, checkBanned, checkPermissions('doctors', 1), async * Inserts a new doctor record into the database. * * @param {number} user_id - The ID of the user associated with the doctor. - * @param {date} date_of_birth - The date of birth of the doctor. - * @param {string} gender - The gender of the doctor. - * @param {string} address - The address of the doctor. - * @param {string} social_security_number - The social security number of the doctor. - * @param {string} insurance_number - The insurance number of the doctor. + * @param {string} email - The email of the doctor. + * @param {string} phone - The phone number of the doctor. + * @param {string} speciality - The speciality of the doctor. + * @param {string} status - The status of the doctor. + * @param {boolean} is_verified - The verification status of the doctor. * @returns {Promise} - A promise that resolves with the result of the insertion. */ -router.post('/', verifyToken, checkBanned, checkPermissions('doctors', 2), async (req, res) => { +router.post('/', verifyToken, checkBanned, checkPermissions('doctor', 2), async (req, res) => { const { user_id, email, phone, speciality, status, is_verified = false } = req.body; + if (!['Available', 'Absent', 'Unavailable'].includes(status)) return await respondWithStatus(res, 400, 'Invalid status'); if ([ user_id, email, phone, speciality, status ].every(Boolean)) { try { const [result] = await pool.execute( @@ -58,6 +59,7 @@ router.post('/', verifyToken, checkBanned, checkPermissions('doctors', 2), async router.post('/register', verifyToken, checkEmailVerified, checkBanned, async (req, res) => { const { email, phone, speciality, status } = req.body; + if (!['Available', 'Absent', 'Unavailable'].includes(status)) return await respondWithStatus(res, 400, 'Invalid status'); if ([ email, phone, speciality, status ].every(Boolean)) { try { const [result] = await pool.execute( @@ -77,12 +79,32 @@ router.post('/register', verifyToken, checkEmailVerified, checkBanned, async (re } }); +router.post('/:doctorId/validate', verifyToken, checkBanned, checkPermissions('doctor', 2), async (req, res) => { + const { doctor_id } = req.body; + if (doctor_id) { + try { + const [result] = await pool.execute('UPDATE doctors SET is_verified = 1 WHERE id = ?', [doctor_id]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error validating doctor'); + const [result2] = await pool.execute('INSERT INTO user_roles (user_id, role_id) VALUES (?, (SELECT id FROM roles WHERE name = ? LIMIT 1))', [req.userId, 'Doctor']); + if (result2.affectedRows === 0) return await respondWithStatus(res, 500, 'Error adding role to user'); + return await respondWithStatus(res, 200, 'Doctor validated successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + router.get('/:doctorId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.doctorId; - const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [id]); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'doctor', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [req.params.doctorId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctor not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'doctors', 1)) return await respondWithStatus(res, 403, 'Missing permission'); return await respondWithStatusJSON(res, 200, rows[0]); } catch (err) { @@ -93,17 +115,16 @@ router.get('/:doctorId', verifyToken, checkBanned, async (req, res) => { router.patch('/:doctorId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.doctorId; const { type, value } = req.body; - const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [id]); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'doctor', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [req.params.doctorId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctor not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'doctors', 2)) return await respondWithStatus(res, 403, 'Missing permission'); const excludedKeys = [ 'id', 'user_id' ]; const fields = rows.map(row => Object.keys(row).filter(key => !excludedKeys.includes(key))); if (fields[0].includes(type)) { - const [result] = await pool.execute(`UPDATE doctors SET ${type} = ? WHERE id = ?`, [value, id]); - + const [result] = await pool.execute(`UPDATE doctors SET ${type} = ? WHERE id = ?`, [value, req.params.doctorId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating doctor'); return await respondWithStatus(res, 200, 'Doctor updated successfully'); } @@ -118,17 +139,17 @@ router.patch('/:doctorId', verifyToken, checkBanned, async (req, res) => { }); router.put('/:doctorId', verifyToken, checkBanned, async (req, res) => { - const id = req.params.doctorId; const { user_id, email, phone, speciality, status, is_verified } = req.body; if ([ user_id, email, phone, speciality, status, is_verified ].every(Boolean)) { try { - const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [id]); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'doctor', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [req.params.doctorId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctor not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'doctors', 2)) return await respondWithStatus(res, 403, 'Missing permission'); const [result] = await pool.execute( 'UPDATE doctors SET name = ?, email = ?, phone = ?, speciality = ?, status = ?, is_verified = ? WHERE id = ?', - [user_id, email, phone, speciality, status, is_verified, id], + [user_id, email, phone, speciality, status, is_verified, req.params.doctorId], ); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating doctor'); @@ -146,13 +167,12 @@ router.put('/:doctorId', verifyToken, checkBanned, async (req, res) => { router.delete('/:doctorId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.doctorId; - const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT', [id]); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'doctor', 4)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM doctors WHERE id = ? LIMIT 1', [req.params.doctorId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctor not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'doctors', 4)) return await respondWithStatus(res, 403, 'Missing permission'); - - const [result] = await pool.execute('DELETE FROM doctors WHERE id = ?', [id]); + const [result] = await pool.execute('DELETE FROM doctors WHERE id = ?', [req.params.doctorId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing doctor'); return await respondWithStatus(res, 200, 'Doctor deleted successfully'); } @@ -163,11 +183,207 @@ router.delete('/:doctorId', verifyToken, checkBanned, async (req, res) => { }); // Appointments endpoints -// GET /:doctorId/appointments -// POST /:doctorId/appointments -// GET /:doctorId/appointments/:appointmentId -// PATCH /:doctorId/appointments/:appointmentId -// PUT /:doctorId/appointments/:appointmentId -// DELETE /:doctorId/appointments/:appointmentId +router.get('/:doctorId/appointments', verifyToken, checkBanned, async (req, res) => { + try { + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 1)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute( + 'SELECT a.*, u.first_name, u.last_name, p.gender, p.date_of_birth, s.service_name, a.service_id FROM appointments AS a JOIN patients AS p ON a.patient_id = p.id JOIN users AS u ON p.user_id = u.id JOIN services AS s ON a.service_id = s.id WHERE a.doctor_id = ?', + [req.params.doctorId], + ); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointments not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.post('/:doctorId/appointments', verifyToken, checkBanned, async (req, res) => { + const { patient_id, service_id, hospital_id, room_id = null, date, time, status } = req.body; + if (!['Confirmed', 'Completed', 'Absent', 'Cancelled by Patient', 'Cancelled by Doctor'].includes(status)) return await respondWithStatus(res, 400, 'Invalid status'); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + if ([patient_id, service_id, hospital_id, date, time, status].every(Boolean)) { + try { + const [result] = await pool.execute( + 'INSERT INTO appointments (patient_id, doctor_id, service_id, hospital_id, room_id, date, time, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', + [patient_id, req.params.doctorId, service_id, hospital_id, room_id, date, time, status], + ); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing appointment'); + return await respondWithStatus(res, 200, 'Appointment created successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + +router.get('/:doctorId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => { + try { + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 1)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute( + 'SELECT a.*, u.first_name, u.last_name, p.gender, p.date_of_birth, s.service_name, a.service_id FROM appointments AS a JOIN patients AS p ON a.patient_id = p.id JOIN users AS u ON p.user_id = u.id WHERE a.id = ? AND a.doctor_id = ? LIMIT 1', + [req.params.appointmentId, req.params.doctorId], + ); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found'); + return await respondWithStatusJSON(res, 200, rows[0]); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.patch('/:doctorId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => { + try { + const { type, value } = req.body; + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM appointments WHERE id = ? LIMIT 1', [req.params.appointmentId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found'); + + const excludedKeys = [ 'id', 'patient_id', 'doctor_id' ]; + const fields = rows.map(row => Object.keys(row).filter(key => !excludedKeys.includes(key))); + if (type === 'status' && !['Confirmed', 'Completed', 'Absent', 'Cancelled by Patient', 'Cancelled by Doctor'].includes(value)) return await respondWithStatus(res, 400, 'Invalid status'); + if (fields[0].includes(type)) { + const [result] = await pool.execute(`UPDATE appointments SET ${type} = ? WHERE id = ?`, [value, req.params.appointmentId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating appointment'); + return await respondWithStatus(res, 200, 'Appointment updated successfully'); + } + else { + return await respondWithStatus(res, 400, 'Invalid type'); + } + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.put('/:doctorId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => { + const { patient_id, service_id, hospital_id, room_id, date, time, status } = req.body; + if (!['Confirmed', 'Completed', 'Absent', 'Cancelled by Patient', 'Cancelled by Doctor'].includes(status)) return await respondWithStatus(res, 400, 'Invalid status'); + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + if ([patient_id, service_id, hospital_id, room_id, date, time, status].every(Boolean)) { + try { + const [rows] = await pool.execute('SELECT * FROM appointments WHERE id = ? LIMIT 1', [req.params.appointmentId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found'); + + const [result] = await pool.execute( + 'UPDATE appointments SET patient_id = ?, doctor_id = ?, service_id = ?, hospital_id = ?, room_id = ?, date = ?, time = ?, status = ? WHERE id = ?', + [patient_id, req.params.doctorId, service_id, hospital_id, room_id, date, time, status, req.params.appointmentId], + ); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating appointment'); + return await respondWithStatus(res, 200, 'Appointment updated successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + +router.delete('/:doctorId/appointments/:appointmentId', verifyToken, checkBanned, async (req, res) => { + try { + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'appointment', 4)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM appointments WHERE id = ? LIMIT 1', [req.params.appointmentId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointment not found'); + + const [result] = await pool.execute('DELETE FROM appointments WHERE id = ?', [req.params.appointmentId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing appointment'); + return await respondWithStatus(res, 200, 'Appointment deleted successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +// Services endpoints +router.get('/:doctorId/services', verifyToken, checkBanned, async (req, res) => { + try { + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'service', 1)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT s.* FROM services s INNER JOIN service_doctors sd ON s.id = sd.service_id WHERE sd.doctor_id = ?', [req.params.doctorId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Services not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.post('/:doctorId/services', verifyToken, checkBanned, async (req, res) => { + const { service_id } = req.body; + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'service', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + if (service_id) { + try { + const [result] = await pool.execute('INSERT INTO service_doctors (doctor_id, service_id) VALUES (?, ?)', [req.params.doctorId, service_id]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing service'); + return await respondWithStatus(res, 200, 'Service added successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + +router.patch('/:doctorId/services/:serviceId', verifyToken, checkBanned, async (req, res) => { + const { type, value } = req.body; + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'service', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + if (type === 'service_id') { + try { + const [result] = await pool.execute('UPDATE service_doctors SET service_id = ? WHERE doctor_id = ? AND service_id = ?', [value, req.params.doctorId, req.params.serviceId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating service'); + return await respondWithStatus(res, 200, 'Service updated successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Invalid type'); + } +}); + +router.delete('/:doctorId/services/:serviceId', verifyToken, checkBanned, async (req, res) => { + const doctorId = await getDoctorId (req.userId); + if (doctorId != req.params.doctorId && !verifyPermissions(req.userId, 'service', 4)) return await respondWithStatus(res, 403, 'Missing permission'); + try { + const [result] = await pool.execute('DELETE FROM service_doctors WHERE doctor_id = ? AND service_id = ?', [req.params.doctorId, req.params.serviceId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing service'); + return await respondWithStatus(res, 200, 'Service removed successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); export default router; + + +async function getDoctorId(userId) { + const [rows] = await pool.execute('SELECT id FROM doctors WHERE user_id = ? LIMIT 1', [userId]); + return rows.length ? rows[0].id : null; +} \ No newline at end of file diff --git a/routes/hospitals.js b/routes/hospitals.js index 315cb79..ed72538 100644 --- a/routes/hospitals.js +++ b/routes/hospitals.js @@ -7,13 +7,10 @@ import { respondWithStatus, respondWithStatusJSON } from '../modules/requestHand const router = express.Router(); -router.get('/', verifyToken, checkBanned, checkPermissions('hospitals', 1), async (req, res) => { +router.get('/', verifyToken, checkBanned, checkPermissions('hospital', 1), async (req, res) => { try { const [rows] = await pool.execute('SELECT * FROM hospitals WHERE 1'); - - if (rows.length === 0) { - return await respondWithStatus(res, 404, 'Hospitals not found'); - } + if (rows.length === 0) return await respondWithStatus(res, 404, 'Hospitals not found'); return await respondWithStatusJSON(res, 200, rows); } catch (err) { @@ -22,7 +19,7 @@ router.get('/', verifyToken, checkBanned, checkPermissions('hospitals', 1), asyn } }); -router.post('/', verifyToken, checkBanned, checkPermissions('hospitals', 2), async (req, res) => { +router.post('/', verifyToken, checkBanned, checkPermissions('hospital', 2), async (req, res) => { const { company_id, name, code, country, region, city, address } = req.body; if ([ company_id, name, code, country, region, city, address ].every(Boolean)) { try { @@ -30,9 +27,7 @@ router.post('/', verifyToken, checkBanned, checkPermissions('hospitals', 2), asy 'INSERT INTO hospitals (company_id, name, code, country, region, city, address) VALUES (?, ?, ?, ?, ?, ?, ?)', [ company_id, name, code, country, region, city, address ], ); - if (result.affectedRows === 0) { - return await respondWithStatus(res, 500, 'Error storing hospital'); - } + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing hospital'); return await respondWithStatus(res, 200, 'Hospital created successfully'); } catch (err) { @@ -45,14 +40,10 @@ router.post('/', verifyToken, checkBanned, checkPermissions('hospitals', 2), asy } }); -router.get('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals', 1), async (req, res) => { +router.get('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospital', 1), async (req, res) => { try { - const id = req.params.hospitalId; - const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [id]); - - if (rows.length === 0) { - return await respondWithStatus(res, 404, 'Hospitals not found'); - } + const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [req.params.hospitalId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Hospitals not found'); return await respondWithStatusJSON(res, 200, rows[0]); } catch (err) { @@ -61,22 +52,16 @@ router.get('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals } }); -router.patch('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals', 2), async (req, res) => { +router.patch('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospital', 2), async (req, res) => { try { - const id = req.params.hospitalId; const { type, value } = req.body; - const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [req.params.hospitalId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Hospital not found'); - if (rows.length === 0) { - return await respondWithStatus(res, 404, 'Hospital not found'); - } const fields = rows.map(row => Object.keys(row)); if (fields[0].includes(type)) { - const [result] = await pool.execute(`UPDATE hospitals SET ${type} = ? WHERE id = ?`, [value, id]); - - if (result.affectedRows === 0) { - return await respondWithStatus(res, 500, 'Error updating hospital'); - } + const [result] = await pool.execute(`UPDATE hospitals SET ${type} = ? WHERE id = ?`, [value, req.params.hospitalId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating hospital'); return await respondWithStatus(res, 200, 'Hospital updated successfully'); } else { @@ -89,7 +74,7 @@ router.patch('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospita } }); -router.put('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals', 2), async (req, res) => { +router.put('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospital', 2), async (req, res) => { const id = req.params.hospitalId; const { company_id, name, code, country, region, city, address } = req.body; if ([company_id, name, code, country, region, city, address].every(Boolean)) { @@ -119,20 +104,13 @@ router.put('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals } }); -router.delete('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospitals', 4), async (req, res) => { +router.delete('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospital', 4), async (req, res) => { try { - const id = req.params.hospitalId; - const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [id]); + const [rows] = await pool.execute('SELECT * FROM hospitals WHERE id = ? LIMIT 1', [req.params.hospitalId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Hospital not found'); - if (rows.length === 0) { - return await respondWithStatus(res, 404, 'Hospital not found'); - } - - const [result] = await pool.execute('DELETE FROM hospitals WHERE id = ?', [id]); - - if (result.affectedRows === 0) { - return await respondWithStatus(res, 500, 'Error removing hospital'); - } + const [result] = await pool.execute('DELETE FROM hospitals WHERE id = ?', [req.params.hospitalId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing hospital'); return await respondWithStatus(res, 200, 'Hospital deleted successfully'); } catch (err) { @@ -142,16 +120,110 @@ router.delete('/:hospitalId', verifyToken, checkBanned, checkPermissions('hospit }); // Doctor endpoints -// GET all doctors in a hospital -// POST a new doctor to a hospital -// DELETE a doctor from a hospital +router.get('/:hospitalId/doctors', verifyToken, checkBanned, checkPermissions('doctor', 1), async (req, res) => { + try { + const [rows] = await pool.execute('SELECT doctors.* FROM hospital_doctors JOIN doctors ON hospital_doctors.doctor_id = doctors.id WHERE hospital_doctors.hospital_id = ?', [req.params.hospitalId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Doctors not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.post('/:hospitalId/doctors', verifyToken, checkBanned, checkPermissions('doctor', 2), async (req, res) => { + const { doctor_id } = req.body; + if ([doctor_id].every(Boolean)) { + try { + const [result] = await pool.execute('INSERT INTO hospital_doctors (hospital_id, doctor_id) VALUES (?, ?)', [req.params.hospitalId, doctor_id]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing doctor'); + return await respondWithStatus(res, 200, 'Doctor added to hospital successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + +router.delete('/:hospitalId/doctors/:doctorId', verifyToken, checkBanned, checkPermissions('doctor', 4), async (req, res) => { + try { + const { hospitalId, doctorId } = req.params; + const [result] = await pool.execute('DELETE FROM hospital_doctors WHERE hospital_id = ? AND doctor_id = ?', [hospitalId, doctorId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing doctor'); + return await respondWithStatus(res, 200, 'Doctor removed from hospital successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); // Service endpoints -// GET all services in a hospital +router.get('/:hospitalId/services', verifyToken, checkBanned, checkPermissions('service', 1), async (req, res) => { + try { + const [rows] = await pool.execute( + 'SELECT services.* FROM hospital_doctors JOIN doctors ON hospital_doctors.doctor_id = doctors.id JOIN doctor_services ON doctors.id = doctor_services.doctor_id JOIN services ON doctor_services.service_id = services.id WHERE hospital_doctors.hospital_id = ?', + [req.params.hospitalId], + ); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Services not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); // Room endpoints -// GET all rooms in a hospital -// POST a new room to a hospital -// DELETE a room from a hospital +router.get('/:hospitalId/rooms', verifyToken, checkBanned, checkPermissions('room', 1), async (req, res) => { + try { + const [rows] = await pool.execute('SELECT * FROM rooms WHERE hospital_id = ?', [req.params.hospitalId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Rooms not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.post('/:hospitalId/rooms', verifyToken, checkBanned, checkPermissions('room', 2), async (req, res) => { + const { name, code, floor, room_number, room_type } = req.body; + if ([name, code, floor, room_number, room_type].every(Boolean)) { + try { + if (!['General Ward', 'Private', 'Intensive Care Unit', 'Labor and Delivery', 'Operating', 'Recovery', 'Isolation', 'Emergency', 'Imaging', 'Procedure', 'Physical Therapy', 'Consultation'].includes(room_type)) return await respondWithStatus(res, 400, 'Invalid room type'); + const [result] = await pool.execute( + 'INSERT INTO rooms (hospital_id, name, code, floor, room_number, room_type) VALUES (?, ?, ?, ?, ?, ?)', + [req.params.hospitalId, name, code, floor, room_number, room_type], + ); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing room'); + return await respondWithStatus(res, 200, 'Room created successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); + +router.delete('/:hospitalId/rooms/:roomId', verifyToken, checkBanned, checkPermissions('room', 4), async (req, res) => { + try { + const [result] = await pool.execute('DELETE FROM rooms WHERE hospital_id = ? AND id = ?', [req.params.hospitalId, req.params.roomId]); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing room'); + return await respondWithStatus(res, 200, 'Room removed from hospital successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); export default router; diff --git a/routes/patients.js b/routes/patients.js index b975cbc..ab44f40 100644 --- a/routes/patients.js +++ b/routes/patients.js @@ -12,7 +12,7 @@ const router = express.Router(); * * @returns {Promise} A promise that resolves to an array of patient objects. */ -router.get('/', verifyToken, checkBanned, checkPermissions('patients', 1), async (req, res) => { +router.get('/', verifyToken, checkBanned, checkPermissions('patient', 1), async (req, res) => { try { const [rows] = await pool.execute('SELECT * FROM patients WHERE 1'); if (rows.length === 0) return await respondWithStatus(res, 404, 'Patients not found'); @@ -35,7 +35,7 @@ router.get('/', verifyToken, checkBanned, checkPermissions('patients', 1), async * @param {string} insurance_number - The insurance number of the patient. * @returns {Promise} - A promise that resolves with the result of the insertion. */ -router.post('/', verifyToken, checkBanned, checkPermissions('patients', 2), async (req, res) => { +router.post('/', verifyToken, checkBanned, checkPermissions('patient', 2), async (req, res) => { const { user_id, date_of_birth, gender, address, social_security_number, insurance_number } = req.body; if ([ user_id, date_of_birth, gender, address, social_security_number, insurance_number ].every(Boolean)) { try { @@ -65,6 +65,9 @@ router.post('/register', verifyToken, checkEmailVerified, checkBanned, async (re [ req.userId, date_of_birth, gender, address, social_security_number, insurance_number ], ); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing patient'); + + const [result2] = await pool.execute('INSERT INTO user_roles (user_id, role_id) VALUES (?, (SELECT id FROM roles WHERE name = ? LIMIT 1))', [req.userId, 'Patient']); + if (result2.affectedRows === 0) return await respondWithStatus(res, 500, 'Error adding role to user'); return await respondWithStatus(res, 200, 'Patient created successfully'); } catch (err) { @@ -79,10 +82,10 @@ router.post('/register', verifyToken, checkEmailVerified, checkBanned, async (re router.get('/:patientId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.patientId; - const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [id]); + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 1)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'patients', 1)) return await respondWithStatus(res, 403, 'Missing permission'); return await respondWithStatusJSON(res, 200, rows[0]); } catch (err) { @@ -93,17 +96,16 @@ router.get('/:patientId', verifyToken, checkBanned, async (req, res) => { router.patch('/:patientId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.patientId; const { type, value } = req.body; - const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [id]); + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'patients', 2)) return await respondWithStatus(res, 403, 'Missing permission'); const excludedKeys = [ 'id', 'user_id' ]; const fields = rows.map(row => Object.keys(row).filter(key => !excludedKeys.includes(key))); if (fields[0].includes(type)) { - const [result] = await pool.execute(`UPDATE patients SET ${type} = ? WHERE id = ?`, [value, id]); - + const [result] = await pool.execute(`UPDATE patients SET ${type} = ? WHERE id = ?`, [value, req.params.patientId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating patient'); return await respondWithStatus(res, 200, 'Patient updated successfully'); } @@ -118,17 +120,17 @@ router.patch('/:patientId', verifyToken, checkBanned, async (req, res) => { }); router.put('/:patientId', verifyToken, checkBanned, async (req, res) => { - const id = req.params.patientId; const { user_id, date_of_birth, gender, address, social_security_number, insurance_number } = req.body; if ([ user_id, date_of_birth, gender, address, social_security_number, insurance_number ].every(Boolean)) { try { - const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [id]); + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'patients', 2)) return await respondWithStatus(res, 403, 'Missing permission'); const [result] = await pool.execute( 'UPDATE patients SET name = ?, date_of_birth = ?, gender = ?, address = ?, social_security_number = ?, insurance_number = ? WHERE id = ?', - [user_id, date_of_birth, gender, address, social_security_number, insurance_number, id], + [user_id, date_of_birth, gender, address, social_security_number, insurance_number, req.params.patientId], ); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error updating patient'); @@ -146,13 +148,12 @@ router.put('/:patientId', verifyToken, checkBanned, async (req, res) => { router.delete('/:patientId', verifyToken, checkBanned, async (req, res) => { try { - const id = req.params.patientId; - const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT', [id]); + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'patient', 4)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute('SELECT * FROM patients WHERE id = ? LIMIT 1', [req.params.patientId]); if (rows.length === 0) return await respondWithStatus(res, 404, 'Patient not found'); - if (rows[0].userId != req.userId && !verifyPermissions(req.userId, 'patients', 4)) return await respondWithStatus(res, 403, 'Missing permission'); - - const [result] = await pool.execute('DELETE FROM patients WHERE id = ?', [id]); + const [result] = await pool.execute('DELETE FROM patients WHERE id = ?', [req.params.patientId]); if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing patient'); return await respondWithStatus(res, 200, 'Patient deleted successfully'); } @@ -163,11 +164,53 @@ router.delete('/:patientId', verifyToken, checkBanned, async (req, res) => { }); // Appointments endpoints -// GET /:patientId/appointments -// POST /:patientId/appointments +router.get('/:patientId/appointments', verifyToken, checkBanned, async (req, res) => { + try { + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 1)) return await respondWithStatus(res, 403, 'Missing permission'); + const [rows] = await pool.execute( + 'SELECT a.id, u.first_name, u.last_name, d.email, d.phone, h.name, h.address, a.date, a.time, a.status, s.name FROM appointments a JOIN doctors d ON a.doctor_id = d.id JOIN users u ON d.user_id = u.id JOIN hospitals h ON a.hospital_id = h.id JOIN services s ON a.service_id = s.id WHERE a.patient_id = ?', + [req.params.patientId], + ); + if (rows.length === 0) return await respondWithStatus(res, 404, 'Appointments not found'); + return await respondWithStatusJSON(res, 200, rows); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } +}); + +router.post('/:patientId/appointments', verifyToken, checkBanned, async (req, res) => { + const { doctor_id, service_id, hospital_id, date, time } = req.body; + if ([ doctor_id, service_id, hospital_id, date, time ].every(Boolean)) { + try { + const patientId = await getPatientId(req.userId); + if (patientId != req.params.patientId && !verifyPermissions(req.userId, 'appointment', 2)) return await respondWithStatus(res, 403, 'Missing permission'); + const [result] = await pool.execute( + 'INSERT INTO appointments (doctor_id, service_id, hospital_id, patient_id, date, time) VALUES (?, ?, ?, ?, ?, ?)', + [ doctor_id, service_id, hospital_id, req.params.patientId, date, time ], + ); + if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error storing appointment'); + return await respondWithStatus(res, 200, 'Appointment created successfully'); + } + catch (err) { + error(err); + return await respondWithStatus(res, 500, 'An error has occured'); + } + } + else { + return await respondWithStatus(res, 400, 'Missing fields'); + } +}); // GET /:patientId/appointments/:appointmentId // PATCH /:patientId/appointments/:appointmentId // PUT /:patientId/appointments/:appointmentId // DELETE /:patientId/appointments/:appointmentId export default router; + +async function getPatientId(userId) { + const [rows] = await pool.execute('SELECT * FROM patients WHERE user_id = ? LIMIT 1', [userId]); + return rows.length ? rows[0].id : null; +} \ No newline at end of file diff --git a/routes/test.js b/routes/test.js index 52dd510..664c23a 100644 --- a/routes/test.js +++ b/routes/test.js @@ -16,7 +16,7 @@ router.post('/', (req, res) => { router.patch('/', (req, res) => { - res.status(200).json({ code: 200, message:'Received PUT request' }); + res.status(200).json({ code: 200, message:'Received PATCH request' }); }); diff --git a/routes/users.js b/routes/users.js index ed02a0e..bbe6e51 100644 --- a/routes/users.js +++ b/routes/users.js @@ -89,8 +89,7 @@ router.post('/login', requestLimiter, async (req, res) => { router.get('/', verifyToken, checkBanned, checkPermissions('user', 1), async (req, res) => { try { - const [rows] = await pool.execute('SELECT * FROM users WHERE 1'); - + const [rows] = await pool.execute('SELECT id, first_name, last_name, username, email, phone FROM users WHERE 1'); if (rows.length === 0) return await respondWithStatus(res, 404, 'Users not found'); return await respondWithStatusJSON(res, 200, rows); } @@ -124,11 +123,9 @@ router.post('/', verifyToken, checkBanned, checkPermissions('user', 2), async (r router.get('/:userId', verifyToken, checkBanned, async (req, res) => { try { if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 1)) return await respondWithStatus(res, 403, 'Missing permission'); - const [rows] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [req.params.userId]); + const [rows] = await pool.execute('SELECT id, first_name, last_name, username, email, phone FROM users WHERE id = ? LIMIT 1', [req.params.userId]); + if (rows.length === 0) return await respondWithStatus(res, 404, 'User not found'); - if (rows.length === 0) { - return await respondWithStatus(res, 404, 'User not found'); - } const user = rows[0]; delete user.password; return await respondWithStatusJSON(res, 200, user);