mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	#98, new option "initialized" which indicates if setup has been finished
This commit is contained in:
		
							
								
								
									
										2
									
								
								db/migrations/0103__add_initialized_option.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								db/migrations/0103__add_initialized_option.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| INSERT INTO options (name, value, dateCreated, dateModified, isSynced) | ||||
| VALUES ('initialized', 'true', '2018-06-01T03:35:55.041Z', '2018-06-01T03:35:55.041Z', 0); | ||||
| @@ -47,7 +47,7 @@ const sessionParser = session({ | ||||
|     cookie: { | ||||
|         //    path: "/", | ||||
|         httpOnly: true, | ||||
|         maxAge:  1800000 | ||||
|         maxAge:  24 * 60 * 60 * 1000 // in milliseconds | ||||
|     }, | ||||
|     store: new FileStore({ | ||||
|         ttl: 30 * 24 * 3600, | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| import utils from "./services/utils.js"; | ||||
|  | ||||
| function SetupModel() { | ||||
|     this.step = ko.observable("setup-type"); | ||||
|     if (syncInProgress) { | ||||
|         setInterval(checkOutstandingSyncs, 1000); | ||||
|     } | ||||
|  | ||||
|     this.step = ko.observable(syncInProgress ? "sync-in-progress" : "setup-type"); | ||||
|     this.setupType = ko.observable(); | ||||
|  | ||||
|     this.setupNewDocument = ko.observable(false); | ||||
| @@ -93,8 +97,6 @@ function SetupModel() { | ||||
|             if (resp.result === 'success') { | ||||
|                 this.step('sync-in-progress'); | ||||
|  | ||||
|                 checkOutstandingSyncs(); | ||||
|  | ||||
|                 setInterval(checkOutstandingSyncs, 1000); | ||||
|             } | ||||
|             else { | ||||
| @@ -105,7 +107,12 @@ function SetupModel() { | ||||
| } | ||||
|  | ||||
| async function checkOutstandingSyncs() { | ||||
|     const stats = await $.get('/api/sync/stats'); | ||||
|     const { stats, initialized } = await $.get('/api/sync/stats'); | ||||
|  | ||||
|     if (initialized) { | ||||
|         window.location.replace("/"); | ||||
|     } | ||||
|  | ||||
|     const totalOutstandingSyncs = stats.outstandingPushes + stats.outstandingPulls; | ||||
|  | ||||
|     $("#outstanding-syncs").html(totalOutstandingSyncs); | ||||
|   | ||||
| @@ -1,11 +1,7 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const sqlInit = require('../../services/sql_init'); | ||||
| const sql = require('../../services/sql'); | ||||
| const rp = require('request-promise'); | ||||
| const Option = require('../../entities/option'); | ||||
| const syncService = require('../../services/sync'); | ||||
| const log = require('../../services/log'); | ||||
| const setupService = require('../../services/setup'); | ||||
|  | ||||
| async function setupNewDocument(req) { | ||||
|     const { username, password } = req.body; | ||||
| @@ -16,44 +12,7 @@ async function setupNewDocument(req) { | ||||
| async function setupSyncFromServer(req) { | ||||
|     const { serverAddress, username, password } = req.body; | ||||
|  | ||||
|     try { | ||||
|         log.info("Getting document options from sync server."); | ||||
|  | ||||
|         // response is expected to contain documentId and documentSecret options | ||||
|         const options = await rp.get({ | ||||
|             uri: serverAddress + '/api/sync/document', | ||||
|             auth: { | ||||
|                 'user': username, | ||||
|                 'pass': password | ||||
|             }, | ||||
|             json: true | ||||
|         }); | ||||
|  | ||||
|         log.info("Creating database for sync"); | ||||
|  | ||||
|         await sql.transactional(async () => { | ||||
|             await sqlInit.createDatabaseForSync(serverAddress); | ||||
|  | ||||
|             for (const opt of options) { | ||||
|                 await new Option(opt).save(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         log.info("Triggering sync."); | ||||
|  | ||||
|         // it's ok to not wait for it here | ||||
|         syncService.sync(); | ||||
|  | ||||
|         return { result: 'success' }; | ||||
|     } | ||||
|     catch (e) { | ||||
|         log.error("Sync failed: " + e.message); | ||||
|  | ||||
|         return { | ||||
|             result: 'failure', | ||||
|             error: e.message | ||||
|         }; | ||||
|     } | ||||
|     return await setupService.setupSyncFromSyncServer(serverAddress, username, password); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -24,7 +24,10 @@ async function testSync() { | ||||
| } | ||||
|  | ||||
| async function getStats() { | ||||
|     return syncService.stats; | ||||
|     return { | ||||
|         initialized: await optionService.getOption('initialized') === 'true', | ||||
|         stats: syncService.stats | ||||
|     }; | ||||
| } | ||||
|  | ||||
| async function checkSync() { | ||||
|   | ||||
| @@ -1,7 +1,25 @@ | ||||
| "use strict"; | ||||
|  | ||||
| function setupPage(req, res) { | ||||
|     res.render('setup', {}); | ||||
| const sqlInit = require('../services/sql_init'); | ||||
| const setupService = require('../services/setup'); | ||||
|  | ||||
| async function setupPage(req, res) { | ||||
|     if (await sqlInit.isDbInitialized()) { | ||||
|         res.redirect('/'); | ||||
|     } | ||||
|  | ||||
|     // we got here because DB is not completely initialized so if schema exists | ||||
|     // it means we're in sync in progress state. | ||||
|     const syncInProgress = await sqlInit.schemaExists(); | ||||
|  | ||||
|     if (syncInProgress) { | ||||
|         // trigger sync if it's not already running | ||||
|         setupService.triggerSync(); | ||||
|     } | ||||
|  | ||||
|     res.render('setup', { | ||||
|         syncInProgress: syncInProgress | ||||
|     }); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
|  | ||||
| const APP_DB_VERSION = 102; | ||||
| const APP_DB_VERSION = 103; | ||||
| const SYNC_VERSION = 1; | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ async function initSyncedOptions(username, password) { | ||||
|     await passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16)); | ||||
| } | ||||
|  | ||||
| async function initNotSyncedOptions(startNotePath = '', syncServerHost = '') { | ||||
| async function initNotSyncedOptions(initialized, startNotePath = '', syncServerHost = '') { | ||||
|     await optionService.createOption('startNotePath', startNotePath, false); | ||||
|     await optionService.createOption('lastBackupDate', dateUtils.nowDate(), false); | ||||
|     await optionService.createOption('dbVersion', appInfo.dbVersion, false); | ||||
| @@ -43,6 +43,8 @@ async function initNotSyncedOptions(startNotePath = '', syncServerHost = '') { | ||||
|     await optionService.createOption('syncServerHost', syncServerHost, false); | ||||
|     await optionService.createOption('syncServerTimeout', 5000, false); | ||||
|     await optionService.createOption('syncProxy', '', false); | ||||
|  | ||||
|     await optionService.createOption('initialized', initialized ? 'true' : 'false', false); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
							
								
								
									
										66
									
								
								src/services/setup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/services/setup.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| const sqlInit = require('./sql_init'); | ||||
| const sql = require('./sql'); | ||||
| const rp = require('request-promise'); | ||||
| const Option = require('../entities/option'); | ||||
| const syncService = require('./sync'); | ||||
| const log = require('./log'); | ||||
| const optionService = require('./options'); | ||||
|  | ||||
| function triggerSync() { | ||||
| // it's ok to not wait for it here | ||||
|     syncService.sync().then(async () => { | ||||
|         await optionService.setOption('initialized', 'true'); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| async function setupSyncFromSyncServer(serverAddress, username, password) { | ||||
|     if (await sqlInit.isDbInitialized()) { | ||||
|         return { | ||||
|             result: 'failure', | ||||
|             error: 'DB is already initialized.' | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         log.info("Getting document options from sync server."); | ||||
|  | ||||
|         // response is expected to contain documentId and documentSecret options | ||||
|         const options = await rp.get({ | ||||
|             uri: serverAddress + '/api/sync/document', | ||||
|             auth: { | ||||
|                 'user': username, | ||||
|                 'pass': password | ||||
|             }, | ||||
|             json: true | ||||
|         }); | ||||
|  | ||||
|         log.info("Creating database for sync"); | ||||
|  | ||||
|         await sql.transactional(async () => { | ||||
|             await sqlInit.createDatabaseForSync(serverAddress); | ||||
|  | ||||
|             for (const opt of options) { | ||||
|                 await new Option(opt).save(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         log.info("Triggering sync."); | ||||
|  | ||||
|         triggerSync(); | ||||
|  | ||||
|         return { result: 'success' }; | ||||
|     } | ||||
|     catch (e) { | ||||
|         log.error("Sync failed: " + e.message); | ||||
|  | ||||
|         return { | ||||
|             result: 'failure', | ||||
|             error: e.message | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     setupSyncFromSyncServer, | ||||
|     triggerSync | ||||
| }; | ||||
| @@ -22,12 +22,22 @@ const dbReady = new Promise(async (resolve, reject) => { | ||||
|     initDbConnection(); | ||||
| }); | ||||
|  | ||||
| async function isDbInitialized() { | ||||
|     const tableResults = await sql.getRows("SELECT name FROM sqlite_master WHERE type='table' AND name='notes'"); | ||||
| async function schemaExists() { | ||||
|     const tableResults = await sql.getRows("SELECT name FROM sqlite_master WHERE type='table' AND name='options'"); | ||||
|  | ||||
|     return tableResults.length === 1; | ||||
| } | ||||
|  | ||||
| async function isDbInitialized() { | ||||
|     if (!await schemaExists()) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     const initialized = await sql.getValue("SELECT value FROM options WHERE name = 'initialized'"); | ||||
|  | ||||
|     return initialized === 'true'; | ||||
| } | ||||
|  | ||||
| async function initDbConnection() { | ||||
|     await cls.init(async () => { | ||||
|         await sql.execute("PRAGMA foreign_keys = ON"); | ||||
| @@ -53,6 +63,10 @@ async function initDbConnection() { | ||||
| async function createInitialDatabase(username, password) { | ||||
|     log.info("Creating initial database ..."); | ||||
|  | ||||
|     if (await isDbInitialized()) { | ||||
|         throw new Error("DB is already initialized"); | ||||
|     } | ||||
|  | ||||
|     const schema = fs.readFileSync(resourceDir.DB_INIT_DIR + '/schema.sql', 'UTF-8'); | ||||
|     const notesSql = fs.readFileSync(resourceDir.DB_INIT_DIR + '/main_notes.sql', 'UTF-8'); | ||||
|     const notesTreeSql = fs.readFileSync(resourceDir.DB_INIT_DIR + '/main_branches.sql', 'UTF-8'); | ||||
| @@ -72,7 +86,7 @@ async function createInitialDatabase(username, password) { | ||||
|  | ||||
|         await optionsInitService.initDocumentOptions(); | ||||
|         await optionsInitService.initSyncedOptions(username, password); | ||||
|         await optionsInitService.initNotSyncedOptions(startNoteId); | ||||
|         await optionsInitService.initNotSyncedOptions(true, startNoteId); | ||||
|  | ||||
|         await require('./sync_table').fillAllSyncRows(); | ||||
|     }); | ||||
| @@ -90,7 +104,7 @@ async function createDatabaseForSync(syncServerHost) { | ||||
|     await sql.transactional(async () => { | ||||
|         await sql.executeScript(schema); | ||||
|  | ||||
|         await require('./options_init').initNotSyncedOptions('', syncServerHost); | ||||
|         await require('./options_init').initNotSyncedOptions(false, '', syncServerHost); | ||||
|     }); | ||||
|  | ||||
|     log.info("Schema and not synced options generated."); | ||||
| @@ -110,6 +124,7 @@ async function isDbUpToDate() { | ||||
|  | ||||
| module.exports = { | ||||
|     dbReady, | ||||
|     schemaExists, | ||||
|     isDbInitialized, | ||||
|     initDbConnection, | ||||
|     isDbUpToDate, | ||||
|   | ||||
| @@ -103,6 +103,7 @@ | ||||
|     const glob = { | ||||
|         sourceId: '' | ||||
|     }; | ||||
|     const syncInProgress = <%= syncInProgress ? 'true' : 'false' %>; | ||||
| </script> | ||||
|  | ||||
| <!-- Required for correct loading of scripts in Electron --> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user