diff options
Diffstat (limited to 'packages/shared')
-rw-r--r-- | packages/shared/src/index.ts | 6 | ||||
-rw-r--r-- | packages/shared/src/schemas/ServiceAction.ts | 4 | ||||
-rw-r--r-- | packages/shared/src/stores/Certificate.ts | 54 | ||||
-rw-r--r-- | packages/shared/src/stores/Profile.ts | 21 | ||||
-rw-r--r-- | packages/shared/src/stores/ServiceBase.ts | 47 | ||||
-rw-r--r-- | packages/shared/src/stores/ServiceState.ts | 72 |
6 files changed, 173 insertions, 31 deletions
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index fa3fbfd..f7c5bcf 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts | |||
@@ -30,6 +30,9 @@ export { ServiceAction } from './schemas/ServiceAction'; | |||
30 | 30 | ||
31 | export { ThemeSource } from './schemas/ThemeSource'; | 31 | export { ThemeSource } from './schemas/ThemeSource'; |
32 | 32 | ||
33 | export type { CertificateSnapshotIn } from './stores/Certificate'; | ||
34 | export { default as Certificate } from './stores/Certificate'; | ||
35 | |||
33 | export type { | 36 | export type { |
34 | GlobalSettingsSnapshotIn, | 37 | GlobalSettingsSnapshotIn, |
35 | GlobalSettingsSnapshotOut, | 38 | GlobalSettingsSnapshotOut, |
@@ -61,6 +64,9 @@ export { | |||
61 | defineServiceSettingsModel, | 64 | defineServiceSettingsModel, |
62 | } from './stores/ServiceSettingsBase'; | 65 | } from './stores/ServiceSettingsBase'; |
63 | 66 | ||
67 | export type { ServiceStateSnapshotIn } from './stores/ServiceState'; | ||
68 | export { default as ServiceState } from './stores/ServiceState'; | ||
69 | |||
64 | export type { | 70 | export type { |
65 | SharedStoreListener, | 71 | SharedStoreListener, |
66 | SharedStoreSnapshotIn, | 72 | SharedStoreSnapshotIn, |
diff --git a/packages/shared/src/schemas/ServiceAction.ts b/packages/shared/src/schemas/ServiceAction.ts index a4a7049..8961bfe 100644 --- a/packages/shared/src/schemas/ServiceAction.ts +++ b/packages/shared/src/schemas/ServiceAction.ts | |||
@@ -42,6 +42,10 @@ export const ServiceAction = /* @__PURE__ */ (() => | |||
42 | action: z.literal('go'), | 42 | action: z.literal('go'), |
43 | url: z.string(), | 43 | url: z.string(), |
44 | }), | 44 | }), |
45 | z.object({ | ||
46 | action: z.literal('temporarily-trust-current-certificate'), | ||
47 | fingerprint: z.string(), | ||
48 | }), | ||
45 | ]))(); | 49 | ]))(); |
46 | 50 | ||
47 | /* | 51 | /* |
diff --git a/packages/shared/src/stores/Certificate.ts b/packages/shared/src/stores/Certificate.ts new file mode 100644 index 0000000..8b2d007 --- /dev/null +++ b/packages/shared/src/stores/Certificate.ts | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { IAnyModelType, Instance, SnapshotIn, types } from 'mobx-state-tree'; | ||
22 | |||
23 | const CertificatePrincipal = /* @__PURE__ */ (() => | ||
24 | types.model('CertificatePrincipal', { | ||
25 | commonName: types.string, | ||
26 | organizations: types.array(types.string), | ||
27 | organizationUnits: types.array(types.string), | ||
28 | locality: types.string, | ||
29 | state: types.string, | ||
30 | country: types.string, | ||
31 | }))(); | ||
32 | |||
33 | const Certificate = /* @__PURE__ */ (() => | ||
34 | types.model('Certificate', { | ||
35 | data: types.string, | ||
36 | issuer: CertificatePrincipal, | ||
37 | issuerName: types.string, | ||
38 | issuerCert: types.maybe(types.late((): IAnyModelType => Certificate)), | ||
39 | subjectName: types.string, | ||
40 | serialNumber: types.string, | ||
41 | validStart: types.number, | ||
42 | validExpiry: types.number, | ||
43 | fingerprint: types.string, | ||
44 | }))(); | ||
45 | |||
46 | /* | ||
47 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
48 | Intentionally naming the type the same as the store definition. | ||
49 | */ | ||
50 | interface Certificate extends Instance<typeof Certificate> {} | ||
51 | |||
52 | export default Certificate; | ||
53 | |||
54 | export interface CertificateSnapshotIn extends SnapshotIn<typeof Certificate> {} | ||
diff --git a/packages/shared/src/stores/Profile.ts b/packages/shared/src/stores/Profile.ts index 49c5195..611ca6f 100644 --- a/packages/shared/src/stores/Profile.ts +++ b/packages/shared/src/stores/Profile.ts | |||
@@ -20,13 +20,26 @@ | |||
20 | 20 | ||
21 | import { Instance, types } from 'mobx-state-tree'; | 21 | import { Instance, types } from 'mobx-state-tree'; |
22 | 22 | ||
23 | import Certificate, { CertificateSnapshotIn } from './Certificate'; | ||
23 | import ProfileSettings from './ProfileSettings'; | 24 | import ProfileSettings from './ProfileSettings'; |
24 | 25 | ||
25 | const Profile = /* @__PURE__ */ (() => | 26 | const Profile = /* @__PURE__ */ (() => |
26 | types.model('Profile', { | 27 | types |
27 | id: types.identifier, | 28 | .model('Profile', { |
28 | settings: ProfileSettings, | 29 | id: types.identifier, |
29 | }))(); | 30 | settings: ProfileSettings, |
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 | })))(); | ||
30 | 43 | ||
31 | /* | 44 | /* |
32 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | 45 | 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 4a17bc5..c69f339 100644 --- a/packages/shared/src/stores/ServiceBase.ts +++ b/packages/shared/src/stores/ServiceBase.ts | |||
@@ -20,7 +20,10 @@ | |||
20 | 20 | ||
21 | import { IAnyModelType, Instance, types } from 'mobx-state-tree'; | 21 | import { IAnyModelType, Instance, types } from 'mobx-state-tree'; |
22 | 22 | ||
23 | import type { CertificateSnapshotIn } from './Certificate'; | ||
24 | import type Profile from './Profile'; | ||
23 | import ServiceSettingsBase from './ServiceSettingsBase'; | 25 | import ServiceSettingsBase from './ServiceSettingsBase'; |
26 | import ServiceState from './ServiceState'; | ||
24 | 27 | ||
25 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | 28 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { |
26 | return types | 29 | return types |
@@ -31,30 +34,7 @@ export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | |||
31 | canGoBack: false, | 34 | canGoBack: false, |
32 | canGoForward: false, | 35 | canGoForward: false, |
33 | title: types.maybe(types.string), | 36 | title: types.maybe(types.string), |
34 | state: types.optional( | 37 | state: ServiceState, |
35 | types.union( | ||
36 | types.model({ | ||
37 | type: types.literal('initializing'), | ||
38 | }), | ||
39 | types.model({ | ||
40 | type: types.literal('loading'), | ||
41 | }), | ||
42 | types.model({ | ||
43 | type: types.literal('loaded'), | ||
44 | }), | ||
45 | types.model({ | ||
46 | type: types.literal('failed'), | ||
47 | errorCode: types.integer, | ||
48 | errorDesc: types.string, | ||
49 | }), | ||
50 | types.model({ | ||
51 | type: types.literal('crashed'), | ||
52 | reason: types.string, | ||
53 | exitCode: types.integer, | ||
54 | }), | ||
55 | ), | ||
56 | { type: 'initializing' }, | ||
57 | ), | ||
58 | directMessageCount: 0, | 38 | directMessageCount: 0, |
59 | indirectMessageCount: 0, | 39 | indirectMessageCount: 0, |
60 | }) | 40 | }) |
@@ -64,12 +44,25 @@ export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | |||
64 | self.state.type === 'initializing' || self.state.type === 'loading' | 44 | self.state.type === 'initializing' || self.state.type === 'loading' |
65 | ); | 45 | ); |
66 | }, | 46 | }, |
67 | get failed(): boolean { | ||
68 | return self.state.type === 'failed'; | ||
69 | }, | ||
70 | get crashed(): boolean { | 47 | get crashed(): boolean { |
71 | return self.state.type === 'crashed'; | 48 | return self.state.type === 'crashed'; |
72 | }, | 49 | }, |
50 | })) | ||
51 | .views((self) => ({ | ||
52 | get hasError(): boolean { | ||
53 | return ( | ||
54 | self.crashed || | ||
55 | self.state.type === 'failed' || | ||
56 | self.state.type === 'certificateError' | ||
57 | ); | ||
58 | }, | ||
59 | isCertificateTemporarilyTrusted( | ||
60 | certificate: CertificateSnapshotIn, | ||
61 | ): boolean { | ||
62 | return ( | ||
63 | self.settings.profile as Profile | ||
64 | ).isCertificateTemporarilyTrusted(certificate); | ||
65 | }, | ||
73 | })); | 66 | })); |
74 | } | 67 | } |
75 | 68 | ||
diff --git a/packages/shared/src/stores/ServiceState.ts b/packages/shared/src/stores/ServiceState.ts new file mode 100644 index 0000000..ad49321 --- /dev/null +++ b/packages/shared/src/stores/ServiceState.ts | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { Instance, SnapshotIn, types } from 'mobx-state-tree'; | ||
22 | |||
23 | import Certificate from './Certificate'; | ||
24 | |||
25 | const ServiceState = /* @__PURE__ */ (() => | ||
26 | types.optional( | ||
27 | types.union( | ||
28 | types.model('ServiceInitializingState', { | ||
29 | type: types.literal('initializing'), | ||
30 | }), | ||
31 | types.model('ServiceLoadingState', { | ||
32 | type: types.literal('loading'), | ||
33 | }), | ||
34 | types.model('ServiceLoadedState', { | ||
35 | type: types.literal('loaded'), | ||
36 | }), | ||
37 | types.model('ServiceFailedState', { | ||
38 | type: types.literal('failed'), | ||
39 | errorCode: types.integer, | ||
40 | errorDesc: types.string, | ||
41 | }), | ||
42 | types.model('ServiceCertificateErrorState', { | ||
43 | type: types.literal('certificateError'), | ||
44 | errorCode: types.string, | ||
45 | certificate: Certificate, | ||
46 | trust: types.optional( | ||
47 | types.union( | ||
48 | types.literal('pending'), | ||
49 | types.literal('rejected'), | ||
50 | types.literal('accepted'), | ||
51 | ), | ||
52 | 'pending', | ||
53 | ), | ||
54 | }), | ||
55 | types.model({ | ||
56 | type: types.literal('crashed'), | ||
57 | reason: types.string, | ||
58 | exitCode: types.integer, | ||
59 | }), | ||
60 | ), | ||
61 | { type: 'initializing' }, | ||
62 | ))(); | ||
63 | |||
64 | /* | ||
65 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
66 | Intentionally naming the type the same as the store definition. | ||
67 | */ | ||
68 | type ServiceState = Instance<typeof ServiceState>; | ||
69 | |||
70 | export default ServiceState; | ||
71 | |||
72 | export type ServiceStateSnapshotIn = SnapshotIn<typeof ServiceState>; | ||