feat: add support for allowing self-signed TLS certificates in gateway configuration
This commit is contained in:
@@ -12,7 +12,7 @@ export interface GatewayRead {
|
||||
name: string;
|
||||
url: string;
|
||||
workspace_root: string;
|
||||
allow_insecure_tls: boolean;
|
||||
allow_insecure_tls?: boolean;
|
||||
disable_device_pairing?: boolean;
|
||||
id: string;
|
||||
organization_id: string;
|
||||
|
||||
@@ -10,4 +10,5 @@ export type GatewaysStatusApiV1GatewaysStatusGetParams = {
|
||||
gateway_url?: string | null;
|
||||
gateway_token?: string | null;
|
||||
gateway_disable_device_pairing?: boolean;
|
||||
gateway_allow_insecure_tls?: boolean;
|
||||
};
|
||||
|
||||
@@ -132,6 +132,7 @@ export default function EditGatewayPage() {
|
||||
gatewayUrl: resolvedGatewayUrl,
|
||||
gatewayToken: resolvedGatewayToken,
|
||||
gatewayDisableDevicePairing: resolvedDisableDevicePairing,
|
||||
gatewayAllowInsecureTls: resolvedAllowInsecureTls,
|
||||
});
|
||||
setGatewayCheckStatus(ok ? "success" : "error");
|
||||
setGatewayCheckMessage(message);
|
||||
@@ -205,7 +206,11 @@ export default function EditGatewayPage() {
|
||||
setGatewayCheckMessage(null);
|
||||
}}
|
||||
onWorkspaceRootChange={setWorkspaceRoot}
|
||||
onAllowInsecureTlsChange={setAllowInsecureTls}
|
||||
onAllowInsecureTlsChange={(next) => {
|
||||
setAllowInsecureTls(next);
|
||||
setGatewayCheckStatus("idle");
|
||||
setGatewayCheckMessage(null);
|
||||
}}
|
||||
/>
|
||||
</DashboardPageLayout>
|
||||
);
|
||||
|
||||
@@ -88,6 +88,7 @@ export default function NewGatewayPage() {
|
||||
gatewayUrl,
|
||||
gatewayToken,
|
||||
gatewayDisableDevicePairing: disableDevicePairing,
|
||||
gatewayAllowInsecureTls: allowInsecureTls,
|
||||
});
|
||||
setGatewayCheckStatus(ok ? "success" : "error");
|
||||
setGatewayCheckMessage(message);
|
||||
@@ -156,7 +157,11 @@ export default function NewGatewayPage() {
|
||||
setGatewayCheckMessage(null);
|
||||
}}
|
||||
onWorkspaceRootChange={setWorkspaceRoot}
|
||||
onAllowInsecureTlsChange={setAllowInsecureTls}
|
||||
onAllowInsecureTlsChange={(next) => {
|
||||
setAllowInsecureTls(next);
|
||||
setGatewayCheckStatus("idle");
|
||||
setGatewayCheckMessage(null);
|
||||
}}
|
||||
/>
|
||||
</DashboardPageLayout>
|
||||
);
|
||||
|
||||
@@ -150,21 +150,30 @@ export function GatewayForm({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="allow-insecure-tls"
|
||||
className="h-4 w-4 rounded border-slate-300 text-blue-600"
|
||||
checked={allowInsecureTls}
|
||||
onChange={(event) => onAllowInsecureTlsChange(event.target.checked)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<label
|
||||
htmlFor="allow-insecure-tls"
|
||||
className="text-sm text-slate-700 cursor-pointer"
|
||||
>
|
||||
Allow self-signed TLS certificates (for localhost or trusted local
|
||||
networks)
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-slate-900">
|
||||
Allow self-signed TLS certificates
|
||||
</label>
|
||||
<label className="flex h-10 items-center gap-3 px-1 text-sm text-slate-900">
|
||||
<button
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={allowInsecureTls}
|
||||
aria-label="Allow self-signed TLS certificates"
|
||||
onClick={() => onAllowInsecureTlsChange(!allowInsecureTls)}
|
||||
disabled={isLoading}
|
||||
className={`inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition ${
|
||||
allowInsecureTls
|
||||
? "border-emerald-600 bg-emerald-600"
|
||||
: "border-slate-300 bg-slate-200"
|
||||
} ${isLoading ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-5 w-5 rounded-full bg-white shadow-sm transition ${
|
||||
allowInsecureTls ? "translate-x-5" : "translate-x-0.5"
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ describe("checkGatewayConnection", () => {
|
||||
mockedGatewaysStatusApiV1GatewaysStatusGet.mockReset();
|
||||
});
|
||||
|
||||
it("passes pairing toggle to gateway status API", async () => {
|
||||
it("passes pairing and TLS toggles to gateway status API", async () => {
|
||||
mockedGatewaysStatusApiV1GatewaysStatusGet.mockResolvedValue({
|
||||
status: 200,
|
||||
data: { connected: true },
|
||||
@@ -39,12 +39,14 @@ describe("checkGatewayConnection", () => {
|
||||
gatewayUrl: "ws://gateway.example:18789",
|
||||
gatewayToken: "secret-token",
|
||||
gatewayDisableDevicePairing: true,
|
||||
gatewayAllowInsecureTls: true,
|
||||
});
|
||||
|
||||
expect(mockedGatewaysStatusApiV1GatewaysStatusGet).toHaveBeenCalledWith({
|
||||
gateway_url: "ws://gateway.example:18789",
|
||||
gateway_token: "secret-token",
|
||||
gateway_disable_device_pairing: true,
|
||||
gateway_allow_insecure_tls: true,
|
||||
});
|
||||
expect(result).toEqual({ ok: true, message: "Gateway reachable." });
|
||||
});
|
||||
@@ -62,6 +64,7 @@ describe("checkGatewayConnection", () => {
|
||||
gatewayUrl: "ws://gateway.example:18789",
|
||||
gatewayToken: "",
|
||||
gatewayDisableDevicePairing: false,
|
||||
gatewayAllowInsecureTls: false,
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: false, message: "missing required scope" });
|
||||
|
||||
@@ -25,15 +25,18 @@ export async function checkGatewayConnection(params: {
|
||||
gatewayUrl: string;
|
||||
gatewayToken: string;
|
||||
gatewayDisableDevicePairing: boolean;
|
||||
gatewayAllowInsecureTls: boolean;
|
||||
}): Promise<{ ok: boolean; message: string }> {
|
||||
try {
|
||||
const requestParams: {
|
||||
gateway_url: string;
|
||||
gateway_token?: string;
|
||||
gateway_disable_device_pairing: boolean;
|
||||
gateway_allow_insecure_tls: boolean;
|
||||
} = {
|
||||
gateway_url: params.gatewayUrl.trim(),
|
||||
gateway_disable_device_pairing: params.gatewayDisableDevicePairing,
|
||||
gateway_allow_insecure_tls: params.gatewayAllowInsecureTls,
|
||||
};
|
||||
if (params.gatewayToken.trim()) {
|
||||
requestParams.gateway_token = params.gatewayToken.trim();
|
||||
|
||||
Reference in New Issue
Block a user