From 66806740f3f25b1ce01ecbfafde60f70a6e2ec72 Mon Sep 17 00:00:00 2001 From: Matteo Luppi <100372313+lups2000@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:42:26 +0200 Subject: [PATCH] Add listen_host and listen_port to wireguard and listen_host to regular (#7086) * create functions to set listen host and port to wireguard mode * update tests wireguard * add listen host to regular --- .../js/__tests__/ducks/modes/regularSpec.tsx | 22 ++++++ .../__tests__/ducks/modes/wireguardSpec.tsx | 76 +++++++++++++++++-- web/src/js/components/Modes/Regular.tsx | 4 + web/src/js/components/Modes/Wireguard.tsx | 26 ++++++- web/src/js/ducks/modes/regular.ts | 17 +++++ web/src/js/ducks/modes/wireguard.ts | 60 ++++++++++++++- 6 files changed, 194 insertions(+), 11 deletions(-) diff --git a/web/src/js/__tests__/ducks/modes/regularSpec.tsx b/web/src/js/__tests__/ducks/modes/regularSpec.tsx index 050492d8c..78156dcc4 100644 --- a/web/src/js/__tests__/ducks/modes/regularSpec.tsx +++ b/web/src/js/__tests__/ducks/modes/regularSpec.tsx @@ -1,6 +1,7 @@ import regularReducer, { getMode, initialState, + setHost, setPort, toggleRegular, } from "./../../../ducks/modes/regular"; @@ -37,6 +38,17 @@ describe("regularReducer", () => { expect(fetchMock).toHaveBeenCalled(); }); + it("should dispatch MODE_REGULAR_SET_HOST and updateMode", async () => { + enableFetchMocks(); + const store = TStore(); + + await store.dispatch(setHost("localhost")); + + const state = store.getState().modes.regular; + expect(state.listen_host).toBe("localhost"); + expect(fetchMock).toHaveBeenCalled(); + }); + it('should handle RECEIVE_STATE action with data.servers containing "regular", an host and a port', () => { const action = { type: backendState.RECEIVE, @@ -167,6 +179,16 @@ describe("regularReducer", () => { expect(fetchMock).toHaveBeenCalled(); expect(store.getState().modes.regular.error).toBe("invalid spec"); }); + + it("should handle error when setting host", async () => { + fetchMock.mockReject(new Error("invalid spec")); + const store = TStore(); + + await store.dispatch(setHost("localhost")); + + expect(fetchMock).toHaveBeenCalled(); + expect(store.getState().modes.regular.error).toBe("invalid spec"); + }); }); describe("getMode", () => { diff --git a/web/src/js/__tests__/ducks/modes/wireguardSpec.tsx b/web/src/js/__tests__/ducks/modes/wireguardSpec.tsx index 6b78a7000..f0b56504a 100644 --- a/web/src/js/__tests__/ducks/modes/wireguardSpec.tsx +++ b/web/src/js/__tests__/ducks/modes/wireguardSpec.tsx @@ -2,6 +2,9 @@ import { enableFetchMocks } from "jest-fetch-mock"; import wireguardReducer, { getMode, initialState, + setFilePath, + setHost, + setPort, toggleWireguard, } from "../../../ducks/modes/wireguard"; import { TStore } from "../tutils"; @@ -25,6 +28,39 @@ describe("wireguardReducer", () => { expect(fetchMock).toHaveBeenCalled(); }); + it("should dispatch MODE_WIREGUARD_SET_PORT and updateMode", async () => { + enableFetchMocks(); + const store = TStore(); + + await store.dispatch(setPort(8082)); + + const state = store.getState().modes.wireguard; + expect(state.listen_port).toBe(8082); + expect(fetchMock).toHaveBeenCalled(); + }); + + it("should dispatch MODE_WIREGUARD_SET_HOST and updateMode", async () => { + enableFetchMocks(); + const store = TStore(); + + await store.dispatch(setHost("localhost")); + + const state = store.getState().modes.wireguard; + expect(state.listen_host).toBe("localhost"); + expect(fetchMock).toHaveBeenCalled(); + }); + + it("should dispatch MODE_WIREGUARD_SET_FILE_PATH and updateMode", async () => { + enableFetchMocks(); + const store = TStore(); + + await store.dispatch(setFilePath("/path/to/local/wireguard.conf")); + + const state = store.getState().modes.wireguard; + expect(state.file_path).toBe("/path/to/local/wireguard.conf"); + expect(fetchMock).toHaveBeenCalled(); + }); + it('should handle RECEIVE_STATE action with data.servers containing "wireguard", an host and a port', () => { const action = { type: backendState.RECEIVE, @@ -46,7 +82,7 @@ describe("wireguardReducer", () => { expect(newState.active).toBe(true); expect(newState.listen_host).toBe("localhost"); expect(newState.listen_port).toBe(8081); - expect(newState.path).toBe("/path_example"); + expect(newState.file_path).toBe("/path_example"); }); it('should handle RECEIVE_STATE action with data.servers containing just "wireguard"', () => { @@ -75,7 +111,7 @@ describe("wireguardReducer", () => { expect(newState.active).toBe(true); expect(newState.listen_host).toBe(""); expect(newState.listen_port).toBe(""); - expect(newState.path).toBe(""); + expect(newState.file_path).toBe(""); }); it("should handle RECEIVE_STATE action with data.servers containing another mode", () => { @@ -83,7 +119,7 @@ describe("wireguardReducer", () => { active: false, listen_host: "localhost", listen_port: 8080, - path: "/path_example", + file_path: "/path_example", }; const action = { type: backendState.RECEIVE, @@ -104,7 +140,7 @@ describe("wireguardReducer", () => { expect(newState.active).toBe(false); expect(newState.listen_host).toBe(initialState.listen_host); expect(newState.listen_port).toBe(initialState.listen_port); - expect(newState.path).toBe(initialState.path); + expect(newState.file_path).toBe(initialState.file_path); }); it("should handle RECEIVE_STATE action without data.servers", () => { @@ -145,6 +181,36 @@ describe("wireguardReducer", () => { expect(fetchMock).toHaveBeenCalled(); expect(store.getState().modes.wireguard.error).toBe("invalid spec"); }); + + it("should handle error when setting port", async () => { + fetchMock.mockReject(new Error("invalid spec")); + const store = TStore(); + + await store.dispatch(setPort(8082)); + + expect(fetchMock).toHaveBeenCalled(); + expect(store.getState().modes.wireguard.error).toBe("invalid spec"); + }); + + it("should handle error when setting host", async () => { + fetchMock.mockReject(new Error("invalid spec")); + const store = TStore(); + + await store.dispatch(setHost("localhost")); + + expect(fetchMock).toHaveBeenCalled(); + expect(store.getState().modes.wireguard.error).toBe("invalid spec"); + }); + + it("should handle error when setting file_path", async () => { + fetchMock.mockReject(new Error("invalid spec")); + const store = TStore(); + + await store.dispatch(setFilePath("/path/to/local/wireguard.conf")); + + expect(fetchMock).toHaveBeenCalled(); + expect(store.getState().modes.wireguard.error).toBe("invalid spec"); + }); }); describe("getMode", () => { @@ -162,7 +228,7 @@ describe("getMode", () => { const modes = { wireguard: { active: false, - path: "/path_example", + file_path: "/path_example", listen_host: "localhost", listen_port: 8080, }, diff --git a/web/src/js/components/Modes/Regular.tsx b/web/src/js/components/Modes/Regular.tsx index fa2954372..bcb179e0c 100644 --- a/web/src/js/components/Modes/Regular.tsx +++ b/web/src/js/components/Modes/Regular.tsx @@ -29,6 +29,10 @@ export default function Regular() { dispatch(setPort(port as unknown as number)); }; + /*const handleHostChange = (host: string) => { + dispatch(setHost(host)); + };*/ + return (

Explicit HTTP(S) Proxy

diff --git a/web/src/js/components/Modes/Wireguard.tsx b/web/src/js/components/Modes/Wireguard.tsx index 0192dee75..09ae1811d 100644 --- a/web/src/js/components/Modes/Wireguard.tsx +++ b/web/src/js/components/Modes/Wireguard.tsx @@ -6,9 +6,13 @@ import { toggleWireguard } from "../../ducks/modes/wireguard"; export default function Wireguard() { const dispatch = useAppDispatch(); - const { active, error: ui_error } = useAppSelector( - (state) => state.modes.wireguard, - ); + const { + active, + error: ui_error, + //listen_host, + //listen_port, + //file_path, + } = useAppSelector((state) => state.modes.wireguard); const backend_error = useAppSelector((state) => { if (state.backendState.servers) { @@ -21,6 +25,21 @@ export default function Wireguard() { return ""; }); + /* + const handlePortChange = (port: string) => { + // FIXME: We should eventually cast to Number and validate. + dispatch(setPort(port as unknown as number)); + }; + + const handleHostChange = (host: string) => { + dispatch(setHost(host)); + }; + + const handleFilePathChange = (path: string) => { + dispatch(setFilePath(path)); + }; + */ + return (

WireGuard Server

@@ -33,6 +52,7 @@ export default function Wireguard() { onChange={() => dispatch(toggleWireguard())} > Run WireGuard Server + {/* Popover will be added here in the next PR */} {(ui_error || backend_error) && (
diff --git a/web/src/js/ducks/modes/regular.ts b/web/src/js/ducks/modes/regular.ts index 9ba3c4a47..ccdd36dc8 100644 --- a/web/src/js/ducks/modes/regular.ts +++ b/web/src/js/ducks/modes/regular.ts @@ -13,6 +13,7 @@ import type { ModesState } from "../modes"; export const MODE_REGULAR_TOGGLE = "MODE_REGULAR_TOGGLE"; export const MODE_REGULAR_SET_PORT = "MODE_REGULAR_SET_PORT"; export const MODE_REGULAR_ERROR = "MODE_REGULAR_ERROR"; +export const MODE_REGULAR_SET_HOST = "MODE_REGULAR_SET_HOST"; export const DEFAULT_PORT = 8080; @@ -46,6 +47,16 @@ export const setPort = (port: number) => async (dispatch) => { } }; +export const setHost = (host: string) => async (dispatch) => { + dispatch({ type: MODE_REGULAR_SET_HOST, host }); + + try { + await dispatch(updateMode()); + } catch (e) { + dispatch({ type: MODE_REGULAR_ERROR, error: e.message }); + } +}; + const regularReducer = (state = initialState, action): RegularState => { switch (action.type) { case MODE_REGULAR_TOGGLE: @@ -60,6 +71,12 @@ const regularReducer = (state = initialState, action): RegularState => { listen_port: action.port as number, error: undefined, }; + case MODE_REGULAR_SET_HOST: + return { + ...state, + listen_host: action.host, + error: undefined, + }; case UPDATE_STATE: case RECEIVE_STATE: if (action.data && action.data.servers) { diff --git a/web/src/js/ducks/modes/wireguard.ts b/web/src/js/ducks/modes/wireguard.ts index 6d2e88ae9..0822b1aa7 100644 --- a/web/src/js/ducks/modes/wireguard.ts +++ b/web/src/js/ducks/modes/wireguard.ts @@ -12,14 +12,18 @@ import type { ModesState } from "../modes"; export const MODE_WIREGUARD_TOGGLE = "MODE_WIREGUARD_TOGGLE"; export const MODE_WIREGUARD_ERROR = "MODE_WIREGUARD_ERROR"; +export const MODE_WIREGUARD_SET_PORT = "MODE_WIREGUARD_SET_PORT"; +export const MODE_WIREGUARD_SET_HOST = "MODE_WIREGUARD_SET_HOST"; +export const MODE_WIREGUARD_SET_FILE_PATH = "MODE_WIREGUARD_SET_FILE_PATH"; interface WireguardState extends ModeState { - path?: string; + file_path?: string; } export const initialState: WireguardState = { active: false, - path: "", + file_path: "", + listen_port: 51820, }; export const getMode = (modes: ModesState): string[] => { @@ -36,6 +40,36 @@ export const toggleWireguard = () => async (dispatch) => { } }; +export const setPort = (port: number) => async (dispatch) => { + dispatch({ type: MODE_WIREGUARD_SET_PORT, port }); + + try { + await dispatch(updateMode()); + } catch (e) { + dispatch({ type: MODE_WIREGUARD_ERROR, error: e.message }); + } +}; + +export const setHost = (host: string) => async (dispatch) => { + dispatch({ type: MODE_WIREGUARD_SET_HOST, host }); + + try { + await dispatch(updateMode()); + } catch (e) { + dispatch({ type: MODE_WIREGUARD_ERROR, error: e.message }); + } +}; + +export const setFilePath = (path: string) => async (dispatch) => { + dispatch({ type: MODE_WIREGUARD_SET_FILE_PATH, path }); + + try { + await dispatch(updateMode()); + } catch (e) { + dispatch({ type: MODE_WIREGUARD_ERROR, error: e.message }); + } +}; + const wireguardReducer = (state = initialState, action): WireguardState => { switch (action.type) { case MODE_WIREGUARD_TOGGLE: @@ -43,6 +77,24 @@ const wireguardReducer = (state = initialState, action): WireguardState => { ...state, active: !state.active, }; + case MODE_WIREGUARD_SET_PORT: + return { + ...state, + listen_port: action.port as number, + error: undefined, + }; + case MODE_WIREGUARD_SET_HOST: + return { + ...state, + listen_host: action.host, + error: undefined, + }; + case MODE_WIREGUARD_SET_FILE_PATH: + return { + ...state, + file_path: action.path, + error: undefined, + }; case UPDATE_STATE: case RECEIVE_STATE: if (action.data && action.data.servers) { @@ -54,13 +106,15 @@ const wireguardReducer = (state = initialState, action): WireguardState => { return { ...state, active: isActive, - path: isActive ? currentModeConfig.data : state.path, listen_host: isActive ? currentModeConfig.listen_host : state.listen_host, listen_port: isActive ? (currentModeConfig.listen_port as number) : state.listen_port, + file_path: isActive + ? currentModeConfig.data + : state.file_path, error: isActive ? undefined : state.error, }; }