Abort login with providers (#6215)

Don't show in changelog
This commit is contained in:
AlexandreS
2024-01-18 12:32:01 +01:00
committed by GitHub
parent 26ee9b3891
commit dd090fd1d7
6 changed files with 46 additions and 6 deletions

View File

@@ -50,6 +50,7 @@ class BrowserLoginProvider
}: {|
provider: IdentityProvider,
loginOptions?: ?LoginOptions,
signal?: AbortSignal,
|}) {
let firebaseProvider = null;
if (provider === 'google') {

View File

@@ -47,19 +47,34 @@ class LocalLoginProvider implements LoginProvider, FirebaseBasedLoginProvider {
async loginOrSignupWithProvider({
provider,
signal,
}: {|
provider: IdentityProvider,
loginOptions?: ?LoginOptions,
signal?: AbortSignal,
|}) {
if (signal && signal.aborted) {
return Promise.reject(
new Error('Login or Signup with provider already aborted.')
);
}
const promise = new Promise((resolve, reject) => {
// Listen for abort event on signal
if (signal) {
signal.addEventListener('abort', () => {
reject(new Error('Login or Signup with provider aborted.'));
});
}
setupAuthenticationWebSocket({
onConnectionEstablished: connectionId => {
if (signal && signal.aborted) return;
const url = new URL(webAppUrl);
url.searchParams.set('initial-dialog', 'login');
url.searchParams.set('connection-id', connectionId);
Window.openExternalURL(url.toString());
},
onTokenReceived: async token => {
if (signal && signal.aborted) return;
try {
await signInWithCustomToken(this.auth, token);
resolve();
@@ -73,6 +88,7 @@ class LocalLoginProvider implements LoginProvider, FirebaseBasedLoginProvider {
}
},
onError: error => {
if (signal && signal.aborted) return;
console.error(
'An error occurred while setting up authentication web socket:',
error

View File

@@ -14,6 +14,7 @@ export interface LoginProvider {
loginOrSignupWithProvider({|
provider: IdentityProvider,
loginOptions?: ?LoginOptions,
signal?: AbortSignal,
|}): Promise<void>;
notifyLogin({|
connectionId: string,

View File

@@ -371,6 +371,7 @@ const GetStartedSection = ({
onForgotPassword={onResetPassword}
error={error}
/>
{/* TODO: Add button to cancel login with providers */}
</div>
</ColumnStackLayout>
<div style={styles.bottomPageButtonContainer}>

View File

@@ -123,6 +123,7 @@ export default class AuthenticatedUserProvider extends React.Component<
};
_automaticallyUpdateUserProfile = true;
_hasNotifiedUserAboutEmailVerification = false;
_abortController: ?AbortController = null;
// Cloud projects are requested in 2 different places at app opening.
// - First one comes from user authenticating and automatically fetching
@@ -765,7 +766,12 @@ export default class AuthenticatedUserProvider extends React.Component<
});
this._automaticallyUpdateUserProfile = false;
try {
await authentication.loginWithProvider(provider, this.state.loginOptions);
this._abortController = new AbortController();
await authentication.loginWithProvider({
provider,
loginOptions: this.state.loginOptions,
signal: this._abortController.signal,
});
await this._fetchUserProfileWithoutThrowingErrors();
this.openLoginDialog(false, null);
this.openCreateAccountDialog(false);
@@ -789,6 +795,13 @@ export default class AuthenticatedUserProvider extends React.Component<
this._automaticallyUpdateUserProfile = true;
};
_cancelLogin = () => {
if (this._abortController) {
this._abortController.abort();
this._abortController = null;
}
};
_doLogin = async (form: LoginForm) => {
const { authentication } = this.props;
if (!authentication) return;
@@ -1127,7 +1140,10 @@ export default class AuthenticatedUserProvider extends React.Component<
{this.state.loginDialogOpen && (
<LoginDialog
authenticatedUser={this.state.authenticatedUser}
onClose={() => this.openLoginDialog(false, null)}
onClose={() => {
this._cancelLogin();
this.openLoginDialog(false, null);
}}
onGoToCreateAccount={() => this.openCreateAccountDialog(true)}
onLogin={this._doLogin}
onLoginOnDesktopApp={this._doAllowLoginOnDesktopApp}

View File

@@ -238,17 +238,22 @@ export default class Authentication {
});
};
loginWithProvider = (
loginWithProvider = ({
provider,
loginOptions,
signal,
}: {|
provider: IdentityProvider,
loginOptions?: ?LoginOptions
): Promise<void> => {
loginOptions?: ?LoginOptions,
signal?: AbortSignal,
|}): Promise<void> => {
const { loginProvider } = this;
if (!loginProvider) {
throw new Error('Login provider not set.');
}
return loginProvider
.loginOrSignupWithProvider({ provider, loginOptions })
.loginOrSignupWithProvider({ provider, loginOptions, signal })
.then(userCredentials => {
// The user is now stored in `this.auth`.
})