diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-06-13 16:03:05 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-06-15 08:49:42 -0300 |
| commit | 47454b7fe8341997e2580811e4aed00084fb741c (patch) | |
| tree | 4532087665b22ec76a9170f0addefe7026467e4b /app | |
| parent | ffc9500d5d57c427378591aab5e4c86960d27fe7 (diff) | |
| download | mullvadvpn-47454b7fe8341997e2580811e4aed00084fb741c.tar.xz mullvadvpn-47454b7fe8341997e2580811e4aed00084fb741c.zip | |
Split `BackendError` into individual error classes
Diffstat (limited to 'app')
| -rw-r--r-- | app/app.js | 10 | ||||
| -rw-r--r-- | app/components/Connect.js | 17 | ||||
| -rw-r--r-- | app/lib/backend.js | 127 |
3 files changed, 78 insertions, 76 deletions
diff --git a/app/app.js b/app/app.js index 055972fdf5..6ec6ac643f 100644 --- a/app/app.js +++ b/app/app.js @@ -9,7 +9,7 @@ import { webFrame, ipcRenderer } from 'electron'; import { log } from './lib/platform'; import makeRoutes from './routes'; import configureStore from './redux/store'; -import { Backend, BackendError } from './lib/backend'; +import { Backend, NoAccountError } from './lib/backend'; import { setShutdownHandler } from './shutdown-handler'; @@ -33,11 +33,9 @@ ipcRenderer.on('backend-info', async (_event, args) => { await backend.fetchSecurityState(); await backend.connect(); } catch (e) { - if (e instanceof BackendError) { - if (e.type === 'NO_ACCOUNT') { - log.debug('No user set in the backend, showing window'); - ipcRenderer.send('show-window'); - } + if (e instanceof NoAccountError) { + log.debug('No user set in the backend, showing window'); + ipcRenderer.send('show-window'); } } }); diff --git a/app/components/Connect.js b/app/components/Connect.js index 3fbe04cefa..f4647678f1 100644 --- a/app/components/Connect.js +++ b/app/components/Connect.js @@ -9,7 +9,7 @@ import { TransparentButton, RedTransparentButton, GreenButton, Label } from './s import Accordion from './Accordion'; import styles from './ConnectStyles'; -import { BackendError } from '../lib/backend'; +import { NoCreditError, NoInternetError } from '../lib/backend'; import Map from './Map'; import type { HeaderBarStyle } from './HeaderBar'; @@ -79,15 +79,18 @@ export default class Connect extends Component<ConnectProps, ConnectState> { ); } - renderError(error: BackendError) { + renderError(error: Error) { + const title = error.userFriendlyTitle || 'Something went wrong'; + const message = error.userFriendlyMessage || error.message; + return ( <View style={styles.connect}> <View style={styles.status_icon}> <Img source="icon-fail" height={60} width={60} alt="" /> </View> <View style={styles.status}> - <View style={styles.error_title}>{error.title}</View> - <View style={styles.error_message}>{error.message}</View> + <View style={styles.error_title}>{title}</View> + <View style={styles.error_message}>{message}</View> {error.type === 'NO_CREDIT' ? ( <View> <GreenButton onPress={this.onExternalLink.bind(this, 'purchase')}> @@ -339,16 +342,16 @@ export default class Connect extends Component<ConnectProps, ConnectState> { return classes; } - displayError(): ?BackendError { + displayError(): ?Error { // Offline? if (!this.props.connection.isOnline) { - return new BackendError('NO_INTERNET'); + return new NoInternetError(); } // No credit? const expiry = this.props.accountExpiry; if (expiry && moment(expiry).isSameOrBefore(moment())) { - return new BackendError('NO_CREDIT'); + return new NoCreditError(); } return null; diff --git a/app/lib/backend.js b/app/lib/backend.js index 89b8945962..c7b4ca53ec 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -12,64 +12,65 @@ import type { ReduxStore } from '../redux/store'; import type { AccountToken, BackendState, RelaySettingsUpdate } from './ipc-facade'; import type { ConnectionState } from '../redux/connection/reducers'; -export type ErrorType = - | 'NO_CREDIT' - | 'NO_INTERNET' - | 'NO_DAEMON' - | 'INVALID_ACCOUNT' - | 'NO_ACCOUNT' - | 'COMMUNICATION_FAILURE' - | 'UNKNOWN_ERROR'; +export class NoCreditError extends Error { + constructor() { + super("Account doesn't have enough credit available for connection"); + } -export class BackendError extends Error { - type: ErrorType; - title: string; - message: string; - cause: ?Error; + get userFriendlyTitle(): string { + return 'Out of time'; + } - constructor(type: ErrorType, cause?: Error) { - super(''); - this.type = type; - this.title = BackendError.localizedTitle(type); - this.message = BackendError.localizedMessage(type, cause); - this.cause = cause; + get userFriendlyMessage(): string { + return 'Buy more time, so you can continue using the internet securely'; } +} - static localizedTitle(type: ErrorType): string { - switch (type) { - case 'NO_CREDIT': - return 'Out of time'; - case 'NO_INTERNET': - return 'Offline'; - default: - return 'Something went wrong'; - } +export class NoInternetError extends Error { + constructor() { + super('Internet connectivity is currently unavailable'); } - static localizedMessage(type: ErrorType, cause: ?Error): string { - // TODO: since instanceof now works, BackendError can be replaced by a set - // of specific error types - switch (type) { - case 'NO_CREDIT': - return 'Buy more time, so you can continue using the internet securely'; - case 'NO_INTERNET': - return 'Your internet connection will be secured when you get back online'; - case 'INVALID_ACCOUNT': - return 'Invalid account number'; - case 'NO_ACCOUNT': - return 'No account was set'; - case 'NO_DAEMON': - return 'Could not connect to the Mullvad daemon'; - case 'COMMUNICATION_FAILURE': - return 'api.mullvad.net is blocked, please check your firewall'; - case 'UNKNOWN_ERROR': { - const message = cause ? ', ' + cause.message : ''; + get userFriendlyTitle(): string { + return 'Offline'; + } - return 'An unknown error occurred' + message; - } - default: - return ''; - } + get userFriendlyMessage(): string { + return 'Your internet connection will be secured when you get back online'; + } +} + +export class NoDaemonError extends Error { + constructor() { + super('Could not connect to Mullvad daemon'); + } +} + +export class InvalidAccountError extends Error { + constructor() { + super('Invalid account number'); + } +} + +export class NoAccountError extends Error { + constructor() { + super('No account was set'); + } +} + +export class CommunicationError extends Error { + constructor() { + super('api.mullvad.net is blocked, please check your firewall'); + } +} + +export class UnknownError extends Error { + constructor(cause: string) { + super(`An unknown error occurred, ${cause}`); + } + + get userFriendlyTitle(): string { + return 'Something went wrong'; } } @@ -187,30 +188,30 @@ export class Backend { } catch (e) { log.error('Failed to log in,', e.message); - const err = this._rpcErrorToBackendError(e); - this._store.dispatch(accountActions.loginFailed(err)); + const error = this._rpcErrorToBackendError(e); + this._store.dispatch(accountActions.loginFailed(error)); } } _rpcErrorToBackendError(e) { - if (e instanceof BackendError) { - return e; - } else if (e instanceof JsonRpcError) { + if (e instanceof JsonRpcError) { switch (e.code) { case -200: // Account doesn't exist - return new BackendError('INVALID_ACCOUNT'); + return new InvalidAccountError(); case -32603: // Internal error // We treat all internal backend errors as the user cannot reach // api.mullvad.net. This is not always true of course, but it is // true so often that we choose to disregard the other edge cases // for now. - return new BackendError('COMMUNICATION_FAILURE'); + return new CommunicationError(); } } else if (e instanceof TimeOutError) { - return new BackendError('COMMUNICATION_FAILURE'); + return new CommunicationError(); + } else if (e instanceof NoDaemonError) { + return e; } - return new BackendError('UNKNOWN_ERROR', e); + return new UnknownError(e.message); } async autologin() { @@ -223,7 +224,7 @@ export class Backend { const accountToken = await this._ipc.getAccount(); if (!accountToken) { - throw new BackendError('NO_ACCOUNT'); + throw new NoAccountError(); } log.debug('The backend had an account number stored: ', accountToken); @@ -361,7 +362,7 @@ export class Backend { const accountToken = await this._ipc.getAccount(); if (!accountToken) { - throw new BackendError('NO_ACCOUNT'); + throw new NoAccountError(); } const accountData = await ipc.getAccountData(accountToken); @@ -527,7 +528,7 @@ export class Backend { } return this._authenticationPromise; } else { - return Promise.reject(new BackendError('NO_DAEMON')); + return Promise.reject(new NoDaemonError()); } } |
