Merge branch 'fix-unauth' into 'main'
[ProtonMail-WebClient.git] / packages / account / securityCheckup / helpers / getSecurityCheckupRecommendations.ts
blobd0f97b7d465017b9d94b39fa52e077bdde2bd251
1 import {
2     getIsAlmostPerfectEmailState,
3     getIsAlmostPerfectPhoneState,
4     getIsPerfectDeviceRecoveryState,
5     getIsPerfectEmailState,
6     getIsPerfectPhoneState,
7     getIsPerfectPhraseState,
8 } from '@proton/shared/lib/helpers/securityCheckup';
9 import type { SecurityCheckupAction } from '@proton/shared/lib/interfaces/securityCheckup';
10 import SecurityCheckupCohort from '@proton/shared/lib/interfaces/securityCheckup/SecurityCheckupCohort';
11 import type SecurityState from '@proton/shared/lib/interfaces/securityCheckup/SecurityState';
13 class Actions {
14     private actionsSet: Set<SecurityCheckupAction>;
16     private securityState: SecurityState;
18     private isPerfectPhraseState: boolean;
20     private isPerfectEmailState: boolean;
22     private isPerfectPhoneState: boolean;
24     private isPerfectDeviceRecoveryState: boolean;
26     public shouldActionDevice: boolean;
28     constructor(securityState: SecurityState) {
29         this.actionsSet = new Set<SecurityCheckupAction>();
31         this.securityState = securityState;
33         this.isPerfectPhraseState = getIsPerfectPhraseState(securityState);
34         this.isPerfectEmailState = getIsPerfectEmailState(securityState);
35         this.isPerfectPhoneState = getIsPerfectPhoneState(securityState);
36         this.isPerfectDeviceRecoveryState = getIsPerfectDeviceRecoveryState(securityState);
38         this.shouldActionDevice =
39             (this.isPerfectEmailState || this.isPerfectPhoneState) && !this.isPerfectDeviceRecoveryState;
40     }
42     public phrase() {
43         if (!this.securityState.phrase.isAvailable) {
44             return;
45         }
47         if (!this.isPerfectPhraseState) {
48             this.actionsSet.add('phrase');
49         }
50     }
52     public email() {
53         if (!this.isPerfectEmailState) {
54             this.actionsSet.add('email');
55         }
56     }
58     public phone() {
59         if (!this.isPerfectPhoneState) {
60             this.actionsSet.add('phone');
61         }
62     }
64     public emailOrPhone() {
65         this.email();
66         this.phone();
67     }
69     public device() {
70         if (!this.securityState.deviceRecovery.isAvailable) {
71             return;
72         }
74         if (this.shouldActionDevice) {
75             this.actionsSet.add('device');
76         }
77     }
79     public toArray() {
80         return Array.from(this.actionsSet);
81     }
84 interface SecurityCheckupHealth {
85     cohort: SecurityCheckupCohort;
86     actions: SecurityCheckupAction[];
87     furtherActions: SecurityCheckupAction[];
90 const getSecurityCheckupRecommendations = (securityState: SecurityState): SecurityCheckupHealth => {
91     const isPerfectPhraseState = getIsPerfectPhraseState(securityState);
93     const isPerfectEmailState = getIsPerfectEmailState(securityState);
94     const isAlmostPerfectEmailState = getIsAlmostPerfectEmailState(securityState);
96     const isPerfectPhoneState = getIsPerfectPhoneState(securityState);
97     const isAlmostPerfectPhoneState = getIsAlmostPerfectPhoneState(securityState);
99     const isPerfectEmailOrPhoneState = isPerfectEmailState || isPerfectPhoneState;
101     const isPerfectDeviceState = getIsPerfectDeviceRecoveryState(securityState);
103     const actions = new Actions(securityState);
104     const furtherActions = new Actions(securityState);
106     const serialize = ({
107         cohort,
108         actions,
109         furtherActions,
110     }: {
111         cohort: SecurityCheckupCohort;
112         actions: Actions;
113         furtherActions: Actions;
114     }) => {
115         return {
116             cohort,
117             actions: actions.toArray(),
118             furtherActions: furtherActions.toArray(),
119         };
120     };
122     /**
123      * COMPLETE_RECOVERY_MULTIPLE
124      **/
125     if (isPerfectPhraseState && isPerfectEmailOrPhoneState && isPerfectDeviceState) {
126         actions.device();
127         furtherActions.emailOrPhone();
129         return serialize({
130             cohort: SecurityCheckupCohort.COMPLETE_RECOVERY_MULTIPLE,
131             actions,
132             furtherActions,
133         });
134     }
136     /**
137      * COMPLETE_RECOVERY_SINGLE
138      **/
139     if (isPerfectPhraseState && !isPerfectEmailOrPhoneState) {
140         actions.emailOrPhone();
142         return serialize({
143             cohort: SecurityCheckupCohort.COMPLETE_RECOVERY_SINGLE,
144             actions,
145             furtherActions,
146         });
147     }
149     if (isPerfectPhraseState && isPerfectEmailOrPhoneState && !isPerfectDeviceState) {
150         actions.device();
152         furtherActions.emailOrPhone();
154         return serialize({
155             cohort: SecurityCheckupCohort.COMPLETE_RECOVERY_SINGLE,
156             actions,
157             furtherActions,
158         });
159     }
161     if (!isPerfectPhraseState && isPerfectEmailOrPhoneState && isPerfectDeviceState) {
162         actions.phrase();
164         furtherActions.emailOrPhone();
166         return serialize({
167             cohort: SecurityCheckupCohort.COMPLETE_RECOVERY_SINGLE,
168             actions,
169             furtherActions,
170         });
171     }
173     /**
174      * ACCOUNT_RECOVERY_ENABLED
175      **/
176     if (!isPerfectPhraseState && isPerfectEmailOrPhoneState && !isPerfectDeviceState) {
177         actions.device();
179         furtherActions.phrase();
180         furtherActions.emailOrPhone();
182         return serialize({
183             cohort: SecurityCheckupCohort.ACCOUNT_RECOVERY_ENABLED,
184             actions,
185             furtherActions,
186         });
187     }
189     /**
190      * NO_RECOVERY_METHOD
191      **/
192     if (isAlmostPerfectEmailState || isAlmostPerfectPhoneState) {
193         if (isAlmostPerfectEmailState) {
194             actions.email();
195         }
196         if (isAlmostPerfectPhoneState) {
197             actions.phone();
198         }
199     }
201     actions.phrase();
203     if (!isAlmostPerfectEmailState) {
204         furtherActions.email();
205     }
207     if (!isAlmostPerfectPhoneState) {
208         furtherActions.phone();
209     }
211     return serialize({
212         cohort: SecurityCheckupCohort.NO_RECOVERY_METHOD,
213         actions,
214         furtherActions,
215     });
218 export default getSecurityCheckupRecommendations;