diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-05-26 15:23:11 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-05-27 21:07:44 +0200 |
commit | f712970fa91ab990c9ce959bf0889f68bfad8658 (patch) | |
tree | 0358e1e2ab232a6369ba93352fa6c301311a313f | |
parent | build: fix test rootDir configuration (diff) | |
download | sophie-f712970fa91ab990c9ce959bf0889f68bfad8658.tar.gz sophie-f712970fa91ab990c9ce959bf0889f68bfad8658.tar.zst sophie-f712970fa91ab990c9ce959bf0889f68bfad8658.zip |
refactor: move certificate trust to main process
There is no need to synchronize the list of trusted certificates to the
renderer process, so we can get away with storing them in the transient
state of the Profile store.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
-rw-r--r-- | packages/main/src/stores/Profile.ts | 43 | ||||
-rw-r--r-- | packages/main/src/stores/Service.ts | 5 | ||||
-rw-r--r-- | packages/shared/src/stores/Profile.ts | 23 | ||||
-rw-r--r-- | packages/shared/src/stores/ServiceBase.ts | 11 | ||||
-rw-r--r-- | packages/shared/src/stores/__tests__/ServiceBase.test.ts | 23 |
5 files changed, 43 insertions, 62 deletions
diff --git a/packages/main/src/stores/Profile.ts b/packages/main/src/stores/Profile.ts index b4343a0..73f4f0b 100644 --- a/packages/main/src/stores/Profile.ts +++ b/packages/main/src/stores/Profile.ts | |||
@@ -18,21 +18,40 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Certificate, Profile as ProfileBase } from '@sophie/shared'; | 21 | import { |
22 | import { clone, getSnapshot, Instance } from 'mobx-state-tree'; | 22 | type Certificate, |
23 | type CertificateSnapshotIn, | ||
24 | Profile as ProfileBase, | ||
25 | } from '@sophie/shared'; | ||
26 | import { getSnapshot, type Instance } from 'mobx-state-tree'; | ||
23 | 27 | ||
24 | import type ProfileConfig from './config/ProfileConfig.js'; | 28 | import type ProfileConfig from './config/ProfileConfig.js'; |
25 | 29 | ||
26 | const Profile = ProfileBase.views((self) => ({ | 30 | const Profile = ProfileBase.volatile( |
27 | get config(): ProfileConfig { | 31 | (): { |
28 | const { id, settings } = self; | 32 | temporarilyTrustedCertificates: string[]; |
29 | return { ...getSnapshot(settings), id }; | 33 | } => ({ |
30 | }, | 34 | temporarilyTrustedCertificates: [], |
31 | })).actions((self) => ({ | 35 | }), |
32 | temporarilyTrustCertificate(certificate: Certificate): void { | 36 | ) |
33 | self.temporarilyTrustedCertificates.push(clone(certificate)); | 37 | .views((self) => ({ |
34 | }, | 38 | get config(): ProfileConfig { |
35 | })); | 39 | const { id, settings } = self; |
40 | return { ...getSnapshot(settings), id }; | ||
41 | }, | ||
42 | isCertificateTemporarilyTrusted( | ||
43 | certificate: CertificateSnapshotIn, | ||
44 | ): boolean { | ||
45 | return self.temporarilyTrustedCertificates.includes( | ||
46 | certificate.fingerprint, | ||
47 | ); | ||
48 | }, | ||
49 | })) | ||
50 | .actions((self) => ({ | ||
51 | temporarilyTrustCertificate(certificate: Certificate): void { | ||
52 | self.temporarilyTrustedCertificates.push(certificate.fingerprint); | ||
53 | }, | ||
54 | })); | ||
36 | 55 | ||
37 | /* | 56 | /* |
38 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 57 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
diff --git a/packages/main/src/stores/Service.ts b/packages/main/src/stores/Service.ts index 3b7d0b2..d062fe1 100644 --- a/packages/main/src/stores/Service.ts +++ b/packages/main/src/stores/Service.ts | |||
@@ -67,6 +67,11 @@ const Service = defineServiceModel(ServiceSettings) | |||
67 | get shouldBeLoaded(): boolean { | 67 | get shouldBeLoaded(): boolean { |
68 | return !self.crashed; | 68 | return !self.crashed; |
69 | }, | 69 | }, |
70 | isCertificateTemporarilyTrusted( | ||
71 | certificate: CertificateSnapshotIn, | ||
72 | ): boolean { | ||
73 | return self.settings.profile.isCertificateTemporarilyTrusted(certificate); | ||
74 | }, | ||
70 | })) | 75 | })) |
71 | .views((self) => ({ | 76 | .views((self) => ({ |
72 | get shouldBeVisible(): boolean { | 77 | get shouldBeVisible(): boolean { |
diff --git a/packages/shared/src/stores/Profile.ts b/packages/shared/src/stores/Profile.ts index 076c639..7d00925 100644 --- a/packages/shared/src/stores/Profile.ts +++ b/packages/shared/src/stores/Profile.ts | |||
@@ -18,28 +18,15 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { Instance, types } from 'mobx-state-tree'; | 21 | import { type Instance, types } from 'mobx-state-tree'; |
22 | 22 | ||
23 | import Certificate, { CertificateSnapshotIn } from './Certificate.js'; | ||
24 | import ProfileSettings from './ProfileSettings.js'; | 23 | import ProfileSettings from './ProfileSettings.js'; |
25 | 24 | ||
26 | const Profile = /* @__PURE__ */ (() => | 25 | const Profile = /* @__PURE__ */ (() => |
27 | types | 26 | types.model('Profile', { |
28 | .model('Profile', { | 27 | id: types.identifier, |
29 | id: types.identifier, | 28 | settings: ProfileSettings, |
30 | settings: ProfileSettings, | 29 | }))(); |
31 | temporarilyTrustedCertificates: types.array(Certificate), | ||
32 | }) | ||
33 | .views((self) => ({ | ||
34 | isCertificateTemporarilyTrusted( | ||
35 | certificate: CertificateSnapshotIn, | ||
36 | ): boolean { | ||
37 | return self.temporarilyTrustedCertificates.some( | ||
38 | (trustedCertificate) => | ||
39 | trustedCertificate.fingerprint === certificate.fingerprint, | ||
40 | ); | ||
41 | }, | ||
42 | })))(); | ||
43 | 30 | ||
44 | /* | 31 | /* |
45 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 32 | eslint-disable-next-line @typescript-eslint/no-redeclare -- |
diff --git a/packages/shared/src/stores/ServiceBase.ts b/packages/shared/src/stores/ServiceBase.ts index 7bd1d68..b2aff67 100644 --- a/packages/shared/src/stores/ServiceBase.ts +++ b/packages/shared/src/stores/ServiceBase.ts | |||
@@ -18,10 +18,8 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { IAnyModelType, Instance, types } from 'mobx-state-tree'; | 21 | import { type IAnyModelType, type Instance, types } from 'mobx-state-tree'; |
22 | 22 | ||
23 | import type { CertificateSnapshotIn } from './Certificate.js'; | ||
24 | import type Profile from './Profile.js'; | ||
25 | import ServiceSettingsBase from './ServiceSettingsBase.js'; | 23 | import ServiceSettingsBase from './ServiceSettingsBase.js'; |
26 | import ServiceState from './ServiceState.js'; | 24 | import ServiceState from './ServiceState.js'; |
27 | 25 | ||
@@ -56,13 +54,6 @@ export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | |||
56 | get crashed(): boolean { | 54 | get crashed(): boolean { |
57 | return self.state.type === 'crashed'; | 55 | return self.state.type === 'crashed'; |
58 | }, | 56 | }, |
59 | isCertificateTemporarilyTrusted( | ||
60 | certificate: CertificateSnapshotIn, | ||
61 | ): boolean { | ||
62 | return ( | ||
63 | self.settings.profile as Profile | ||
64 | ).isCertificateTemporarilyTrusted(certificate); | ||
65 | }, | ||
66 | get securityLabel(): SecurityLabelKind { | 57 | get securityLabel(): SecurityLabelKind { |
67 | const { | 58 | const { |
68 | state: { type: stateType }, | 59 | state: { type: stateType }, |
diff --git a/packages/shared/src/stores/__tests__/ServiceBase.test.ts b/packages/shared/src/stores/__tests__/ServiceBase.test.ts index e7aa078..e2b0aa9 100644 --- a/packages/shared/src/stores/__tests__/ServiceBase.test.ts +++ b/packages/shared/src/stores/__tests__/ServiceBase.test.ts | |||
@@ -66,14 +66,10 @@ const testCertificate: SnapshotIn<typeof Certificate> = { | |||
66 | 66 | ||
67 | function createTestService( | 67 | function createTestService( |
68 | snapshot: Partial<SnapshotIn<typeof ServiceBase>>, | 68 | snapshot: Partial<SnapshotIn<typeof ServiceBase>>, |
69 | profileSnapshot?: Partial<SnapshotIn<typeof Profile>>, | ||
70 | ): ServiceBase { | 69 | ): ServiceBase { |
71 | const sharedStore = SharedStoreBase.create({ | 70 | const sharedStore = SharedStoreBase.create({ |
72 | profilesById: { | 71 | profilesById: { |
73 | testProfile: { | 72 | testProfile, |
74 | ...testProfile, | ||
75 | ...profileSnapshot, | ||
76 | }, | ||
77 | }, | 73 | }, |
78 | servicesById: { | 74 | servicesById: { |
79 | testService: { | 75 | testService: { |
@@ -187,20 +183,3 @@ test('shows a certificate error warning if there is a certificate error', () => | |||
187 | expect(service.securityLabel).toBe(SecurityLabelKind.CertificateError); | 183 | expect(service.securityLabel).toBe(SecurityLabelKind.CertificateError); |
188 | expect(service.alwaysShowLocationBar).toBe(true); | 184 | expect(service.alwaysShowLocationBar).toBe(true); |
189 | }); | 185 | }); |
190 | |||
191 | test('does not trust an untrusted certificate', () => { | ||
192 | const service = createTestService({}); | ||
193 | |||
194 | expect(service.isCertificateTemporarilyTrusted(testCertificate)).toBe(false); | ||
195 | }); | ||
196 | |||
197 | test('trusts a trusted certificate', () => { | ||
198 | const service = createTestService( | ||
199 | {}, | ||
200 | { | ||
201 | temporarilyTrustedCertificates: [testCertificate], | ||
202 | }, | ||
203 | ); | ||
204 | |||
205 | expect(service.isCertificateTemporarilyTrusted(testCertificate)).toBe(true); | ||
206 | }); | ||