diff --git a/api/eslint.config.js b/api/eslint.config.js index 1941a35..4b4bbab 100644 --- a/api/eslint.config.js +++ b/api/eslint.config.js @@ -2,9 +2,18 @@ import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; - export default [ - {languageOptions: { globals: globals.node }}, pluginJs.configs.recommended, ...tseslint.configs.recommended, + + { + languageOptions: { + globals: globals.node + }, + + rules: { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "off" + } + }, ]; \ No newline at end of file diff --git a/api/src/backendimpl/passyfire-reimpl/index.ts b/api/src/backendimpl/passyfire-reimpl/index.ts index 72d393a..de454ed 100644 --- a/api/src/backendimpl/passyfire-reimpl/index.ts +++ b/api/src/backendimpl/passyfire-reimpl/index.ts @@ -55,7 +55,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 ( @@ -63,7 +63,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" @@ -216,7 +216,7 @@ export class PassyFireBackendProvider implements BackendBaseClass { static checkParametersBackendInstance(data: string): ParameterReturnedValue { try { parseBackendProviderString(data); - // @ts-expect-error + // @ts-expect-error: We write the function, and we know we're returning an error } catch (e: Error) { return { success: false, diff --git a/api/src/backendimpl/passyfire-reimpl/routes.ts b/api/src/backendimpl/passyfire-reimpl/routes.ts index 68e09e8..d814e12 100644 --- a/api/src/backendimpl/passyfire-reimpl/routes.ts +++ b/api/src/backendimpl/passyfire-reimpl/routes.ts @@ -69,7 +69,7 @@ export function route(instance: PassyFireBackendProvider) { }, }, (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { username: string; password: string; @@ -115,7 +115,7 @@ export function route(instance: PassyFireBackendProvider) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; } = req.body; @@ -132,8 +132,7 @@ export function route(instance: PassyFireBackendProvider) { req.hostname.indexOf(":") + 1, ); - // @ts-expect-error - // parseInt(...) can take a number just fine, at least in Node.JS + // @ts-expect-error: parseInt(...) can take a number just fine, at least in Node.JS const port = parseInt(unparsedPort == "" ? proxiedPort : unparsedPort); // This protocol is so confusing. I'm sorry. diff --git a/api/src/backendimpl/passyfire-reimpl/socket.ts b/api/src/backendimpl/passyfire-reimpl/socket.ts index 189d88a..ee9607a 100644 --- a/api/src/backendimpl/passyfire-reimpl/socket.ts +++ b/api/src/backendimpl/passyfire-reimpl/socket.ts @@ -14,7 +14,7 @@ function authenticateSocket( ws: WebSocket, message: string, state: ConnectedClientExt, -): Boolean { +): boolean { if (!message.startsWith("Accept: ")) { ws.send("400 Bad Request"); return false; @@ -57,8 +57,8 @@ export function requestHandler( let state: "authentication" | "data" = "authentication"; let socket: dgram.Socket | net.Socket | undefined; - // @ts-expect-error - let connectedClient: ConnectedClientExt = {}; + // @ts-expect-error: FIXME because this is a mess + const connectedClient: ConnectedClientExt = {}; ws.on("close", () => { instance.clients.splice( diff --git a/api/src/backendimpl/ssh.ts b/api/src/backendimpl/ssh.ts index a04e47a..e7bdd62 100644 --- a/api/src/backendimpl/ssh.ts +++ b/api/src/backendimpl/ssh.ts @@ -92,7 +92,7 @@ export class SSHBackendProvider implements BackendBaseClass { this.logs.push(`Failed to start SSHBackendProvider! Error: '${e}'`); this.state = "stopped"; - // @ts-expect-error + // @ts-expect-error: We know that stuff will be initialized in order, so this will be safe this.sshInstance = null; return false; @@ -112,7 +112,7 @@ export class SSHBackendProvider implements BackendBaseClass { this.sshInstance.dispose(); - // @ts-expect-error + // @ts-expect-error: We know that stuff will be initialized in order, so this will be safe this.sshInstance = null; this.logs.push("Successfully stopped SSHBackendProvider."); @@ -255,7 +255,7 @@ export class SSHBackendProvider implements BackendBaseClass { static checkParametersBackendInstance(data: string): ParameterReturnedValue { try { parseBackendProviderString(data); - // @ts-expect-error + // @ts-expect-error: We write the function, and we know we're returning an error } catch (e: Error) { return { success: false, diff --git a/api/src/routes/backends/create.ts b/api/src/routes/backends/create.ts index 52ceeb9..cd221f0 100644 --- a/api/src/routes/backends/create.ts +++ b/api/src/routes/backends/create.ts @@ -35,12 +35,12 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; name: string; description?: string; - connectionDetails: any; + connectionDetails: unknown; backend: string; } = req.body; diff --git a/api/src/routes/backends/lookup.ts b/api/src/routes/backends/lookup.ts index 4439d9c..a387ffc 100644 --- a/api/src/routes/backends/lookup.ts +++ b/api/src/routes/backends/lookup.ts @@ -33,7 +33,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id?: number; @@ -69,7 +69,7 @@ export function route(routeOptions: RouteOptions) { success: true, data: prismaBackends.map(i => ({ id: i.id, - + name: i.name, description: i.description, diff --git a/api/src/routes/backends/remove.ts b/api/src/routes/backends/remove.ts index eeced09..711286b 100644 --- a/api/src/routes/backends/remove.ts +++ b/api/src/routes/backends/remove.ts @@ -30,7 +30,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id: number; diff --git a/api/src/routes/forward/connections.ts b/api/src/routes/forward/connections.ts index 80f17f8..6358ead 100644 --- a/api/src/routes/forward/connections.ts +++ b/api/src/routes/forward/connections.ts @@ -27,7 +27,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id: number; @@ -59,8 +59,12 @@ export function route(routeOptions: RouteOptions) { return { success: true, - data: backends[forward.destProviderID].getAllConnections().filter((i) => { - return i.connectionDetails.sourceIP == forward.sourceIP && i.connectionDetails.sourcePort == forward.sourcePort && i.connectionDetails.destPort == forward.destPort; + data: backends[forward.destProviderID].getAllConnections().filter(i => { + return ( + i.connectionDetails.sourceIP == forward.sourceIP && + i.connectionDetails.sourcePort == forward.sourcePort && + i.connectionDetails.destPort == forward.destPort + ); }), }; }, diff --git a/api/src/routes/forward/create.ts b/api/src/routes/forward/create.ts index cf4dd8a..2363416 100644 --- a/api/src/routes/forward/create.ts +++ b/api/src/routes/forward/create.ts @@ -50,7 +50,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; diff --git a/api/src/routes/forward/lookup.ts b/api/src/routes/forward/lookup.ts index 1aa29d8..3b87c36 100644 --- a/api/src/routes/forward/lookup.ts +++ b/api/src/routes/forward/lookup.ts @@ -41,7 +41,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; diff --git a/api/src/routes/forward/remove.ts b/api/src/routes/forward/remove.ts index 70c4558..264b82a 100644 --- a/api/src/routes/forward/remove.ts +++ b/api/src/routes/forward/remove.ts @@ -30,7 +30,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id: number; diff --git a/api/src/routes/forward/start.ts b/api/src/routes/forward/start.ts index aa8c664..fea55fa 100644 --- a/api/src/routes/forward/start.ts +++ b/api/src/routes/forward/start.ts @@ -30,7 +30,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id: number; @@ -58,8 +58,7 @@ export function route(routeOptions: RouteOptions) { error: "Backend not found", }); - // Other restrictions in place make it so that it MUST be either TCP or UDP - // @ts-expect-error + // @ts-expect-error: Other restrictions in place make it so that it MUST be either TCP or UDP const protocol: "tcp" | "udp" = forward.protocol; backends[forward.destProviderID].addConnection( diff --git a/api/src/routes/forward/stop.ts b/api/src/routes/forward/stop.ts index 3a609b0..e933b0a 100644 --- a/api/src/routes/forward/stop.ts +++ b/api/src/routes/forward/stop.ts @@ -30,7 +30,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id: number; @@ -58,8 +58,7 @@ export function route(routeOptions: RouteOptions) { error: "Backend not found", }); - // Other restrictions in place make it so that it MUST be either TCP or UDP - // @ts-expect-error + // @ts-expect-error: Other restrictions in place make it so that it MUST be either TCP or UDP const protocol: "tcp" | "udp" = forward.protocol; backends[forward.destProviderID].removeConnection( diff --git a/api/src/routes/getPermissions.ts b/api/src/routes/getPermissions.ts index 4cb9b31..e000085 100644 --- a/api/src/routes/getPermissions.ts +++ b/api/src/routes/getPermissions.ts @@ -22,7 +22,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; } = req.body; diff --git a/api/src/routes/user/create.ts b/api/src/routes/user/create.ts index 204c337..034faa1 100644 --- a/api/src/routes/user/create.ts +++ b/api/src/routes/user/create.ts @@ -29,7 +29,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { name: string; email: string; @@ -87,9 +87,9 @@ export function route(routeOptions: RouteOptions) { } if (options.allowUnsafeGlobalTokens) { - // @ts-expect-error + // @ts-expect-error: Setting this correctly is a goddamn mess, but this is safe to an extent. It won't crash at least userData.rootToken = generateRandomData(); - // @ts-expect-error + // @ts-expect-error: Read above. userData.isRootServiceAccount = true; } diff --git a/api/src/routes/user/login.ts b/api/src/routes/user/login.ts index 54fd6d7..b44d880 100644 --- a/api/src/routes/user/login.ts +++ b/api/src/routes/user/login.ts @@ -20,27 +20,28 @@ export function route(routeOptions: RouteOptions) { properties: { email: { type: "string" }, username: { type: "string" }, - password: { type: "string" } + password: { type: "string" }, }, }, }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { email?: string; username?: string; password: string; } = req.body; - if (!body.email && !body.username) return res.status(400).send({ - error: "missing both email and username. please supply at least one." - }); + if (!body.email && !body.username) + return res.status(400).send({ + error: "missing both email and username. please supply at least one.", + }); const userSearch = await prisma.user.findFirst({ where: { email: body.email, - username: body.username + username: body.username, }, }); diff --git a/api/src/routes/user/lookup.ts b/api/src/routes/user/lookup.ts index 3b853f1..8359231 100644 --- a/api/src/routes/user/lookup.ts +++ b/api/src/routes/user/lookup.ts @@ -31,7 +31,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; id?: number; @@ -64,7 +64,7 @@ export function route(routeOptions: RouteOptions) { name: i.name, email: i.email, isServiceAccount: i.isRootServiceAccount, - username: i.username + username: i.username, })), }; }, diff --git a/api/src/routes/user/remove.ts b/api/src/routes/user/remove.ts index df5a515..f7159d9 100644 --- a/api/src/routes/user/remove.ts +++ b/api/src/routes/user/remove.ts @@ -30,7 +30,7 @@ export function route(routeOptions: RouteOptions) { }, }, async (req, res) => { - // @ts-expect-error + // @ts-expect-error: Fastify routes schema parsing is trustworthy, so we can "assume" invalid types const body: { token: string; uid: number; diff --git a/lom/eslint.config.js b/lom/eslint.config.js index 1941a35..70cdd16 100644 --- a/lom/eslint.config.js +++ b/lom/eslint.config.js @@ -4,7 +4,17 @@ import tseslint from "typescript-eslint"; export default [ - {languageOptions: { globals: globals.node }}, pluginJs.configs.recommended, ...tseslint.configs.recommended, + + { + languageOptions: { + globals: globals.node, + }, + + rules: { + "@typescript-eslint/no-explicit-any": "off", + "no-constant-condition": "warn" + } + }, ]; \ No newline at end of file diff --git a/lom/src/commands.ts b/lom/src/commands.ts index 19448fa..bb06314 100644 --- a/lom/src/commands.ts +++ b/lom/src/commands.ts @@ -4,7 +4,7 @@ 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: any[]) => void; +export type PrintLine = (...str: unknown[]) => void; export type KeyboardRead = (disableEcho?: boolean) => Promise; type Command = ( @@ -12,7 +12,7 @@ type Command = ( println: PrintLine, axios: Axios, apiKey: string, - keyboardRead: KeyboardRead + keyboardRead: KeyboardRead, ) => Promise; type Commands = { @@ -30,7 +30,9 @@ export const commands: Commands = [ printf(`${command.name}: ${command.description}\n`); }); - printf("\nRun a command of your choosing with --help to see more options.\n"); + printf( + "\nRun a command of your choosing with --help to see more options.\n", + ); }, }, { @@ -43,21 +45,21 @@ export const commands: Commands = [ { name: "conn", description: "Manages connections for NextNet", - run: connection + run: connection, }, { name: "user", description: "Manages users for NextNet", - run: users + run: users, }, { name: "backend", description: "Manages backends for NextNet", - run: backends + run: backends, }, { name: "back", description: "(alias) Manages backends for NextNet", - run: backends - } + run: backends, + }, ]; diff --git a/lom/src/commands/backends.ts b/lom/src/commands/backends.ts index 66d35f9..0930bbb 100644 --- a/lom/src/commands/backends.ts +++ b/lom/src/commands/backends.ts @@ -119,8 +119,7 @@ export async function run( password?: string; }, ) => { - // Yes it can index for what we need it to do. - // @ts-expect-error + // @ts-expect-error: Yes it can index for what we need it to do. const isUnsupportedPlatform: boolean = !addRequiredOptions[provider]; if (isUnsupportedPlatform) { @@ -141,9 +140,8 @@ export async function run( connectionDetails = options.customParameters; } else if (provider == "ssh") { for (const argument of addRequiredOptions["ssh"]) { - // No. - // @ts-expect-error - const hasArgument = options[argument] as any; + // @ts-expect-error: No. + const hasArgument = options[argument]; if (!hasArgument) { return println("ERROR: Missing argument '%s'\n", argument); @@ -177,8 +175,7 @@ export async function run( connectionDetails = JSON.stringify(unstringifiedArguments); } else if (provider == "passyfire") { for (const argument of addRequiredOptions["passyfire"]) { - // No. - // @ts-expect-error + // @ts-expect-error: No. const hasArgument = options[argument]; if (!hasArgument) { @@ -218,7 +215,9 @@ export async function run( } if (options.userAsk) { - while (true) { + let shouldContinueAsking: boolean = true; + + while (shouldContinueAsking) { println("Creating a user.\nUsername: "); const username = await readKeyboard(); @@ -247,14 +246,12 @@ export async function run( }); println("\nShould we continue creating users? (y/n) "); - const shouldContinueAsking = (await readKeyboard()) + shouldContinueAsking = (await readKeyboard()) .toLowerCase() .trim() .startsWith("y"); println("\n\n"); - - if (!shouldContinueAsking) break; } } @@ -420,6 +417,7 @@ export async function run( // We don't know what we're recieving. We just try to parse it (hence the any type) // {} is more accurate but TS yells at us if we do that :( + // eslint-disable-next-line let parsedJSONData: any | undefined; try { diff --git a/lom/src/commands/connections.ts b/lom/src/commands/connections.ts index d22bad2..29f4eb6 100644 --- a/lom/src/commands/connections.ts +++ b/lom/src/commands/connections.ts @@ -382,6 +382,8 @@ export async function run( if (options.tail) { let previousEntries: string[] = []; + // FIXME? + // eslint-disable-next-line no-constant-condition while (true) { const response = await axios.post("/api/v1/forward/connections", { token, @@ -407,6 +409,7 @@ export async function run( simplifiedArray, previousEntries, ); + const removedItems: string[] = difference( previousEntries, simplifiedArray, diff --git a/lom/src/commands/users.ts b/lom/src/commands/users.ts index e3adbad..e8dda1d 100644 --- a/lom/src/commands/users.ts +++ b/lom/src/commands/users.ts @@ -80,8 +80,7 @@ export async function run( password = passwordConfirmOne; } else { - // From the first check we do, we know this is safe (you MUST specify a password) - // @ts-expect-error + // @ts-expect-error: From the first check we do, we know this is safe (you MUST specify a password) password = options.password; } @@ -120,7 +119,7 @@ export async function run( return; } - let response = await axios.post("/api/v1/users/remove", { + const response = await axios.post("/api/v1/users/remove", { token: apiKey, uid, }); diff --git a/lom/src/index.ts b/lom/src/index.ts index 17299f4..72c2993 100644 --- a/lom/src/index.ts +++ b/lom/src/index.ts @@ -31,7 +31,7 @@ const serverBaseURL: string = const axios = baseAxios.create({ baseURL: serverBaseURL, - validateStatus: () => true + validateStatus: () => true, }); try { @@ -70,7 +70,9 @@ const server: ssh2.Server = new ssh2.Server({ server.on("connection", client => { let token: string = ""; + // eslint-disable-next-line let username: string = ""; + // eslint-disable-next-line let password: string = ""; client.on("authentication", async auth => { @@ -79,11 +81,11 @@ server.on("connection", client => { username: auth.username, password: auth.password, }); - + if (response.status == 403) { return auth.reject(["password", "publickey"]); } - + token = response.data.token; username = auth.username; @@ -133,12 +135,12 @@ server.on("connection", client => { auth.accept(); } else { - return auth.reject(["password", "publickey"]); + return auth.reject(["password", "publickey"]); } }); client.on("ready", () => { - client.on("session", (accept, reject) => { + client.on("session", accept => { const conn = accept(); conn.on("exec", async (accept, reject, info) => { @@ -149,32 +151,32 @@ server.on("connection", client => { } // Matches on ; and && - const commandsRecv = info.command.split(/;|&&/).map((i) => i.trim()); + const commandsRecv = info.command.split(/;|&&/).map(i => i.trim()); - function println(...data: any[]) { + function println(...data: unknown[]) { stream.write(format(...data).replaceAll("\n", "\r\n")); - }; + } for (const command of commandsRecv) { const argv = parseArgsStringToArgv(command); - + if (argv[0] == "exit") { stream.close(); } else { const command = commands.find(i => i.name == argv[0]); - + if (!command) { - stream.write( - `Unknown command ${argv[0]}.\r\n`, - ); + stream.write(`Unknown command ${argv[0]}.\r\n`); continue; } - - await command.run(argv, println, axios, token, (disableEcho) => readFromKeyboard(stream, disableEcho)); + + await command.run(argv, println, axios, token, disableEcho => + readFromKeyboard(stream, disableEcho), + ); } } - + return stream.close(); }); @@ -191,26 +193,28 @@ server.on("connection", client => { "Welcome to NextNet LOM. Run 'help' to see commands.\r\n\r\n~$ ", ); - function println(...data: any[]) { + function println(...data: unknown[]) { stream.write(format(...data).replaceAll("\n", "\r\n")); - }; + } + // FIXME (greysoh): wtf? this isn't setting correctly. + // @eslint-disable-next-line while (true) { const line = await readFromKeyboard(stream); stream.write("\r\n"); - + if (line == "") { stream.write(`~$ `); continue; } const argv = parseArgsStringToArgv(line); - + if (argv[0] == "exit") { stream.close(); } else { const command = commands.find(i => i.name == argv[0]); - + if (!command) { stream.write( `Unknown command ${argv[0]}. Run 'help' to see commands.\r\n~$ `, @@ -218,8 +222,10 @@ server.on("connection", client => { continue; } - - await command.run(argv, println, axios, token, (disableEcho) => readFromKeyboard(stream, disableEcho)); + + await command.run(argv, println, axios, token, disableEcho => + readFromKeyboard(stream, disableEcho), + ); stream.write("~$ "); } } diff --git a/lom/src/libs/patchCommander.ts b/lom/src/libs/patchCommander.ts index 95a44a7..f30e492 100644 --- a/lom/src/libs/patchCommander.ts +++ b/lom/src/libs/patchCommander.ts @@ -5,7 +5,7 @@ export class SSHCommand extends Command { hasRecievedExitSignal: boolean; println: PrintLine; - exitEventHandlers: ((...any: any[]) => void)[]; + exitEventHandlers: ((...any: unknown[]) => void)[]; parent: SSHCommand | null; /** @@ -81,11 +81,11 @@ export class SSHCommand extends Command { action(fn: (...args: any[]) => void | Promise): this { super.action(fn); - // @ts-expect-error + // @ts-expect-error: This parameter is private, but we need control over it. // prettier-ignore const oldActionHandler: (...args: any[]) => void | Promise = this._actionHandler; - // @ts-expect-error + // @ts-expect-error: Overriding private parameters (but this works) this._actionHandler = async (...args: any[]): Promise => { if (this.hasRecievedExitSignal) return; await oldActionHandler(...args);