const express = require('express'); const fs = require('fs'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); const crypto = require('crypto'); const { sendResponse } = require('../helpers/responseHelper'); const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses') const {schemas} = require("../models/schemaMapper"); const DepartmentAlreadyExistsError = require("../exceptions/departmentAlreadyExistsError"); const InvalidDepartmentJsonError = require("../exceptions/invalidDepartmentJsonError"); const DepartmentNotExistingError = require("../exceptions/departmentNotExistingError"); const router = express.Router(); router.get('/', (req, res) => { try { const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json'); const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8'); const departments = JSON.parse(departmentsData); return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK], departments); } catch (error) { console.error(`Error: ${error.message}`); return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]); } }); function generateAESKey() { return crypto.randomBytes(32).toString('hex'); } router.post('/', validateRegisterBody, createDepartment, addSecurityLevel, (req, res) => { return res; }); function validateRegisterBody(req, res, next) { const { error, value } = schemas.departmentRegisterModelSchema.validate(req.body); if (error) { return sendResponse(res, httpStatus.BAD_REQUEST, error.details[0].message); } req.jsonModel = value; next(); } function createDepartment(req, res, next) { try { const { name } = req.jsonModel; const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json'); const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8'); const departments = JSON.parse(departmentsData); const existingDepartment = departments.find(department => department.name === name); if (existingDepartment) { throw new DepartmentAlreadyExistsError(); } const departmentId = uuidv4(); const aesKey = generateAESKey(); const newDepartment = { id: departmentId, name: name, key: aesKey }; departments.push(newDepartment); fs.writeFileSync(departmentsFilePath, JSON.stringify(departments, null, 2)); req.departmentId = departmentId; next(); return res; } catch (error) { console.error(`Error: ${error.message}`); if (error instanceof DepartmentAlreadyExistsError) { return sendResponse(res, httpStatus.CONFLICT, error.message); } return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]); } } function addSecurityLevel(req, res) { try { const { departmentId } = req; const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json'); const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8'); const securityLevels = JSON.parse(securityLevelsData); const nextIndex = Object.keys(securityLevels).length + 1; securityLevels[nextIndex] = departmentId; fs.writeFileSync(securityLevelsFilePath, JSON.stringify(securityLevels, null, 2)); return sendResponse(res, httpStatus.CREATED, httpStatusMessages[httpStatus.CREATED]); } catch (error) { console.error(`Error: ${error.message}`); return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]); } } router.put('/', validateDepartmentsJson, validateSecurityLevels, updateSecurityLevels); function validateDepartmentsJson(req, res, next) { try { for (const key in req.body) { if (!Number.isInteger(parseInt(key)) || typeof req.body[key] !== 'string') { throw new InvalidDepartmentJsonError(); } } next(); } catch (error) { console.error(`Error: ${error.message}`); return sendResponse(res, httpStatus.BAD_REQUEST, error.message); } } function validateSecurityLevels(req, res, next) { try { const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json'); const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8'); const securityLevels = JSON.parse(securityLevelsData); if (Object.keys(req.body).length !== Object.keys(securityLevels).length) { throw new InvalidDepartmentJsonError('Number of keys does not match the database'); } const encounteredValues = new Set(); const securityLevelValues = Object.values(securityLevels); for (const key in req.body) { const requestBodyValue = req.body[key]; if (!securityLevels.hasOwnProperty(key)) { throw new InvalidDepartmentJsonError('Invalid key found in request body'); } const securityLevelValue = securityLevels[key]; if (!securityLevelValues.includes(securityLevelValue)) { throw new InvalidDepartmentJsonError('Values do not match the database'); } if (encounteredValues.has(requestBodyValue)) { throw new InvalidDepartmentJsonError('Duplicate values found in request body'); } encounteredValues.add(requestBodyValue); } next(); return res; } catch (error) { console.error(`Error: ${error.message}`); return sendResponse(res, httpStatus.BAD_REQUEST, error.message); } } function updateSecurityLevels(req, res) { try { const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json'); fs.writeFileSync(securityLevelsFilePath, JSON.stringify(req.body, null, 2)); return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]); } catch (error) { console.error(`Error: ${error.message}`); return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]); } } router.delete('/:id', async (req, res) => { const id = req.params.id; try { deleteDepartment(id, res); } catch (error) { console.error(`Error: ${error.message}`); if (error instanceof DepartmentNotExistingError) { return sendResponse(res, httpStatus.NOT_FOUND, error.message); } return sendResponse(res, httpStatus.INTERNAL_SERVER_ERROR, httpStatusMessages[httpStatus.INTERNAL_SERVER_ERROR]); } }); function deleteDepartment(id, res) { const departmentsFilePath = path.join(__dirname, '..', 'db', 'departments.json'); const departmentsData = fs.readFileSync(departmentsFilePath, 'utf8'); const departmentsJson = JSON.parse(departmentsData); const index = departmentsJson.findIndex(department => department.id === id); if (index === -1) { throw new DepartmentNotExistingError(); } departmentsJson.splice(index, 1); fs.writeFileSync(departmentsFilePath, JSON.stringify(departmentsJson, null, 2)); const securityLevelsFilePath = path.join(__dirname, '..', 'db', 'security_levels.json'); const securityLevelsData = fs.readFileSync(securityLevelsFilePath, 'utf8'); const securityLevelsJson = JSON.parse(securityLevelsData); const securityIndex = securityLevelsJson.findIndex(level => level.id === id); if (securityIndex !== -1) { securityLevelsJson.splice(securityIndex, 1); fs.writeFileSync(securityLevelsFilePath, JSON.stringify(securityLevelsJson, null, 2)); } return sendResponse(res, httpStatus.OK, httpStatusMessages[httpStatus.OK]); } router.use((req, res) => { return sendResponse(res, httpStatus.NOT_FOUND, "Path not found"); }); module.exports = router;