mirror of
https://github.com/zadam/trilium.git
synced 2025-02-24 23:13:43 +08:00
converted file, script, search and sender routes
This commit is contained in:
parent
aa57a64c61
commit
cfe0ae1eda
6 changed files with 114 additions and 106 deletions
|
@ -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, {
|
||||
title: originalName,
|
||||
content: file.buffer,
|
||||
target: 'into',
|
||||
isProtected: false,
|
||||
type: 'file',
|
||||
mime: file.mimetype
|
||||
}, req, sourceId)).noteId;
|
||||
const {noteId} = await notes.createNewNote(parentNoteId, {
|
||||
title: originalName,
|
||||
content: file.buffer,
|
||||
target: 'into',
|
||||
isProtected: false,
|
||||
type: 'file',
|
||||
mime: file.mimetype
|
||||
}, req, sourceId);
|
||||
|
||||
await labels.createLabel(noteId, "original_file_name", originalName, sourceId);
|
||||
await labels.createLabel(noteId, "file_size", size, sourceId);
|
||||
await labels.createLabel(noteId, "original_file_name", originalName, sourceId);
|
||||
await labels.createLabel(noteId, "file_size", size, sourceId);
|
||||
|
||||
res.send({
|
||||
noteId: noteId
|
||||
});
|
||||
});
|
||||
}));
|
||||
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,61 +21,44 @@ 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();
|
||||
const token = utils.randomSecureToken();
|
||||
|
||||
await sql.insert("api_tokens", {
|
||||
apiTokenId: apiTokenId,
|
||||
token: token,
|
||||
dateCreated: utils.nowDate(),
|
||||
isDeleted: false
|
||||
});
|
||||
const apiTokenId = utils.newApiTokenId();
|
||||
|
||||
await sync_table.addApiTokenSync(apiTokenId);
|
||||
});
|
||||
await sql.insert("api_tokens", {
|
||||
apiTokenId: apiTokenId,
|
||||
token: token,
|
||||
dateCreated: utils.nowDate(),
|
||||
isDeleted: false
|
||||
});
|
||||
|
||||
res.send({
|
||||
token: token
|
||||
});
|
||||
}
|
||||
}));
|
||||
await sync_table.addApiTokenSync(apiTokenId);
|
||||
|
||||
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
|
||||
}
|
||||
return {
|
||||
token: token
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
};
|
Loading…
Reference in a new issue