mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 18:05:55 +01:00 
			
		
		
		
	converted file, script, search and sender routes
This commit is contained in:
		| @@ -1,16 +1,11 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const express = require('express'); | ||||
| const router = express.Router(); | ||||
| const sql = require('../../services/sql'); | ||||
| const auth = require('../../services/auth'); | ||||
| const notes = require('../../services/notes'); | ||||
| const labels = require('../../services/labels'); | ||||
| const protected_session = require('../../services/protected_session'); | ||||
| const multer = require('multer')(); | ||||
| const wrap = require('express-promise-wrap').wrap; | ||||
|  | ||||
| router.post('/upload/:parentNoteId', auth.checkApiAuthOrElectron, multer.single('upload'), wrap(async (req, res, next) => { | ||||
| async function uploadFile(req) { | ||||
|     const sourceId = req.headers.source_id; | ||||
|     const parentNoteId = req.params.parentNoteId; | ||||
|     const file = req.file; | ||||
| @@ -20,29 +15,27 @@ router.post('/upload/:parentNoteId', auth.checkApiAuthOrElectron, multer.single( | ||||
|     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.`]; | ||||
|     } | ||||
|  | ||||
|     await sql.doInTransaction(async () => { | ||||
|         const noteId = (await notes.createNewNote(parentNoteId, { | ||||
|     const {noteId} = await notes.createNewNote(parentNoteId, { | ||||
|         title: originalName, | ||||
|         content: file.buffer, | ||||
|         target: 'into', | ||||
|         isProtected: false, | ||||
|         type: 'file', | ||||
|         mime: file.mimetype | ||||
|         }, req, sourceId)).noteId; | ||||
|     }, req, sourceId); | ||||
|  | ||||
|     await labels.createLabel(noteId, "original_file_name", originalName, sourceId); | ||||
|     await labels.createLabel(noteId, "file_size", size, sourceId); | ||||
|  | ||||
|         res.send({ | ||||
|     return { | ||||
|         noteId: noteId | ||||
|         }); | ||||
|     }); | ||||
| })); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| router.get('/download/:noteId', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => { | ||||
| async function downloadFile(req, res) { | ||||
|     const noteId = req.params.noteId; | ||||
|     const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||
|     const protectedSessionId = req.query.protectedSessionId; | ||||
| @@ -69,6 +62,9 @@ router.get('/download/:noteId', auth.checkApiAuthOrElectron, wrap(async (req, re | ||||
|     res.setHeader('Content-Type', note.mime); | ||||
|  | ||||
|     res.send(note.content); | ||||
| })); | ||||
| } | ||||
|  | ||||
| module.exports = router; | ||||
| module.exports = { | ||||
|     uploadFile, | ||||
|     downloadFile | ||||
| }; | ||||
| @@ -1,55 +1,56 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const express = require('express'); | ||||
| const router = express.Router(); | ||||
| const auth = require('../../services/auth'); | ||||
| const wrap = require('express-promise-wrap').wrap; | ||||
| const labels = require('../../services/labels'); | ||||
| const script = require('../../services/script'); | ||||
| const Repository = require('../../services/repository'); | ||||
|  | ||||
| router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function exec(req) { | ||||
|     const ret = await script.executeScript(req, req.body.script, req.body.params, req.body.startNoteId, req.body.currentNoteId); | ||||
|  | ||||
|     res.send({ | ||||
|     return { | ||||
|         executionResult: ret | ||||
|     }); | ||||
| })); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| router.post('/run/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function run(req) { | ||||
|     const repository = new Repository(req); | ||||
|     const note = await repository.getNote(req.params.noteId); | ||||
|  | ||||
|     const ret = await script.executeNote(req, note); | ||||
|  | ||||
|     res.send({ | ||||
|     return { | ||||
|         executionResult: ret | ||||
|     }); | ||||
| })); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| router.get('/startup', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function getStartupBundles(req) { | ||||
|     const repository = new Repository(req); | ||||
|     const notes = await labels.getNotesWithLabel(repository, "run", "frontend_startup"); | ||||
|  | ||||
|     const scripts = []; | ||||
|     const bundles = []; | ||||
|  | ||||
|     for (const note of notes) { | ||||
|         const bundle = await script.getScriptBundle(note); | ||||
|  | ||||
|         if (bundle) { | ||||
|             scripts.push(bundle); | ||||
|             bundles.push(bundle); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     res.send(scripts); | ||||
| })); | ||||
|     return bundles; | ||||
| } | ||||
|  | ||||
| router.get('/bundle/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function getBundle(req) { | ||||
|     const repository = new Repository(req); | ||||
|     const note = await repository.getNote(req.params.noteId); | ||||
|     const bundle = await script.getScriptBundle(note); | ||||
|  | ||||
|     res.send(bundle); | ||||
| })); | ||||
|     return bundle; | ||||
| } | ||||
|  | ||||
| module.exports = router; | ||||
| module.exports = { | ||||
|     exec, | ||||
|     run, | ||||
|     getStartupBundles, | ||||
|     getBundle | ||||
| }; | ||||
| @@ -1,25 +1,21 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const express = require('express'); | ||||
| const router = express.Router(); | ||||
| const auth = require('../../services/auth'); | ||||
| const sql = require('../../services/sql'); | ||||
| const notes = require('../../services/notes'); | ||||
| const wrap = require('express-promise-wrap').wrap; | ||||
| const parseFilters = require('../../services/parse_filters'); | ||||
| const buildSearchQuery = require('../../services/build_search_query'); | ||||
|  | ||||
| router.get('/:searchString', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function searchNotes(req) { | ||||
|     const {attrFilters, searchText} = parseFilters(req.params.searchString); | ||||
|  | ||||
|     const {query, params} = buildSearchQuery(attrFilters, searchText); | ||||
|  | ||||
|     const noteIds = await sql.getColumn(query, params); | ||||
|  | ||||
|     res.send(noteIds); | ||||
| })); | ||||
|     return noteIds; | ||||
| } | ||||
|  | ||||
| router.post('/:searchString', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| async function saveSearchToNote(req) { | ||||
|     const noteContent = { | ||||
|         searchString: req.params.searchString | ||||
|     }; | ||||
| @@ -30,7 +26,10 @@ router.post('/:searchString', auth.checkApiAuth, wrap(async (req, res, next) => | ||||
|         mime: "application/json" | ||||
|     }); | ||||
|  | ||||
|     res.send({ noteId }); | ||||
| })); | ||||
|     return { noteId }; | ||||
| } | ||||
|  | ||||
| module.exports = router; | ||||
| module.exports = { | ||||
|     searchNotes, | ||||
|     saveSearchToNote | ||||
| }; | ||||
| @@ -13,7 +13,7 @@ const password_encryption = require('../../services/password_encryption'); | ||||
| const options = require('../../services/options'); | ||||
| const sync_table = require('../../services/sync_table'); | ||||
|  | ||||
| router.post('/login', wrap(async (req, res, next) => { | ||||
| async function login(req) { | ||||
|     const username = req.body.username; | ||||
|     const password = req.body.password; | ||||
|  | ||||
| @@ -21,12 +21,11 @@ router.post('/login', wrap(async (req, res, next) => { | ||||
|     const isPasswordValid = await password_encryption.verifyPassword(password); | ||||
|  | ||||
|     if (!isUsernameValid || !isPasswordValid) { | ||||
|         res.status(401).send("Incorrect username/password"); | ||||
|         return [401, "Incorrect username/password"]; | ||||
|     } | ||||
|     else { | ||||
|  | ||||
|     const token = utils.randomSecureToken(); | ||||
|  | ||||
|         await sql.doInTransaction(async () => { | ||||
|     const apiTokenId = utils.newApiTokenId(); | ||||
|  | ||||
|     await sql.insert("api_tokens", { | ||||
| @@ -37,45 +36,29 @@ router.post('/login', wrap(async (req, res, next) => { | ||||
|     }); | ||||
|  | ||||
|     await sync_table.addApiTokenSync(apiTokenId); | ||||
|         }); | ||||
|  | ||||
|         res.send({ | ||||
|     return { | ||||
|         token: token | ||||
|         }); | ||||
|     } | ||||
| })); | ||||
|  | ||||
| async function checkSenderToken(req, res, next) { | ||||
|     const token = req.headers.authorization; | ||||
|  | ||||
|     if (await sql.getValue("SELECT COUNT(*) FROM api_tokens WHERE isDeleted = 0 AND token = ?", [token]) === 0) { | ||||
|         res.status(401).send("Not authorized"); | ||||
|     } | ||||
|     else if (await sql.isDbUpToDate()) { | ||||
|         next(); | ||||
|     } | ||||
|     else { | ||||
|         res.status(409).send("Mismatched app versions"); // need better response than that | ||||
|     } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| router.post('/image', checkSenderToken, multer.single('upload'), wrap(async (req, res, next) => { | ||||
| async function uploadImage(req) { | ||||
|     const file = req.file; | ||||
|  | ||||
|     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 parentNoteId = await date_notes.getDateNoteId(req.headers['x-local-date']); | ||||
|  | ||||
|     const noteId = (await notes.createNewNote(parentNoteId, { | ||||
|     const {noteId} = await notes.createNewNote(parentNoteId, { | ||||
|         title: "Sender image", | ||||
|         content: "", | ||||
|         target: 'into', | ||||
|         isProtected: false, | ||||
|         type: 'text', | ||||
|         mime: 'text/html' | ||||
|     })).noteId; | ||||
|     }); | ||||
|  | ||||
|     const {fileName, imageId} = await image.saveImage(file, null, noteId); | ||||
|  | ||||
| @@ -84,11 +67,9 @@ router.post('/image', checkSenderToken, multer.single('upload'), wrap(async (req | ||||
|     const content = `<img src="${url}"/>`; | ||||
|  | ||||
|     await sql.execute("UPDATE notes SET content = ? WHERE noteId = ?", [content, noteId]); | ||||
| } | ||||
|  | ||||
|     res.send({}); | ||||
| })); | ||||
|  | ||||
| router.post('/note', checkSenderToken, wrap(async (req, res, next) => { | ||||
| async function saveNote(req) { | ||||
|     const parentNoteId = await date_notes.getDateNoteId(req.headers['x-local-date']); | ||||
|  | ||||
|     await notes.createNewNote(parentNoteId, { | ||||
| @@ -99,8 +80,10 @@ router.post('/note', checkSenderToken, wrap(async (req, res, next) => { | ||||
|         type: 'text', | ||||
|         mime: 'text/html' | ||||
|     }); | ||||
| } | ||||
|  | ||||
|     res.send({}); | ||||
| })); | ||||
|  | ||||
| module.exports = router; | ||||
| module.exports = { | ||||
|     login, | ||||
|     uploadImage, | ||||
|     saveNote | ||||
| }; | ||||
| @@ -92,6 +92,7 @@ function route(method, path, middleware, routeHandler, resultHandler) { | ||||
| } | ||||
|  | ||||
| const GET = 'get', POST = 'post', PUT = 'put', DELETE = 'delete'; | ||||
| const uploadMiddleware = multer.single('upload'); | ||||
|  | ||||
| function register(app) { | ||||
|     app.use('/', indexRoute); | ||||
| @@ -180,10 +181,23 @@ function register(app) { | ||||
|  | ||||
|     httpApiRoute(GET, '/api/images/:imageId/:filename', imageRoute.returnImage); | ||||
|     httpApiRoute(POST, '/api/images', imageRoute.uploadImage); | ||||
|     app.use('/api/script', scriptRoute); | ||||
|     app.use('/api/sender', senderRoute); | ||||
|     app.use('/api/files', filesRoute); | ||||
|     app.use('/api/search', searchRoute); | ||||
|  | ||||
|     apiRoute(POST, '/api/script/exec', scriptRoute.exec); | ||||
|     apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); | ||||
|     apiRoute(GET, '/api/script/startup', scriptRoute.getStartupBundles); | ||||
|     apiRoute(GET, '/api/script/bundle/:noteId', scriptRoute.getBundle); | ||||
|  | ||||
|     route(POST, '/api/sender/login', [], senderRoute.login, apiResultHandler); | ||||
|     route(POST, '/api/sender/image', [auth.checkSenderToken], senderRoute.uploadImage, apiResultHandler); | ||||
|     route(POST, '/api/sender/note', [auth.checkSenderToken], senderRoute.saveNote, apiResultHandler); | ||||
|  | ||||
|     route(POST, '/api/files/upload/:parentNoteId', [auth.checkApiAuthOrElectron, uploadMiddleware], | ||||
|         filesRoute.uploadFile, apiResultHandler); | ||||
|  | ||||
|     route(GET, '/api/files/download/:noteId', [auth.checkApiAuthOrElectron], filesRoute.downloadFile); | ||||
|  | ||||
|     apiRoute(GET, '/api/search/:searchString', searchRoute.searchNotes); | ||||
|     apiRoute(POST, '/api/search/:searchString', searchRoute.saveSearchToNote); | ||||
|  | ||||
|     app.use('', router); | ||||
|  | ||||
|   | ||||
| @@ -72,11 +72,26 @@ async function checkAppNotInitialized(req, res, next) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function checkSenderToken(req, res, next) { | ||||
|     const token = req.headers.authorization; | ||||
|  | ||||
|     if (await sql.getValue("SELECT COUNT(*) FROM api_tokens WHERE isDeleted = 0 AND token = ?", [token]) === 0) { | ||||
|         res.status(401).send("Not authorized"); | ||||
|     } | ||||
|     else if (await sql.isDbUpToDate()) { | ||||
|         next(); | ||||
|     } | ||||
|     else { | ||||
|         res.status(409).send("Mismatched app versions"); // need better response than that | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     checkAuth, | ||||
|     checkAuthForMigrationPage, | ||||
|     checkApiAuth, | ||||
|     checkApiAuthForMigrationPage, | ||||
|     checkAppNotInitialized, | ||||
|     checkApiAuthOrElectron | ||||
|     checkApiAuthOrElectron, | ||||
|     checkSenderToken | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user