#98, sync is now configured in the options

This commit is contained in:
azivner 2018-07-22 22:21:16 +02:00
parent 073300bbcd
commit e7460ca3a9
15 changed files with 115 additions and 46 deletions

View File

@ -9,9 +9,3 @@ https=false
# path to certificate (run "bash generate-cert.sh" to generate self-signed certificate). Relevant only if https=true
certPath=
keyPath=
[Sync]
syncServerHost=
syncServerTimeout=10000
syncProxy=
syncServerCertificate=

View File

@ -0,0 +1,8 @@
INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
VALUES ('syncServerHost', '', '2018-06-01T03:35:55.041Z', '2018-06-01T03:35:55.041Z', 0);
INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
VALUES ('syncServerTimeout', '5000', '2018-06-01T03:35:55.041Z', '2018-06-01T03:35:55.041Z', 0);
INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
VALUES ('syncProxy', '', '2018-06-01T03:35:55.041Z', '2018-06-01T03:35:55.041Z', 0);

View File

@ -61,6 +61,7 @@
"simple-node-logger": "^0.93.37",
"sqlite": "^2.9.2",
"tar-stream": "^1.6.1",
"tmp-promise": "^1.0.5",
"unescape": "^1.0.1",
"ws": "^5.2.1",
"xml2js": "^0.4.19"

View File

