1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-23 22:36:32 +02:00

All: Add support for public-private key pairs and improved master password support (#5438)

Also improved SCSS support, which was needed for the master password dialog.
This commit is contained in:
Laurent
2021-10-03 16:00:49 +01:00
committed by GitHub
parent e5e1382255
commit c758377188
72 changed files with 4495 additions and 5296 deletions

View File

@@ -22,8 +22,9 @@ import TaskQueue from './TaskQueue';
import ItemUploader from './services/synchronizer/ItemUploader';
import { FileApi } from './file-api';
import JoplinDatabase from './JoplinDatabase';
import { fetchSyncInfo, getActiveMasterKey, localSyncInfo, mergeSyncInfos, saveLocalSyncInfo, syncInfoEquals, uploadSyncInfo } from './services/synchronizer/syncInfoUtils';
import { setupAndDisableEncryption, setupAndEnableEncryption } from './services/e2ee/utils';
import { fetchSyncInfo, getActiveMasterKey, localSyncInfo, mergeSyncInfos, saveLocalSyncInfo, SyncInfo, syncInfoEquals, uploadSyncInfo } from './services/synchronizer/syncInfoUtils';
import { getMasterPassword, setupAndDisableEncryption, setupAndEnableEncryption } from './services/e2ee/utils';
import { generateKeyPair } from './services/e2ee/ppk';
const { sprintf } = require('sprintf-js');
const { Dirnames } = require('./services/synchronizer/utils/types');
@@ -321,6 +322,16 @@ export default class Synchronizer {
return '';
}
private async setPpkIfNotExist(localInfo: SyncInfo, remoteInfo: SyncInfo) {
if (localInfo.ppk || remoteInfo.ppk) return localInfo;
const password = getMasterPassword(false);
if (!password) return localInfo;
localInfo.ppk = await generateKeyPair(this.encryptionService(), password);
return localInfo;
}
private async apiCall(fnName: string, ...args: any[]) {
if (this.syncTargetIsLocked_) throw new JoplinError('Sync target is locked - aborting API call', 'lockError');
@@ -420,49 +431,52 @@ export default class Synchronizer {
this.api().setTempDirName(Dirnames.Temp);
try {
const remoteInfo = await fetchSyncInfo(this.api());
let remoteInfo = await fetchSyncInfo(this.api());
logger.info('Sync target remote info:', remoteInfo);
if (!remoteInfo.version) {
logger.info('Sync target is new - setting it up...');
await this.migrationHandler().upgrade(Setting.value('syncVersion'));
} else {
logger.info('Sync target is already setup - checking it...');
remoteInfo = await fetchSyncInfo(this.api());
}
await this.migrationHandler().checkCanSync(remoteInfo);
logger.info('Sync target is already setup - checking it...');
const localInfo = await localSyncInfo();
await this.migrationHandler().checkCanSync(remoteInfo);
logger.info('Sync target local info:', localInfo);
let localInfo = await localSyncInfo();
// console.info('LOCAL', localInfo);
// console.info('REMOTE', remoteInfo);
logger.info('Sync target local info:', localInfo);
if (!syncInfoEquals(localInfo, remoteInfo)) {
const newInfo = mergeSyncInfos(localInfo, remoteInfo);
const previousE2EE = localInfo.e2ee;
logger.info('Sync target info differs between local and remote - merging infos: ', newInfo.toObject());
localInfo = await this.setPpkIfNotExist(localInfo, remoteInfo);
await this.lockHandler().acquireLock(LockType.Exclusive, this.appType_, this.clientId_, { clearExistingSyncLocksFromTheSameClient: true });
await uploadSyncInfo(this.api(), newInfo);
await saveLocalSyncInfo(newInfo);
await this.lockHandler().releaseLock(LockType.Exclusive, this.appType_, this.clientId_);
// console.info('LOCAL', localInfo);
// console.info('REMOTE', remoteInfo);
// console.info('NEW', newInfo);
if (!syncInfoEquals(localInfo, remoteInfo)) {
const newInfo = mergeSyncInfos(localInfo, remoteInfo);
const previousE2EE = localInfo.e2ee;
logger.info('Sync target info differs between local and remote - merging infos: ', newInfo.toObject());
if (newInfo.e2ee !== previousE2EE) {
if (newInfo.e2ee) {
const mk = getActiveMasterKey(newInfo);
await setupAndEnableEncryption(this.encryptionService(), mk);
} else {
await setupAndDisableEncryption(this.encryptionService());
}
await this.lockHandler().acquireLock(LockType.Exclusive, this.appType_, this.clientId_, { clearExistingSyncLocksFromTheSameClient: true });
await uploadSyncInfo(this.api(), newInfo);
await saveLocalSyncInfo(newInfo);
await this.lockHandler().releaseLock(LockType.Exclusive, this.appType_, this.clientId_);
// console.info('NEW', newInfo);
if (newInfo.e2ee !== previousE2EE) {
if (newInfo.e2ee) {
const mk = getActiveMasterKey(newInfo);
await setupAndEnableEncryption(this.encryptionService(), mk);
} else {
await setupAndDisableEncryption(this.encryptionService());
}
} else {
// Set it to remote anyway so that timestamps are the same
// Note: that's probably not needed anymore?
// await uploadSyncInfo(this.api(), remoteInfo);
}
} else {
// Set it to remote anyway so that timestamps are the same
// Note: that's probably not needed anymore?
// await uploadSyncInfo(this.api(), remoteInfo);
}
} catch (error) {
if (error.code === 'outdatedSyncTarget') {