diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-09-26 16:16:52 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-11-30 10:36:19 +0100 |
| commit | 6f15a08566c716237b0b51bced94ee849f899ca2 (patch) | |
| tree | 64a996400740663ee733fcbadab12aa241cfdc38 /gui/src | |
| parent | 3fd327525882bc6459ed425de67ed687c949ef3f (diff) | |
| download | mullvadvpn-6f15a08566c716237b0b51bced94ee849f899ca2.tar.xz mullvadvpn-6f15a08566c716237b0b51bced94ee849f899ca2.zip | |
Update logic to work with new ErrorState structures
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/index.ts | 1 | ||||
| -rw-r--r-- | gui/src/main/notification-controller.ts | 3 | ||||
| -rw-r--r-- | gui/src/main/user-interface.ts | 2 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/Connect.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/HeaderBar.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/NotificationArea.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/TunnelControl.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/redux/connection/actions.ts | 6 | ||||
| -rw-r--r-- | gui/src/shared/auth-failure.ts | 81 | ||||
| -rw-r--r-- | gui/src/shared/notifications/error.ts | 104 |
11 files changed, 69 insertions, 138 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 320185abd8..06796a7be1 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -934,7 +934,6 @@ class ApplicationMain this.settings.splitTunnel.enableExclusions && this.settings.splitTunnel.appsList.length > 0, this.userInterface?.isWindowVisible() ?? false, this.settings.gui.enableSystemNotifications, - this.account.accountData?.expiry, ); IpcMainEventChannel.tunnel.notify?.(tunnelState); diff --git a/gui/src/main/notification-controller.ts b/gui/src/main/notification-controller.ts index 06a05366a7..3ea65fa5a0 100644 --- a/gui/src/main/notification-controller.ts +++ b/gui/src/main/notification-controller.ts @@ -56,14 +56,13 @@ export default class NotificationController { hasExcludedApps: boolean, isWindowVisible: boolean, areSystemNotificationsEnabled: boolean, - accountExpiry?: string, ) { const notificationProviders: SystemNotificationProvider[] = [ new ConnectingNotificationProvider({ tunnelState, reconnecting: this.reconnecting }), new ConnectedNotificationProvider(tunnelState), new ReconnectingNotificationProvider(tunnelState), new DisconnectedNotificationProvider({ tunnelState, blockWhenDisconnected }), - new ErrorNotificationProvider({ tunnelState, accountExpiry, hasExcludedApps }), + new ErrorNotificationProvider({ tunnelState, hasExcludedApps }), ]; const notificationProvider = notificationProviders.find((notification) => diff --git a/gui/src/main/user-interface.ts b/gui/src/main/user-interface.ts index 2c1ac03f27..9870c89702 100644 --- a/gui/src/main/user-interface.ts +++ b/gui/src/main/user-interface.ts @@ -653,7 +653,7 @@ export default class UserInterface implements WindowControllerDelegate { return 'securing'; case 'error': - if (!tunnelState.details.blockFailure) { + if (!tunnelState.details.blockingError) { return 'securing'; } else { return 'unsecured'; diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index ae7cdec881..e78462041b 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -754,7 +754,7 @@ export default class AppRenderer { break; case 'error': - actions.updateBlockState(!tunnelState.details.blockFailure); + actions.updateBlockState(!tunnelState.details.blockingError); break; } } diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx index 492fcc3fc9..79de3c5242 100644 --- a/gui/src/renderer/components/Connect.tsx +++ b/gui/src/renderer/components/Connect.tsx @@ -97,7 +97,7 @@ export default function Connect() { case 'connected': return MarkerStyle.secure; case 'error': - return !connection.status.details.blockFailure ? MarkerStyle.secure : MarkerStyle.unsecure; + return !connection.status.details.blockingError ? MarkerStyle.secure : MarkerStyle.unsecure; case 'disconnected': return MarkerStyle.unsecure; case 'disconnecting': diff --git a/gui/src/renderer/components/HeaderBar.tsx b/gui/src/renderer/components/HeaderBar.tsx index 3cf96df6fc..7c436e3c16 100644 --- a/gui/src/renderer/components/HeaderBar.tsx +++ b/gui/src/renderer/components/HeaderBar.tsx @@ -139,7 +139,7 @@ export function calculateHeaderBarStyle(tunnelState: TunnelState): HeaderBarStyl case 'connected': return HeaderBarStyle.success; case 'error': - return !tunnelState.details.blockFailure ? HeaderBarStyle.success : HeaderBarStyle.error; + return !tunnelState.details.blockingError ? HeaderBarStyle.success : HeaderBarStyle.error; case 'disconnecting': switch (tunnelState.details) { case 'block': diff --git a/gui/src/renderer/components/NotificationArea.tsx b/gui/src/renderer/components/NotificationArea.tsx index acd1aaf2df..317cc1e923 100644 --- a/gui/src/renderer/components/NotificationArea.tsx +++ b/gui/src/renderer/components/NotificationArea.tsx @@ -51,7 +51,7 @@ export default function NotificationArea(props: IProps) { blockWhenDisconnected, hasExcludedApps, }), - new ErrorNotificationProvider({ tunnelState, accountExpiry, hasExcludedApps }), + new ErrorNotificationProvider({ tunnelState, hasExcludedApps }), new InconsistentVersionNotificationProvider({ consistent: version.consistent }), new UnsupportedVersionNotificationProvider(version), ]; diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx index db0503cb0a..c9fd568a3f 100644 --- a/gui/src/renderer/components/TunnelControl.tsx +++ b/gui/src/renderer/components/TunnelControl.tsx @@ -139,7 +139,7 @@ export default class TunnelControl extends React.Component<ITunnelControlProps> case 'error': if ( this.props.tunnelState.state === 'error' && - this.props.tunnelState.details.blockFailure + this.props.tunnelState.details.blockingError ) { return ( <Wrapper> diff --git a/gui/src/renderer/redux/connection/actions.ts b/gui/src/renderer/redux/connection/actions.ts index 20c63d433d..35af568fb2 100644 --- a/gui/src/renderer/redux/connection/actions.ts +++ b/gui/src/renderer/redux/connection/actions.ts @@ -1,6 +1,6 @@ import { AfterDisconnect, - IErrorState, + ErrorState, ILocation, ITunnelStateRelayInfo, } from '../../../shared/daemon-rpc-types'; @@ -26,7 +26,7 @@ interface IDisconnectingAction { interface IBlockedAction { type: 'TUNNEL_ERROR'; - errorState: IErrorState; + errorState: ErrorState; } interface INewLocationAction { @@ -75,7 +75,7 @@ function disconnecting(afterDisconnect: AfterDisconnect): IDisconnectingAction { }; } -function blocked(errorState: IErrorState): IBlockedAction { +function blocked(errorState: ErrorState): IBlockedAction { return { type: 'TUNNEL_ERROR', errorState, diff --git a/gui/src/shared/auth-failure.ts b/gui/src/shared/auth-failure.ts deleted file mode 100644 index f8db50d82e..0000000000 --- a/gui/src/shared/auth-failure.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { messages } from './gettext'; - -export enum AuthFailureKind { - invalidAccount, - expiredAccount, - tooManyConnections, - unknown, -} - -interface IAuthFailure { - kind: AuthFailureKind; - message: string; -} - -export function parseAuthFailure(rawFailureMessage?: string): IAuthFailure { - if (rawFailureMessage) { - const results = /^\[(\w+)\]\s*(.*)$/.exec(rawFailureMessage); - - if (results && results.length === 3) { - const kind = parseRawFailureKind(results[1]); - const message = kind === AuthFailureKind.unknown ? results[2] : messageForFailureKind(kind); - - return { - kind, - message, - }; - } else { - return { - kind: AuthFailureKind.unknown, - message: rawFailureMessage, - }; - } - } else { - return { - kind: AuthFailureKind.unknown, - message: messageForFailureKind(AuthFailureKind.unknown), - }; - } -} - -function parseRawFailureKind(failureId: string): AuthFailureKind { - // These strings should match up with mullvad-types/src/auth_failed.rs - switch (failureId) { - case 'INVALID_ACCOUNT': - return AuthFailureKind.invalidAccount; - - case 'EXPIRED_ACCOUNT': - return AuthFailureKind.expiredAccount; - - case 'TOO_MANY_CONNECTIONS': - return AuthFailureKind.tooManyConnections; - - default: - return AuthFailureKind.unknown; - } -} - -function messageForFailureKind(kind: AuthFailureKind): string { - switch (kind) { - case AuthFailureKind.invalidAccount: - return messages.pgettext( - 'auth-failure', - 'You are logged in with an invalid account number. Please log out and try another one.', - ); - - case AuthFailureKind.expiredAccount: - return messages.pgettext('auth-failure', 'Blocking internet: account is out of time'); - - case AuthFailureKind.tooManyConnections: - return messages.pgettext( - 'auth-failure', - 'Too many simultaneous connections on this account. Disconnect another device or try connecting again shortly.', - ); - - case AuthFailureKind.unknown: - return messages.pgettext( - 'auth-failure', - 'Unable to authenticate account. Please contact support.', - ); - } -} diff --git a/gui/src/shared/notifications/error.ts b/gui/src/shared/notifications/error.ts index c901c5de67..08462fa6db 100644 --- a/gui/src/shared/notifications/error.ts +++ b/gui/src/shared/notifications/error.ts @@ -1,9 +1,13 @@ import { sprintf } from 'sprintf-js'; import { strings } from '../../config.json'; -import { hasExpired } from '../account-expiry'; -import { AuthFailureKind, parseAuthFailure } from '../auth-failure'; -import { IErrorState, TunnelParameterError, TunnelState } from '../daemon-rpc-types'; +import { + AuthFailedError, + ErrorState, + ErrorStateCause, + TunnelParameterError, + TunnelState, +} from '../daemon-rpc-types'; import { messages } from '../gettext'; import { InAppNotification, @@ -13,7 +17,6 @@ import { interface ErrorNotificationContext { tunnelState: TunnelState; - accountExpiry?: string; hasExcludedApps: boolean; } @@ -25,8 +28,8 @@ export class ErrorNotificationProvider public getSystemNotification() { if (this.context.tunnelState.state === 'error') { - let message = getMessage(this.context.tunnelState.details, this.context.accountExpiry); - if (!this.context.tunnelState.details.blockFailure && this.context.hasExcludedApps) { + let message = getMessage(this.context.tunnelState.details); + if (!this.context.tunnelState.details.blockingError && this.context.hasExcludedApps) { message = `${message} ${sprintf( messages.pgettext( 'notifications', @@ -38,7 +41,7 @@ export class ErrorNotificationProvider return { message, - critical: !!this.context.tunnelState.details.blockFailure, + critical: !!this.context.tunnelState.details.blockingError, }; } else { return undefined; @@ -47,8 +50,8 @@ export class ErrorNotificationProvider public getInAppNotification(): InAppNotification | undefined { if (this.context.tunnelState.state === 'error') { - let subtitle = getMessage(this.context.tunnelState.details, this.context.accountExpiry); - if (!this.context.tunnelState.details.blockFailure && this.context.hasExcludedApps) { + let subtitle = getMessage(this.context.tunnelState.details); + if (!this.context.tunnelState.details.blockingError && this.context.hasExcludedApps) { subtitle = `${subtitle} ${sprintf( messages.pgettext( 'notifications', @@ -60,10 +63,12 @@ export class ErrorNotificationProvider return { indicator: - this.context.tunnelState.details.cause.reason === 'is_offline' ? 'warning' : 'error', - title: !this.context.tunnelState.details.blockFailure - ? messages.pgettext('in-app-notifications', 'BLOCKING INTERNET') - : messages.pgettext('in-app-notifications', 'NETWORK TRAFFIC MIGHT BE LEAKING'), + this.context.tunnelState.details.cause === ErrorStateCause.isOffline + ? 'warning' + : 'error', + title: this.context.tunnelState.details.blockingError + ? messages.pgettext('in-app-notifications', 'NETWORK TRAFFIC MIGHT BE LEAKING') + : messages.pgettext('in-app-notifications', 'BLOCKING INTERNET'), subtitle, }; } else { @@ -72,9 +77,9 @@ export class ErrorNotificationProvider } } -function getMessage(errorDetails: IErrorState, accountExpiry?: string): string { - if (errorDetails.blockFailure) { - if (errorDetails.cause.reason === 'set_firewall_policy_error') { +function getMessage(errorState: ErrorState): string { + if (errorState.blockingError) { + if (errorState.cause === ErrorStateCause.setFirewallPolicyError) { switch (process.platform ?? window.env.platform) { case 'win32': return messages.pgettext( @@ -94,28 +99,37 @@ function getMessage(errorDetails: IErrorState, accountExpiry?: string): string { 'Unable to block all network traffic. Please troubleshoot or contact support.', ); } else { - switch (errorDetails.cause.reason) { - case 'auth_failed': { - const authFailure = parseAuthFailure(errorDetails.cause.details); - if ( - authFailure.kind === AuthFailureKind.unknown && - accountExpiry && - hasExpired(accountExpiry) - ) { - return messages.pgettext( - 'auth-failure', - 'You are logged in with an invalid account number. Please log out and try another one.', - ); - } else { - return authFailure.message; + switch (errorState.cause) { + case ErrorStateCause.authFailed: + switch (errorState.authFailedError) { + case AuthFailedError.invalidAccount: + return messages.pgettext( + 'auth-failure', + 'You are logged in with an invalid account number. Please log out and try another one.', + ); + + case AuthFailedError.expiredAccount: + return messages.pgettext('auth-failure', 'Blocking internet: account is out of time'); + + case AuthFailedError.tooManyConnections: + return messages.pgettext( + 'auth-failure', + 'Too many simultaneous connections on this account. Disconnect another device or try connecting again shortly.', + ); + + case AuthFailedError.unknown: + default: + return messages.pgettext( + 'auth-failure', + 'Unable to authenticate account. Please contact support.', + ); } - } - case 'ipv6_unavailable': + case ErrorStateCause.ipv6Unavailable: return messages.pgettext( 'notifications', 'Could not configure IPv6. Disable it in the app or enable it on your device.', ); - case 'set_firewall_policy_error': + case ErrorStateCause.setFirewallPolicyError: switch (process.platform ?? window.env.platform) { case 'win32': return messages.pgettext( @@ -130,24 +144,24 @@ function getMessage(errorDetails: IErrorState, accountExpiry?: string): string { default: return messages.pgettext('notifications', 'Unable to apply firewall rules.'); } - case 'set_dns_error': + case ErrorStateCause.setDnsError: return messages.pgettext( 'notifications', 'Unable to set system DNS server. Please contact support.', ); - case 'start_tunnel_error': + case ErrorStateCause.startTunnelError: return messages.pgettext( 'notifications', 'Unable to start tunnel connection. Please contact support.', ); - case 'tunnel_parameter_error': - return getTunnelParameterMessage(errorDetails.cause.details); - case 'is_offline': + case ErrorStateCause.tunnelParameterError: + return getTunnelParameterMessage(errorState.parameterError); + case ErrorStateCause.isOffline: return messages.pgettext( 'notifications', 'Your device is offline. The tunnel will automatically connect once your device is back online.', ); - case 'split_tunnel_error': + case ErrorStateCause.splitTunnelError: return messages.pgettext( 'notifications', 'Unable to communicate with Mullvad kernel driver. Try reconnecting or contact support.', @@ -156,16 +170,16 @@ function getMessage(errorDetails: IErrorState, accountExpiry?: string): string { } } -function getTunnelParameterMessage(err: TunnelParameterError): string { - switch (err) { +function getTunnelParameterMessage(error: TunnelParameterError): string { + switch (error) { /// TODO: once bridge constraints can be set, add a more descriptive error message - case 'no_matching_bridge_relay': - case 'no_matching_relay': + case TunnelParameterError.noMatchingBridgeRelay: + case TunnelParameterError.noMatchingRelay: return messages.pgettext( 'notifications', 'No servers in your selected location match your settings.', ); - case 'no_wireguard_key': + case TunnelParameterError.noWireguardKey: return sprintf( // TRANSLATORS: Available placeholders: // TRANSLATORS: %(wireguard)s - will be replaced with "WireGuard" @@ -175,7 +189,7 @@ function getTunnelParameterMessage(err: TunnelParameterError): string { ), { wireguard: strings.wireguard }, ); - case 'custom_tunnel_host_resultion_error': + case TunnelParameterError.customTunnelHostResolutionError: return messages.pgettext( 'notifications', 'Unable to resolve host of custom tunnel. Try changing your settings.', |
