mirror of
https://github.com/vector-im/element-web.git
synced 2025-12-04 00:41:28 +01:00
Add a new state between LOADING/SOFT_LOGOUT and LOGGED_IN
... so that we can transition into COMPLETE_SECURITY without going via LOGGED_IN.
This commit is contained in:
parent
66dd507ea2
commit
a525c53fd9
@ -27,6 +27,7 @@ const notLoggedInMap: Record<Exclude<Views, Views.LOGGED_IN>, ScreenName> = {
|
||||
[Views.FORGOT_PASSWORD]: "ForgotPassword",
|
||||
[Views.COMPLETE_SECURITY]: "CompleteSecurity",
|
||||
[Views.E2E_SETUP]: "E2ESetup",
|
||||
[Views.PENDING_CLIENT_START]: "Loading",
|
||||
[Views.SOFT_LOGOUT]: "SoftLogout",
|
||||
[Views.LOCK_STOLEN]: "SessionLockStolen",
|
||||
};
|
||||
|
||||
108
src/Views.ts
108
src/Views.ts
@ -20,52 +20,62 @@ Please see LICENSE files in the repository root for full details.
|
||||
* │ LOADING │─────────────────────────────►│ CONFIRM_LOCK_ │
|
||||
* │ │◄─────────────────────────────│ THEFT │
|
||||
* └─────────────────┘ Lock theft confirmed └─────────────────┘
|
||||
* Session recovered │ │ │
|
||||
* ┌──────────────┘ │ └────────────────┐
|
||||
* │ ┌─────────────┘ │ No previous session
|
||||
* │ │ Token/OIDC login succeeded │
|
||||
* │ │ ▼
|
||||
* │ │ ┌─────────────────┐
|
||||
* │ │ │ WELCOME │ (from all other states
|
||||
* │ │ │ │ except LOCK_STOLEN)
|
||||
* │ │ └─────────────────┘ │
|
||||
* │ │ "Create Account" │ │ "Sign in" │ Client logged out
|
||||
* │ │ ┌────────────────────────┘ │ │
|
||||
* │ │ │ │ ┌────────────────────┘
|
||||
* │ │ │ │ │
|
||||
* │ │ ▼ "Create an ▼ ▼ "Forgot
|
||||
* │ │ ┌─────────────────┐ account" ┌─────────────────┐ password" ┌─────────────────┐
|
||||
* │ │ │ REGISTER │◄───────────────│ LOGIN │───────────────►│ FORGOT_PASSWORD │
|
||||
* │ │ │ │───────────────►│ │◄───────────────│ │
|
||||
* │ │ └─────────────────┘ "Sign in here" └─────────────────┘ Complete / └─────────────────┘
|
||||
* │ │ │ │ "Sign in instead" ▲
|
||||
* │ │ └────────────────────────────────┐ │ │
|
||||
* │ └────────────────────────────────────────┐ │ │ │
|
||||
* │ ▼ ▼ ▼ │
|
||||
* │ ┌──────────────────┐ │
|
||||
* │ │ (postLoginSetup) │ │
|
||||
* │ └──────────────────┘ │
|
||||
* │ ┌────────────────────────────────────┘ │ │ │
|
||||
* │ │ E2EE not enabled ┌─────────────┘ └──────┐ │
|
||||
* │ │ │ Account has │ Account lacks │
|
||||
* │ │ │ cross-signing │ cross-signing │
|
||||
* │ │ │ keys │ keys │
|
||||
* │ │ Client started and ▼ ▼ │
|
||||
* │ │ force_verification ┌─────────────────┐ ┌─────────────────┐ │
|
||||
* │ │ pending │ COMPLETE_ │ │ E2E_SETUP │ │
|
||||
* │ │ ┌─────────────────►│ SECURITY │ │ │ │
|
||||
* │ │ │ └─────────────────┘ └─────────────────┘ │ "Forgotten
|
||||
* │ │ │ ┌───────────────────────┘ │ │ your
|
||||
* │ │ │ │ ┌───────────────────────────────────────────────┘ │ password?"
|
||||
* │ │ │ │ │ │
|
||||
* │ │ │ │ │ (from all other states │
|
||||
* │ │ │ │ │ except LOCK_STOLEN) │
|
||||
* │ │ │ │ │ └──────────────┐ │
|
||||
* ▼ ▼ │ ▼ ▼ Soft logout error ▼ │
|
||||
* ┌─────────────────┐ ┌─────────────────┐
|
||||
* │ LOGGED_IN │ Re-authentication succeeded │ SOFT_LOGOUT │
|
||||
* │ │◄────────────────────────────────────────────────────────│ │
|
||||
* └─────────────────┘ └─────────────────┘
|
||||
* Session recovered │ │ │ Token/OIDC login succeeded
|
||||
* ┌──────────────┘ │ └──────────────────────────────────────────────────────────────────┐
|
||||
* │ └───────────────────────────────────────────┐ │
|
||||
* │ │ No previous session │
|
||||
* │ ▼ │
|
||||
* │ (from all other states ┌─────────────────┐ │
|
||||
* │ except LOCK_STOLEN) │ WELCOME │ │
|
||||
* │ │ │ │ │
|
||||
* │ │ Client logged out └─────────────────┘ │
|
||||
* │ │ │ │ │
|
||||
* │ └──────────────────────────┐ "Sign in" │ │ "Create account" │
|
||||
* │ │ ┌────────────┘ └──────────────┐ │
|
||||
* │ │ │ │ │
|
||||
* │ "Forgot ▼ ▼ "Create an ▼ │
|
||||
* │ ┌─────────────────┐ password" ┌─────────────────┐ account" ┌─────────────────┐ │
|
||||
* │ │ FORGOT_PASSWORD │◄───────────────│ LOGIN │───────────────►│ REGISTER │ │
|
||||
* │ │ │───────────────►│ │◄───────────────│ │ │
|
||||
* │ └─────────────────┘ Complete / └─────────────────┘ "Sign in here" └─────────────────┘ │
|
||||
* │ ▲ "Sign in instead" │ │ │
|
||||
* │ │ └──────────────────────┐ ┌─────────┘ │
|
||||
* │ │"Forgotten your │ │ ┌──────────────────┘
|
||||
* │ │ password?" │ │ │
|
||||
* │ │ │ │ │
|
||||
* │ ┌─────────────────┐ Soft-logout error │ │ │
|
||||
* │ │ SOFT_LOGOUT │◄───────────── (from all other states │ │ │
|
||||
* │ │ │ except LOCK_STOLEN) │ │ │
|
||||
* │ └─────────────────┘ │ │ │
|
||||
* │ │ Re-authentication succeeded ▼ ▼ ▼
|
||||
* │ │ ┌──────────────────┐
|
||||
* ▼ ▼ │ (postLoginSetup) │
|
||||
* ┌─────────────────┐ └──────────────────┘
|
||||
* │ PENDING_CLIENT_ │ Account has │ │ │ Account lacks
|
||||
* │ START │ cross-signing │ │ │ cross-signing
|
||||
* └─────────────────┘ keys │ │ │ keys
|
||||
* │ │ │ │ │
|
||||
* │ └───────────────────────────────┐ │ │ │
|
||||
* │ Client started, │ │ │ └──────┐
|
||||
* │ force_verification pending │ │ │ │
|
||||
* │ ▼ │ │ │
|
||||
* │ Client started, ┌─────────────────┐ │ │ │
|
||||
* │ force_verification │ COMPLETE_ │◄────────────┘ │ ▼
|
||||
* │ not needed │ SECURITY │ │ ┌─────────────────┐
|
||||
* │ └─────────────────┘ │ │ E2E_SETUP │
|
||||
* │ │ │ │ │
|
||||
* │ ┌─────────────────────────────────────┘ E2EE not enabled │ └─────────────────┘
|
||||
* │ │ ┌─────────────────────────────────────────────────────────────┘ │
|
||||
* │ │ │ ┌──────────────────────────────────────────────────────────────────────┘
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* │ │ │ │
|
||||
* ▼ ▼ ▼ ▼
|
||||
* ┌─────────────────┐
|
||||
* │ LOGGED_IN │
|
||||
* │ │
|
||||
* └─────────────────┘
|
||||
*
|
||||
* (from all other states)
|
||||
* │
|
||||
@ -102,6 +112,12 @@ enum Views {
|
||||
// flow to setup SSSS / cross-signing on this account
|
||||
E2E_SETUP,
|
||||
|
||||
/**
|
||||
* We have successfully recovered a session from localstorage, but the client
|
||||
* has not yet been started.
|
||||
*/
|
||||
PENDING_CLIENT_START,
|
||||
|
||||
// we are logged in with an active matrix client. The logged_in state also
|
||||
// includes guests users as they too are logged in at the client level.
|
||||
LOGGED_IN,
|
||||
|
||||
@ -1535,18 +1535,27 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
this.stores.client = MatrixClientPeg.safeGet();
|
||||
StorageManager.tryPersistStorage();
|
||||
|
||||
// If we're in the middle of a login/registration, we wait for it to complete before transitioning to the logged
|
||||
// in view the login flow will call `postLoginSetup` when it's done, which will arrange for `onShowPostLoginScreen`
|
||||
// to be called.
|
||||
// If we're loading the app for the first time, we can now transition to a splash screen while we wait for the
|
||||
// client to start. The exceptions are:
|
||||
//
|
||||
// - If there is a token login in flight: in that case we wait for the login to complete (which hits
|
||||
// `postLoginSetup`).
|
||||
//
|
||||
// - Lifecycle emits an `Action.OnLoggedIn` event during startup even if the localstorage flag indicating a
|
||||
// previous soft logout is set. In that situation we actually want to wait for the `Action.ClientNotViable`
|
||||
// event, which will transition us into Views.SOFT_LOGOUT. We therefore have to check for !isSoftLogout().
|
||||
// There will be a subsequent `Action.OnLoggedIn` event once the reauthentication completes.
|
||||
//
|
||||
// XXX: fix this properly by having Lifecycle not emit OnLoggedIn when it knows it is about to emit a
|
||||
// ClientNotViable.
|
||||
//
|
||||
// If we're already in the SOFT_LOGOUT view, that means that reauthentication has succeeded, and we can
|
||||
// transition to the splash screen.
|
||||
if (
|
||||
!this.tokenLogin &&
|
||||
!Lifecycle.isSoftLogout() &&
|
||||
this.state.view !== Views.LOGIN &&
|
||||
this.state.view !== Views.REGISTER &&
|
||||
this.state.view !== Views.COMPLETE_SECURITY &&
|
||||
this.state.view !== Views.E2E_SETUP
|
||||
(this.state.view === Views.LOADING && !Lifecycle.isSoftLogout() && !this.tokenLogin) ||
|
||||
this.state.view === Views.SOFT_LOGOUT
|
||||
) {
|
||||
this.onShowPostLoginScreen();
|
||||
this.setStateForNewView({ view: Views.PENDING_CLIENT_START });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1779,15 +1788,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
|
||||
const shouldForceVerification = await this.shouldForceVerification();
|
||||
// XXX: Don't replace the screen if it's already one of these: postLoginSetup
|
||||
// changes to these screens in certain circumstances so we shouldn't clobber it.
|
||||
// We should probably have one place where we decide what the next screen is after
|
||||
// login.
|
||||
if (![Views.COMPLETE_SECURITY, Views.E2E_SETUP].includes(this.state.view)) {
|
||||
if (shouldForceVerification) {
|
||||
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
|
||||
}
|
||||
}
|
||||
|
||||
const crypto = cli.getCrypto();
|
||||
if (crypto) {
|
||||
@ -1804,6 +1804,19 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
this.setState({
|
||||
ready: true,
|
||||
});
|
||||
|
||||
// If the view is PENDING_CLIENT_START, that means we recovered the session from localstorage, or from
|
||||
// soft-logout: we can now transition to the logged-in view.
|
||||
//
|
||||
// If the view is something else, that probably means it's a login or registration view; we handle that in
|
||||
// `postLoginSetup`.
|
||||
if (this.state.view === Views.PENDING_CLIENT_START) {
|
||||
if (shouldForceVerification) {
|
||||
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
|
||||
} else {
|
||||
await this.onShowPostLoginScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public showScreen(screen: string, params?: { [key: string]: any }): void {
|
||||
@ -2162,6 +2175,15 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
view = <CompleteSecurity onFinished={this.onCompleteSecurityE2eSetupFinished} />;
|
||||
} else if (this.state.view === Views.E2E_SETUP) {
|
||||
view = <E2eSetup onCancelled={this.onCompleteSecurityE2eSetupFinished} />;
|
||||
} else if (this.state.view === Views.PENDING_CLIENT_START) {
|
||||
// we think we are logged in, but are still waiting for the /sync to complete
|
||||
view = (
|
||||
<LoginSplashView
|
||||
matrixClient={MatrixClientPeg.safeGet()}
|
||||
onLogoutClick={this.onLogoutClick}
|
||||
syncError={this.state.syncError}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.LOGGED_IN) {
|
||||
// `ready` and `view==LOGGED_IN` may be set before `page_type` (because the
|
||||
// latter is set via the dispatcher). If we don't yet have a `page_type`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user