mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
#98, sync is now configured in the options
This commit is contained in:
parent
073300bbcd
commit
e7460ca3a9
@ -9,9 +9,3 @@ https=false
|
|||||||
# path to certificate (run "bash generate-cert.sh" to generate self-signed certificate). Relevant only if https=true
|
# path to certificate (run "bash generate-cert.sh" to generate self-signed certificate). Relevant only if https=true
|
||||||
certPath=
|
certPath=
|
||||||
keyPath=
|
keyPath=
|
||||||
|
|
||||||
[Sync]
|
|
||||||
syncServerHost=
|
|
||||||
syncServerTimeout=10000
|
|
||||||
syncProxy=
|
|
||||||
syncServerCertificate=
|
|
8
db/migrations/0101__add_sync_options.sql
Normal file
8
db/migrations/0101__add_sync_options.sql
Normal 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);
|
@ -61,6 +61,7 @@
|
|||||||
"simple-node-logger": "^0.93.37",
|
"simple-node-logger": "^0.93.37",
|
||||||
"sqlite": "^2.9.2",
|
"sqlite": "^2.9.2",
|
||||||
"tar-stream": "^1.6.1",
|
"tar-stream": "^1.6.1",
|
||||||
|
"tmp-promise": "^1.0.5",
|
||||||
"unescape": "^1.0.1",
|
"unescape": "^1.0.1",
|
||||||
"ws": "^5.2.1",
|
"ws": "^5.2.1",
|
||||||
"xml2js": "^0.4.19"
|
"xml2js": "^0.4.19"
|
||||||
|
@ -34,8 +34,8 @@ async function showDialog() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveOptions(optionName, optionValue) {
|
async function saveOptions(options) {
|
||||||
await server.put('options/' + encodeURIComponent(optionName) + '/' + encodeURIComponent(optionValue));
|
await server.put('options', options);
|
||||||
|
|
||||||
infoService.showMessage("Options change have been saved.");
|
infoService.showMessage("Options change have been saved.");
|
||||||
}
|
}
|
||||||
@ -129,16 +129,15 @@ addTabHandler((function() {
|
|||||||
addTabHandler((function() {
|
addTabHandler((function() {
|
||||||
const $form = $("#protected-session-timeout-form");
|
const $form = $("#protected-session-timeout-form");
|
||||||
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||||
const optionName = 'protectedSessionTimeout';
|
|
||||||
|
|
||||||
function optionsLoaded(options) {
|
function optionsLoaded(options) {
|
||||||
$protectedSessionTimeout.val(options[optionName]);
|
$protectedSessionTimeout.val(options['protectedSessionTimeout']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$form.submit(() => {
|
$form.submit(() => {
|
||||||
const protectedSessionTimeout = $protectedSessionTimeout.val();
|
const protectedSessionTimeout = $protectedSessionTimeout.val();
|
||||||
|
|
||||||
saveOptions(optionName, protectedSessionTimeout).then(() => {
|
saveOptions({ 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
|
||||||
protectedSessionHolder.setProtectedSessionTimeout(protectedSessionTimeout);
|
protectedSessionHolder.setProtectedSessionTimeout(protectedSessionTimeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -153,14 +152,13 @@ addTabHandler((function() {
|
|||||||
addTabHandler((function () {
|
addTabHandler((function () {
|
||||||
const $form = $("#note-revision-snapshot-time-interval-form");
|
const $form = $("#note-revision-snapshot-time-interval-form");
|
||||||
const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
||||||
const optionName = 'noteRevisionSnapshotTimeInterval';
|
|
||||||
|
|
||||||
function optionsLoaded(options) {
|
function optionsLoaded(options) {
|
||||||
$timeInterval.val(options[optionName]);
|
$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$form.submit(() => {
|
$form.submit(() => {
|
||||||
saveOptions(optionName, $timeInterval.val());
|
saveOptions({ 'noteRevisionSnapshotTimeInterval': $timeInterval.val() });
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -189,6 +187,33 @@ addTabHandler((async function () {
|
|||||||
return {};
|
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 () {
|
addTabHandler((async function () {
|
||||||
const $forceFullSyncButton = $("#force-full-sync-button");
|
const $forceFullSyncButton = $("#force-full-sync-button");
|
||||||
const $fillSyncRowsButton = $("#fill-sync-rows-button");
|
const $fillSyncRowsButton = $("#fill-sync-rows-button");
|
||||||
|
@ -5,7 +5,8 @@ const optionService = require('../../services/options');
|
|||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
|
|
||||||
// options allowed to be updated directly in options dialog
|
// 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() {
|
async function getOptions() {
|
||||||
const options = await sql.getMap("SELECT name, value FROM options WHERE name IN ("
|
const options = await sql.getMap("SELECT name, value FROM options WHERE name IN ("
|
||||||
@ -17,16 +18,35 @@ async function getOptions() {
|
|||||||
async function updateOption(req) {
|
async function updateOption(req) {
|
||||||
const {name, value} = req.params;
|
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)) {
|
if (!ALLOWED_OPTIONS.includes(name)) {
|
||||||
return [400, "not allowed option to set"];
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(`Updating option ${name} to ${value}`);
|
log.info(`Updating option ${name} to ${value}`);
|
||||||
|
|
||||||
await optionService.setOption(name, value);
|
await optionService.setOption(name, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getOptions,
|
getOptions,
|
||||||
updateOption
|
updateOption,
|
||||||
|
updateOptions
|
||||||
};
|
};
|
@ -144,6 +144,7 @@ function register(app) {
|
|||||||
|
|
||||||
apiRoute(GET, '/api/options', optionsApiRoute.getOptions);
|
apiRoute(GET, '/api/options', optionsApiRoute.getOptions);
|
||||||
apiRoute(PUT, '/api/options/:name/:value', optionsApiRoute.updateOption);
|
apiRoute(PUT, '/api/options/:name/:value', optionsApiRoute.updateOption);
|
||||||
|
apiRoute(PUT, '/api/options', optionsApiRoute.updateOptions);
|
||||||
|
|
||||||
apiRoute(POST, '/api/password/change', passwordApiRoute.changePassword);
|
apiRoute(POST, '/api/password/change', passwordApiRoute.changePassword);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const build = require('./build');
|
const build = require('./build');
|
||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
|
|
||||||
const APP_DB_VERSION = 100;
|
const APP_DB_VERSION = 101;
|
||||||
const SYNC_VERSION = 1;
|
const SYNC_VERSION = 1;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -73,7 +73,7 @@ async function sendPing(client, lastSentSyncId) {
|
|||||||
await sendMessage(client, {
|
await sendMessage(client, {
|
||||||
type: 'sync',
|
type: 'sync',
|
||||||
data: syncData,
|
data: syncData,
|
||||||
changesToPushCount: syncSetup.isSyncSetup ? changesToPushCount : 0
|
changesToPushCount: await syncSetup.isSyncSetup() ? changesToPushCount : 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ async function migrate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sqlInit.isDbUpToDate()) {
|
if (await sqlInit.isDbUpToDate()) {
|
||||||
await sqlInit.initDbConnection();
|
await sqlInit.initDbConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,10 @@ async function initOptions(startNotePath, username, password) {
|
|||||||
await optionService.createOption('encryptedDataKeyIv', '');
|
await optionService.createOption('encryptedDataKeyIv', '');
|
||||||
|
|
||||||
await passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16));
|
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 = {
|
module.exports = {
|
||||||
|
@ -31,8 +31,8 @@ async function initDbConnection() {
|
|||||||
|
|
||||||
await sql.execute("PRAGMA foreign_keys = ON");
|
await sql.execute("PRAGMA foreign_keys = ON");
|
||||||
|
|
||||||
if (isDbInitialized()) {
|
if (!await isDbInitialized()) {
|
||||||
log.info("DB not found, please visit setup page to initialize Trilium.");
|
log.info("DB not initialized, please visit setup page to initialize Trilium.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ const syncMutexService = require('./sync_mutex');
|
|||||||
const cls = require('./cls');
|
const cls = require('./cls');
|
||||||
|
|
||||||
let proxyToggle = true;
|
let proxyToggle = true;
|
||||||
let syncServerCertificate = null;
|
|
||||||
|
|
||||||
async function sync() {
|
async function sync() {
|
||||||
try {
|
try {
|
||||||
@ -169,7 +168,7 @@ async function checkContentHash(syncContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncRequest(syncContext, method, uri, body) {
|
async function syncRequest(syncContext, method, uri, body) {
|
||||||
const fullUri = syncSetup.SYNC_SERVER + uri;
|
const fullUri = await syncSetup.getSyncServer() + uri;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {
|
const options = {
|
||||||
@ -178,15 +177,13 @@ async function syncRequest(syncContext, method, uri, body) {
|
|||||||
jar: syncContext.cookieJar,
|
jar: syncContext.cookieJar,
|
||||||
json: true,
|
json: true,
|
||||||
body: body,
|
body: body,
|
||||||
timeout: syncSetup.SYNC_TIMEOUT
|
timeout: await syncSetup.getSyncTimeout()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (syncServerCertificate) {
|
const syncProxy = await syncSetup.getSyncProxy();
|
||||||
options.ca = syncServerCertificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncSetup.SYNC_PROXY && proxyToggle) {
|
if (syncProxy && proxyToggle) {
|
||||||
options.proxy = syncSetup.SYNC_PROXY;
|
options.proxy = syncProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await rp(options);
|
return await rp(options);
|
||||||
@ -270,18 +267,14 @@ async function setLastSyncedPush(lastSyncedPush) {
|
|||||||
await optionService.setOption('lastSyncedPush', lastSyncedPush);
|
await optionService.setOption('lastSyncedPush', lastSyncedPush);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlInit.dbReady.then(() => {
|
sqlInit.dbReady.then(async () => {
|
||||||
if (syncSetup.isSyncSetup) {
|
if (await syncSetup.isSyncSetup()) {
|
||||||
log.info("Setting up sync to " + syncSetup.SYNC_SERVER + " with timeout " + syncSetup.SYNC_TIMEOUT);
|
log.info("Setting up sync to " + await syncSetup.getSyncServer() + " with timeout " + await syncSetup.getSyncTimeout());
|
||||||
|
|
||||||
if (syncSetup.SYNC_PROXY) {
|
const syncProxy = await syncSetup.getSyncProxy();
|
||||||
log.info("Sync proxy: " + syncSetup.SYNC_PROXY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncSetup.SYNC_CERT_PATH) {
|
if (syncProxy) {
|
||||||
log.info('Sync certificate: ' + syncSetup.SYNC_CERT_PATH);
|
log.info("Sync proxy: " + syncProxy);
|
||||||
|
|
||||||
syncServerCertificate = fs.readFileSync(syncSetup.SYNC_CERT_PATH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(cls.wrap(sync), 60000);
|
setInterval(cls.wrap(sync), 60000);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
const optionService = require('./options');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
SYNC_SERVER: config['Sync']['syncServerHost'],
|
getSyncServer: async () => await optionService.getOption('syncServerHost'),
|
||||||
isSyncSetup: !!config['Sync']['syncServerHost'],
|
isSyncSetup: async () => !!await optionService.getOption('syncServerHost'),
|
||||||
SYNC_TIMEOUT: config['Sync']['syncServerTimeout'] || 5000,
|
getSyncTimeout: async () => await optionService.getOption('syncServerTimeout'),
|
||||||
SYNC_PROXY: config['Sync']['syncProxy'],
|
getSyncProxy: async () => await optionService.getOption('syncProxy')
|
||||||
SYNC_CERT_PATH: config['Sync']['syncServerCertificate']
|
|
||||||
};
|
};
|
@ -54,7 +54,7 @@ async function addEntitySync(entityName, entityId, sourceId) {
|
|||||||
sourceId: sourceId || cls.getSourceId() || sourceIdService.getCurrentSourceId()
|
sourceId: sourceId || cls.getSourceId() || sourceIdService.getCurrentSourceId()
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!syncSetup.isSyncSetup) {
|
if (!await syncSetup.isSyncSetup()) {
|
||||||
// this is because the "server" instances shouldn't have outstanding pushes
|
// 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
|
// 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')");
|
await sql.execute("UPDATE options SET value = (SELECT MAX(id) FROM sync) WHERE name IN('lastSyncedPush', 'lastSyncedPull')");
|
||||||
|
@ -334,6 +334,7 @@
|
|||||||
<li><a href="#change-password">Change password</a></li>
|
<li><a href="#change-password">Change password</a></li>
|
||||||
<li><a href="#protected-session-timeout">Protected session</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="#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="#advanced">Advanced</a></li>
|
||||||
<li><a href="#about">About Trilium</a></li>
|
<li><a href="#about">About Trilium</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -404,6 +405,28 @@
|
|||||||
<button class="btn btn-sm">Save</button>
|
<button class="btn btn-sm">Save</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</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">
|
<div id="advanced">
|
||||||
<h4 style="margin-top: 0px;">Sync</h4>
|
<h4 style="margin-top: 0px;">Sync</h4>
|
||||||
<button id="force-full-sync-button" class="btn btn-sm">Force full sync</button>
|
<button id="force-full-sync-button" class="btn btn-sm">Force full sync</button>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user