diff options
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 13 | ||||
| -rw-r--r-- | gui/src/main/errors.ts | 6 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 6 | ||||
| -rw-r--r-- | gui/src/renderer/components/Login.tsx | 9 | ||||
| -rw-r--r-- | gui/src/renderer/redux/account/actions.ts | 14 | ||||
| -rw-r--r-- | gui/src/renderer/redux/account/reducers.ts | 7 |
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, |
