Skip to content

Commit 75bf436

Browse files
Add localhost option to print URL in vpncli and implement withHostname utility
1 parent 7aea7c1 commit 75bf436

4 files changed

Lines changed: 51 additions & 5 deletions

File tree

src/src/getAdminCredentials.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import retry from "async-retry";
1717
import { getRpcCall } from "./api/getRpcCall";
1818
import { API_PORT, NO_HOSTNAME_RETURNED_ERROR } from "./params";
1919
import { renderQrCode } from "./utils/renderQrCode";
20+
import { withHostname } from "./utils/withHostname";
2021
import { VpnStatus } from "./types";
2122

2223
/* eslint-disable no-console */
@@ -47,6 +48,8 @@ class NotReadyError extends Error {
4748

4849
(async function(): Promise<void> {
4950
try {
51+
const localhost = process.argv.includes("--localhost");
52+
5053
console.log(
5154
`Fetching DAppNode VPN credentials. It may take some time; use CTRL + C to stop`
5255
);
@@ -81,14 +84,15 @@ class NotReadyError extends Error {
8184
);
8285

8386
const { url } = await api.getMasterAdminCred();
87+
const outputUrl = localhost ? withHostname(url, "localhost") : url;
8488

8589
// If rendering the QR fails, show the error and continue, the raw URL is consumable
8690
console.log(`
8791
88-
${await renderQrCode(url).catch(e => e.stack)}
92+
${await renderQrCode(outputUrl).catch(e => e.stack)}
8993
9094
To connect to your DAppNode scan the QR above or copy/paste link below into your browser:
91-
${url}`);
95+
${outputUrl}`);
9296
} catch (e) {
9397
// Exit process cleanly to prevent showing 'Unhandled rejection'
9498
console.error(e);

src/src/utils/withHostname.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export function withHostname(rawUrl: string, hostname: string): string {
2+
try {
3+
const parsed = new URL(rawUrl);
4+
parsed.hostname = hostname;
5+
return parsed.toString();
6+
} catch (e) {
7+
return rawUrl;
8+
}
9+
}

src/src/vpncli.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import chalk from "chalk";
66
import prettyjson from "prettyjson";
77
import { getRpcCall } from "./api/getRpcCall";
88
import { API_PORT } from "./params";
9+
import { withHostname } from "./utils/withHostname";
910

1011
/* eslint-disable no-console */
1112

@@ -25,6 +26,13 @@ const idArg: CommandBuilder<{}, { id: string }> = yargs =>
2526
demandOption: true
2627
});
2728

29+
const getArg: CommandBuilder<{}, { id: string; localhost: boolean }> = yargs =>
30+
idArg(yargs).option("localhost", {
31+
describe: "Print URL using localhost instead of the configured hostname",
32+
type: "boolean",
33+
default: false
34+
});
35+
2836
yargs
2937
.usage(`Usage: vpncli <command> [options]`)
3038
.alias("h", "help")
@@ -57,10 +65,13 @@ yargs
5765
.command({
5866
command: "get <id>",
5967
describe: "Generate device URL to download config file.",
60-
builder: idArg,
61-
handler: async ({ id }) => {
68+
builder: getArg,
69+
handler: async ({ id, localhost }) => {
6270
const { url } = await api.getDeviceCredentials({ id });
63-
console.log(chalk.green(`Credentials generated for ${id}:\n${url}`));
71+
const outputUrl = localhost ? withHostname(url, "localhost") : url;
72+
console.log(
73+
chalk.green(`Credentials generated for ${id}:\n${outputUrl}`)
74+
);
6475
}
6576
})
6677
.command({
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import "mocha";
2+
import { expect } from "chai";
3+
4+
import { withHostname } from "../../src/utils/withHostname";
5+
6+
describe("utils > withHostname", () => {
7+
it("Should replace hostname preserving port, path, query, and hash", () => {
8+
const inputUrl =
9+
"http://9442df98a3a59a65.dyndns.dappnode.io:8092/?id=xkmTGRv3sdu9XUuz#0P%2Blna33F5loAIUx13fgm3F7%2FRLFFvOigZDt9h2kcp8%3D";
10+
11+
const outputUrl = withHostname(inputUrl, "localhost");
12+
13+
expect(outputUrl).to.equal(
14+
"http://localhost:8092/?id=xkmTGRv3sdu9XUuz#0P%2Blna33F5loAIUx13fgm3F7%2FRLFFvOigZDt9h2kcp8%3D"
15+
);
16+
});
17+
18+
it("Should return the raw input if it is not a valid URL", () => {
19+
const inputUrl = "not-a-url";
20+
expect(withHostname(inputUrl, "localhost")).to.equal(inputUrl);
21+
});
22+
});

0 commit comments

Comments
 (0)