1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Desktop: Fixes #8143: Fixes crash when using multiple profiles along with certain plugins

This commit is contained in:
Laurent Cozic 2023-05-08 16:45:18 +01:00
parent f390eca4de
commit 6672f63981
3 changed files with 46 additions and 9 deletions

View File

@ -1,4 +1,4 @@
import Setting, { SettingSectionSource, SettingStorage } from '../models/Setting';
import Setting, { SettingItemType, SettingSectionSource, SettingStorage } from '../models/Setting';
import { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, msleep } from '../testing/test-utils';
import { readFile, stat, mkdirp, writeFile, pathExists, readdir } from 'fs-extra';
import Logger from '../Logger';
@ -297,12 +297,21 @@ describe('models/Setting', () => {
expect(Setting.isSet('spellChecker.languages')).toBe(false);
}));
it('should load sub-profile settings - 1', async () => {
it('should load sub-profile settings', async () => {
await Setting.reset();
await Setting.registerSetting('non_builtin', {
public: true,
storage: SettingStorage.File,
isGlobal: true,
type: SettingItemType.Bool,
value: false,
});
Setting.setValue('locale', 'fr_FR'); // Global setting
Setting.setValue('theme', Setting.THEME_DARK); // Global setting
Setting.setValue('sync.target', 9); // Local setting
Setting.setValue('non_builtin', true); // Local setting
await Setting.saveAll();
await switchToSubProfileSettings();
@ -311,6 +320,9 @@ describe('models/Setting', () => {
expect(Setting.value('theme')).toBe(Setting.THEME_DARK); // Should come from the root profile
expect(Setting.value('sync.target')).toBe(0); // Should come from the local profile
// Non-built-in variables are not copied
expect(() => Setting.value('non_builtin')).toThrow();
// Also check that the special loadOne() function works as expected
expect((await Setting.loadOne('locale')).value).toBe('fr_FR');
@ -318,7 +330,7 @@ describe('models/Setting', () => {
expect((await Setting.loadOne('sync.target')).value).toBe(undefined);
});
it('should save sub-profile settings - 2', async () => {
it('should save sub-profile settings', async () => {
await Setting.reset();
Setting.setValue('locale', 'fr_FR'); // Global setting
Setting.setValue('theme', Setting.THEME_DARK); // Global setting

View File

@ -313,6 +313,7 @@ class Setting extends BaseModel {
private static fileHandler_: FileHandler = null;
private static rootFileHandler_: FileHandler = null;
private static settingFilename_: string = 'settings.json';
private static buildInMetadata_: SettingItems = null;
public static tableName() {
return 'settings';
@ -407,7 +408,7 @@ class Setting extends BaseModel {
return output;
};
this.metadata_ = {
this.buildInMetadata_ = {
'clientId': {
value: '',
type: SettingItemType.String,
@ -1697,6 +1698,8 @@ class Setting extends BaseModel {
};
this.metadata_ = { ...this.buildInMetadata_ };
this.metadata_ = Object.assign(this.metadata_, this.customMetadata_);
if (this.constants_.env === Env.Dev) this.validateMetadata(this.metadata_);
@ -1710,6 +1713,10 @@ class Setting extends BaseModel {
}
}
public static isBuiltinKey(key: string): boolean {
return key in this.buildInMetadata_;
}
public static customCssFilePath(filename: string): string {
return `${this.value('rootProfileDir')}/${filename}`;
}
@ -2256,7 +2263,7 @@ class Setting extends BaseModel {
public static enumOptions(key: string) {
const metadata = this.metadata();
if (!metadata[key]) throw new Error(`Unknown key: ${key}`);
if (!metadata[key]) throw new JoplinError(`Unknown key: ${key}`, 'unknown_key');
if (!metadata[key].options) throw new Error(`No options for: ${key}`);
return metadata[key].options();
}

View File

@ -7,14 +7,32 @@ export default (rootSettings: Record<string, any>, subProfileSettings: Record<st
const output: Record<string, any> = { ...subProfileSettings };
for (const k of Object.keys(output)) {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
delete output[k];
if (k in rootSettings) output[k] = rootSettings[k];
try {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {
delete output[k];
if (k in rootSettings) output[k] = rootSettings[k];
}
} catch (error) {
if (error.code === 'unknown_key') {
// The root settings may contain plugin parameters, but the
// sub-profile won't necessarily have these plugins. In that
// case, the app will throw an error, but we can ignore it since
// we don't need this particular setting.
// https://github.com/laurent22/joplin/issues/8143
logger.info(`Ignoring unknown key in root settings: ${k}`);
}
}
}
for (const k of Object.keys(rootSettings)) {
// We only copy built-in key and not, for example, plugin keys, because
// those are plugin-specific
if (!Setting.isBuiltinKey(k)) {
logger.info(`Skipping non-built-in key: ${k}`);
continue;
}
try {
const md = Setting.settingMetadata(k);
if (md.isGlobal) {