diff --git a/src/routes/api/image.js b/src/routes/api/image.js index d8ce83bfb..b95c411cf 100644 --- a/src/routes/api/image.js +++ b/src/routes/api/image.js @@ -1,12 +1,7 @@ "use strict"; -const express = require('express'); -const router = express.Router(); const sql = require('../../services/sql'); -const auth = require('../../services/auth'); const image = require('../../services/image'); -const multer = require('multer')(); -const wrap = require('express-promise-wrap').wrap; const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; const fs = require('fs'); @@ -14,7 +9,7 @@ async function returnImage(req, res) { const image = await sql.getRow("SELECT * FROM images WHERE imageId = ?", [req.params.imageId]); if (!image) { - return res.status(404).send({}); + return res.sendStatus(404); } else if (image.data === null) { res.set('Content-Type', 'image/png'); @@ -26,7 +21,7 @@ async function returnImage(req, res) { res.send(image.data); } -async function uploadImage(req, res) { +async function uploadImage(req) { const sourceId = req.headers.source_id; const noteId = req.query.noteId; const file = req.file; @@ -34,19 +29,19 @@ async function uploadImage(req, res) { const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); if (!note) { - return res.status(404).send(`Note ${noteId} doesn't exist.`); + return [404, `Note ${noteId} doesn't exist.`]; } if (!["image/png", "image/jpeg", "image/gif"].includes(file.mimetype)) { - return res.status(400).send("Unknown image type: " + file.mimetype); + return [400, "Unknown image type: " + file.mimetype]; } const {fileName, imageId} = await image.saveImage(file, sourceId, noteId); - res.send({ + return { uploaded: true, url: `/api/images/${imageId}/${fileName}` - }); + }; } module.exports = { diff --git a/src/routes/api/import.js b/src/routes/api/import.js index 6d57f880d..65c75f6a9 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -90,7 +90,7 @@ async function parseImportFile(file) { }); } -async function importTar(req, res) { +async function importTar(req) { const sourceId = req.headers.source_id; const parentNoteId = req.params.parentNoteId; const file = req.file; @@ -98,14 +98,12 @@ async function importTar(req, res) { const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [parentNoteId]); if (!note) { - return res.status(404).send(`Note ${parentNoteId} doesn't exist.`); + return [404, `Note ${parentNoteId} doesn't exist.`]; } const files = await parseImportFile(file); await importNotes(files, parentNoteId, sourceId); - - res.send({}); } async function importNotes(files, parentNoteId, sourceId) { diff --git a/src/routes/api/login.js b/src/routes/api/login.js index befc3bba3..044fb572c 100644 --- a/src/routes/api/login.js +++ b/src/routes/api/login.js @@ -1,17 +1,13 @@ "use strict"; -const express = require('express'); -const router = express.Router(); const options = require('../../services/options'); const utils = require('../../services/utils'); const source_id = require('../../services/source_id'); -const auth = require('../../services/auth'); const password_encryption = require('../../services/password_encryption'); const protected_session = require('../../services/protected_session'); const app_info = require('../../services/app_info'); -const wrap = require('express-promise-wrap').wrap; -router.post('/sync', wrap(async (req, res, next) => { +async function loginSync(req) { const timestampStr = req.body.timestamp; const timestamp = utils.parseDateTime(timestampStr); @@ -19,15 +15,13 @@ router.post('/sync', wrap(async (req, res, next) => { const now = new Date(); if (Math.abs(timestamp.getTime() - now.getTime()) > 5000) { - res.status(400); - res.send({ message: 'Auth request time is out of sync' }); + return [400, { message: 'Auth request time is out of sync' }]; } const dbVersion = req.body.dbVersion; if (dbVersion !== app_info.db_version) { - res.status(400); - res.send({ message: 'Non-matching db versions, local is version ' + app_info.db_version }); + return [400, { message: 'Non-matching db versions, local is version ' + app_info.db_version }]; } const documentSecret = await options.getOption('document_secret'); @@ -36,38 +30,37 @@ router.post('/sync', wrap(async (req, res, next) => { const givenHash = req.body.hash; if (expectedHash !== givenHash) { - res.status(400); - res.send({ message: "Sync login hash doesn't match" }); + return [400, { message: "Sync login hash doesn't match" }]; } req.session.loggedIn = true; - res.send({ + return { sourceId: source_id.getCurrentSourceId() - }); -})); + }; +} -// this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username) -router.post('/protected', auth.checkApiAuth, wrap(async (req, res, next) => { +async function loginToProtectedSession(req) { const password = req.body.password; if (!await password_encryption.verifyPassword(password)) { - res.send({ + return { success: false, message: "Given current password doesn't match hash" - }); - - return; + }; } const decryptedDataKey = await password_encryption.getDataKey(password); const protectedSessionId = protected_session.setDataKey(req, decryptedDataKey); - res.send({ + return { success: true, protectedSessionId: protectedSessionId - }); -})); + }; +} -module.exports = router; \ No newline at end of file +module.exports = { + loginSync, + loginToProtectedSession +}; \ No newline at end of file diff --git a/src/routes/api/migration.js b/src/routes/api/migration.js index 332289aaf..5210e18d5 100644 --- a/src/routes/api/migration.js +++ b/src/routes/api/migration.js @@ -1,26 +1,25 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../../services/auth'); const options = require('../../services/options'); const migration = require('../../services/migration'); const app_info = require('../../services/app_info'); -const wrap = require('express-promise-wrap').wrap; -router.get('', auth.checkApiAuthForMigrationPage, wrap(async (req, res, next) => { - res.send({ +async function getMigrationInfo() { + return { db_version: parseInt(await options.getOption('db_version')), app_db_version: app_info.db_version - }); -})); + }; +} -router.post('', auth.checkApiAuthForMigrationPage, wrap(async (req, res, next) => { +async function executeMigration() { const migrations = await migration.migrate(); - res.send({ + return { migrations: migrations - }); -})); + }; +} -module.exports = router; \ No newline at end of file +module.exports = { + getMigrationInfo, + executeMigration +}; \ No newline at end of file diff --git a/src/routes/index.js b/src/routes/index.js index 479294652..7d19650dd 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,15 +1,11 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../services/auth'); const source_id = require('../services/source_id'); const sql = require('../services/sql'); const Repository = require('../services/repository'); const labels = require('../services/labels'); -const wrap = require('express-promise-wrap').wrap; -router.get('', auth.checkAuth, wrap(async (req, res, next) => { +async function index(req, res) { const repository = new Repository(req); res.render('index', { @@ -17,7 +13,7 @@ router.get('', auth.checkAuth, wrap(async (req, res, next) => { maxSyncIdAtLoad: await sql.getValue("SELECT MAX(id) FROM sync"), appCss: await getAppCss(repository) }); -})); +} async function getAppCss(repository) { let css = ''; @@ -33,4 +29,6 @@ ${note.content} return css; } -module.exports = router; +module.exports = { + index +}; diff --git a/src/routes/login.js b/src/routes/login.js index 84a724877..7c38b5623 100644 --- a/src/routes/login.js +++ b/src/routes/login.js @@ -1,17 +1,14 @@ "use strict"; -const express = require('express'); -const router = express.Router(); const utils = require('../services/utils'); const options = require('../services/options'); const my_scrypt = require('../services/my_scrypt'); -const wrap = require('express-promise-wrap').wrap; -router.get('', wrap(async (req, res, next) => { - res.render('login', { 'failedAuth': false }); -})); +function loginPage(req, res) { + res.render('login', { failedAuth: false }); +} -router.post('', wrap(async (req, res, next) => { +async function login(req, res) { const userName = await options.getOption('username'); const guessedPassword = req.body.password; @@ -33,15 +30,27 @@ router.post('', wrap(async (req, res, next) => { else { res.render('login', {'failedAuth': true}); } -})); +} - -async function verifyPassword(guessed_password) { +async function verifyPassword(guessedPassword) { const hashed_password = utils.fromBase64(await options.getOption('password_verification_hash')); - const guess_hashed = await my_scrypt.getVerificationHash(guessed_password); + const guess_hashed = await my_scrypt.getVerificationHash(guessedPassword); return guess_hashed.equals(hashed_password); } -module.exports = router; +function logout(req, res) { + req.session.regenerate(() => { + req.session.loggedIn = false; + + res.redirect('/'); + }); + +} + +module.exports = { + loginPage, + login, + logout +}; diff --git a/src/routes/logout.js b/src/routes/logout.js deleted file mode 100644 index 0c4b63bee..000000000 --- a/src/routes/logout.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -const express = require('express'); -const router = express.Router(); -const wrap = require('express-promise-wrap').wrap; - -router.post('', wrap(async (req, res, next) => { - req.session.regenerate(() => { - req.session.loggedIn = false; - - res.redirect('/'); - }); - -})); - -module.exports = router; diff --git a/src/routes/migration.js b/src/routes/migration.js index 38218bb67..51045e4c9 100644 --- a/src/routes/migration.js +++ b/src/routes/migration.js @@ -1,12 +1,9 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../services/auth'); -const wrap = require('express-promise-wrap').wrap; - -router.get('', auth.checkAuthForMigrationPage, wrap(async (req, res, next) => { +function migrationPage(req, res) { res.render('migration', {}); -})); +} -module.exports = router; +module.exports = { + migrationPage +}; diff --git a/src/routes/routes.js b/src/routes/routes.js index 602721963..1de2b1364 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -1,6 +1,5 @@ const indexRoute = require('./index'); const loginRoute = require('./login'); -const logoutRoute = require('./logout'); const migrationRoute = require('./migration'); const setupRoute = require('./setup'); const multer = require('multer')(); @@ -63,11 +62,6 @@ function apiRoute(method, path, routeHandler) { route(method, path, [auth.checkApiAuth], routeHandler, apiResultHandler); } -// API routes requiring HTTP protocol. This means we ignore route return value and make an electron auth exception -function httpApiRoute(method, path, routeHandler) { - route(method, path, [auth.checkApiAuth, multer.single('upload')], routeHandler); -} - function route(method, path, middleware, routeHandler, resultHandler) { router[method](path, ...middleware, async (req, res, next) => { try { @@ -95,11 +89,12 @@ const GET = 'get', POST = 'post', PUT = 'put', DELETE = 'delete'; const uploadMiddleware = multer.single('upload'); function register(app) { - app.use('/', indexRoute); - app.use('/login', loginRoute); - app.use('/logout', logoutRoute); - app.use('/migration', migrationRoute); - app.use('/setup', setupRoute); + route(GET, '/', [auth.checkAuth], indexRoute.index); + route(GET, '/login', [], loginRoute.loginPage); + route(POST, '/login', [], loginRoute.login); + route(POST, '/logout', [auth.checkAuth], loginRoute.logout); + route(GET, '/migration', [auth.checkAuthForMigrationPage], migrationRoute.migrationPage); + route(GET, '/setup', [auth.checkAppNotInitialized], setupRoute.setupPage); apiRoute(GET, '/api/tree', treeApiRoute.getTree); apiRoute(PUT, '/api/tree/:branchId/set-prefix', treeApiRoute.setPrefix); @@ -167,8 +162,8 @@ function register(app) { apiRoute(PUT, '/api/recent-notes/:branchId/:notePath', recentNotesRoute.addRecentNote); apiRoute(GET, '/api/app-info', appInfoRoute.getAppInfo); - httpApiRoute(GET, '/api/export/:noteId', exportRoute.exportNote); - httpApiRoute(POST, '/api/import/:parentNoteId', importRoute.importTar); + route(GET, '/api/export/:noteId', [auth.checkApiAuthOrElectron], exportRoute.exportNote); + route(POST, '/api/import/:parentNoteId', [auth.checkApiAuthOrElectron], importRoute.importTar, apiResultHandler); route(POST, '/api/setup', [auth.checkAppNotInitialized], setupApiRoute.setup, apiResultHandler); @@ -179,8 +174,8 @@ function register(app) { apiRoute(POST, '/api/cleanup/cleanup-unused-images', cleanupRoute.cleanupUnusedImages); apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase); - httpApiRoute(GET, '/api/images/:imageId/:filename', imageRoute.returnImage); - httpApiRoute(POST, '/api/images', imageRoute.uploadImage); + route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); + route(POST, '/api/images', [auth.checkApiAuthOrElectron], imageRoute.uploadImage, apiResultHandler); apiRoute(POST, '/api/script/exec', scriptRoute.exec); apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); @@ -199,11 +194,14 @@ function register(app) { apiRoute(GET, '/api/search/:searchString', searchRoute.searchNotes); apiRoute(POST, '/api/search/:searchString', searchRoute.saveSearchToNote); + route(GET, '/api/migration', [auth.checkApiAuthForMigrationPage], migrationApiRoute.getMigrationInfo, apiResultHandler); + route(POST, '/api/migration', [auth.checkApiAuthForMigrationPage], migrationApiRoute.executeMigration, apiResultHandler); + + route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler); + // this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username) + apiRoute(POST, '/api/login/protected', loginApiRoute.loginToProtectedSession); + app.use('', router); - - - app.use('/api/migration', migrationApiRoute); - app.use('/api/login', loginApiRoute); } module.exports = { diff --git a/src/routes/setup.js b/src/routes/setup.js index 6cdeb8672..79082b920 100644 --- a/src/routes/setup.js +++ b/src/routes/setup.js @@ -1,12 +1,9 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../services/auth'); -const wrap = require('express-promise-wrap').wrap; - -router.get('', auth.checkAppNotInitialized, wrap(async (req, res, next) => { +function setupPage(req, res) { res.render('setup', {}); -})); +} -module.exports = router; +module.exports = { + setupPage +};