mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	converted export/import notes
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
import treeService from './tree.js';
 | 
			
		||||
import protectedSessionHolder from './protected_session_holder.js';
 | 
			
		||||
import utils from './utils.js';
 | 
			
		||||
import server from './server.js';
 | 
			
		||||
 | 
			
		||||
function exportSubTree(noteId) {
 | 
			
		||||
    const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId="
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,11 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
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) => {
 | 
			
		||||
    res.send(app_info);
 | 
			
		||||
}));
 | 
			
		||||
async function getAppInfo() {
 | 
			
		||||
    return app_info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = router;
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getAppInfo
 | 
			
		||||
};
 | 
			
		||||
@@ -1,18 +1,12 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
    const result = await sql.getRows("SELECT * FROM event_log ORDER BY dateAdded DESC");
 | 
			
		||||
 | 
			
		||||
    res.send(result);
 | 
			
		||||
}));
 | 
			
		||||
    return await sql.getRows("SELECT * FROM event_log ORDER BY dateAdded DESC");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function deleteOld() {
 | 
			
		||||
    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";
 | 
			
		||||
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
const sql = require('../../services/sql');
 | 
			
		||||
const html = require('html');
 | 
			
		||||
const auth = require('../../services/auth');
 | 
			
		||||
const wrap = require('express-promise-wrap').wrap;
 | 
			
		||||
const tar = require('tar-stream');
 | 
			
		||||
const sanitize = require("sanitize-filename");
 | 
			
		||||
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 repo = new Repository(req);
 | 
			
		||||
 | 
			
		||||
@@ -18,7 +14,7 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next)
 | 
			
		||||
 | 
			
		||||
    const pack = tar.pack();
 | 
			
		||||
 | 
			
		||||
    const name = await exportNote(branchId, '', pack, repo);
 | 
			
		||||
    const name = await exportNoteInner(branchId, '', pack, repo);
 | 
			
		||||
 | 
			
		||||
    pack.finalize();
 | 
			
		||||
 | 
			
		||||
@@ -26,9 +22,9 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next)
 | 
			
		||||
    res.setHeader('Content-Type', 'application/tar');
 | 
			
		||||
 | 
			
		||||
    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 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) {
 | 
			
		||||
        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 parentNoteId = req.params.parentNoteId;
 | 
			
		||||
    const file = req.file;
 | 
			
		||||
@@ -103,12 +103,10 @@ router.post('/:parentNoteId', auth.checkApiAuthOrElectron, multer.single('upload
 | 
			
		||||
 | 
			
		||||
    const files = await parseImportFile(file);
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await importNotes(files, parentNoteId, sourceId);
 | 
			
		||||
    });
 | 
			
		||||
    await importNotes(files, parentNoteId, sourceId);
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function importNotes(files, parentNoteId, sourceId) {
 | 
			
		||||
    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";
 | 
			
		||||
 | 
			
		||||
const express = require('express');
 | 
			
		||||
const router = express.Router();
 | 
			
		||||
const sql = require('../../services/sql');
 | 
			
		||||
const auth = require('../../services/auth');
 | 
			
		||||
const utils = require('../../services/utils');
 | 
			
		||||
const sync_table = require('../../services/sync_table');
 | 
			
		||||
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() {
 | 
			
		||||
    return await sql.getRows(`
 | 
			
		||||
@@ -49,4 +20,27 @@ async function getRecentNotes() {
 | 
			
		||||
      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 migrationRoute = require('./migration');
 | 
			
		||||
const setupRoute = require('./setup');
 | 
			
		||||
const multer = require('multer')();
 | 
			
		||||
 | 
			
		||||
// API routes
 | 
			
		||||
const treeApiRoute = require('./api/tree');
 | 
			
		||||
@@ -39,17 +40,13 @@ const auth = require('../services/auth');
 | 
			
		||||
const cls = require('../services/cls');
 | 
			
		||||
const sql = require('../services/sql');
 | 
			
		||||
 | 
			
		||||
function apiRoute(method, path, handler) {
 | 
			
		||||
    router[method](path, auth.checkApiAuth, 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 handler(req, res, next);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
function apiRoute(method, path, routeHandler) {
 | 
			
		||||
    route({
 | 
			
		||||
        method,
 | 
			
		||||
        path,
 | 
			
		||||
        middleware: [auth.checkApiAuth],
 | 
			
		||||
        routeHandler,
 | 
			
		||||
        resultHandler: (res, result) => {
 | 
			
		||||
            // 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])) {
 | 
			
		||||
                const [statusCode, response] = result;
 | 
			
		||||
@@ -67,12 +64,38 @@ function apiRoute(method, path, handler) {
 | 
			
		||||
                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) {
 | 
			
		||||
            log.info(`${method} ${path} threw exception: ` + e.stack);
 | 
			
		||||
 | 
			
		||||
            res.send(500);
 | 
			
		||||
 | 
			
		||||
            next(e);
 | 
			
		||||
            res.sendStatus(500);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
@@ -146,12 +169,16 @@ function register(app) {
 | 
			
		||||
    apiRoute(PUT, '/api/sync/labels', syncApiRoute.updateLabel);
 | 
			
		||||
    apiRoute(PUT, '/api/sync/api_tokens', syncApiRoute.updateApiToken);
 | 
			
		||||
 | 
			
		||||
    app.use('/api/login', loginApiRoute);
 | 
			
		||||
    app.use('/api/event-log', eventLogRoute);
 | 
			
		||||
    app.use('/api/recent-notes', recentNotesRoute);
 | 
			
		||||
    app.use('/api/app-info', appInfoRoute);
 | 
			
		||||
    app.use('/api/export', exportRoute);
 | 
			
		||||
    app.use('/api/import', importRoute);
 | 
			
		||||
    apiRoute(GET, '/api/event-log', eventLogRoute.getEventLog);
 | 
			
		||||
 | 
			
		||||
    apiRoute(GET, '/api/recent-notes', recentNotesRoute.getRecentNotes);
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    app.use('/api/setup', setupApiRoute);
 | 
			
		||||
    app.use('/api/sql', sqlRoute);
 | 
			
		||||
    app.use('/api/anonymization', anonymizationRoute);
 | 
			
		||||
@@ -166,6 +193,7 @@ function register(app) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    app.use('/api/migration', migrationApiRoute);
 | 
			
		||||
    app.use('/api/login', loginApiRoute);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user