From 531b7c0c257a2b97169eed7f602fc9b498db2bef Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 3 Jun 2021 16:30:33 -0700 Subject: [PATCH] feat: add splitOnFirstEquals function --- src/node/cli.ts | 23 +++++++++++++++++++++++ src/node/routes/login.ts | 11 +---------- test/unit/cli.test.ts | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/node/cli.ts b/src/node/cli.ts index 39d38fb3..01c93349 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -240,6 +240,25 @@ export const optionDescriptions = (): string[] => { }) } +export function splitOnFirstEquals(str: string): string[] { + // we use regex instead of "=" to ensure we split at the first + // "=" and return the following substring with it + // important for the hashed-password which looks like this + // $argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY + // 2 means return two items + // Source: https://stackoverflow.com/a/4607799/3015595 + const split = str.split(/=(.+)/, 2) + + // It should always return two elements + // because it's used in a place where + // it expected two elements + if (split.length === 1) { + split.push("") + } + + return split +} + export const parse = ( argv: string[], opts?: { @@ -270,6 +289,7 @@ export const parse = ( let key: keyof Args | undefined let value: string | undefined if (arg.startsWith("--")) { + // TODO fix this const split = arg.replace(/^--/, "").split("=", 2) key = split[0] as keyof Args value = split[1] @@ -543,6 +563,7 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA const config = yaml.load(configFile, { filename: configPath, }) + console.log("what is this config", config) if (!config || typeof config === "string") { throw new Error(`invalid config: ${config}`) } @@ -555,9 +576,11 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA } return `--${optName}=${opt}` }) + console.log("what are the configFileArgv", configFileArgv) const args = parse(configFileArgv, { configFile: configPath, }) + console.log(args, "args") return { ...args, config: configPath, diff --git a/src/node/routes/login.ts b/src/node/routes/login.ts index b09585ca..6b8ab4d2 100644 --- a/src/node/routes/login.ts +++ b/src/node/routes/login.ts @@ -2,18 +2,9 @@ import { Router, Request } from "express" import { promises as fs } from "fs" import { RateLimiter as Limiter } from "limiter" import * as path from "path" -import safeCompare from "safe-compare" import { rootPath } from "../constants" import { authenticated, getCookieDomain, redirect, replaceTemplates } from "../http" -import { - getPasswordMethod, - handlePasswordValidation, - hash, - hashLegacy, - humanPath, - isHashLegacyMatch, - isHashMatch, -} from "../util" +import { getPasswordMethod, handlePasswordValidation, humanPath } from "../util" export enum Cookie { Key = "key", diff --git a/test/unit/cli.test.ts b/test/unit/cli.test.ts index e8164222..252bc56c 100644 --- a/test/unit/cli.test.ts +++ b/test/unit/cli.test.ts @@ -3,7 +3,7 @@ import { promises as fs } from "fs" import * as net from "net" import * as os from "os" import * as path from "path" -import { Args, parse, setDefaults, shouldOpenInExistingInstance } from "../../src/node/cli" +import { Args, parse, setDefaults, shouldOpenInExistingInstance, splitOnFirstEquals } from "../../src/node/cli" import { tmpdir } from "../../src/node/constants" import { paths } from "../../src/node/util" @@ -337,6 +337,18 @@ describe("parser", () => { "proxy-domain": ["coder.com", "coder.org"], }) }) + it("should allow '=,$/' in strings", async () => { + const args = parse([ + "--enable-proposed-api", + "$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy", + ]) + expect(args).toEqual({ + _: [], + "enable-proposed-api": [ + "$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy", + ], + }) + }) }) describe("cli", () => { @@ -411,3 +423,28 @@ describe("cli", () => { expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined) }) }) + +describe("splitOnFirstEquals", () => { + it("should split on the first equals", () => { + const testStr = "--enabled-proposed-api=test=value" + const actual = splitOnFirstEquals(testStr) + const expected = ["--enabled-proposed-api", "test=value"] + expect(actual).toEqual(expect.arrayContaining(expected)) + }) + it("should split on first equals regardless of multiple equals signs", () => { + const testStr = + "--hashed-password=$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY" + const actual = splitOnFirstEquals(testStr) + const expected = [ + "--hashed-password", + "$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY", + ] + expect(actual).toEqual(expect.arrayContaining(expected)) + }) + it("should always return two elements", () => { + const testStr = "" + const actual = splitOnFirstEquals(testStr) + const expected = ["", ""] + expect(actual).toEqual(expect.arrayContaining(expected)) + }) +})