summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-09-02 15:27:57 +0100
committerEmīls Piņķis <emils@mullvad.net>2019-09-05 10:46:54 +0100
commit8f47cab67f7f92b1b246d5b993f3d2d846dd4219 (patch)
treeb40fc803aa34b99a8b8769f14a4c384a064e3fb3
parent96d52dfc0a69928c274531d65f9ddf1965ad5026 (diff)
downloadmullvadvpn-8f47cab67f7f92b1b246d5b993f3d2d846dd4219.tar.xz
mullvadvpn-8f47cab67f7f92b1b246d5b993f3d2d846dd4219.zip
Add button to regenerate key
-rw-r--r--gui/src/main/daemon-rpc.ts15
-rw-r--r--gui/src/main/index.ts5
-rw-r--r--gui/src/renderer/app.tsx24
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx156
-rw-r--r--gui/src/renderer/components/WireguardKeysStyles.tsx1
-rw-r--r--gui/src/renderer/containers/WireguardKeysPage.tsx9
-rw-r--r--gui/src/renderer/redux/settings/actions.ts41
-rw-r--r--gui/src/renderer/redux/settings/reducers.ts72
-rw-r--r--gui/src/shared/daemon-rpc-types.ts10
-rw-r--r--gui/src/shared/ipc-event-channel.ts9
10 files changed, 260 insertions, 82 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 0a55833731..2d4141304e 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -8,6 +8,7 @@ import {
ILocation,
IRelayList,
ISettings,
+ IWireguardPublicKey,
KeygenEvent,
RelaySettingsUpdate,
TunnelState,
@@ -337,10 +338,18 @@ const settingsSchema = partialObject({
tunnel_options: tunnelOptionsSchema,
});
+const wireguardPublicKey = object({
+ key: string,
+ created: string,
+});
+
const keygenEventSchema = oneOf(
enumeration('too_many_keys', 'generation_failure'),
object({
- new_key: string,
+ new_key: object({
+ key: string,
+ created: string,
+ }),
}),
);
@@ -567,10 +576,10 @@ export class DaemonRpc {
}
}
- public async getWireguardKey(): Promise<string | undefined> {
+ public async getWireguardKey(): Promise<IWireguardPublicKey | undefined> {
const response = await this.transport.send('get_wireguard_key');
try {
- return validate(maybe(string), response) || undefined;
+ return validate(maybe(wireguardPublicKey), response) || undefined;
} catch (error) {
throw new ResponseParseError('Invalid response from get_wireguard_key');
}
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts
index efe76bdfab..a0694e814c 100644
--- a/gui/src/main/index.ts
+++ b/gui/src/main/index.ts
@@ -14,6 +14,7 @@ import {
IRelayList,
IRelayListHostname,
ISettings,
+ IWireguardPublicKey,
KeygenEvent,
RelaySettings,
RelaySettingsUpdate,
@@ -143,7 +144,7 @@ class ApplicationMain {
// The UI locale which is set once from onReady handler
private locale = 'en';
- private wireguardPublicKey?: string;
+ private wireguardPublicKey?: IWireguardPublicKey;
private accountDataCache = new AccountDataCache(
(accountToken) => {
@@ -560,7 +561,7 @@ class ApplicationMain {
}
}
- private setWireguardKey(wireguardKey?: string) {
+ private setWireguardKey(wireguardKey?: IWireguardPublicKey) {
this.wireguardPublicKey = wireguardKey;
if (this.windowController) {
IpcMainEventChannel.wireguardKeys.notify(this.windowController.webContents, wireguardKey);
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 094b4f376d..b08743dab4 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -16,6 +16,7 @@ import AppRoutes from './routes';
import accountActions from './redux/account/actions';
import connectionActions from './redux/connection/actions';
import settingsActions from './redux/settings/actions';
+import { IWgKey } from './redux/settings/reducers';
import configureStore from './redux/store';
import userInterfaceActions from './redux/userinterface/actions';
import versionActions from './redux/version/actions';
@@ -33,6 +34,7 @@ import {
ILocation,
IRelayList,
ISettings,
+ IWireguardPublicKey,
KeygenEvent,
liftConstraint,
RelaySettings,
@@ -129,7 +131,7 @@ export default class AppRenderer {
this.storeAutoStart(autoStart);
});
- IpcRendererEventChannel.wireguardKeys.listen((publicKey?: string) => {
+ IpcRendererEventChannel.wireguardKeys.listen((publicKey?: IWireguardPublicKey) => {
this.setWireguardPublicKey(publicKey);
});
@@ -303,11 +305,16 @@ export default class AppRenderer {
IpcRendererEventChannel.guiSettings.setMonochromaticIcon(monochromaticIcon);
}
- public async verifyWireguardKey(publicKey: string) {
+ public async verifyWireguardKey(publicKey: IWgKey) {
const actions = this.reduxActions;
actions.settings.verifyWireguardKey(publicKey);
- const valid = await IpcRendererEventChannel.wireguardKeys.verifyKey();
- actions.settings.completeWireguardKeyVerification(valid);
+ try {
+ const valid = await IpcRendererEventChannel.wireguardKeys.verifyKey();
+ actions.settings.completeWireguardKeyVerification(valid);
+ } catch (error) {
+ log.error(`Failed to verify WireGuard key - ${error.message}`);
+ actions.settings.completeWireguardKeyVerification(undefined);
+ }
}
public async generateWireguardKey() {
@@ -317,6 +324,13 @@ export default class AppRenderer {
actions.settings.setWireguardKeygenEvent(keygenEvent);
}
+ public async replaceWireguardKey(oldKey: IWgKey) {
+ const actions = this.reduxActions;
+ actions.settings.replaceWireguardKey(oldKey);
+ const keygenEvent = await IpcRendererEventChannel.wireguardKeys.generateKey();
+ actions.settings.setWireguardKeygenEvent(keygenEvent);
+ }
+
private setRelaySettings(relaySettings: RelaySettings) {
const actions = this.reduxActions;
@@ -554,7 +568,7 @@ export default class AppRenderer {
this.reduxActions.settings.updateAutoStart(autoStart);
}
- private setWireguardPublicKey(publicKey?: string) {
+ private setWireguardPublicKey(publicKey?: IWireguardPublicKey) {
this.reduxActions.settings.setWireguardKey(publicKey);
}
}
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index d66ef68cf2..9ea386ec91 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -1,7 +1,10 @@
+import log from 'electron-log';
+import moment from 'moment';
import * as React from 'react';
import { Component, Text, View } from 'reactxp';
+import { sprintf } from 'sprintf-js';
import { messages } from '../../shared/gettext';
-import { WgKeyState } from '../redux/settings/reducers';
+import { IWgKey, WgKeyState } from '../redux/settings/reducers';
import * as AppButton from './AppButton';
import ImageView from './ImageView';
import { Container, Layout } from './Layout';
@@ -12,11 +15,13 @@ import styles from './WireguardKeysStyles';
export interface IProps {
keyState: WgKeyState;
isOffline: boolean;
+ locale: string;
+ onClose: () => void;
onGenerateKey: () => void;
- onVerifyKey: (publicKey: string) => void;
+ onReplaceKey: (old: IWgKey) => void;
+ onVerifyKey: (publicKey: IWgKey) => void;
onVisitWebsiteKey: () => void;
- onClose: () => void;
}
export default class WireguardKeys extends Component<IProps> {
@@ -46,11 +51,24 @@ export default class WireguardKeys extends Component<IProps> {
<Text style={styles.wgkeys__row_label}>
{messages.pgettext('wireguard-keys', 'Public key')}
</Text>
- <View style={styles.wgkeys__row_value}>{this.getKeyRow()}</View>
+ <View style={styles.wgkeys__row_value}>{this.getKeyText()}</View>
+ <Text style={styles.wgkeys__row_label}>
+ {messages.pgettext('wireguard-keys', 'Key generated')}
+ </Text>
+ <Text style={styles.wgkeys__row_value}>{this.ageOfKeyString()}</Text>
<View style={styles.wgkeys__validity_row}>{this.keyValidityLabel()}</View>
</View>
- <View style={styles.wgkeys__row}>{this.getActionButton()}</View>
+ <View style={styles.wgkeys__row}>{this.getGenerateButton()}</View>
+ <View style={styles.wgkeys__row}>
+ <AppButton.GreenButton
+ disabled={this.isVerifyButtonDisabled()}
+ onPress={this.getOnVerifyKeyCb()}>
+ <AppButton.Label>
+ {messages.pgettext('wireguard-key-view', 'Verify key')}
+ </AppButton.Label>
+ </AppButton.GreenButton>
+ </View>
<View style={styles.wgkeys__row}>
<AppButton.GreenButton
disabled={this.props.isOffline}
@@ -68,34 +86,50 @@ export default class WireguardKeys extends Component<IProps> {
);
}
- /// Action button can either generate or verify a key
- private getActionButton() {
+ private isVerifyButtonDisabled(): boolean {
switch (this.props.keyState.type) {
case 'key-set':
- const publicKey = this.props.keyState.publicKey;
- // if the key is known to be invalid, allow the user to generate a new one
- if (this.props.keyState.valid === false) {
- break;
- }
+ return false || this.props.isOffline;
+ default:
+ return true;
+ }
+ }
- const verificationCallback = () => this.props.onVerifyKey(publicKey);
+ private getOnVerifyKeyCb() {
+ return () => {
+ switch (this.props.keyState.type) {
+ case 'key-set':
+ const key = this.props.keyState.key;
+ this.props.onVerifyKey(key);
+ break;
+ default:
+ log.error(`onVerifyKey called from invalid state - ${this.props.keyState.type}`);
+ }
+ };
+ }
- return (
- <AppButton.GreenButton disabled={this.props.isOffline} onPress={verificationCallback}>
- <AppButton.Label>
- {messages.pgettext('wireguard-key-view', 'Verify key')}
- </AppButton.Label>
- </AppButton.GreenButton>
- );
+ /// Action button can either generate or verify a key
+ private getGenerateButton() {
+ const generateText = messages.pgettext('wireguard-key-view', 'Generate key');
+ const regenerateText = messages.pgettext('wireguard-key-view', 'Regenerate key');
+ let buttonText = generateText;
+ let generateKey = this.props.onGenerateKey;
+ switch (this.props.keyState.type) {
+ case 'key-set':
+ buttonText = regenerateText;
+ const key = this.props.keyState.key;
+ generateKey = () => this.props.onReplaceKey(key);
+ break;
case 'being-verified':
- return this.busyButton(messages.pgettext('wireguard-key-view', 'Verifying key'));
+ return this.busyButton(regenerateText);
+ case 'being-replaced':
case 'being-generated':
return this.busyButton(messages.pgettext('wireguard-key-view', 'Generating key'));
}
return (
- <AppButton.GreenButton disabled={this.props.isOffline} onPress={this.props.onGenerateKey}>
- <AppButton.Label>{messages.pgettext('wireguard-key-view', 'Generate key')}</AppButton.Label>
+ <AppButton.GreenButton disabled={this.props.isOffline} onPress={generateKey}>
+ <AppButton.Label>{buttonText}</AppButton.Label>
</AppButton.GreenButton>
);
}
@@ -109,30 +143,26 @@ export default class WireguardKeys extends Component<IProps> {
);
}
- private getKeyRow() {
+ private getKeyText() {
switch (this.props.keyState.type) {
case 'being-verified':
case 'key-set':
// mimicking the truncating of the key from website
return (
- <View title={this.props.keyState.publicKey}>
+ <View title={this.props.keyState.key.publicKey}>
<Text style={styles.wgkeys__row_value}>
- {this.props.keyState.publicKey.substring(0, 20) + '...'}
+ {this.props.keyState.key.publicKey.substring(0, 20) + '...'}
</Text>
</View>
);
+ case 'being-replaced':
case 'being-generated':
- return <ImageView source="icon-spinner" height={25} width={25} />;
+ return <ImageView source="icon-spinner" height={19} width={19} />;
case 'too-many-keys':
- return (
- <Text style={styles.wgkeys__invalid_key}>
- {messages.pgettext('wireguard-key-view', 'Account has too many keys already')}
- </Text>
- );
case 'generation-failure':
return (
<Text style={styles.wgkeys__invalid_key}>
- {messages.pgettext('wireguard-key-view', 'Failed to generate key')}
+ {this.formatKeygenFailure(this.props.keyState.type)}
</Text>
);
default:
@@ -147,23 +177,75 @@ export default class WireguardKeys extends Component<IProps> {
private keyValidityLabel() {
switch (this.props.keyState.type) {
case 'being-verified':
- return <ImageView source="icon-spinner" height={25} width={25} />;
+ return <ImageView source="icon-spinner" height={20} width={20} />;
case 'key-set':
- if (this.props.keyState.valid === true) {
+ const key = this.props.keyState.key;
+ if (key.valid === true) {
return (
<Text style={styles.wgkeys__valid_key}>
{messages.pgettext('account-view', 'Key is valid')}
</Text>
);
- } else if (this.props.keyState.valid === false) {
+ } else if (key.valid === false) {
return (
<Text style={styles.wgkeys__invalid_key}>
{messages.pgettext('wireguard-key-view', 'Key is invalid')}
</Text>
);
+ } else if (key.replacementFailure) {
+ let failure = '';
+ switch (key.replacementFailure) {
+ case 'too_many_keys':
+ failure = this.formatKeygenFailure('too-many-keys');
+ break;
+ case 'generation_failure':
+ failure = this.formatKeygenFailure('generation-failure');
+ break;
+ }
+
+ const failureMessage = sprintf(
+ messages.pgettext('wireguard-key-view', 'Failed to replace key - %(failure)s'),
+ { failure },
+ );
+ return <Text style={styles.wgkeys__invalid_key}>{failureMessage}</Text>;
+ } else if (key.verificationFailed) {
+ return (
+ <Text style={styles.wgkeys__invalid_key}>
+ {messages.pgettext('wireguard-key-view', 'Key verification failed')}
+ </Text>
+ );
}
+
+ default:
+ return (
+ // Placeholder to take up the same amount of space as the validity text/spinner
+ <View style={{ marginBottom: 20 }} />
+ );
+ }
+ }
+
+ private ageOfKeyString(): string {
+ let keyCreatedSince = '-';
+ switch (this.props.keyState.type) {
+ case 'key-set':
+ case 'being-verified':
+ keyCreatedSince = moment(this.props.keyState.key.created)
+ .locale(this.props.locale)
+ .fromNow();
+ break;
+ }
+
+ return keyCreatedSince;
+ }
+
+ private formatKeygenFailure(failure: 'too-many-keys' | 'generation-failure'): string {
+ switch (failure) {
+ case 'too-many-keys':
+ return messages.pgettext('wireguard-key-view', 'Account has too many keys already');
+ case 'generation-failure':
+ return messages.pgettext('wireguard-key-view', 'Failed to generate a key');
default:
- return '';
+ return failure;
}
}
diff --git a/gui/src/renderer/components/WireguardKeysStyles.tsx b/gui/src/renderer/components/WireguardKeysStyles.tsx
index 2172b79dae..ec3fd6cf2f 100644
--- a/gui/src/renderer/components/WireguardKeysStyles.tsx
+++ b/gui/src/renderer/components/WireguardKeysStyles.tsx
@@ -24,7 +24,6 @@ export default {
lineHeight: 20,
letterSpacing: -0.2,
color: colors.white60,
- marginBottom: 9,
}),
wgkeys__validity_row: Styles.createViewStyle({
paddingTop: 5,
diff --git a/gui/src/renderer/containers/WireguardKeysPage.tsx b/gui/src/renderer/containers/WireguardKeysPage.tsx
index 2fb185cb1d..813526ff29 100644
--- a/gui/src/renderer/containers/WireguardKeysPage.tsx
+++ b/gui/src/renderer/containers/WireguardKeysPage.tsx
@@ -4,20 +4,23 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { links } from '../../config.json';
import WireguardKeys from '../components/WireguardKeys';
+import { IWgKey } from '../redux/settings/reducers';
import { IReduxState, ReduxDispatch } from '../redux/store';
import { ISharedRouteProps } from '../routes';
-const mapStateToProps = (state: IReduxState, _props: ISharedRouteProps) => ({
+const mapStateToProps = (state: IReduxState, props: ISharedRouteProps) => ({
keyState: state.settings.wireguardKeyState,
isOffline: state.connection.isBlocked,
+ locale: props.locale,
});
const mapDispatchToProps = (dispatch: ReduxDispatch, props: ISharedRouteProps) => {
const history = bindActionCreators({ push, goBack }, dispatch);
return {
+ onClose: () => history.goBack(),
onGenerateKey: () => props.app.generateWireguardKey(),
- onVerifyKey: (publicKey: string) => props.app.verifyWireguardKey(publicKey),
+ onReplaceKey: (oldKey: IWgKey) => props.app.replaceWireguardKey(oldKey),
+ onVerifyKey: (publicKey: IWgKey) => props.app.verifyWireguardKey(publicKey),
onVisitWebsiteKey: () => shell.openExternal(links.manageKeys),
- onClose: () => history.goBack(),
};
};
diff --git a/gui/src/renderer/redux/settings/actions.ts b/gui/src/renderer/redux/settings/actions.ts
index 6c87c18fa9..a7c766e7fd 100644
--- a/gui/src/renderer/redux/settings/actions.ts
+++ b/gui/src/renderer/redux/settings/actions.ts
@@ -1,6 +1,6 @@
-import { BridgeState, KeygenEvent } from '../../../shared/daemon-rpc-types';
+import { BridgeState, IWireguardPublicKey, KeygenEvent } from '../../../shared/daemon-rpc-types';
import { IGuiSettingsState } from '../../../shared/gui-settings-state';
-import { IRelayLocationRedux, RelaySettingsRedux } from './reducers';
+import { IRelayLocationRedux, IWgKey, RelaySettingsRedux } from './reducers';
export interface IUpdateGuiSettingsAction {
type: 'UPDATE_GUI_SETTINGS';
@@ -50,16 +50,21 @@ export interface IUpdateAutoStartAction {
// Used to set wireguard key when accounts are changed.
export interface IWireguardSetKey {
type: 'SET_WIREGUARD_KEY';
- publicKey?: string;
+ key?: IWgKey;
}
export interface IWireguardGenerateKey {
type: 'GENERATE_WIREGUARD_KEY';
}
+export interface IWireguardReplaceKey {
+ type: 'REPLACE_WIREGUARD_KEY';
+ oldKey: IWgKey;
+}
+
export interface IWireguardVerifyKey {
type: 'VERIFY_WIREGUARD_KEY';
- publicKey: string;
+ key: IWgKey;
}
export interface IWireguardKeygenEvent {
@@ -69,7 +74,7 @@ export interface IWireguardKeygenEvent {
export interface IWireguardKeyVerifiedAction {
type: 'WIREGUARD_KEY_VERIFICATION_COMPLETE';
- verified: boolean;
+ verified?: boolean;
}
export type SettingsAction =
@@ -85,6 +90,7 @@ export type SettingsAction =
| IWireguardSetKey
| IWireguardVerifyKey
| IWireguardGenerateKey
+ | IWireguardReplaceKey
| IWireguardKeygenEvent
| IWireguardKeyVerifiedAction;
@@ -153,10 +159,17 @@ function updateAutoStart(autoStart: boolean): IUpdateAutoStartAction {
};
}
-function setWireguardKey(publicKey?: string): IWireguardSetKey {
+function setWireguardKey(publicKey?: IWireguardPublicKey): IWireguardSetKey {
+ const key = publicKey
+ ? {
+ publicKey: publicKey.key,
+ created: publicKey.created,
+ valid: undefined,
+ }
+ : undefined;
return {
type: 'SET_WIREGUARD_KEY',
- publicKey,
+ key,
};
}
@@ -173,14 +186,21 @@ function generateWireguardKey(): IWireguardGenerateKey {
};
}
-function verifyWireguardKey(publicKey: string): IWireguardVerifyKey {
+function replaceWireguardKey(oldKey: IWgKey): IWireguardReplaceKey {
+ return {
+ type: 'REPLACE_WIREGUARD_KEY',
+ oldKey,
+ };
+}
+
+function verifyWireguardKey(key: IWgKey): IWireguardVerifyKey {
return {
type: 'VERIFY_WIREGUARD_KEY',
- publicKey,
+ key,
};
}
-function completeWireguardKeyVerification(verified: boolean): IWireguardKeyVerifiedAction {
+function completeWireguardKeyVerification(verified?: boolean): IWireguardKeyVerifiedAction {
return {
type: 'WIREGUARD_KEY_VERIFICATION_COMPLETE',
verified,
@@ -200,6 +220,7 @@ export default {
setWireguardKey,
setWireguardKeygenEvent,
generateWireguardKey,
+ replaceWireguardKey,
verifyWireguardKey,
completeWireguardKeyVerification,
};
diff --git a/gui/src/renderer/redux/settings/reducers.ts b/gui/src/renderer/redux/settings/reducers.ts
index e90022062c..5d7f37fb50 100644
--- a/gui/src/renderer/redux/settings/reducers.ts
+++ b/gui/src/renderer/redux/settings/reducers.ts
@@ -54,10 +54,17 @@ export interface IRelayLocationRedux {
cities: IRelayLocationCityRedux[];
}
-interface IWgKeySet {
- type: 'key-set';
+export interface IWgKey {
publicKey: string;
+ created: string;
valid?: boolean;
+ replacementFailure?: KeygenEvent;
+ verificationFailed?: boolean;
+}
+
+interface IWgKeySet {
+ type: 'key-set';
+ key: IWgKey;
}
interface IWgKeyNotSet {
@@ -76,9 +83,14 @@ interface IWgKeyBeingGenerated {
type: 'being-generated';
}
+interface IWgKeyBeingReplaced {
+ type: 'being-replaced';
+ oldKey: IWgKey;
+}
+
interface IWgKeyBeingVerified {
type: 'being-verified';
- publicKey: string;
+ key: IWgKey;
}
export type WgKeyState =
@@ -87,6 +99,7 @@ export type WgKeyState =
| IWgKeyGenerationFailure
| IWgTooManyKeys
| IWgKeyBeingVerified
+ | IWgKeyBeingReplaced
| IWgKeyBeingGenerated;
export interface ISettingsReduxState {
@@ -199,12 +212,12 @@ export default function(
case 'SET_WIREGUARD_KEY':
return {
...state,
- wireguardKeyState: setWireguardKey(action.publicKey),
+ wireguardKeyState: setWireguardKey(action.key),
};
case 'WIREGUARD_KEYGEN_EVENT':
return {
...state,
- wireguardKeyState: setWireguardKeygenEvent(action.event),
+ wireguardKeyState: setWireguardKeygenEvent(state, action.event),
};
case 'WIREGUARD_KEY_VERIFICATION_COMPLETE':
return {
@@ -214,7 +227,7 @@ export default function(
case 'VERIFY_WIREGUARD_KEY':
return {
...state,
- wireguardKeyState: { type: 'being-verified', publicKey: action.publicKey },
+ wireguardKeyState: { type: 'being-verified', key: action.key },
};
case 'GENERATE_WIREGUARD_KEY':
@@ -223,16 +236,22 @@ export default function(
wireguardKeyState: { type: 'being-generated' },
};
+ case 'REPLACE_WIREGUARD_KEY':
+ return {
+ ...state,
+ wireguardKeyState: { type: 'being-replaced', oldKey: action.oldKey },
+ };
+
default:
return state;
}
}
-function setWireguardKey(publicKey?: string): WgKeyState {
- if (publicKey) {
+function setWireguardKey(key?: IWgKey): WgKeyState {
+ if (key) {
return {
type: 'key-set',
- publicKey,
+ key,
};
} else {
return {
@@ -241,7 +260,23 @@ function setWireguardKey(publicKey?: string): WgKeyState {
}
}
-function setWireguardKeygenEvent(keygenEvent: KeygenEvent): WgKeyState {
+function setWireguardKeygenEvent(state: ISettingsReduxState, keygenEvent: KeygenEvent): WgKeyState {
+ const oldKeyState = state.wireguardKeyState;
+ if (oldKeyState.type === 'being-replaced') {
+ switch (keygenEvent) {
+ case 'too_many_keys':
+ case 'generation_failure':
+ return {
+ type: 'key-set',
+ key: {
+ ...oldKeyState.oldKey,
+ replacementFailure: keygenEvent,
+ },
+ };
+ default:
+ break;
+ }
+ }
switch (keygenEvent) {
case 'too_many_keys':
return { type: 'too-many-keys' };
@@ -250,19 +285,26 @@ function setWireguardKeygenEvent(keygenEvent: KeygenEvent): WgKeyState {
default:
return {
type: 'key-set',
- publicKey: keygenEvent.newKey,
- valid: true,
+ key: {
+ publicKey: keygenEvent.newKey.key,
+ created: keygenEvent.newKey.created,
+ valid: undefined,
+ },
};
}
}
-function applyKeyVerification(state: WgKeyState, verified: boolean): WgKeyState {
+function applyKeyVerification(state: WgKeyState, verified?: boolean): WgKeyState {
+ const verificationFailed = verified === undefined ? true : undefined;
switch (state.type) {
case 'being-verified':
return {
- ...state,
type: 'key-set',
- valid: verified,
+ key: {
+ ...state.key,
+ valid: verified,
+ verificationFailed,
+ },
};
// drop the verification event if the key wasn't being verified.
default:
diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts
index f88cd29404..0f73586275 100644
--- a/gui/src/shared/daemon-rpc-types.ts
+++ b/gui/src/shared/daemon-rpc-types.ts
@@ -295,10 +295,16 @@ export interface ISettings {
bridgeState: BridgeState;
}
-export type KeygenEvent = INewWireguardKey | 'too_many_keys' | 'generation_failure';
+export type KeygenEvent = INewWireguardKey | KeygenFailure;
+export type KeygenFailure = 'too_many_keys' | 'generation_failure';
export interface INewWireguardKey {
- newKey: string;
+ newKey: IWireguardPublicKey;
+}
+
+export interface IWireguardPublicKey {
+ key: string;
+ created: string;
}
export type BridgeState = 'auto' | 'on' | 'off';
diff --git a/gui/src/shared/ipc-event-channel.ts b/gui/src/shared/ipc-event-channel.ts
index 8283cf43dc..7bdeb6e759 100644
--- a/gui/src/shared/ipc-event-channel.ts
+++ b/gui/src/shared/ipc-event-channel.ts
@@ -13,6 +13,7 @@ import {
ILocation,
IRelayList,
ISettings,
+ IWireguardPublicKey,
KeygenEvent,
RelaySettingsUpdate,
TunnelState,
@@ -31,7 +32,7 @@ export interface IAppStateSnapshot {
currentVersion: ICurrentAppVersionInfo;
upgradeVersion: IAppUpgradeInfo;
guiSettings: IGuiSettingsState;
- wireguardPublicKey?: string;
+ wireguardPublicKey?: IWireguardPublicKey;
}
interface ISender<T> {
@@ -114,13 +115,13 @@ interface IAutoStartHandlers extends ISender<boolean> {
handleSet(fn: (value: boolean) => Promise<void>): void;
}
-interface IWireguardKeyMethods extends IReceiver<string | undefined> {
+interface IWireguardKeyMethods extends IReceiver<IWireguardPublicKey | undefined> {
listenKeygenEvents(fn: (event: KeygenEvent) => void): void;
generateKey(): Promise<KeygenEvent>;
verifyKey(): Promise<boolean>;
}
-interface IWireguardKeyHandlers extends ISender<string | undefined> {
+interface IWireguardKeyHandlers extends ISender<IWireguardPublicKey | undefined> {
notifyKeygenEvent(webContents: WebContents, event: KeygenEvent): void;
handleGenerateKey(fn: () => Promise<KeygenEvent>): void;
handleVerifyKey(fn: () => Promise<boolean>): void;
@@ -340,7 +341,7 @@ export class IpcMainEventChannel {
};
public static wireguardKeys: IWireguardKeyHandlers = {
- notify: sender<string | undefined>(WIREGUARD_KEY_SET),
+ notify: sender<IWireguardPublicKey | undefined>(WIREGUARD_KEY_SET),
notifyKeygenEvent: sender<KeygenEvent>(WIREGUARD_KEYGEN_EVENT),
handleGenerateKey: requestHandler(GENERATE_WIREGUARD_KEY),
handleVerifyKey: requestHandler(VERIFY_WIREGUARD_KEY),