Skip to content

Commit b679693

Browse files
authored
Documentation for initialisation/login code (#31297)
* Documentation in MatrixChat and Lifecycle * State transition diagram for `View`
1 parent fbb43d5 commit b679693

File tree

3 files changed

+130
-3
lines changed

3 files changed

+130
-3
lines changed

src/Lifecycle.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,9 @@ async function abortLogin(): Promise<void> {
599599
}
600600

601601
/** Attempt to restore the session from localStorage or indexeddb.
602+
*
603+
* If the credentials are found, and the session is successfully restored,
604+
* emits {@link Action.OnLoggedIn}, {@link Action.WillStartClient} and {@link Action.StartedClient}.
602605
*
603606
* @returns true if a session was found; false if no existing session was found.
604607
*
@@ -787,6 +790,8 @@ async function createOidcTokenRefresher(credentials: IMatrixClientCreds): Promis
787790
* optionally clears localstorage, persists new credentials
788791
* to localstorage, starts the new client.
789792
*
793+
* Emits {@link Action.OnLoggedIn}, {@link Action.WillStartClient} and {@link Action.StartedClient}.
794+
*
790795
* @param {IMatrixClientCreds} credentials The credentials to use
791796
* @param {Boolean} clearStorageEnabled True to clear storage before starting the new client
792797
* @param {Boolean} isFreshLogin True if this is a fresh login, false if it is previous session being restored
@@ -1019,6 +1024,12 @@ export function isLoggingOut(): boolean {
10191024
* Starts the matrix client and all other react-sdk services that
10201025
* listen for events while a session is logged in.
10211026
*
1027+
* By the time this method is called, we have successfully logged in if necessary, and the client has been set up with
1028+
* the access token.
1029+
*
1030+
* Emits {@link Acction.WillStartClient} before starting the client, and {@link Action.ClientStarted} when the client has
1031+
* been started.
1032+
*
10221033
* @param client the matrix client to start
10231034
* @param startSyncing - `true` to actually start syncing the client.
10241035
* @param clientPegOpts - Options to pass through to {@link MatrixClientPeg.start}.

src/Views.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,76 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
66
Please see LICENSE files in the repository root for full details.
77
*/
88

9-
/** constants for MatrixChat.state.view */
9+
/**
10+
* Constants for MatrixChat.state.view.
11+
*
12+
* The `View` is the primary state machine of the application: it has different states for the various setup flows
13+
* that the user may find themselves in. Once we have a functioning client, we can transition to the `LOGGED_IN` state
14+
* which is the "normal" state of the application.
15+
*
16+
* An incomplete state transition diagram follows.
17+
*
18+
* (initial state)
19+
* ┌─────────────────┐ Lock held by other instance ┌─────────────────┐
20+
* │ LOADING │─────────────────────────────►│ CONFIRM_LOCK_ │
21+
* │ │◄─────────────────────────────│ THEFT │
22+
* └─────────────────┘ Lock theft confirmed └─────────────────┘
23+
* Session recovered │ │ │
24+
* ┌──────────────┘ │ └────────────────┐
25+
* │ ┌─────────────┘ │ No previous session
26+
* │ │ Token/OIDC login succeeded │
27+
* │ │ ▼
28+
* │ │ ┌─────────────────┐
29+
* │ │ │ WELCOME │ (from all other states
30+
* │ │ │ │ except LOCK_STOLEN)
31+
* │ │ └─────────────────┘ │
32+
* │ │ "Create Account" │ │ "Sign in" │ Client logged out
33+
* │ │ ┌────────────────────────┘ │ │
34+
* │ │ │ │ ┌────────────────────┘
35+
* │ │ │ │ │
36+
* │ │ ▼ "Create an ▼ ▼ "Forgot
37+
* │ │ ┌─────────────────┐ account" ┌─────────────────┐ password" ┌─────────────────┐
38+
* │ │ │ REGISTER │◄───────────────│ LOGIN │───────────────►│ FORGOT_PASSWORD │
39+
* │ │ │ │───────────────►│ │◄───────────────│ │
40+
* │ │ └─────────────────┘ "Sign in here" └─────────────────┘ Complete / └─────────────────┘
41+
* │ │ │ │ "Sign in instead" ▲
42+
* │ │ └────────────────────────────────┐ │ │
43+
* │ └────────────────────────────────────────┐ │ │ │
44+
* │ ▼ ▼ ▼ │
45+
* │ ┌──────────────────┐ │
46+
* │ │ (postLoginSetup) │ │
47+
* │ └──────────────────┘ │
48+
* │ ┌────────────────────────────────────┘ │ │ │
49+
* │ │ E2EE not enabled ┌─────────────┘ └──────┐ │
50+
* │ │ │ Account has │ Account lacks │
51+
* │ │ │ cross-signing │ cross-signing │
52+
* │ │ │ keys │ keys │
53+
* │ │ Client started and ▼ ▼ │
54+
* │ │ force_verification ┌─────────────────┐ ┌─────────────────┐ │
55+
* │ │ pending │ COMPLETE_ │ │ E2E_SETUP │ │
56+
* │ │ ┌─────────────────►│ SECURITY │ │ │ │
57+
* │ │ │ └─────────────────┘ └─────────────────┘ │ "Forgotten
58+
* │ │ │ ┌───────────────────────┘ │ │ your
59+
* │ │ │ │ ┌───────────────────────────────────────────────┘ │ password?"
60+
* │ │ │ │ │ │
61+
* │ │ │ │ │ (from all other states │
62+
* │ │ │ │ │ except LOCK_STOLEN) │
63+
* │ │ │ │ │ └──────────────┐ │
64+
* ▼ ▼ │ ▼ ▼ Soft logout error ▼ │
65+
* ┌─────────────────┐ ┌─────────────────┐
66+
* │ LOGGED_IN │ Re-authentication succeeded │ SOFT_LOGOUT │
67+
* │ │◄────────────────────────────────────────────────────────│ │
68+
* └─────────────────┘ └─────────────────┘
69+
*
70+
* (from all other states)
71+
* │
72+
* │ Session lock stolen
73+
* ▼
74+
* ┌─────────────────┐
75+
* │ LOCK_STOLEN │
76+
* │ │
77+
* └─────────────────┘
78+
*/
1079
enum Views {
1180
// a special initial state which is only used at startup, while we are
1281
// trying to re-animate a matrix client or register as a guest.

src/components/structures/MatrixChat.tsx

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ interface IState {
202202
hideToSRUsers: boolean;
203203
syncError: Error | null;
204204
serverConfig?: ValidatedServerConfig;
205+
206+
/** Has our MatrixClient started? */
205207
ready: boolean;
208+
206209
threepidInvite?: IThreepidInvite;
207210
roomOobData?: object;
208211
pendingInitialSync?: boolean;
@@ -225,7 +228,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
225228
private firstSyncPromise: PromiseWithResolvers<void>;
226229

227230
private screenAfterLogin?: IScreen;
231+
232+
/** True if we have successfully completed an OIDC or token login.
233+
*
234+
* XXX it's unclear if this is ever cleared, so what happens if the user logs out and then logs back in?
235+
*/
228236
private tokenLogin?: boolean;
237+
229238
// What to focus on next component update, if anything
230239
private focusNext: FocusNextType;
231240
private subTitleStatus: string;
@@ -386,6 +395,26 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
386395
await Lifecycle.onSessionLockStolen();
387396
}
388397

398+
/**
399+
* Perform actions that are specific to a user that has just logged in (compare {@link onLoggedIn}, which, despite
400+
* its name, is called when an already-logged-in client is restored at session startup).
401+
*
402+
* Called when:
403+
*
404+
* - We successfully completed an OIDC or token login, via {@link initSession}.
405+
* - The {@link Login} or {@link Register} components notify us that we successfully completed a non-OIDC login or
406+
* registration.
407+
*
408+
* In both cases, {@link Action.OnLoggedIn} will already have been emitted, but the call to {@link onLoggedIn} will
409+
* have been suppressed (by either {@link tokenLogin} being set, or the view being set to {@link Views.LOGIN} or
410+
* {@link Views.REGISTER}).
411+
*
412+
* {@link onWillStartClient} and {@link onClientStarted} will already have been called (but not necessarily
413+
* completed).
414+
*
415+
* This method either calls {@link onLiggedIn} directly, or switches to {@link Views.E2E_SETUP} or
416+
* {@link Views.COMPLETE_SECURITY}, which will later call {@link onCompleteSecurityE2eSetupFinished}.
417+
*/
389418
private async postLoginSetup(): Promise<void> {
390419
const cli = MatrixClientPeg.safeGet();
391420
const cryptoEnabled = Boolean(cli.getCrypto());
@@ -1369,7 +1398,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
13691398
}
13701399

13711400
/**
1372-
* Called when a new logged in session has started
1401+
* Called when a new logged in session has started.
1402+
*
1403+
* Called:
1404+
*
1405+
* - on {@link Action.OnLoggedIn}, but only when we don't expect a separate call to {@link postLoginSetup}.
1406+
* - from {@link postLoginSetup}, when we don't have crypto setup tasks to perform after the login.
1407+
*
1408+
* It's never actually called if we have crypto setup tasks to perform after login (which we normally do, unless
1409+
* crypto is disabled.) XXX: is this a bug or a feature?
13731410
*/
13741411
private async onLoggedIn(): Promise<void> {
13751412
ThemeController.isLogin = false;
@@ -1379,6 +1416,16 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
13791416
await this.onShowPostLoginScreen();
13801417
}
13811418

1419+
/**
1420+
* Show the first screen after the application is successfully loaded in a logged-in state.
1421+
*
1422+
* Called:
1423+
*
1424+
* - by {@link onLoggedIn}
1425+
* - by {@link onCompleteSecurityE2eSetupFinished}
1426+
*
1427+
* In other words, whenever we think we have completed the login and E2E setup tasks.
1428+
*/
13821429
private async onShowPostLoginScreen(): Promise<void> {
13831430
this.setStateForNewView({ view: Views.LOGGED_IN });
13841431
// If a specific screen is set to be shown after login, show that above
@@ -2043,7 +2090,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
20432090
PerformanceMonitor.instance.stop(PerformanceEntryNames.REGISTER);
20442091
};
20452092

2046-
// complete security / e2e setup has finished
2093+
/** Called when {@link Views.E2E_SETUP} or {@link Views.COMPLETE_SECURITY} have completed. */
20472094
private onCompleteSecurityE2eSetupFinished = async (): Promise<void> => {
20482095
const forceVerify = await this.shouldForceVerification();
20492096
if (forceVerify) {

0 commit comments

Comments
 (0)