const express = require('express'); const fs = require('fs'); const fsExtra = require('fs-extra'); const path = require('path'); const Joi = require('joi'); const { httpStatus } = require('../helpers/http_status'); const {lockFile, unlockFile} = require("../helpers/lock_mechanism"); const {decryptFileInPlace, encryptFileInPlace} = require("../src/main/aes_encrypt"); const app = express(); app.use(express.json()); const server = require('http').createServer(app); const connections = []; // Store active connections to close them on shutdown server.on('connection', (conn) => { connections.push(conn); conn.on('close', () => { connections.splice(connections.indexOf(conn), 1); }); }); const filePathSchema = Joi.object({ filePath: Joi.string().required() }); async function getBaseDirectory() { const filePath = path.join(__dirname, '..', 'dirBackup.json'); try { const data = await fs.promises.readFile(filePath, 'utf8'); const jsonData = JSON.parse(data); return jsonData.path; } catch (error) { console.error('Error reading the base directory:', error); throw error; } } app.post('/file_path', async (req, res) => { const { error, value } = filePathSchema.validate(req.body); if (error) { return res.status(httpStatus.BAD_REQUEST).json({ message: 'Invalid input', data: error.details }); } try { const basePath = await getBaseDirectory(); let { filePath } = value; const baseDirName = path.basename(basePath); if (filePath.startsWith(baseDirName + path.sep)) { filePath = filePath.slice(baseDirName.length + 1); } const fullPath = path.resolve(basePath, filePath); fs.stat(fullPath, (err, stats) => { if (err) { if (err.code === 'ENOENT') { return res.status(httpStatus.NOT_FOUND).json({ message: 'File not found' }); } return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Error accessing the file' }); } if (!stats.isFile()) { return res.status(httpStatus.BAD_REQUEST).json({ message: 'Path is not a file' }); } // Stream the file as binary data res.writeHead(httpStatus.OK, { 'Content-Type': 'application/octet-stream', 'Content-Disposition': `attachment; filename="${path.basename(fullPath)}"` }); const fileStream = fs.createReadStream(fullPath); fileStream.pipe(res); }); } catch (error) { return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Error processing request' }); } }); async function addFilePathToJson(filePath) { const jsonFilePath = path.join(__dirname, '..', 'filesReceived.json'); try { let data = { receivedFiles: [] }; if (await fsExtra.pathExists(jsonFilePath)) { await lockFile(jsonFilePath); data = await fsExtra.readJson(jsonFilePath); }else{ await lockFile(jsonFilePath); } data.receivedFiles.push(filePath); await fsExtra.writeJson(jsonFilePath, data, { spaces: 2 }); await unlockFile(jsonFilePath); console.log('File path added successfully.'); } catch (error) { console.error('Error updating JSON file:', error); throw error; // Rethrow the error for further handling if necessary } } app.use('/share_file', express.raw({ type: 'application/octet-stream', limit: '50mb' })); async function decryptAndGetShareDir(filePath) { try { await lockFile(filePath); await decryptFileInPlace(filePath); const fileContent = await fs.promises.readFile(filePath, 'utf8'); const jsonData = JSON.parse(fileContent); const serverIP = jsonData.path; await encryptFileInPlace(filePath) await unlockFile(filePath); return serverIP; } catch (error) { console.error('An error occurred:', error); return null; } } app.post('/share_file', async (req, res) => { // Extract metadata from headers const idUser = req.headers['x-iduser']; const nameOfFile = req.headers['x-nameoffile']; const sizeOfFile = req.headers['x-sizeoffile']; // You might want to validate the metadata here if (!idUser || !nameOfFile || !sizeOfFile) { return res.status(httpStatus.BAD_REQUEST).send('Missing metadata headers'); } // Construct the file path using the metadata const shareDirPath = await decryptAndGetShareDir(path.join(__dirname, '..', 'shareDir.json')); const baseDir = path.join(shareDirPath, idUser); fsExtra.ensureDirSync(baseDir); const filePath = path.join(shareDirPath, nameOfFile); try { fs.writeFileSync(filePath, req.body); res.status(httpStatus.OK).json({ message: 'Upload successful.' }); } catch (error) { console.error('Error during file upload:', error); res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Internal server error.' }); } }); console.log('external_endpoints.json started.'); const PORT = process.env.PORT || 3000; server.listen(PORT, () => console.log(`Server running on port ${PORT}`)); process.on('SIGINT', () => { console.log('SIGINT signal received. Shutting down gracefully.'); server.close(() => { console.log('Server closed.'); // Ensure all connections are closed connections.forEach(conn => conn.end()); setTimeout(() => connections.forEach(conn => conn.destroy()), 5000); process.exit(0); }); });