1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-11 18:24:43 +02:00
This commit is contained in:
Laurent Cozic 2022-04-12 17:33:06 +01:00
parent 55db877f85
commit 7103f07904
4 changed files with 65 additions and 3 deletions

View File

@ -254,6 +254,7 @@ export default class EncryptionService {
model.created_time = now;
model.updated_time = now;
model.source_application = Setting.value('appId');
model.hasBeenUsed = false;
return model;
}

View File

@ -8,6 +8,7 @@ export interface MasterKeyEntity {
content?: string;
type_?: number;
enabled?: number;
hasBeenUsed?: boolean;
}
export type RSAKeyPair = any; // Depends on implementation

View File

@ -1,6 +1,6 @@
import { afterAllCleanUp, setupDatabaseAndSynchronizer, switchClient, encryptionService } from '../../testing/test-utils';
import { afterAllCleanUp, setupDatabaseAndSynchronizer, switchClient, encryptionService, msleep } from '../../testing/test-utils';
import MasterKey from '../../models/MasterKey';
import { masterKeyEnabled, setMasterKeyEnabled, SyncInfo, syncInfoEquals } from './syncInfoUtils';
import { masterKeyEnabled, mergeSyncInfos, setMasterKeyEnabled, SyncInfo, syncInfoEquals } from './syncInfoUtils';
describe('syncInfoUtils', function() {
@ -92,4 +92,33 @@ describe('syncInfoUtils', function() {
}
});
it('should merge sync target info and takes into account usage of master key - 1', async () => {
const syncInfo1 = new SyncInfo();
syncInfo1.masterKeys = [{
id: '1',
content: 'content1',
hasBeenUsed: true,
}];
syncInfo1.activeMasterKeyId = '1';
await msleep(1);
const syncInfo2 = new SyncInfo();
syncInfo2.masterKeys = [{
id: '2',
content: 'content2',
hasBeenUsed: false,
}];
syncInfo2.activeMasterKeyId = '2';
// If one master key has been used and the other not, it should select
// the one that's been used regardless of timestamps.
expect(mergeSyncInfos(syncInfo1, syncInfo2).activeMasterKeyId).toBe('1');
// If both master keys have been used it should rely on timestamp
// (latest modified is picked).
syncInfo2.masterKeys[0].hasBeenUsed = true;
expect(mergeSyncInfos(syncInfo1, syncInfo2).activeMasterKeyId).toBe('2');
});
});

View File

@ -90,11 +90,32 @@ export function localSyncInfoFromState(state: State): SyncInfo {
return new SyncInfo(state.settings['syncInfoCache']);
}
const mergeActiveMasterKeys = (s1: SyncInfo, s2: SyncInfo, output: SyncInfo) => {
const activeMasterKey1 = getActiveMasterKey(s1);
const activeMasterKey2 = getActiveMasterKey(s2);
let doDefaultAction = false;
if (activeMasterKey1 && activeMasterKey2) {
if (activeMasterKey1.hasBeenUsed && !activeMasterKey2.hasBeenUsed) {
output.setWithTimestamp(s1, 'activeMasterKeyId');
} else if (!activeMasterKey1.hasBeenUsed && activeMasterKey2.hasBeenUsed) {
output.setWithTimestamp(s2, 'activeMasterKeyId');
} else {
doDefaultAction = true;
}
} else {
doDefaultAction = true;
}
if (doDefaultAction) {
output.setWithTimestamp(s1.keyTimestamp('activeMasterKeyId') > s2.keyTimestamp('activeMasterKeyId') ? s1 : s2, 'activeMasterKeyId');
}
};
export function mergeSyncInfos(s1: SyncInfo, s2: SyncInfo): SyncInfo {
const output: SyncInfo = new SyncInfo();
output.setWithTimestamp(s1.keyTimestamp('e2ee') > s2.keyTimestamp('e2ee') ? s1 : s2, 'e2ee');
output.setWithTimestamp(s1.keyTimestamp('activeMasterKeyId') > s2.keyTimestamp('activeMasterKeyId') ? s1 : s2, 'activeMasterKeyId');
output.setWithTimestamp(s1.keyTimestamp('ppk') > s2.keyTimestamp('ppk') ? s1 : s2, 'ppk');
output.version = s1.version > s2.version ? s1.version : s2.version;
@ -110,6 +131,8 @@ export function mergeSyncInfos(s1: SyncInfo, s2: SyncInfo): SyncInfo {
}
}
mergeActiveMasterKeys(s1, s2, output);
return output;
}
@ -154,6 +177,14 @@ export class SyncInfo {
this.activeMasterKeyId_ = 'activeMasterKeyId' in s ? s.activeMasterKeyId : { value: '', updatedTime: 0 };
this.masterKeys_ = 'masterKeys' in s ? s.masterKeys : [];
this.ppk_ = 'ppk' in s ? s.ppk : { value: null, updatedTime: 0 };
// Migration for master keys that didn't have "hasBeenUsed" property -
// in that case we assume they've been used at least once.
for (const mk of this.masterKeys_) {
if (!('hasBeenUsed' in mk) || mk.hasBeenUsed === undefined) {
mk.hasBeenUsed = true;
}
}
}
public setWithTimestamp(fromSyncInfo: SyncInfo, propName: string) {