mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	"sync now" button
This commit is contained in:
		
							
								
								
									
										20
									
								
								public/javascripts/sync.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								public/javascripts/sync.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					function syncNow() {
 | 
				
			||||||
 | 
					    $.ajax({
 | 
				
			||||||
 | 
					        url: baseApiUrl + 'sync/now',
 | 
				
			||||||
 | 
					        type: 'POST',
 | 
				
			||||||
 | 
					        success: result => {
 | 
				
			||||||
 | 
					            if (result.success) {
 | 
				
			||||||
 | 
					                alert("Sync finished successfully");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (const l of result.log)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    console.log(l);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                alert("Sync failed");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        error: () => alert("Sync failed")
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,6 +5,15 @@ const router = express.Router();
 | 
				
			|||||||
const auth = require('../../services/auth');
 | 
					const auth = require('../../services/auth');
 | 
				
			||||||
const sync = require('../../services/sync');
 | 
					const sync = require('../../services/sync');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					router.post('/now', auth.checkApiAuth, async (req, res, next) => {
 | 
				
			||||||
 | 
					    const log = await sync.sync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    res.send({
 | 
				
			||||||
 | 
					        success: true,
 | 
				
			||||||
 | 
					        log: log
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.get('/changed/:since', auth.checkApiAuth, async (req, res, next) => {
 | 
					router.get('/changed/:since', auth.checkApiAuth, async (req, res, next) => {
 | 
				
			||||||
    const since = parseInt(req.params.since);
 | 
					    const since = parseInt(req.params.since);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ const SYNC_SERVER = config['Sync']['syncServerHost'];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let syncInProgress = false;
 | 
					let syncInProgress = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function pullSync(cookieJar) {
 | 
					async function pullSync(cookieJar, syncLog) {
 | 
				
			||||||
    const lastSyncedPull = parseInt(await sql.getOption('last_synced_pull'));
 | 
					    const lastSyncedPull = parseInt(await sql.getOption('last_synced_pull'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const resp = await rp({
 | 
					    const resp = await rp({
 | 
				
			||||||
@@ -28,7 +28,7 @@ async function pullSync(cookieJar) {
 | 
				
			|||||||
    try {
 | 
					    try {
 | 
				
			||||||
        await sql.beginTransaction();
 | 
					        await sql.beginTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await putChanged(resp);
 | 
					        await putChanged(resp, syncLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const noteId of resp.notes) {
 | 
					        for (const noteId of resp.notes) {
 | 
				
			||||||
            const note = await rp({
 | 
					            const note = await rp({
 | 
				
			||||||
@@ -41,7 +41,7 @@ async function pullSync(cookieJar) {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await putNote(note);
 | 
					            await putNote(note, syncLog);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.setOption('last_synced_pull', resp.syncTimestamp);
 | 
					        await sql.setOption('last_synced_pull', resp.syncTimestamp);
 | 
				
			||||||
@@ -55,12 +55,15 @@ async function pullSync(cookieJar) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function pushSync(cookieJar) {
 | 
					async function pushSync(cookieJar, syncLog) {
 | 
				
			||||||
    const lastSyncedPush = parseInt(await sql.getOption('last_synced_push'));
 | 
					    const lastSyncedPush = parseInt(await sql.getOption('last_synced_push'));
 | 
				
			||||||
    const syncStarted = utils.nowTimestamp();
 | 
					    const syncStarted = utils.nowTimestamp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const changed = await getChangedSince(lastSyncedPush);
 | 
					    const changed = await getChangedSince(lastSyncedPush);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (changed.tree.length > 0 || changed.audit_log.length > 0) {
 | 
				
			||||||
 | 
					        logSync("Sending " + changed.tree.length + " tree changes and " + changed.audit_log.length + " audit changes", syncLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await rp({
 | 
					        await rp({
 | 
				
			||||||
            method: 'PUT',
 | 
					            method: 'PUT',
 | 
				
			||||||
            uri: SYNC_SERVER + '/api/sync/changed',
 | 
					            uri: SYNC_SERVER + '/api/sync/changed',
 | 
				
			||||||
@@ -71,8 +74,11 @@ async function pushSync(cookieJar) {
 | 
				
			|||||||
            json: true,
 | 
					            json: true,
 | 
				
			||||||
            jar: cookieJar
 | 
					            jar: cookieJar
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const noteId of changed.notes) {
 | 
					    for (const noteId of changed.notes) {
 | 
				
			||||||
 | 
					        logSync("Sending note " + noteId, syncLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const note = await getNoteSince(noteId);
 | 
					        const note = await getNoteSince(noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await rp({
 | 
					        await rp({
 | 
				
			||||||
@@ -93,8 +99,10 @@ async function pushSync(cookieJar) {
 | 
				
			|||||||
async function login() {
 | 
					async function login() {
 | 
				
			||||||
    const timestamp = utils.nowTimestamp();
 | 
					    const timestamp = utils.nowTimestamp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const hmac = crypto.createHmac('sha256', documentSecret);
 | 
					    const documentSecret = await sql.getOption('document_secret');
 | 
				
			||||||
    hmac.update(timestamp);
 | 
					
 | 
				
			||||||
 | 
					    const hmac = crypto.createHmac('sha256', Buffer.from(documentSecret.toString(), 'ASCII'));
 | 
				
			||||||
 | 
					    hmac.update(timestamp.toString());
 | 
				
			||||||
    const hash = hmac.digest('base64');
 | 
					    const hash = hmac.digest('base64');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const cookieJar = rp.jar();
 | 
					    const cookieJar = rp.jar();
 | 
				
			||||||
@@ -120,6 +128,7 @@ async function sync() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    syncInProgress = true;
 | 
					    syncInProgress = true;
 | 
				
			||||||
 | 
					    const syncLog = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        if (!await migration.isDbUpToDate()) {
 | 
					        if (!await migration.isDbUpToDate()) {
 | 
				
			||||||
@@ -128,16 +137,26 @@ async function sync() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const cookieJar = await login();
 | 
					        const cookieJar = await login();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await pushSync(cookieJar);
 | 
					        await pushSync(cookieJar, syncLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await pullSync(cookieJar);
 | 
					        await pullSync(cookieJar, syncLog);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    catch (e) {
 | 
					    catch (e) {
 | 
				
			||||||
        log.error("sync failed: " + e.stack);
 | 
					        logSync("sync failed: " + e.stack, syncLog);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    finally {
 | 
					    finally {
 | 
				
			||||||
        syncInProgress = false;
 | 
					        syncInProgress = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return syncLog;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function logSync(message, syncLog) {
 | 
				
			||||||
 | 
					    log.info(message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (syncLog !== null) {
 | 
				
			||||||
 | 
					        syncLog.push(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getChangedSince(since) {
 | 
					async function getChangedSince(since) {
 | 
				
			||||||
@@ -158,27 +177,29 @@ async function getNoteSince(noteId, since) {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function putChanged(changed) {
 | 
					async function putChanged(changed, syncLog) {
 | 
				
			||||||
    for (const treeItem of changed.tree) {
 | 
					    for (const treeItem of changed.tree) {
 | 
				
			||||||
        delete treeItem['id'];
 | 
					        delete treeItem['id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.insert("notes_tree", treeItem, true);
 | 
					        await sql.insert("notes_tree", treeItem, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log.info("Update/sync notes_tree " + treeItem.note_id);
 | 
					        logSync("Update/sync notes_tree " + treeItem.note_id, syncLog);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const audit of changed.audit_log) {
 | 
					    for (const audit of changed.audit_log) {
 | 
				
			||||||
        await sql.insert("audit_log", audit, true);
 | 
					        await sql.insert("audit_log", audit, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        log.info("Update/sync audit_log for noteId=" + audit.note_id);
 | 
					        logSync("Update/sync audit_log for noteId=" + audit.note_id, syncLog);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (changed.tree.length > 0 || changed.audit_log.length > 0) {
 | 
					    if (changed.tree.length > 0 || changed.audit_log.length > 0) {
 | 
				
			||||||
 | 
					        logSync("Added final audit", syncLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.addAudit(audit_category.SYNC);
 | 
					        await sql.addAudit(audit_category.SYNC);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function putNote(note) {
 | 
					async function putNote(note, syncLog) {
 | 
				
			||||||
    const origNote = await sql.getSingleResult();
 | 
					    const origNote = await sql.getSingleResult();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (origNote !== null && origNote.date_modified >= note.detail.date_modified) {
 | 
					    if (origNote !== null && origNote.date_modified >= note.detail.date_modified) {
 | 
				
			||||||
@@ -203,7 +224,7 @@ async function putNote(note) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    await sql.addAudit(audit_category.SYNC);
 | 
					    await sql.addAudit(audit_category.SYNC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log.info("Update/sync note " + note.detail.note_id);
 | 
					    logSync("Update/sync note " + note.detail.note_id, syncLog);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (SYNC_SERVER) {
 | 
					if (SYNC_SERVER) {
 | 
				
			||||||
@@ -219,6 +240,7 @@ else {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
 | 
					    sync,
 | 
				
			||||||
    getChangedSince,
 | 
					    getChangedSince,
 | 
				
			||||||
    getNoteSince,
 | 
					    getNoteSince,
 | 
				
			||||||
    putChanged,
 | 
					    putChanged,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ function randomString(length) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function randomSecureToken(bytes = 32) {
 | 
					function randomSecureToken(bytes = 32) {
 | 
				
			||||||
    crypto.randomBytes(bytes).toString('base64');
 | 
					    return crypto.randomBytes(bytes).toString('base64');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function nowTimestamp() {
 | 
					function nowTimestamp() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,8 @@
 | 
				
			|||||||
          <span id="top-message"></span>
 | 
					          <span id="top-message"></span>
 | 
				
			||||||
          <span id="error-message"></span>
 | 
					          <span id="error-message"></span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <button class="btn btn-xs" onclick="syncNow();">Sync now</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <button class="btn btn-xs" onclick="displaySettings();">Settings</button>
 | 
					          <button class="btn btn-xs" onclick="displaySettings();">Settings</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <form action="logout" method="POST" style="display: inline;">
 | 
					          <form action="logout" method="POST" style="display: inline;">
 | 
				
			||||||
@@ -274,6 +276,7 @@
 | 
				
			|||||||
    <script src="javascripts/note_history.js"></script>
 | 
					    <script src="javascripts/note_history.js"></script>
 | 
				
			||||||
    <script src="javascripts/recent_changes.js"></script>
 | 
					    <script src="javascripts/recent_changes.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="javascripts/sync.js"></script>
 | 
				
			||||||
    <script src="javascripts/utils.js"></script>
 | 
					    <script src="javascripts/utils.js"></script>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user