@ -34,8 +34,8 @@ async function showDialog() {
}
}
async function saveOptions(optionName, optionValue) {
await server.put('options/' + encodeURIComponent(optionName) + '/' + encodeURIComponent(optionValue));
async function saveOptions(options) {
await server.put('options', options);
infoService.showMessage("Options change have been saved.");
}
@ -129,16 +129,15 @@ addTabHandler((function() {
addTabHandler((function() {
const $form = $("#protected-session-timeout-form");
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
const optionName = 'protectedSessionTimeout';
function optionsLoaded(options) {
$protectedSessionTimeout.val(options[optionName]);
$protectedSessionTimeout.val(options['protectedSessionTimeout']);
}
$form.submit(() => {
const protectedSessionTimeout = $protectedSessionTimeout.val();
saveOptions(optionName, protectedSessionTimeout).then(() => {
saveOptions({ 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
protectedSessionHolder.setProtectedSessionTimeout(protectedSessionTimeout);
});
@ -153,14 +152,13 @@ addTabHandler((function() {
addTabHandler((function () {
const $form = $("#note-revision-snapshot-time-interval-form");
const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
const optionName = 'noteRevisionSnapshotTimeInterval';
function optionsLoaded(options) {
$timeInterval.val(options[optionName]);
$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
}
$form.submit(() => {
saveOptions(optionName, $timeInterval.val());
saveOptions({ 'noteRevisionSnapshotTimeInterval': $timeInterval.val() });
return false;
});
@ -189,6 +187,33 @@ addTabHandler((async function () {
return {};
})());
addTabHandler((function() {
const $form = $("#sync-setup-form");
const $syncServerHost = $("#sync-server-host");
const $syncServerTimeout = $("#sync-server-timeout");
const $syncProxy = $("#sync-proxy");
function optionsLoaded(options) {
$syncServerHost.val(options['syncServerHost']);
$syncServerTimeout.val(options['syncServerTimeout']);
$syncProxy.val(options['syncProxy']);
}
$form.submit(() => {
saveOptions({
'syncServerHost': $syncServerHost.val(),
'syncServerTimeout': $syncServerTimeout.val(),
'syncProxy': $syncProxy.val()
});
return false;
});
return {
optionsLoaded
};
})());
addTabHandler((async function () {
const $forceFullSyncButton = $("#force-full-sync-button");
const $fillSyncRowsButton = $("#fill-sync-rows-button");

View File

@ -5,7 +5,8 @@ const optionService = require('../../services/options');
const log = require('../../services/log');
// options allowed to be updated directly in options dialog
const ALLOWED_OPTIONS = ['protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval', 'zoomFactor', 'theme'];
const ALLOWED_OPTIONS = ['protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval',
'zoomFactor', 'theme', 'syncServerHost', 'syncServerTimeout', 'syncProxy'];
async function getOptions() {
const options = await sql.getMap("SELECT name, value FROM options WHERE name IN ("
@ -17,16 +18,35 @@ async function getOptions() {
async function updateOption(req) {
const {name, value} = req.params;
if (!update(name, value)) {
return [400, "not allowed option to change"];
}
}
async function updateOptions(req) {
for (const optionName in req.body) {
if (!update(optionName, req.body[optionName])) {
// this should be improved
// it should return 400 instead of current 500, but at least it now rollbacks transaction
throw new Error(`${optionName} is not allowed to change`);
}
}
}
async function update(name, value) {
if (!ALLOWED_OPTIONS.includes(name)) {
return [400, "not allowed option to set"];
return false;
}
log.info(`Updating option ${name} to ${value}`);
await optionService.setOption(name, value);
return true;
}
module.exports = {
getOptions,
updateOption
updateOption,
updateOptions
};

View File

@ -144,6 +144,7 @@ function register(app) {
apiRoute(GET, '/api/options', optionsApiRoute.getOptions);
apiRoute(PUT, '/api/options/:name/:value', optionsApiRoute.updateOption);
apiRoute(PUT, '/api/options', optionsApiRoute.updateOptions);
apiRoute(POST, '/api/password/change', passwordApiRoute.changePassword);

View File

@ -3,7 +3,7 @@
const build = require('./build');
const packageJson = require('../../package');
const APP_DB_VERSION = 100;
const APP_DB_VERSION = 101;
const SYNC_VERSION = 1;
module.exports = {

View File

@ -73,7 +73,7 @@ async function sendPing(client, lastSentSyncId) {
await sendMessage(client, {
type: 'sync',
data: syncData,
changesToPushCount: syncSetup.isSyncSetup ? changesToPushCount : 0
changesToPushCount: await syncSetup.isSyncSetup() ? changesToPushCount : 0
});
}

View File

@ -85,7 +85,7 @@ async function migrate() {
}
}
if (sqlInit.isDbUpToDate()) {
if (await sqlInit.isDbUpToDate()) {
await sqlInit.initDbConnection();
}

View File

@ -34,6 +34,10 @@ async function initOptions(startNotePath, username, password) {
await optionService.createOption('encryptedDataKeyIv', '');
await passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16));
await optionService.createOption('syncServerHost', '', false);
await optionService.createOption('syncServerTimeout', 5000, false);
await optionService.createOption('syncProxy', '', false);
}
module.exports = {

View File

@ -31,8 +31,8 @@ async function initDbConnection() {
await sql.execute("PRAGMA foreign_keys = ON");
if (isDbInitialized()) {
log.info("DB not found, please visit setup page to initialize Trilium.");
if (!await isDbInitialized()) {
log.info("DB not initialized, please visit setup page to initialize Trilium.");
return;
}

View File

@ -17,7 +17,6 @@ const syncMutexService = require('./sync_mutex');
const cls = require('./cls');
let proxyToggle = true;
let syncServerCertificate = null;
async function sync() {
try {
@ -169,7 +168,7 @@ async function checkContentHash(syncContext) {
}
async function syncRequest(syncContext, method, uri, body) {
const fullUri = syncSetup.SYNC_SERVER + uri;
const fullUri = await syncSetup.getSyncServer() + uri;
try {
const options = {
@ -178,15 +177,13 @@ async function syncRequest(syncContext, method, uri, body) {
jar: syncContext.cookieJar,
json: true,
body: body,
timeout: syncSetup.SYNC_TIMEOUT
timeout: await syncSetup.getSyncTimeout()
};
if (syncServerCertificate) {
options.ca = syncServerCertificate;
}
const syncProxy = await syncSetup.getSyncProxy();
if (syncSetup.SYNC_PROXY && proxyToggle) {
options.proxy = syncSetup.SYNC_PROXY;
if (syncProxy && proxyToggle) {
options.proxy = syncProxy;
}
return await rp(options);
@ -270,18 +267,14 @@ async function setLastSyncedPush(lastSyncedPush) {
await optionService.setOption('lastSyncedPush', lastSyncedPush);
}
sqlInit.dbReady.then(() => {
if (syncSetup.isSyncSetup) {
log.info("Setting up sync to " + syncSetup.SYNC_SERVER + " with timeout " + syncSetup.SYNC_TIMEOUT);
sqlInit.dbReady.then(async () => {
if (await syncSetup.isSyncSetup()) {
log.info("Setting up sync to " + await syncSetup.getSyncServer() + " with timeout " + await syncSetup.getSyncTimeout());
if (syncSetup.SYNC_PROXY) {
log.info("Sync proxy: " + syncSetup.SYNC_PROXY);
}
const syncProxy = await syncSetup.getSyncProxy();
if (syncSetup.SYNC_CERT_PATH) {
log.info('Sync certificate: ' + syncSetup.SYNC_CERT_PATH);
syncServerCertificate = fs.readFileSync(syncSetup.SYNC_CERT_PATH);
if (syncProxy) {
log.info("Sync proxy: " + syncProxy);
}
setInterval(cls.wrap(sync), 60000);

View File

@ -1,11 +1,11 @@
"use strict";
const config = require('./config');
const optionService = require('./options');
module.exports = {
SYNC_SERVER: config['Sync']['syncServerHost'],
isSyncSetup: !!config['Sync']['syncServerHost'],
SYNC_TIMEOUT: config['Sync']['syncServerTimeout'] || 5000,
SYNC_PROXY: config['Sync']['syncProxy'],
SYNC_CERT_PATH: config['Sync']['syncServerCertificate']
getSyncServer: async () => await optionService.getOption('syncServerHost'),
isSyncSetup: async () => !!await optionService.getOption('syncServerHost'),
getSyncTimeout: async () => await optionService.getOption('syncServerTimeout'),
getSyncProxy: async () => await optionService.getOption('syncProxy')
};

View File

@ -54,7 +54,7 @@ async function addEntitySync(entityName, entityId, sourceId) {
sourceId: sourceId || cls.getSourceId() || sourceIdService.getCurrentSourceId()
});
if (!syncSetup.isSyncSetup) {
if (!await syncSetup.isSyncSetup()) {
// this is because the "server" instances shouldn't have outstanding pushes
// useful when you fork the DB for new "client" instance, it won't try to sync the whole DB
await sql.execute("UPDATE options SET value = (SELECT MAX(id) FROM sync) WHERE name IN('lastSyncedPush', 'lastSyncedPull')");

View File

@ -334,6 +334,7 @@
<li><a href="#change-password">Change password</a></li>
<li><a href="#protected-session-timeout">Protected session</a></li>
<li><a href="#note-revision-snapshot-time-interval">Note revisions</a></li>
<li><a href="#sync-setup">Sync</a></li>
<li><a href="#advanced">Advanced</a></li>
<li><a href="#about">About Trilium</a></li>
</ul>
@ -404,6 +405,28 @@
<button class="btn btn-sm">Save</button>
</form>
</div>
<div id="sync-setup">
<h4 style="margin-top: 0px;">Sync</h4>
<form id="sync-setup-form">
<div class="form-group">
<label for="sync-server-host">Sync server host</label>
<input class="form-control" id="sync-server-host" placeholder="https://<host>:<port>">
</div>
<div class="form-group">
<label for="sync-server-timeout">Sync timeout (milliseconds)</label>
<input class="form-control" id="sync-server-timeout" min="1" max="10000000" type="number">
</div>
<div class="form-group">
<label for="sync-proxy">Sync proxy server (optional)</label>
<input class="form-control" id="sync-proxy" placeholder="https://<host>:<port>">
</div>
<button class="btn btn-sm">Save</button>
</form>
</div>
<div id="advanced">
<h4 style="margin-top: 0px;">Sync</h4>
<button id="force-full-sync-button" class="btn btn-sm">Force full sync</button>