mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 03:29:02 +01:00 
			
		
		
		
	converted export/import notes
This commit is contained in:
		
							parent
							
								
									88c07a9e48
								
							
						
					
					
						commit
						e36a81e189
					
				| @ -1,6 +1,7 @@ | |||||||
| import treeService from './tree.js'; | import treeService from './tree.js'; | ||||||
| import protectedSessionHolder from './protected_session_holder.js'; | import protectedSessionHolder from './protected_session_holder.js'; | ||||||
| import utils from './utils.js'; | import utils from './utils.js'; | ||||||
|  | import server from './server.js'; | ||||||
| 
 | 
 | ||||||
| function exportSubTree(noteId) { | function exportSubTree(noteId) { | ||||||
|     const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId=" |     const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId=" | ||||||
|  | |||||||
| @ -1,13 +1,11 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const app_info = require('../../services/app_info'); | const app_info = require('../../services/app_info'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.get('', auth.checkApiAuth, wrap(async (req, res, next) => { | async function getAppInfo() { | ||||||
|     res.send(app_info); |     return app_info; | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     getAppInfo | ||||||
|  | }; | ||||||
| @ -1,18 +1,12 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.get('', auth.checkApiAuth, wrap(async (req, res, next) => { | async function getEventLog() { | ||||||
|     await deleteOld(); |     await deleteOld(); | ||||||
| 
 | 
 | ||||||
|     const result = await sql.getRows("SELECT * FROM event_log ORDER BY dateAdded DESC"); |     return await sql.getRows("SELECT * FROM event_log ORDER BY dateAdded DESC"); | ||||||
| 
 | } | ||||||
|     res.send(result); |  | ||||||
| })); |  | ||||||
| 
 | 
 | ||||||
| async function deleteOld() { | async function deleteOld() { | ||||||
|     const cutoffId = await sql.getValue("SELECT id FROM event_log ORDER BY id DESC LIMIT 1000, 1"); |     const cutoffId = await sql.getValue("SELECT id FROM event_log ORDER BY id DESC LIMIT 1000, 1"); | ||||||
| @ -24,4 +18,6 @@ async function deleteOld() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     getEventLog | ||||||
|  | }; | ||||||
| @ -1,16 +1,12 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const html = require('html'); | const html = require('html'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| const tar = require('tar-stream'); | const tar = require('tar-stream'); | ||||||
| const sanitize = require("sanitize-filename"); | const sanitize = require("sanitize-filename"); | ||||||
| const Repository = require("../../services/repository"); | const Repository = require("../../services/repository"); | ||||||
| 
 | 
 | ||||||
| router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => { | async function exportNote(req, res) { | ||||||
|     const noteId = req.params.noteId; |     const noteId = req.params.noteId; | ||||||
|     const repo = new Repository(req); |     const repo = new Repository(req); | ||||||
| 
 | 
 | ||||||
| @ -18,7 +14,7 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next) | |||||||
| 
 | 
 | ||||||
|     const pack = tar.pack(); |     const pack = tar.pack(); | ||||||
| 
 | 
 | ||||||
|     const name = await exportNote(branchId, '', pack, repo); |     const name = await exportNoteInner(branchId, '', pack, repo); | ||||||
| 
 | 
 | ||||||
|     pack.finalize(); |     pack.finalize(); | ||||||
| 
 | 
 | ||||||
| @ -26,9 +22,9 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next) | |||||||
|     res.setHeader('Content-Type', 'application/tar'); |     res.setHeader('Content-Type', 'application/tar'); | ||||||
| 
 | 
 | ||||||
|     pack.pipe(res); |     pack.pipe(res); | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| async function exportNote(branchId, directory, pack, repo) { | async function exportNoteInner(branchId, directory, pack, repo) { | ||||||
|     const branch = await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]); |     const branch = await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]); | ||||||
|     const note = await repo.getEntity("SELECT notes.* FROM notes WHERE noteId = ?", [branch.noteId]); |     const note = await repo.getEntity("SELECT notes.* FROM notes WHERE noteId = ?", [branch.noteId]); | ||||||
| 
 | 
 | ||||||
| @ -55,7 +51,7 @@ async function exportNote(branchId, directory, pack, repo) { | |||||||
| 
 | 
 | ||||||
|     if (children.length > 0) { |     if (children.length > 0) { | ||||||
|         for (const child of children) { |         for (const child of children) { | ||||||
|             await exportNote(child.branchId, childFileName + "/", pack, repo); |             await exportNoteInner(child.branchId, childFileName + "/", pack, repo); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -77,4 +73,6 @@ async function getMetadata(note) { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     exportNote | ||||||
|  | }; | ||||||
| @ -90,7 +90,7 @@ async function parseImportFile(file) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| router.post('/:parentNoteId', auth.checkApiAuthOrElectron, multer.single('upload'), wrap(async (req, res, next) => { | async function importTar(req, res) { | ||||||
|     const sourceId = req.headers.source_id; |     const sourceId = req.headers.source_id; | ||||||
|     const parentNoteId = req.params.parentNoteId; |     const parentNoteId = req.params.parentNoteId; | ||||||
|     const file = req.file; |     const file = req.file; | ||||||
| @ -103,12 +103,10 @@ router.post('/:parentNoteId', auth.checkApiAuthOrElectron, multer.single('upload | |||||||
| 
 | 
 | ||||||
|     const files = await parseImportFile(file); |     const files = await parseImportFile(file); | ||||||
| 
 | 
 | ||||||
|     await sql.doInTransaction(async () => { |  | ||||||
|     await importNotes(files, parentNoteId, sourceId); |     await importNotes(files, parentNoteId, sourceId); | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|     res.send({}); |     res.send({}); | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| async function importNotes(files, parentNoteId, sourceId) { | async function importNotes(files, parentNoteId, sourceId) { | ||||||
|     for (const file of files) { |     for (const file of files) { | ||||||
| @ -136,4 +134,6 @@ async function importNotes(files, parentNoteId, sourceId) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     importTar | ||||||
|  | }; | ||||||
| @ -1,38 +1,9 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const utils = require('../../services/utils'); | const utils = require('../../services/utils'); | ||||||
| const sync_table = require('../../services/sync_table'); | const sync_table = require('../../services/sync_table'); | ||||||
| const options = require('../../services/options'); | const options = require('../../services/options'); | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 |  | ||||||
| router.get('', auth.checkApiAuth, wrap(async (req, res, next) => { |  | ||||||
|     res.send(await getRecentNotes()); |  | ||||||
| })); |  | ||||||
| 
 |  | ||||||
| router.put('/:branchId/:notePath', auth.checkApiAuth, wrap(async (req, res, next) => { |  | ||||||
|     const branchId = req.params.branchId; |  | ||||||
|     const notePath = req.params.notePath; |  | ||||||
|     const sourceId = req.headers.source_id; |  | ||||||
| 
 |  | ||||||
|     await sql.doInTransaction(async () => { |  | ||||||
|         await sql.replace('recent_notes', { |  | ||||||
|             branchId: branchId, |  | ||||||
|             notePath: notePath, |  | ||||||
|             dateAccessed: utils.nowDate(), |  | ||||||
|             isDeleted: 0 |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         await sync_table.addRecentNoteSync(branchId, sourceId); |  | ||||||
| 
 |  | ||||||
|         await options.setOption('start_note_path', notePath, sourceId); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     res.send(await getRecentNotes()); |  | ||||||
| })); |  | ||||||
| 
 | 
 | ||||||
| async function getRecentNotes() { | async function getRecentNotes() { | ||||||
|     return await sql.getRows(` |     return await sql.getRows(` | ||||||
| @ -49,4 +20,27 @@ async function getRecentNotes() { | |||||||
|       LIMIT 200`);
 |       LIMIT 200`);
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | 
 | ||||||
|  | async function addRecentNote(req) { | ||||||
|  |     const branchId = req.params.branchId; | ||||||
|  |     const notePath = req.params.notePath; | ||||||
|  |     const sourceId = req.headers.source_id; | ||||||
|  | 
 | ||||||
|  |     await sql.replace('recent_notes', { | ||||||
|  |         branchId: branchId, | ||||||
|  |         notePath: notePath, | ||||||
|  |         dateAccessed: utils.nowDate(), | ||||||
|  |         isDeleted: 0 | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     await sync_table.addRecentNoteSync(branchId, sourceId); | ||||||
|  | 
 | ||||||
|  |     await options.setOption('start_note_path', notePath, sourceId); | ||||||
|  | 
 | ||||||
|  |     return await getRecentNotes(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | module.exports = { | ||||||
|  |     getRecentNotes, | ||||||
|  |     addRecentNote | ||||||
|  | }; | ||||||
| @ -3,6 +3,7 @@ const loginRoute = require('./login'); | |||||||
| const logoutRoute = require('./logout'); | const logoutRoute = require('./logout'); | ||||||
| const migrationRoute = require('./migration'); | const migrationRoute = require('./migration'); | ||||||
| const setupRoute = require('./setup'); | const setupRoute = require('./setup'); | ||||||
|  | const multer = require('multer')(); | ||||||
| 
 | 
 | ||||||
| // API routes
 | // API routes
 | ||||||
| const treeApiRoute = require('./api/tree'); | const treeApiRoute = require('./api/tree'); | ||||||
| @ -39,17 +40,13 @@ const auth = require('../services/auth'); | |||||||
| const cls = require('../services/cls'); | const cls = require('../services/cls'); | ||||||
| const sql = require('../services/sql'); | const sql = require('../services/sql'); | ||||||
| 
 | 
 | ||||||
| function apiRoute(method, path, handler) { | function apiRoute(method, path, routeHandler) { | ||||||
|     router[method](path, auth.checkApiAuth, async (req, res, next) => { |     route({ | ||||||
|         try { |         method, | ||||||
|             const result = await cls.init(async () => { |         path, | ||||||
|                 cls.namespace.set('sourceId', req.headers.source_id); |         middleware: [auth.checkApiAuth], | ||||||
| 
 |         routeHandler, | ||||||
|                 return await sql.doInTransaction(async () => { |         resultHandler: (res, result) => { | ||||||
|                     return await handler(req, res, next); |  | ||||||
|                 }); |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             // if it's an array and first element is integer then we consider this to be [statusCode, response] format
 |             // if it's an array and first element is integer then we consider this to be [statusCode, response] format
 | ||||||
|             if (Array.isArray(result) && result.length > 0 && Number.isInteger(result[0])) { |             if (Array.isArray(result) && result.length > 0 && Number.isInteger(result[0])) { | ||||||
|                 const [statusCode, response] = result; |                 const [statusCode, response] = result; | ||||||
| @ -67,12 +64,38 @@ function apiRoute(method, path, handler) { | |||||||
|                 res.status(200).send(result); |                 res.status(200).send(result); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 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, | ||||||
|  |         middleware: [auth.checkApiAuth, multer.single('upload')], | ||||||
|  |         routeHandler | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function route({ method, path, middleware, routeHandler, resultHandler }) { | ||||||
|  |     router[method](path, ...middleware, async (req, res, next) => { | ||||||
|  |         try { | ||||||
|  |             const result = await cls.init(async () => { | ||||||
|  |                 cls.namespace.set('sourceId', req.headers.source_id); | ||||||
|  | 
 | ||||||
|  |                 return await sql.doInTransaction(async () => { | ||||||
|  |                     return await routeHandler(req, res, next); | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             if (resultHandler) { | ||||||
|  |                 resultHandler(res, result); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         catch (e) { |         catch (e) { | ||||||
|             log.info(`${method} ${path} threw exception: ` + e.stack); |             log.info(`${method} ${path} threw exception: ` + e.stack); | ||||||
| 
 | 
 | ||||||
|             res.send(500); |             res.sendStatus(500); | ||||||
| 
 |  | ||||||
|             next(e); |  | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @ -146,12 +169,16 @@ function register(app) { | |||||||
|     apiRoute(PUT, '/api/sync/labels', syncApiRoute.updateLabel); |     apiRoute(PUT, '/api/sync/labels', syncApiRoute.updateLabel); | ||||||
|     apiRoute(PUT, '/api/sync/api_tokens', syncApiRoute.updateApiToken); |     apiRoute(PUT, '/api/sync/api_tokens', syncApiRoute.updateApiToken); | ||||||
| 
 | 
 | ||||||
|     app.use('/api/login', loginApiRoute); |     apiRoute(GET, '/api/event-log', eventLogRoute.getEventLog); | ||||||
|     app.use('/api/event-log', eventLogRoute); | 
 | ||||||
|     app.use('/api/recent-notes', recentNotesRoute); |     apiRoute(GET, '/api/recent-notes', recentNotesRoute.getRecentNotes); | ||||||
|     app.use('/api/app-info', appInfoRoute); |     apiRoute(PUT, '/api/recent-notes/:branchId/:notePath', recentNotesRoute.addRecentNote); | ||||||
|     app.use('/api/export', exportRoute); |     apiRoute(GET, '/api/app-info', appInfoRoute.getAppInfo); | ||||||
|     app.use('/api/import', importRoute); | 
 | ||||||
|  |     httpApiRoute(GET, '/api/export/:noteId', exportRoute.exportNote); | ||||||
|  | 
 | ||||||
|  |     httpApiRoute(POST, '/api/import/:parentNoteId', importRoute.importTar); | ||||||
|  | 
 | ||||||
|     app.use('/api/setup', setupApiRoute); |     app.use('/api/setup', setupApiRoute); | ||||||
|     app.use('/api/sql', sqlRoute); |     app.use('/api/sql', sqlRoute); | ||||||
|     app.use('/api/anonymization', anonymizationRoute); |     app.use('/api/anonymization', anonymizationRoute); | ||||||
| @ -166,6 +193,7 @@ function register(app) { | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     app.use('/api/migration', migrationApiRoute); |     app.use('/api/migration', migrationApiRoute); | ||||||
|  |     app.use('/api/login', loginApiRoute); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports = { | module.exports = { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 azivner
						azivner