diff --git a/src/routes/api/sync.js b/src/routes/api/sync.js index c6da183c3..6441fa603 100644 --- a/src/routes/api/sync.js +++ b/src/routes/api/sync.js @@ -1,8 +1,5 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../../services/auth'); const sync = require('../../services/sync'); const syncUpdate = require('../../services/sync_update'); const sync_table = require('../../services/sync_table'); @@ -10,124 +7,111 @@ const sql = require('../../services/sql'); const options = require('../../services/options'); const content_hash = require('../../services/content_hash'); const log = require('../../services/log'); -const wrap = require('express-promise-wrap').wrap; -router.get('/check', auth.checkApiAuth, wrap(async (req, res, next) => { - res.send({ +async function checkSync() { + return { 'hashes': await content_hash.getHashes(), 'max_sync_id': await sql.getValue('SELECT MAX(id) FROM sync') - }); -})); + }; +} -router.post('/now', auth.checkApiAuth, wrap(async (req, res, next) => { - res.send(await sync.sync()); -})); +async function syncNow() { + return await sync.sync(); +} -router.post('/fill-sync-rows', auth.checkApiAuth, wrap(async (req, res, next) => { - await sql.doInTransaction(async () => { - await sync_table.fillAllSyncRows(); - }); +async function fillSyncRows() { + await sync_table.fillAllSyncRows(); log.info("Sync rows have been filled."); +} - res.send({}); -})); - -router.post('/force-full-sync', auth.checkApiAuth, wrap(async (req, res, next) => { - await sql.doInTransaction(async () => { - await options.setOption('last_synced_pull', 0); - await options.setOption('last_synced_push', 0); - }); +async function forceFullSync() { + await options.setOption('last_synced_pull', 0); + await options.setOption('last_synced_push', 0); log.info("Forcing full sync."); // not awaiting for the job to finish (will probably take a long time) sync.sync(); +} - res.send({}); -})); - -router.post('/force-note-sync/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function forceNoteSync(req) { const noteId = req.params.noteId; - await sql.doInTransaction(async () => { - await sync_table.addNoteSync(noteId); + await sync_table.addNoteSync(noteId); - for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE isDeleted = 0 AND noteId = ?", [noteId])) { - await sync_table.addBranchSync(branchId); - await sync_table.addRecentNoteSync(branchId); - } + for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE isDeleted = 0 AND noteId = ?", [noteId])) { + await sync_table.addBranchSync(branchId); + await sync_table.addRecentNoteSync(branchId); + } - for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) { - await sync_table.addNoteRevisionsSync(noteRevisionId); - } - }); + for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) { + await sync_table.addNoteRevisionsSync(noteRevisionId); + } log.info("Forcing note sync for " + noteId); // not awaiting for the job to finish (will probably take a long time) sync.sync(); +} - res.send({}); -})); - -router.get('/changed', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getChanged() { const lastSyncId = parseInt(req.query.lastSyncId); - res.send(await sql.getRows("SELECT * FROM sync WHERE id > ?", [lastSyncId])); -})); + return await sql.getRows("SELECT * FROM sync WHERE id > ?", [lastSyncId]); +} -router.get('/notes/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getNote(req) { const noteId = req.params.noteId; const entity = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); sync.serializeNoteContentBuffer(entity); - res.send({ + return { entity: entity - }); -})); + }; +} -router.get('/branches/:branchId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getBranch(req) { const branchId = req.params.branchId; - res.send(await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId])); -})); + return await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]); +} -router.get('/note_revisions/:noteRevisionId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getNoteRevision(req) { const noteRevisionId = req.params.noteRevisionId; - res.send(await sql.getRow("SELECT * FROM note_revisions WHERE noteRevisionId = ?", [noteRevisionId])); -})); + return await sql.getRow("SELECT * FROM note_revisions WHERE noteRevisionId = ?", [noteRevisionId]); +} -router.get('/options/:name', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getOption(req) { const name = req.params.name; const opt = await sql.getRow("SELECT * FROM options WHERE name = ?", [name]); if (!opt.isSynced) { - res.send("This option can't be synced."); + return [400, "This option can't be synced."]; } else { - res.send(opt); + return opt; } -})); +} -router.get('/note_reordering/:parentNoteId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getNoteReordering(req) { const parentNoteId = req.params.parentNoteId; - res.send({ + return { parentNoteId: parentNoteId, ordering: await sql.getMap("SELECT branchId, notePosition FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [parentNoteId]) - }); -})); + }; +} -router.get('/recent_notes/:branchId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getRecentNote(req) { const branchId = req.params.branchId; - res.send(await sql.getRow("SELECT * FROM recent_notes WHERE branchId = ?", [branchId])); -})); + return await sql.getRow("SELECT * FROM recent_notes WHERE branchId = ?", [branchId]); +} -router.get('/images/:imageId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getImage(req) { const imageId = req.params.imageId; const entity = await sql.getRow("SELECT * FROM images WHERE imageId = ?", [imageId]); @@ -135,85 +119,92 @@ router.get('/images/:imageId', auth.checkApiAuth, wrap(async (req, res, next) => entity.data = entity.data.toString('base64'); } - res.send(entity); -})); + return entity; +} -router.get('/note_images/:noteImageId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getNoteImage(req) { const noteImageId = req.params.noteImageId; - res.send(await sql.getRow("SELECT * FROM note_images WHERE noteImageId = ?", [noteImageId])); -})); + return await sql.getRow("SELECT * FROM note_images WHERE noteImageId = ?", [noteImageId]); +} -router.get('/labels/:labelId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getLabel(req) { const labelId = req.params.labelId; - res.send(await sql.getRow("SELECT * FROM labels WHERE labelId = ?", [labelId])); -})); + return await sql.getRow("SELECT * FROM labels WHERE labelId = ?", [labelId]); +} -router.get('/api_tokens/:apiTokenId', auth.checkApiAuth, wrap(async (req, res, next) => { +async function getApiToken(req) { const apiTokenId = req.params.apiTokenId; - res.send(await sql.getRow("SELECT * FROM api_tokens WHERE apiTokenId = ?", [apiTokenId])); -})); + return await sql.getRow("SELECT * FROM api_tokens WHERE apiTokenId = ?", [apiTokenId]); +} -router.put('/notes', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateNote(req) { await syncUpdate.updateNote(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/branches', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateBranch(req) { await syncUpdate.updateBranch(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/note_revisions', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateNoteRevision(req) { await syncUpdate.updateNoteRevision(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/note_reordering', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateNoteReordering(req) { await syncUpdate.updateNoteReordering(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/options', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateOption(req) { await syncUpdate.updateOptions(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/recent_notes', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateRecentNote(req) { await syncUpdate.updateRecentNotes(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/images', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateImage(req) { await syncUpdate.updateImage(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/note_images', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateNoteImage(req) { await syncUpdate.updateNoteImage(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/labels', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateLabel(req) { await syncUpdate.updateLabel(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -router.put('/api_tokens', auth.checkApiAuth, wrap(async (req, res, next) => { +async function updateApiToken(req) { await syncUpdate.updateApiToken(req.body.entity, req.body.sourceId); +} - res.send({}); -})); - -module.exports = router; \ No newline at end of file +module.exports = { + checkSync, + syncNow, + fillSyncRows, + forceFullSync, + forceNoteSync, + getChanged, + getNote, + getBranch, + getImage, + getNoteImage, + getNoteReordering, + getNoteRevision, + getRecentNote, + getOption, + getLabel, + getApiToken, + updateNote, + updateBranch, + updateImage, + updateNoteImage, + updateNoteReordering, + updateNoteRevision, + updateRecentNote, + updateOption, + updateLabel, + updateApiToken +}; \ No newline at end of file diff --git a/src/routes/routes.js b/src/routes/routes.js index cb53f458c..fef767357 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -120,7 +120,32 @@ function register(app) { apiRoute(POST, '/api/password/change', passwordApiRoute.changePassword); - app.use('/api/sync', syncApiRoute); + apiRoute(GET, '/api/sync/check', syncApiRoute.checkSync); + apiRoute(POST, '/api/sync/now', syncApiRoute.syncNow); + apiRoute(POST, '/api/sync/fill-sync-rows', syncApiRoute.fillSyncRows); + apiRoute(POST, '/api/sync/force-full-sync', syncApiRoute.forceFullSync); + apiRoute(POST, '/api/sync/force-note-sync/:noteId', syncApiRoute.forceNoteSync); + apiRoute(GET, '/api/sync/changed', syncApiRoute.getChanged); + apiRoute(GET, '/api/sync/notes/:noteId', syncApiRoute.getNote); + apiRoute(GET, '/api/sync/branches/:branchId', syncApiRoute.getBranch); + apiRoute(GET, '/api/sync/note_revisions/:noteRevisionId', syncApiRoute.getNoteRevision); + apiRoute(GET, '/api/sync/options/:name', syncApiRoute.getOption); + apiRoute(GET, '/api/sync/note_reordering/:parentNoteId', syncApiRoute.getNoteReordering); + apiRoute(GET, '/api/sync/recent_notes/:branchId', syncApiRoute.getRecentNote); + apiRoute(GET, '/api/sync/images/:imageId', syncApiRoute.getImage); + apiRoute(GET, '/api/sync/note_images/:noteImageId', syncApiRoute.getNoteImage); + apiRoute(GET, '/api/sync/labels/:labelId', syncApiRoute.getLabel); + apiRoute(GET, '/api/sync/api_tokens/:apiTokenId', syncApiRoute.getApiToken); + apiRoute(PUT, '/api/sync/notes', syncApiRoute.updateNote); + apiRoute(PUT, '/api/sync/note_revisions', syncApiRoute.updateNoteRevision); + apiRoute(PUT, '/api/sync/note_reordering', syncApiRoute.updateNoteReordering); + apiRoute(PUT, '/api/sync/options', syncApiRoute.updateOption); + apiRoute(PUT, '/api/sync/recent_notes', syncApiRoute.updateRecentNote); + apiRoute(PUT, '/api/sync/images', syncApiRoute.updateImage); + apiRoute(PUT, '/api/sync/note_images', syncApiRoute.updateNoteImage); + 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);