2023-03-08 21:08:05 +02:00
|
|
|
/* eslint-disable jest/require-top-level-describe */
|
|
|
|
|
2021-05-21 17:02:29 +02:00
|
|
|
import KeychainService from '@joplin/lib/services/keychain/KeychainService';
|
|
|
|
import shim from '@joplin/lib/shim';
|
|
|
|
import Setting from '@joplin/lib/models/Setting';
|
|
|
|
import { db, setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
|
2020-10-20 17:16:18 +02:00
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
function describeIfCompatible(name: string, fn: any, elseFn: any) {
|
2020-10-20 17:16:18 +02:00
|
|
|
if (['win32', 'darwin'].includes(shim.platformName())) {
|
|
|
|
return describe(name, fn);
|
2020-11-10 17:59:30 +02:00
|
|
|
} else {
|
|
|
|
elseFn();
|
2020-10-20 17:16:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 17:02:29 +02:00
|
|
|
describeIfCompatible('services_KeychainService', () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
|
2022-11-15 12:23:50 +02:00
|
|
|
beforeEach(async () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
await setupDatabaseAndSynchronizer(1, { keychainEnabled: true });
|
|
|
|
await switchClient(1, { keychainEnabled: true });
|
|
|
|
await Setting.deleteKeychainPasswords();
|
|
|
|
});
|
|
|
|
|
2022-11-15 12:23:50 +02:00
|
|
|
afterEach(async () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
await Setting.deleteKeychainPasswords();
|
|
|
|
});
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should be enabled on macOS and Windows', (async () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
expect(Setting.value('keychain.supported')).toBe(1);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should set, get and delete passwords', (async () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
const service = KeychainService.instance();
|
|
|
|
|
|
|
|
const isSet = await service.setPassword('zz_testunit', 'password');
|
|
|
|
expect(isSet).toBe(true);
|
|
|
|
|
|
|
|
const password = await service.password('zz_testunit');
|
|
|
|
expect(password).toBe('password');
|
|
|
|
|
|
|
|
await service.deletePassword('zz_testunit');
|
|
|
|
|
|
|
|
expect(await service.password('zz_testunit')).toBe(null);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should save and load secure settings', (async () => {
|
2020-10-20 17:16:18 +02:00
|
|
|
Setting.setObjectValue('encryption.passwordCache', 'testing', '123456');
|
|
|
|
await Setting.saveAll();
|
|
|
|
await Setting.load();
|
|
|
|
const passwords = Setting.value('encryption.passwordCache');
|
|
|
|
expect(passwords.testing).toBe('123456');
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should delete db settings if they have been saved in keychain', (async () => {
|
2024-02-26 12:16:23 +02:00
|
|
|
// First save some secure settings and make sure it ends up in the database
|
2020-10-20 17:16:18 +02:00
|
|
|
KeychainService.instance().enabled = false;
|
|
|
|
|
|
|
|
Setting.setValue('sync.5.password', 'password');
|
|
|
|
await Setting.saveAll();
|
|
|
|
|
|
|
|
{
|
|
|
|
// Check that it is in the database
|
|
|
|
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
|
|
|
|
expect(row.value).toBe('password');
|
|
|
|
}
|
|
|
|
|
|
|
|
KeychainService.instance().enabled = true;
|
|
|
|
|
|
|
|
// Change any setting to make sure a save operation is triggered
|
|
|
|
Setting.setValue('sync.5.path', '/tmp');
|
|
|
|
|
|
|
|
// Save the settings - now db secure keys should have been cleared and moved to keychain
|
|
|
|
await Setting.saveAll();
|
|
|
|
|
|
|
|
{
|
|
|
|
// Check that it's been removed from the database
|
|
|
|
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
|
|
|
|
expect(row).toBe(undefined);
|
|
|
|
}
|
|
|
|
|
|
|
|
// However we should still get it via the Setting class, since it will use the keychain
|
|
|
|
expect(Setting.value('sync.5.password')).toBe('password');
|
2020-10-20 17:37:14 +02:00
|
|
|
|
|
|
|
// Now do it again - because there was a bug that would cause the second attempt to save to the db instead
|
|
|
|
Setting.setValue('sync.5.username', 'john');
|
|
|
|
await Setting.saveAll();
|
|
|
|
|
|
|
|
{
|
|
|
|
// Check that it's been removed from the database
|
|
|
|
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
|
|
|
|
expect(row).toBe(undefined);
|
|
|
|
}
|
2020-10-20 17:16:18 +02:00
|
|
|
}));
|
|
|
|
|
2020-11-10 17:59:30 +02:00
|
|
|
}, () => {
|
|
|
|
|
|
|
|
it('will pass', () => {
|
|
|
|
expect(true).toBe(true);
|
|
|
|
});
|
|
|
|
|
2020-10-20 17:16:18 +02:00
|
|
|
});
|