diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-04-26 16:55:57 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-05-16 00:55:02 +0200 |
commit | b971de0717a66ae6085670fe5d3a469e236a9446 (patch) | |
tree | c64352908648512bad713fc1e91dd5f07a66968c /packages/main/src/infrastructure | |
parent | refactor: remove json5 dependency (diff) | |
download | sophie-b971de0717a66ae6085670fe5d3a469e236a9446.tar.gz sophie-b971de0717a66ae6085670fe5d3a469e236a9446.tar.zst sophie-b971de0717a66ae6085670fe5d3a469e236a9446.zip |
refactor: config file saving and debugging
Reduce the number of dependencies and the amount of code running in a
security sensitive context.
Instead of a deep comparison, we just compare the serialized versions
of the config files.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/main/src/infrastructure')
4 files changed, 37 insertions, 37 deletions
diff --git a/packages/main/src/infrastructure/config/ConfigRepository.ts b/packages/main/src/infrastructure/config/ConfigRepository.ts index e00f5a0..67bffb0 100644 --- a/packages/main/src/infrastructure/config/ConfigRepository.ts +++ b/packages/main/src/infrastructure/config/ConfigRepository.ts | |||
@@ -18,17 +18,16 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import type Config from '../../stores/config/Config'; | ||
22 | import type Disposer from '../../utils/Disposer'; | 21 | import type Disposer from '../../utils/Disposer'; |
23 | 22 | ||
24 | export type ReadConfigResult = | 23 | export type ReadConfigResult = |
25 | | { found: true; data: unknown } | 24 | | { found: true; contents: string } |
26 | | { found: false }; | 25 | | { found: false }; |
27 | 26 | ||
28 | export default interface ConfigPersistence { | 27 | export default interface ConfigPersistence { |
29 | readConfig(): Promise<ReadConfigResult>; | 28 | readConfig(): Promise<ReadConfigResult>; |
30 | 29 | ||
31 | writeConfig(config: Config): Promise<void>; | 30 | writeConfig(contents: string): Promise<void>; |
32 | 31 | ||
33 | watchConfig(callback: () => Promise<void>, throttleMs: number): Disposer; | 32 | watchConfig(callback: () => Promise<void>, throttleMs: number): Disposer; |
34 | } | 33 | } |
diff --git a/packages/main/src/infrastructure/config/impl/ConfigFile.ts b/packages/main/src/infrastructure/config/impl/ConfigFile.ts index c4e6d22..8b110a2 100644 --- a/packages/main/src/infrastructure/config/impl/ConfigFile.ts +++ b/packages/main/src/infrastructure/config/impl/ConfigFile.ts | |||
@@ -24,7 +24,6 @@ import path from 'node:path'; | |||
24 | 24 | ||
25 | import { throttle } from 'lodash-es'; | 25 | import { throttle } from 'lodash-es'; |
26 | 26 | ||
27 | import type Config from '../../../stores/config/Config'; | ||
28 | import type Disposer from '../../../utils/Disposer'; | 27 | import type Disposer from '../../../utils/Disposer'; |
29 | import isErrno from '../../../utils/isErrno'; | 28 | import isErrno from '../../../utils/isErrno'; |
30 | import { getLogger } from '../../../utils/log'; | 29 | import { getLogger } from '../../../utils/log'; |
@@ -48,9 +47,9 @@ export default class ConfigFile implements ConfigRepository { | |||
48 | } | 47 | } |
49 | 48 | ||
50 | async readConfig(): Promise<ReadConfigResult> { | 49 | async readConfig(): Promise<ReadConfigResult> { |
51 | let configStr: string; | 50 | let contents: string; |
52 | try { | 51 | try { |
53 | configStr = await readFile(this.configFilePath, 'utf8'); | 52 | contents = await readFile(this.configFilePath, 'utf8'); |
54 | } catch (error) { | 53 | } catch (error) { |
55 | if (isErrno(error, 'ENOENT')) { | 54 | if (isErrno(error, 'ENOENT')) { |
56 | log.debug('Config file', this.configFilePath, 'was not found'); | 55 | log.debug('Config file', this.configFilePath, 'was not found'); |
@@ -61,15 +60,14 @@ export default class ConfigFile implements ConfigRepository { | |||
61 | log.info('Read config file', this.configFilePath); | 60 | log.info('Read config file', this.configFilePath); |
62 | return { | 61 | return { |
63 | found: true, | 62 | found: true, |
64 | data: JSON.parse(configStr), | 63 | contents, |
65 | }; | 64 | }; |
66 | } | 65 | } |
67 | 66 | ||
68 | async writeConfig(configSnapshot: Config): Promise<void> { | 67 | async writeConfig(contents: string): Promise<void> { |
69 | const configJson = JSON.stringify(configSnapshot, undefined, 2); | ||
70 | this.writingConfig = true; | 68 | this.writingConfig = true; |
71 | try { | 69 | try { |
72 | await writeFile(this.configFilePath, configJson, 'utf8'); | 70 | await writeFile(this.configFilePath, contents, 'utf8'); |
73 | const { mtime } = await stat(this.configFilePath); | 71 | const { mtime } = await stat(this.configFilePath); |
74 | log.trace('Config file', this.configFilePath, 'last written at', mtime); | 72 | log.trace('Config file', this.configFilePath, 'last written at', mtime); |
75 | this.timeLastWritten = mtime; | 73 | this.timeLastWritten = mtime; |
diff --git a/packages/main/src/infrastructure/electron/impl/devTools.ts b/packages/main/src/infrastructure/electron/impl/devTools.ts index 10f4545..6db88d1 100644 --- a/packages/main/src/infrastructure/electron/impl/devTools.ts +++ b/packages/main/src/infrastructure/electron/impl/devTools.ts | |||
@@ -18,34 +18,32 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import type { BrowserWindow } from 'electron'; | 21 | import { app, type BrowserWindow } from 'electron'; |
22 | |||
23 | /* eslint-disable | ||
24 | import/no-extraneous-dependencies, | ||
25 | global-require, | ||
26 | @typescript-eslint/no-var-requires, | ||
27 | unicorn/prefer-module -- | ||
28 | Hack to lazily require a CJS module from an ES module transpiled into a CJS module. | ||
29 | */ | ||
22 | 30 | ||
23 | /** | 31 | /** |
24 | * URL prefixes Sophie is allowed load in dev mode. | 32 | * Makes sure we use a separate data dir for development. |
25 | * | ||
26 | * In dev mode, in addition to the application itself, | ||
27 | * Sophie must be able do download and load the devtools and related extensions, | ||
28 | * so we have to make exceptions in the UI process request filter. | ||
29 | */ | 33 | */ |
30 | export const DEVMODE_ALLOWED_URL_PREFIXES = [ | 34 | export function ensureDevDataDir(): void { |
31 | 'chrome-extension:', | 35 | // Use alternative directory when debugging to avoid clobbering the main installation. |
32 | 'devtools:', | 36 | app.setPath('userData', `${app.getPath('userData')}-dev`); |
33 | 'https://clients2.google.com/service/update2/crx', | 37 | const userData = app.getPath('userData'); |
34 | 'https://clients2.googleusercontent.com/crx', | 38 | const mkdirp = require('mkdirp') as typeof import('mkdirp'); |
35 | ]; | 39 | mkdirp.sync(userData); |
40 | } | ||
36 | 41 | ||
37 | /** | 42 | /** |
38 | * Enables using source maps for node stack traces. | 43 | * Enables using source maps for node stack traces. |
39 | */ | 44 | */ |
40 | export function enableStacktraceSourceMaps(): void { | 45 | export function enableStacktraceSourceMaps(): void { |
41 | const sourceMapSupport = | 46 | const sourceMapSupport = |
42 | /* eslint-disable-next-line | ||
43 | import/no-extraneous-dependencies, | ||
44 | global-require, | ||
45 | @typescript-eslint/no-var-requires, | ||
46 | unicorn/prefer-module -- | ||
47 | Hack to lazily require a CJS module from an ES module transpiled into a CJS module. | ||
48 | */ | ||
49 | require('source-map-support') as typeof import('source-map-support'); | 47 | require('source-map-support') as typeof import('source-map-support'); |
50 | sourceMapSupport.install(); | 48 | sourceMapSupport.install(); |
51 | } | 49 | } |
@@ -61,13 +59,6 @@ export async function installDevToolsExtensions(): Promise<void> { | |||
61 | default: installExtension, | 59 | default: installExtension, |
62 | REACT_DEVELOPER_TOOLS, | 60 | REACT_DEVELOPER_TOOLS, |
63 | REDUX_DEVTOOLS, | 61 | REDUX_DEVTOOLS, |
64 | /* eslint-disable-next-line | ||
65 | import/no-extraneous-dependencies, | ||
66 | global-require, | ||
67 | @typescript-eslint/no-var-requires, | ||
68 | unicorn/prefer-module -- | ||
69 | Hack to lazily require a CJS module from an ES module transpiled into a CJS module. | ||
70 | */ | ||
71 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); | 62 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); |
72 | await installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS], { | 63 | await installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS], { |
73 | forceDownload: false, | 64 | forceDownload: false, |
diff --git a/packages/main/src/infrastructure/electron/impl/hardenSession.ts b/packages/main/src/infrastructure/electron/impl/hardenSession.ts index 10b694a..53675a7 100644 --- a/packages/main/src/infrastructure/electron/impl/hardenSession.ts +++ b/packages/main/src/infrastructure/electron/impl/hardenSession.ts | |||
@@ -25,7 +25,19 @@ import type { Session } from 'electron'; | |||
25 | import { getLogger } from '../../../utils/log'; | 25 | import { getLogger } from '../../../utils/log'; |
26 | import type Resources from '../../resources/Resources'; | 26 | import type Resources from '../../resources/Resources'; |
27 | 27 | ||
28 | import { DEVMODE_ALLOWED_URL_PREFIXES } from './devTools'; | 28 | /** |
29 | * URL prefixes Sophie is allowed load in dev mode. | ||
30 | * | ||
31 | * In dev mode, in addition to the application itself, | ||
32 | * Sophie must be able do download and load the devtools and related extensions, | ||
33 | * so we have to make exceptions in the UI process request filter. | ||
34 | */ | ||
35 | export const DEVMODE_ALLOWED_URL_PREFIXES = [ | ||
36 | 'chrome-extension:', | ||
37 | 'devtools:', | ||
38 | 'https://clients2.google.com/service/update2/crx', | ||
39 | 'https://clients2.googleusercontent.com/crx', | ||
40 | ]; | ||
29 | 41 | ||
30 | const log = getLogger('hardenSession'); | 42 | const log = getLogger('hardenSession'); |
31 | 43 | ||