| 
									
										
										
										
											2017-10-21 21:10:33 -04:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | const log = require('./log'); | 
					
						
							|  |  |  | const rp = require('request-promise'); | 
					
						
							|  |  |  | const sql = require('./sql'); | 
					
						
							| 
									
										
										
										
											2017-11-02 20:48:02 -04:00
										 |  |  | const options = require('./options'); | 
					
						
							| 
									
										
										
										
											2017-10-26 21:16:21 -04:00
										 |  |  | const utils = require('./utils'); | 
					
						
							| 
									
										
										
										
											2017-11-16 21:50:00 -05:00
										 |  |  | const source_id = require('./source_id'); | 
					
						
							| 
									
										
										
										
											2017-11-05 10:41:54 -05:00
										 |  |  | const notes = require('./notes'); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | const syncUpdate = require('./sync_update'); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | const content_hash = require('./content_hash'); | 
					
						
							|  |  |  | const event_log = require('./event_log'); | 
					
						
							| 
									
										
										
										
											2017-12-01 20:39:48 -05:00
										 |  |  | const fs = require('fs'); | 
					
						
							| 
									
										
										
										
											2017-12-03 22:29:23 -05:00
										 |  |  | const app_info = require('./app_info'); | 
					
						
							| 
									
										
										
										
											2017-12-12 23:47:17 -05:00
										 |  |  | const messaging = require('./messaging'); | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  | const sync_setup = require('./sync_setup'); | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | let syncInProgress = false; | 
					
						
							| 
									
										
										
										
											2017-11-16 20:08:04 -05:00
										 |  |  | let proxyToggle = true; | 
					
						
							| 
									
										
										
										
											2017-12-01 20:39:48 -05:00
										 |  |  | let syncServerCertificate = null; | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | async function sync() { | 
					
						
							|  |  |  |     if (syncInProgress) { | 
					
						
							|  |  |  |         log.info("Sync already in progress"); | 
					
						
							| 
									
										
										
										
											2017-10-26 20:31:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         return { | 
					
						
							|  |  |  |             success: false, | 
					
						
							|  |  |  |             message: "Sync already in progress" | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     syncInProgress = true; | 
					
						
							| 
									
										
										
										
											2017-10-29 14:55:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try { | 
					
						
							| 
									
										
										
										
											2017-12-10 12:56:59 -05:00
										 |  |  |         if (!await sql.isDbUpToDate()) { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             return { | 
					
						
							|  |  |  |                 success: false, | 
					
						
							|  |  |  |                 message: "DB not up to date" | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-31 19:34:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         const syncContext = await login(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await pushSync(syncContext); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await pullSync(syncContext); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await pushSync(syncContext); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  |         await checkContentHash(syncContext); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         return { | 
					
						
							|  |  |  |             success: true | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2017-10-29 14:55:48 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     catch (e) { | 
					
						
							| 
									
										
										
										
											2017-11-16 20:08:04 -05:00
										 |  |  |         proxyToggle = !proxyToggle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         if (e.message.indexOf('ECONNREFUSED') !== -1) { | 
					
						
							|  |  |  |             log.info("No connection to sync server."); | 
					
						
							| 
									
										
										
										
											2017-10-26 20:31:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             return { | 
					
						
							|  |  |  |                 success: false, | 
					
						
							|  |  |  |                 message: "No connection to sync server." | 
					
						
							|  |  |  |             }; | 
					
						
							| 
									
										
										
										
											2017-10-31 19:34:58 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         else { | 
					
						
							|  |  |  |             log.info("sync failed: " + e.stack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return { | 
					
						
							|  |  |  |                 success: false, | 
					
						
							|  |  |  |                 message: e.message | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-10-31 19:34:58 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     } | 
					
						
							|  |  |  |     finally { | 
					
						
							|  |  |  |         syncInProgress = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function login() { | 
					
						
							| 
									
										
										
										
											2017-12-10 15:45:17 -05:00
										 |  |  |     const timestamp = utils.nowDate(); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const documentSecret = await options.getOption('document_secret'); | 
					
						
							|  |  |  |     const hash = utils.hmac(documentSecret, timestamp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const syncContext = { cookieJar: rp.jar() }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 23:25:23 -05:00
										 |  |  |     const resp = await syncRequest(syncContext, 'POST', '/api/login/sync', { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         timestamp: timestamp, | 
					
						
							| 
									
										
										
										
											2017-12-03 22:29:23 -05:00
										 |  |  |         dbVersion: app_info.db_version, | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         hash: hash | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-22 06:48:24 -05:00
										 |  |  |     if (source_id.isLocalSourceId(resp.sourceId)) { | 
					
						
							|  |  |  |         throw new Error(`Sync server has source ID ${resp.sourceId} which is also local. Try restarting sync server.`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     syncContext.sourceId = resp.sourceId; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return syncContext; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | async function getLastSyncedPull() { | 
					
						
							|  |  |  |     return parseInt(await options.getOption('last_synced_pull')); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 20:52:38 -05:00
										 |  |  | async function setLastSyncedPull(syncId) { | 
					
						
							|  |  |  |     await sql.doInTransaction(async () => { | 
					
						
							|  |  |  |         await options.setOption('last_synced_pull', syncId); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | async function pullSync(syncContext) { | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  |     const lastSyncedPull = await getLastSyncedPull(); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 21:50:00 -05:00
										 |  |  |     const changesUri = '/api/sync/changed?lastSyncId=' + lastSyncedPull; | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const syncRows = await syncRequest(syncContext, 'GET', changesUri); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     log.info("Pulled " + syncRows.length + " changes from " + changesUri); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const sync of syncRows) { | 
					
						
							| 
									
										
										
										
											2017-11-16 21:50:00 -05:00
										 |  |  |         if (source_id.isLocalSourceId(sync.source_id)) { | 
					
						
							| 
									
										
										
										
											2017-12-16 00:05:37 -05:00
										 |  |  |             log.info(`Skipping pull #${sync.id} ${sync.entity_name} ${sync.entity_id} because ${sync.source_id} is a local source id.`); | 
					
						
							| 
									
										
										
										
											2017-11-16 21:50:00 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 20:52:38 -05:00
										 |  |  |             await setLastSyncedPull(sync.id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-16 21:50:00 -05:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-21 22:18:37 -05:00
										 |  |  |         const resp = await syncRequest(syncContext, 'GET', "/api/sync/" + sync.entity_name + "/" + encodeURIComponent(sync.entity_id)); | 
					
						
							| 
									
										
										
										
											2017-10-31 19:34:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 12:21:56 -05:00
										 |  |  |         if (!resp || (sync.entity_name === 'notes' && !resp.entity)) { | 
					
						
							| 
									
										
										
										
											2017-12-15 22:16:28 -05:00
										 |  |  |             log.error(`Empty response to pull for sync #${sync.id} ${sync.entity_name}, id=${sync.entity_id}`); | 
					
						
							| 
									
										
										
										
											2017-11-23 23:54:54 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-12-10 15:45:17 -05:00
										 |  |  |         else if (sync.entity_name === 'notes') { | 
					
						
							| 
									
										
										
										
											2017-11-29 20:47:01 -05:00
										 |  |  |             await syncUpdate.updateNote(resp.entity, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-10-31 20:09:07 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         else if (sync.entity_name === 'notes_tree') { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             await syncUpdate.updateNoteTree(resp, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-10-31 20:09:07 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         else if (sync.entity_name === 'notes_history') { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             await syncUpdate.updateNoteHistory(resp, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-10-31 20:09:07 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |         else if (sync.entity_name === 'notes_reordering') { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             await syncUpdate.updateNoteReordering(resp, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-02 20:48:02 -04:00
										 |  |  |         else if (sync.entity_name === 'options') { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             await syncUpdate.updateOptions(resp, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-11-02 20:48:02 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-05 00:16:02 -04:00
										 |  |  |         else if (sync.entity_name === 'recent_notes') { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             await syncUpdate.updateRecentNotes(resp, syncContext.sourceId); | 
					
						
							| 
									
										
										
										
											2017-11-05 00:16:02 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-31 20:09:07 -04:00
										 |  |  |         else { | 
					
						
							| 
									
										
										
										
											2017-12-15 22:16:28 -05:00
										 |  |  |             throw new Error(`Unrecognized entity type ${sync.entity_name} in sync #${sync.id}`); | 
					
						
							| 
									
										
										
										
											2017-10-31 20:09:07 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-28 20:52:38 -05:00
										 |  |  |         await setLastSyncedPull(sync.id); | 
					
						
							| 
									
										
										
										
											2017-10-26 20:31:31 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-31 19:34:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     log.info("Finished pull"); | 
					
						
							| 
									
										
										
										
											2017-10-26 20:31:31 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | async function getLastSyncedPush() { | 
					
						
							|  |  |  |     return parseInt(await options.getOption('last_synced_push')); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 20:47:01 -05:00
										 |  |  | async function setLastSyncedPush(lastSyncedPush) { | 
					
						
							|  |  |  |     await sql.doInTransaction(async () => { | 
					
						
							|  |  |  |         await options.setOption('last_synced_push', lastSyncedPush); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | async function pushSync(syncContext) { | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  |     let lastSyncedPush = await getLastSyncedPush(); | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     while (true) { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         const sync = await sql.getFirstOrNull('SELECT * FROM sync WHERE id > ? LIMIT 1', [lastSyncedPush]); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (sync === null) { | 
					
						
							|  |  |  |             // nothing to sync
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             log.info("Nothing to push"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2017-10-29 14:55:48 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         if (sync.source_id === syncContext.sourceId) { | 
					
						
							| 
									
										
										
										
											2017-12-15 21:49:46 -05:00
										 |  |  |             log.info(`Skipping push #${sync.id} ${sync.entity_name} ${sync.entity_id} because it originates from sync target`); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2017-12-16 21:23:35 -05:00
										 |  |  |             await pushEntity(sync, syncContext); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lastSyncedPush = sync.id; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 20:47:01 -05:00
										 |  |  |         await setLastSyncedPush(lastSyncedPush); | 
					
						
							| 
									
										
										
										
											2017-10-26 21:16:21 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 21:23:35 -05:00
										 |  |  | async function pushEntity(sync, syncContext) { | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     let entity; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sync.entity_name === 'notes') { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         entity = await sql.getFirst('SELECT * FROM notes WHERE note_id = ?', [sync.entity_id]); | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (sync.entity_name === 'notes_tree') { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         entity = await sql.getFirst('SELECT * FROM notes_tree WHERE note_tree_id = ?', [sync.entity_id]); | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (sync.entity_name === 'notes_history') { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         entity = await sql.getFirst('SELECT * FROM notes_history WHERE note_history_id = ?', [sync.entity_id]); | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |     else if (sync.entity_name === 'notes_reordering') { | 
					
						
							|  |  |  |         entity = { | 
					
						
							| 
									
										
										
										
											2017-12-19 21:40:48 -05:00
										 |  |  |             parent_note_id: sync.entity_id, | 
					
						
							|  |  |  |             ordering: await sql.getMap('SELECT note_tree_id, note_position FROM notes_tree WHERE parent_note_id = ?', [sync.entity_id]) | 
					
						
							| 
									
										
										
										
											2017-11-02 22:55:22 -04:00
										 |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-02 20:48:02 -04:00
										 |  |  |     else if (sync.entity_name === 'options') { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         entity = await sql.getFirst('SELECT * FROM options WHERE opt_name = ?', [sync.entity_id]); | 
					
						
							| 
									
										
										
										
											2017-11-02 20:48:02 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-05 00:16:02 -04:00
										 |  |  |     else if (sync.entity_name === 'recent_notes') { | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |         entity = await sql.getFirst('SELECT * FROM recent_notes WHERE note_tree_id = ?', [sync.entity_id]); | 
					
						
							| 
									
										
										
										
											2017-11-05 00:16:02 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2017-12-15 21:49:46 -05:00
										 |  |  |         throw new Error(`Unrecognized entity type ${sync.entity_name} in sync #${sync.id}`); | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 22:10:41 -04:00
										 |  |  |     if (!entity) { | 
					
						
							| 
									
										
										
										
											2017-12-15 21:49:46 -05:00
										 |  |  |         log.info(`Sync #${sync.id} entity for ${sync.entity_name} ${sync.entity_id} doesn't exist. Skipping.`); | 
					
						
							| 
									
										
										
										
											2017-11-04 22:10:41 -04:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 21:49:46 -05:00
										 |  |  |     log.info(`Pushing changes in sync #${sync.id} ${sync.entity_name} ${sync.entity_id}`); | 
					
						
							| 
									
										
										
										
											2017-11-01 23:16:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |     const payload = { | 
					
						
							| 
									
										
										
										
											2017-12-23 13:55:13 -05:00
										 |  |  |         sourceId: source_id.getCurrentSourceId(), | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |         entity: entity | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2017-10-29 22:22:30 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 21:23:35 -05:00
										 |  |  |     await syncRequest(syncContext, 'PUT', '/api/sync/' + sync.entity_name, payload); | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-10-28 22:17:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | async function checkContentHash(syncContext) { | 
					
						
							| 
									
										
										
										
											2017-12-16 12:30:37 -05:00
										 |  |  |     const resp = await syncRequest(syncContext, 'GET', '/api/sync/check'); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 12:30:37 -05:00
										 |  |  |     if (await getLastSyncedPull() < resp.max_sync_id) { | 
					
						
							|  |  |  |         log.info("There are some outstanding pulls, skipping content check."); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 12:30:37 -05:00
										 |  |  |     const lastSyncedPush = await getLastSyncedPush(); | 
					
						
							| 
									
										
										
										
											2017-12-23 11:02:38 -05:00
										 |  |  |     const notPushedSyncs = await sql.getFirstValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-16 12:30:37 -05:00
										 |  |  |     if (notPushedSyncs > 0) { | 
					
						
							|  |  |  |         log.info("There's " + notPushedSyncs + " outstanding pushes, skipping content check."); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 21:14:10 -05:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const hashes = await content_hash.getHashes(); | 
					
						
							|  |  |  |     let allChecksPassed = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const key in hashes) { | 
					
						
							|  |  |  |         if (hashes[key] !== resp.hashes[key]) { | 
					
						
							| 
									
										
										
										
											2017-12-15 21:36:21 -05:00
										 |  |  |             allChecksPassed = false; | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 21:14:10 -05:00
										 |  |  |             await event_log.addEvent(`Content hash check for ${key} FAILED. Local is ${hashes[key]}, remote is ${resp.hashes[key]}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (key !== 'recent_notes') { | 
					
						
							|  |  |  |                 // let's not get alarmed about recent notes which get updated often and can cause failures in race conditions
 | 
					
						
							| 
									
										
										
										
											2017-12-19 23:22:21 -05:00
										 |  |  |                 await messaging.sendMessageToAllClients({type: 'sync-hash-check-failed'}); | 
					
						
							| 
									
										
										
										
											2017-12-15 21:14:10 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-12-12 23:47:17 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 21:14:10 -05:00
										 |  |  |     if (allChecksPassed) { | 
					
						
							|  |  |  |         log.info("Content hash checks PASSED"); | 
					
						
							| 
									
										
										
										
											2017-11-21 22:11:27 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  | async function syncRequest(syncContext, method, uri, body) { | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |     const fullUri = sync_setup.SYNC_SERVER + uri; | 
					
						
							| 
									
										
										
										
											2017-10-28 22:17:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 14:55:48 -04:00
										 |  |  |     try { | 
					
						
							| 
									
										
										
										
											2017-11-13 19:45:13 -05:00
										 |  |  |         const options = { | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             method: method, | 
					
						
							|  |  |  |             uri: fullUri, | 
					
						
							|  |  |  |             jar: syncContext.cookieJar, | 
					
						
							| 
									
										
										
										
											2017-10-29 14:55:48 -04:00
										 |  |  |             json: true, | 
					
						
							| 
									
										
										
										
											2017-11-09 20:52:47 -05:00
										 |  |  |             body: body, | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |             timeout: sync_setup.SYNC_TIMEOUT | 
					
						
							| 
									
										
										
										
											2017-11-13 19:45:13 -05:00
										 |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 20:39:48 -05:00
										 |  |  |         if (syncServerCertificate) { | 
					
						
							|  |  |  |             options.ca = syncServerCertificate; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |         if (sync_setup.SYNC_PROXY && proxyToggle) { | 
					
						
							|  |  |  |             options.proxy = sync_setup.SYNC_PROXY; | 
					
						
							| 
									
										
										
										
											2017-11-13 19:45:13 -05:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return await rp(options); | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |     catch (e) { | 
					
						
							| 
									
										
										
										
											2017-12-15 21:49:46 -05:00
										 |  |  |         throw new Error(`Request to ${method} ${fullUri} failed, inner exception: ${e.stack}`); | 
					
						
							| 
									
										
										
										
											2017-11-05 00:16:02 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-03 19:18:33 -05:00
										 |  |  | sql.dbReady.then(() => { | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |     if (sync_setup.isSyncSetup) { | 
					
						
							|  |  |  |         log.info("Setting up sync to " + sync_setup.SYNC_SERVER + " with timeout " + sync_setup.SYNC_TIMEOUT); | 
					
						
							| 
									
										
										
										
											2017-10-25 22:39:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |         if (sync_setup.SYNC_PROXY) { | 
					
						
							|  |  |  |             log.info("Sync proxy: " + sync_setup.SYNC_PROXY); | 
					
						
							| 
									
										
										
										
											2017-12-03 19:18:33 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-14 21:54:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |         if (sync_setup.SYNC_CERT_PATH) { | 
					
						
							|  |  |  |             log.info('Sync certificate: ' + sync_setup.SYNC_CERT_PATH); | 
					
						
							| 
									
										
										
										
											2017-12-01 20:39:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |             syncServerCertificate = fs.readFileSync(sync_setup.SYNC_CERT_PATH); | 
					
						
							| 
									
										
										
										
											2017-12-03 19:18:33 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-12-01 20:39:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-03 19:18:33 -05:00
										 |  |  |         setInterval(sync, 60000); | 
					
						
							| 
									
										
										
										
											2017-10-26 23:21:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-03 19:18:33 -05:00
										 |  |  |         // kickoff initial sync immediately
 | 
					
						
							|  |  |  |         setTimeout(sync, 1000); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         log.info("Sync server not configured, sync timer not running.") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2017-10-26 21:16:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | module.exports = { | 
					
						
							| 
									
										
										
										
											2017-12-13 23:03:48 -05:00
										 |  |  |     sync | 
					
						
							| 
									
										
										
										
											2017-10-26 21:16:21 -04:00
										 |  |  | }; |