summaryrefslogtreecommitdiffhomepage
path: root/gui
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2021-11-03 19:56:48 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-03-14 13:58:44 +0100
commit511c4eb17c91faf2176f3ff56dbf690589e5a0d0 (patch)
treee632dba30536b65ac06a89f1dbb5a727acfcfe0c /gui
parentd5f21653bec09d342112d66c5d20eca38e16b49e (diff)
downloadmullvadvpn-511c4eb17c91faf2176f3ff56dbf690589e5a0d0.tar.xz
mullvadvpn-511c4eb17c91faf2176f3ff56dbf690589e5a0d0.zip
Handle too many devices login error
Diffstat (limited to 'gui')
-rw-r--r--gui/src/main/daemon-rpc.ts13
-rw-r--r--gui/src/main/errors.ts6
-rw-r--r--gui/src/renderer/app.tsx6
-rw-r--r--gui/src/renderer/components/Login.tsx9
-rw-r--r--gui/src/renderer/redux/account/actions.ts14
-rw-r--r--gui/src/renderer/redux/account/reducers.ts7
6 files changed, 50 insertions, 5 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index f17505bd80..2ef9feb99d 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -54,7 +54,7 @@ import log from '../shared/logging';
import { ManagementServiceClient } from './management_interface/management_interface_grpc_pb';
import * as grpcTypes from './management_interface/management_interface_pb';
-import { CommunicationError, InvalidAccountError } from './errors';
+import { CommunicationError, InvalidAccountError, TooManyDevicesError } from './errors';
const NETWORK_CALL_TIMEOUT = 10000;
const CHANNEL_STATE_TIMEOUT = 1000 * 60 * 60;
@@ -259,7 +259,16 @@ export class DaemonRpc {
}
public async loginAccount(accountToken: AccountToken): Promise<void> {
- await this.callString(this.client.loginAccount, accountToken);
+ try {
+ await this.callString(this.client.loginAccount, accountToken);
+ } catch (e) {
+ const error = e as grpc.ServiceError;
+ if (error.code == grpc.status.RESOURCE_EXHAUSTED) {
+ throw new TooManyDevicesError();
+ } else {
+ throw error;
+ }
+ }
}
public async logoutAccount(): Promise<void> {
diff --git a/gui/src/main/errors.ts b/gui/src/main/errors.ts
index 261ee7a164..b7cc82c365 100644
--- a/gui/src/main/errors.ts
+++ b/gui/src/main/errors.ts
@@ -15,3 +15,9 @@ export class CommunicationError extends Error {
super('api.mullvad.net is blocked, please check your firewall');
}
}
+
+export class TooManyDevicesError extends Error {
+ constructor() {
+ super('Too many devices');
+ }
+}
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 595ded57c5..fc387c114c 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -271,7 +271,11 @@ export default class AppRenderer {
this.redirectToConnect();
} catch (e) {
const error = e as Error;
- actions.account.loginFailed(error);
+ if (error.message === 'Too many devices') {
+ actions.account.loginTooManyDevices(error);
+ } else {
+ actions.account.loginFailed(error);
+ }
}
}
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 31afee88b0..ab93e1d6ac 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -151,6 +151,7 @@ export default class Login extends React.Component<IProps, IState> {
private formTitle() {
switch (this.props.loginState.type) {
case 'logging in':
+ case 'too many devices':
return this.props.loginState.method === 'existing_account'
? messages.pgettext('login-view', 'Logging in...')
: messages.pgettext('login-view', 'Creating account...');
@@ -173,6 +174,8 @@ export default class Login extends React.Component<IProps, IState> {
return this.props.loginState.method === 'existing_account'
? this.props.loginState.error.message || messages.pgettext('login-view', 'Unknown error')
: messages.pgettext('login-view', 'Failed to create account');
+ case 'too many devices':
+ return messages.pgettext('login-view', 'Too many devices');
case 'logging in':
return this.props.loginState.method === 'existing_account'
? messages.pgettext('login-view', 'Checking account number')
@@ -209,7 +212,11 @@ export default class Login extends React.Component<IProps, IState> {
}
private allowInteraction() {
- return this.props.loginState.type !== 'logging in' && this.props.loginState.type !== 'ok';
+ return (
+ this.props.loginState.type !== 'logging in' &&
+ this.props.loginState.type !== 'ok' &&
+ this.props.loginState.type !== 'too many devices'
+ );
}
private allowCreateAccount() {
diff --git a/gui/src/renderer/redux/account/actions.ts b/gui/src/renderer/redux/account/actions.ts
index 2eb9f21a17..5affa1bb26 100644
--- a/gui/src/renderer/redux/account/actions.ts
+++ b/gui/src/renderer/redux/account/actions.ts
@@ -16,6 +16,11 @@ interface ILoginFailedAction {
error: Error;
}
+interface ILoginTooManyDevicesAction {
+ type: 'TOO_MANY_DEVICES';
+ error: Error;
+}
+
interface ILoggedOutAction {
type: 'LOGGED_OUT';
}
@@ -63,6 +68,7 @@ export type AccountAction =
| IStartLoginAction
| ILoggedInAction
| ILoginFailedAction
+ | ILoginTooManyDevicesAction
| ILoggedOutAction
| IResetLoginErrorAction
| IStartCreateAccount
@@ -95,6 +101,13 @@ function loginFailed(error: Error): ILoginFailedAction {
};
}
+function loginTooManyDevices(error: Error): ILoginTooManyDevicesAction {
+ return {
+ type: 'TOO_MANY_DEVICES',
+ error,
+ };
+}
+
function loggedOut(): ILoggedOutAction {
return {
type: 'LOGGED_OUT',
@@ -158,6 +171,7 @@ export default {
startLogin,
loggedIn,
loginFailed,
+ loginTooManyDevices,
loggedOut,
resetLoginError,
startCreateAccount,
diff --git a/gui/src/renderer/redux/account/reducers.ts b/gui/src/renderer/redux/account/reducers.ts
index 39b3a1a525..6c5fa1d76b 100644
--- a/gui/src/renderer/redux/account/reducers.ts
+++ b/gui/src/renderer/redux/account/reducers.ts
@@ -5,7 +5,7 @@ type LoginMethod = 'existing_account' | 'new_account';
export type LoginState =
| { type: 'none' }
| { type: 'logging in' | 'ok'; method: LoginMethod }
- | { type: 'failed'; method: LoginMethod; error: Error };
+ | { type: 'failed' | 'too many devices'; method: LoginMethod; error: Error };
export interface IAccountReduxState {
accountToken?: AccountToken;
deviceName?: string;
@@ -46,6 +46,11 @@ export default function (
status: { type: 'failed', method: 'existing_account', error: action.error },
accountToken: undefined,
};
+ case 'TOO_MANY_DEVICES':
+ return {
+ ...state,
+ status: { type: 'too many devices', method: 'existing_account', error: action.error },
+ };
case 'LOGGED_OUT':
return {
...state,