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