summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-01-31 13:11:59 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-01-31 13:11:59 +0100
commit0d9abfd26b0d0e2151eaebaae1bd01f2f439466b (patch)
tree6f7c6c6fd29bcf69cd5906a56a14c3cdeeab3d45 /gui/src
parent9b9da3ebbd90d52cec84c17edb4d99a472fd9a61 (diff)
parent87cb3b634dd7b9a5e173637dff956f9544aaccd3 (diff)
downloadmullvadvpn-0d9abfd26b0d0e2151eaebaae1bd01f2f439466b.tar.xz
mullvadvpn-0d9abfd26b0d0e2151eaebaae1bd01f2f439466b.zip
Merge branch 'correctly-handle-removal-disabling-of-access-method-des-561'
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/main/daemon-rpc.ts23
-rw-r--r--gui/src/main/default-settings.ts29
-rw-r--r--gui/src/renderer/components/ApiAccessMethods.tsx62
-rw-r--r--gui/src/renderer/components/EditApiAccessMethod.tsx5
-rw-r--r--gui/src/renderer/components/Switch.tsx2
-rw-r--r--gui/src/renderer/components/TransitionContainer.tsx1
-rw-r--r--gui/src/renderer/redux/settings/reducers.ts3
-rw-r--r--gui/src/shared/daemon-rpc-types.ts6
8 files changed, 95 insertions, 36 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 681eb0a454..6290aa7a92 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -1163,7 +1163,7 @@ function convertFromSettings(settings: grpcTypes.Settings): ISettings | undefine
const splitTunnel = settingsObject.splitTunnel ?? { enableExclusions: false, appsList: [] };
const obfuscationSettings = convertFromObfuscationSettings(settingsObject.obfuscationSettings);
const customLists = convertFromCustomListSettings(settings.getCustomLists());
- const apiAccessMethods = convertFromApiAccessMethodSettings(settings.getApiAccessMethods());
+ const apiAccessMethods = convertFromApiAccessMethodSettings(settings.getApiAccessMethods()!);
return {
...settings.toObject(),
bridgeState,
@@ -1893,14 +1893,25 @@ function convertToSocksAuth(authentication: SocksAuth): grpcTypes.SocksAuth {
}
function convertFromApiAccessMethodSettings(
- accessMethods?: grpcTypes.ApiAccessMethodSettings,
+ accessMethods: grpcTypes.ApiAccessMethodSettings,
): ApiAccessMethodSettings {
- return (
+ const direct = convertFromApiAccessMethodSetting(
+ ensureExists(accessMethods.getDirect(), "no 'Direct' access method was found"),
+ );
+ const bridges = convertFromApiAccessMethodSetting(
+ ensureExists(accessMethods.getMullvadBridges(), "no 'Mullvad Bridges' access method was found"),
+ );
+ const custom =
accessMethods
- ?.getAccessMethodSettingsList()
+ .getCustomList()
.filter((setting) => setting.hasId() && setting.hasAccessMethod())
- .map(convertFromApiAccessMethodSetting) ?? []
- );
+ .map(convertFromApiAccessMethodSetting) ?? [];
+
+ return {
+ direct,
+ mullvadBridges: bridges,
+ custom,
+ };
}
function convertFromApiAccessMethodSetting(
diff --git a/gui/src/main/default-settings.ts b/gui/src/main/default-settings.ts
index 4510a71896..7f7656a56a 100644
--- a/gui/src/main/default-settings.ts
+++ b/gui/src/main/default-settings.ts
@@ -1,4 +1,9 @@
-import { ISettings, ObfuscationType, Ownership } from '../shared/daemon-rpc-types';
+import {
+ ApiAccessMethodSettings,
+ ISettings,
+ ObfuscationType,
+ Ownership,
+} from '../shared/daemon-rpc-types';
export function getDefaultSettings(): ISettings {
return {
@@ -71,6 +76,26 @@ export function getDefaultSettings(): ISettings {
},
},
customLists: [],
- apiAccessMethods: [],
+ apiAccessMethods: getDefaultApiAccessMethods(),
+ };
+}
+
+export function getDefaultApiAccessMethods(): ApiAccessMethodSettings {
+ // 'id's are UUIDs generated by the daemon when an access method is created,
+ // and as such we can't provide a good default value for them.
+ return {
+ direct: {
+ id: '',
+ name: 'Direct',
+ enabled: true,
+ type: 'direct',
+ },
+ mullvadBridges: {
+ id: '',
+ name: 'Mullvad Bridges',
+ enabled: false,
+ type: 'bridges',
+ },
+ custom: [],
};
}
diff --git a/gui/src/renderer/components/ApiAccessMethods.tsx b/gui/src/renderer/components/ApiAccessMethods.tsx
index c8a6f98b19..0774fcc320 100644
--- a/gui/src/renderer/components/ApiAccessMethods.tsx
+++ b/gui/src/renderer/components/ApiAccessMethods.tsx
@@ -125,11 +125,20 @@ export default function ApiAccessMethods() {
<StyledSettingsContent>
<Cell.Group>
- {methods.map((method) => (
+ <ApiAccessMethod
+ method={methods.direct}
+ inUse={methods.direct.id === currentMethod?.id}
+ />
+ <ApiAccessMethod
+ method={methods.mullvadBridges}
+ inUse={methods.mullvadBridges.id === currentMethod?.id}
+ />
+ {methods.custom.map((method) => (
<ApiAccessMethod
key={method.id}
method={method}
inUse={method.id === currentMethod?.id}
+ custom
/>
))}
</Cell.Group>
@@ -150,6 +159,7 @@ export default function ApiAccessMethods() {
interface ApiAccessMethodProps {
method: AccessMethodSetting;
inUse: boolean;
+ custom?: boolean;
}
function ApiAccessMethod(props: ApiAccessMethodProps) {
@@ -186,8 +196,8 @@ function ApiAccessMethod(props: ApiAccessMethodProps) {
}
}, [testApiAccessMethod, props.method.id]);
- const menuItems = useMemo<Array<ContextMenuItem>>(
- () => [
+ const menuItems = useMemo<Array<ContextMenuItem>>(() => {
+ const items: Array<ContextMenuItem> = [
{
type: 'item' as const,
label: 'Use',
@@ -195,28 +205,30 @@ function ApiAccessMethod(props: ApiAccessMethodProps) {
onClick: setApiAccessMethod,
},
{ type: 'item' as const, label: 'Test', onClick: () => testApiAccessMethod(props.method.id) },
- // Edit and Delete shouldn't be available for direct and bridges.
- ...(props.method.type === 'direct' || props.method.type === 'bridges'
- ? []
- : [
- { type: 'separator' as const },
- {
- type: 'item' as const,
- label: 'Edit',
- onClick: () =>
- history.push(
- generateRoutePath(RoutePath.editApiAccessMethods, { id: props.method.id }),
- ),
- },
- {
- type: 'item' as const,
- label: 'Delete',
- onClick: showRemoveConfirmation,
- },
- ]),
- ],
- [props.method.id, props.inUse, setApiAccessMethod, testApiAccessMethod, history.push],
- );
+ ];
+
+ // Edit and Delete shouldn't be available for direct and bridges.
+ if (props.custom) {
+ items.push(
+ { type: 'separator' as const },
+ {
+ type: 'item' as const,
+ label: 'Edit',
+ onClick: () =>
+ history.push(
+ generateRoutePath(RoutePath.editApiAccessMethods, { id: props.method.id }),
+ ),
+ },
+ {
+ type: 'item' as const,
+ label: 'Delete',
+ onClick: showRemoveConfirmation,
+ },
+ );
+ }
+
+ return items;
+ }, [props.method.id, props.inUse, setApiAccessMethod, testApiAccessMethod, history.push]);
return (
<Cell.Row>
diff --git a/gui/src/renderer/components/EditApiAccessMethod.tsx b/gui/src/renderer/components/EditApiAccessMethod.tsx
index c56329214b..ecb633ae98 100644
--- a/gui/src/renderer/components/EditApiAccessMethod.tsx
+++ b/gui/src/renderer/components/EditApiAccessMethod.tsx
@@ -55,7 +55,10 @@ function AccessMethodForm() {
// Use id in url to figure out which method is to be edited. undefined means this is a new method.
const { id } = useParams<{ id: string | undefined }>();
- const method = methods.find((method) => method.id === id);
+ // Ugly way of iterating over all access methods, but it works.
+ const method = [methods.direct, methods.mullvadBridges, ...methods.custom].find(
+ (method) => method.id === id,
+ );
const updatedMethod = useRef<NewAccessMethodSetting | undefined>(method);
const updateMethod = useCallback(
diff --git a/gui/src/renderer/components/Switch.tsx b/gui/src/renderer/components/Switch.tsx
index 595bc422a2..f87bf2a52b 100644
--- a/gui/src/renderer/components/Switch.tsx
+++ b/gui/src/renderer/components/Switch.tsx
@@ -5,7 +5,9 @@ import { colors } from '../../config.json';
interface IProps {
id?: string;
+ // eslint-disable-next-line @typescript-eslint/naming-convention
'aria-labelledby'?: string;
+ // eslint-disable-next-line @typescript-eslint/naming-convention
'aria-describedby'?: string;
isOn: boolean;
onChange?: (isOn: boolean) => void;
diff --git a/gui/src/renderer/components/TransitionContainer.tsx b/gui/src/renderer/components/TransitionContainer.tsx
index 3e7007e3c8..9773c64512 100644
--- a/gui/src/renderer/components/TransitionContainer.tsx
+++ b/gui/src/renderer/components/TransitionContainer.tsx
@@ -48,6 +48,7 @@ interface StyledTransitionContentProps {
export const StyledTransitionContent = styled.div.attrs<
StyledTransitionContentProps,
+ // eslint-disable-next-line @typescript-eslint/naming-convention
{ 'data-testid': string }
>({
'data-testid': 'transition-content',
diff --git a/gui/src/renderer/redux/settings/reducers.ts b/gui/src/renderer/redux/settings/reducers.ts
index cdff32e22c..bb971f896a 100644
--- a/gui/src/renderer/redux/settings/reducers.ts
+++ b/gui/src/renderer/redux/settings/reducers.ts
@@ -1,3 +1,4 @@
+import { getDefaultApiAccessMethods } from '../../../main/default-settings';
import { IWindowsApplication } from '../../../shared/application-types';
import {
AccessMethodSetting,
@@ -178,7 +179,7 @@ const initialState: ISettingsReduxState = {
},
},
customLists: [],
- apiAccessMethods: [],
+ apiAccessMethods: getDefaultApiAccessMethods(),
currentApiAccessMethod: undefined,
};
diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts
index 71f6936804..f048549b7a 100644
--- a/gui/src/shared/daemon-rpc-types.ts
+++ b/gui/src/shared/daemon-rpc-types.ts
@@ -533,7 +533,11 @@ export type AccessMethodSetting = NewAccessMethodSetting & {
id: string;
};
-export type ApiAccessMethodSettings = Array<AccessMethodSetting>;
+export type ApiAccessMethodSettings = {
+ direct: AccessMethodSetting;
+ mullvadBridges: AccessMethodSetting;
+ custom: Array<AccessMethodSetting>;
+};
export function parseSocketAddress(socketAddrStr: string): ISocketAddress {
const re = new RegExp(/(.+):(\d+)$/);