diff --git a/api/src/backendimpl/passyfire-reimpl/index.ts b/api/src/backendimpl/passyfire-reimpl/index.ts index 5ffd7f2..aef97bd 100644 --- a/api/src/backendimpl/passyfire-reimpl/index.ts +++ b/api/src/backendimpl/passyfire-reimpl/index.ts @@ -54,6 +54,7 @@ function parseBackendProviderString(data: string): BackendParsedProviderString { if (typeof jsonData.ip != "string") throw new Error("IP field is not a string"); + if (typeof jsonData.port != "number") throw new Error("Port is not a number"); if ( @@ -61,6 +62,7 @@ function parseBackendProviderString(data: string): BackendParsedProviderString { typeof jsonData.publicPort != "number" ) throw new Error("(optional field) Proxied port is not a number"); + if ( typeof jsonData.isProxied != "undefined" && typeof jsonData.isProxied != "boolean" diff --git a/api/src/backendimpl/ssh.ts b/api/src/backendimpl/ssh.ts index 4033b33..5541d16 100644 --- a/api/src/backendimpl/ssh.ts +++ b/api/src/backendimpl/ssh.ts @@ -32,10 +32,12 @@ function parseBackendProviderString(data: string): BackendParsedProviderString { if (typeof jsonData.ip != "string") throw new Error("IP field is not a string"); + if (typeof jsonData.port != "number") throw new Error("Port is not a number"); if (typeof jsonData.username != "string") throw new Error("Username is not a string"); + if (typeof jsonData.privateKey != "string") throw new Error("Private key is not a string"); diff --git a/lom/src/commands.ts b/lom/src/commands.ts index c25b751..52663ef 100644 --- a/lom/src/commands.ts +++ b/lom/src/commands.ts @@ -1,6 +1,8 @@ import type { Axios } from "axios"; import { run as connection } from "./commands/connections.js"; +import { run as backends } from "./commands/backends.js"; +import { run as users } from "./commands/users.js"; export type PrintLine = (...str: string[]) => void; @@ -17,8 +19,6 @@ type Commands = { run: Command; }[]; -// TODO: add commands! - export const commands: Commands = [ { name: "help", @@ -27,6 +27,8 @@ export const commands: Commands = [ commands.forEach(command => { printf(`${command.name}: ${command.description}\n`); }); + + printf("\nRun a command of your choosing with --help to see more options.\n"); }, }, { @@ -37,8 +39,23 @@ export const commands: Commands = [ }, }, { - name: "connection", - description: "Various connection related utilities", + name: "conn", + description: "Manages connections for NextNet", run: connection + }, + { + name: "user", + description: "Manages users for NextNet", + run: users + }, + { + name: "backend", + description: "Manages backends for NextNet", + run: backends + }, + { + name: "back", + description: "(alias) Manages backends for NextNet", + run: backends } ]; diff --git a/lom/src/commands/backends.ts b/lom/src/commands/backends.ts new file mode 100644 index 0000000..b614874 --- /dev/null +++ b/lom/src/commands/backends.ts @@ -0,0 +1,91 @@ +import type { Axios } from "axios"; + +import { SSHCommand } from "../libs/patchCommander.js"; +import type { PrintLine } from "../commands.js"; + +export async function run( + argv: string[], + println: PrintLine, + axios: Axios, + apiKey: string, +) { + const program = new SSHCommand(println); + program.description("Manages backends for NextNet"); + program.version("v0.1.0-preprod"); + + const addBackend = new SSHCommand(println, "add"); + addBackend.description("Adds a backend"); + addBackend.argument("", "Name of the backend"); + + addBackend.argument( + "", + "Provider of the backend (ex. passyfire, ssh)", + ); + + addBackend.option( + "-d, --description", + "Description for the backend", + ); + + addBackend.option( + "-f, --force-custom-parameters", + "If turned on, this forces you to use custom parameters", + ); + + addBackend.option( + "-c, --custom-parameters", + "Custom parameters. Use this if the backend you're using isn't native to SSH yet, or if you manually turn on -f.", + ); + + // SSH provider + addBackend.option( + "-k, --ssh-key", + "(SSH) SSH private key to use to authenticate with the server", + ); + + addBackend.option( + "-u, --username", + "(SSH, PassyFire) Username to authenticate with. With PassyFire, it's the username you create", + ); + + addBackend.option( + "-h, --host", + "(SSH, PassyFire) Host to connect to. With PassyFire, it's what you listen on", + ); + + // PassyFire provider + addBackend.option( + "-pe, --is-proxied", + "(PassyFire) Specify if you're behind a proxy or not so we can get the right IP", + ); + + addBackend.option( + "-pp, --proxied-port", + "(PassyFire) If you're behind a proxy, and the port is different, specify the port to return", + ); + + addBackend.option("-g, --guest", "(PassyFire) Enable the guest user"); + + addBackend.option( + "-ua, --user-ask", + "(PassyFire) Ask what users you want to create", + ); + + addBackend.option( + "-p, --password", + "(PassyFire) What password you want to use for the primary user", + ); + + const removeBackend = new SSHCommand(println, "rm"); + removeBackend.description("Removes a backend"); + removeBackend.argument("", "Id of the backend"); + + const lookupBackend = new SSHCommand(println, "find"); + lookupBackend.description("Looks up a backend based on your arguments"); + + program.addCommand(addBackend); + program.addCommand(removeBackend); + program.addCommand(lookupBackend); + + program.parse(argv); +} diff --git a/lom/src/commands/connections.ts b/lom/src/commands/connections.ts index f8224c0..da87512 100644 --- a/lom/src/commands/connections.ts +++ b/lom/src/commands/connections.ts @@ -1,7 +1,6 @@ -import { Command } from "commander"; import type { Axios } from "axios"; -import { type AppState, patchCommander } from "../libs/patchCommander.js"; +import { SSHCommand } from "../libs/patchCommander.js"; import type { PrintLine } from "../commands.js"; export async function run( @@ -10,19 +9,83 @@ export async function run( axios: Axios, apiKey: string, ) { - const program = new Command(); - const appState: AppState = { - hasRecievedExitSignal: false - }; + const program = new SSHCommand(println); + program.description("Manages connections for NextNet"); + program.version("v0.1.0-preprod"); - patchCommander(program, appState, println); + const addCommand = new SSHCommand(println, "add"); + addCommand.description("Creates a new connection"); - program - .option('-d, --debug', 'output extra debugging') - .option('-s, --small', 'small pizza size') - .option('-p, --pizza-type ', 'flavour of pizza'); + addCommand.argument( + "", + "The backend ID to use. Can be fetched by the command 'backend search'", + ); - program.parse(["node", ...argv]); + addCommand.argument("", "The name for the tunnel"); + addCommand.argument("", "The protocol to use. Either TCP or UDP"); - if (appState.hasRecievedExitSignal) return; + addCommand.argument( + "", + "Source IP and port combo (ex. '192.168.0.63:25565'", + ); + + addCommand.argument("", "Destination port to use"); + + addCommand.option("--description, -d", "Description for the tunnel"); + + const lookupCommand = new SSHCommand(println, "find"); + + lookupCommand.description( + "Looks up all connections based on the arguments you specify", + ); + + lookupCommand.option( + "--backend_id, -b ", + "The backend ID to use. Can be fetched by 'back find'", + ); + + lookupCommand.option("--name, -n ", "The name for the tunnel"); + + lookupCommand.option( + "--protocol, -p ", + "The protocol to use. Either TCP or UDP", + ); + + lookupCommand.option( + "--source, -s ", + "Source IP and port combo (ex. '192.168.0.63:25565'", + ); + + lookupCommand.option("--dest_port, -d ", "Destination port to use"); + + lookupCommand.option( + "--description, -o ", + "Description for the tunnel", + ); + + const startTunnel = new SSHCommand(println, "start"); + startTunnel.description("Starts a tunnel"); + startTunnel.argument("", "Tunnel ID to start"); + + const stopTunnel = new SSHCommand(println, "stop"); + stopTunnel.description("Stops a tunnel"); + stopTunnel.argument("", "Tunnel ID to stop"); + + const getInbound = new SSHCommand(println, "get-inbound"); + getInbound.description("Shows all current connections"); + getInbound.argument("", "Tunnel ID to view inbound connections of"); + getInbound.option("-t, --tail", "Live-view of connection list"); + + const removeTunnel = new SSHCommand(println, "rm"); + removeTunnel.description("Removes a tunnel"); + removeTunnel.argument("", "Tunnel ID to remove"); + + program.addCommand(addCommand); + program.addCommand(lookupCommand); + program.addCommand(startTunnel); + program.addCommand(stopTunnel); + program.addCommand(getInbound); + program.addCommand(removeTunnel); + + program.parse(argv); } diff --git a/lom/src/commands/users.ts b/lom/src/commands/users.ts new file mode 100644 index 0000000..b994893 --- /dev/null +++ b/lom/src/commands/users.ts @@ -0,0 +1,45 @@ +import type { Axios } from "axios"; + +import { SSHCommand } from "../libs/patchCommander.js"; +import type { PrintLine } from "../commands.js"; + +export async function run( + argv: string[], + println: PrintLine, + axios: Axios, + apiKey: string, +) { + const program = new SSHCommand(println); + program.description("Manages users for NextNet"); + program.version("v0.1.0-preprod"); + + const addCommand = new SSHCommand(println, "add"); + addCommand.description("Create a new user"); + addCommand.argument("", "Username of new user"); + addCommand.argument("", "Email of new user"); + addCommand.argument("[name]", "Name of new user (defaults to username)"); + + addCommand.option("-p, --password", "Password of User"); + addCommand.option( + "-a, --ask-password, --ask-pass, --askpass", + "Asks for a password. Hides output", + ); + + const removeCommand = new SSHCommand(println, "rm"); + removeCommand.description("Remove a user"); + removeCommand.argument("", "ID of user to remove"); + + const lookupCommand = new SSHCommand(println, "find"); + lookupCommand.description("Find a user"); + lookupCommand.option("-i, --id ", "UID of User"); + lookupCommand.option("-n, --name ", "Name of User"); + lookupCommand.option("-u, --username ", "Username of User"); + lookupCommand.option("-e, --email ", "Email of User"); + lookupCommand.option("-s, --service", "The User is a service account"); + + program.addCommand(addCommand); + program.addCommand(removeCommand); + program.addCommand(lookupCommand); + + program.parse(argv); +}