converted file, script, search and sender routes

This commit is contained in:
azivner 2018-03-30 17:29:13 -04:00
parent aa57a64c61
commit cfe0ae1eda
6 changed files with 114 additions and 106 deletions

View file

@ -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
};

View file

@ -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
};

View file

@ -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
};

View file

@ -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
};

View file

@ -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);

View file

@ -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
};