Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6d240a0

Browse files
committed
refactor: parse options with multiple = in cli
There was a case with the hashed-password which had multiple equal signs in the value and it wasn't being parsed correctly. This uses a new function and adds a few tests.
1 parent e3171dd commit 6d240a0

File tree

7 files changed

+75
-63
lines changed

7 files changed

+75
-63
lines changed

‎docs/FAQ.md‎

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,38 @@
22
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
33
# FAQ
44

5-
- [FAQ](#faq)
6-
- [Questions?](#questions)
7-
- [iPad Status?](#ipad-status)
8-
- [Community Projects (awesome-code-server)](#community-projects-awesome-code-server)
9-
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
10-
- [Differences compared to VS Code?](#differences-compared-to-vs-code)
11-
- [Installing an extension](#installing-an-extension)
12-
- [How can I request a missing extension?](#how-can-i-request-a-missing-extension)
13-
- [Installing an extension manually](#installing-an-extension-manually)
14-
- [How do I configure the marketplace URL?](#how-do-i-configure-the-marketplace-url)
15-
- [Where are extensions stored?](#where-are-extensions-stored)
16-
- [How is this different from VS Code Codespaces?](#how-is-this-different-from-vs-code-codespaces)
17-
- [How should I expose code-server to the internet?](#how-should-i-expose-code-server-to-the-internet)
18-
- [Can I store my password hashed?](#can-i-store-my-password-hashed)
19-
- [How do I securely access web services?](#how-do-i-securely-access-web-services)
20-
- [Sub-paths](#sub-paths)
21-
- [Sub-domains](#sub-domains)
22-
- [Why does the code-server proxy strip `/proxy/<port>` from the request path?](#why-does-the-code-server-proxy-strip-proxyport-from-the-request-path)
23-
- [Proxying to Create React App](#proxying-to-create-react-app)
24-
- [Multi-tenancy](#multi-tenancy)
25-
- [Docker in code-server container?](#docker-in-code-server-container)
26-
- [How can I disable telemetry?](#how-can-i-disable-telemetry)
27-
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
28-
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
29-
- [Heartbeat File](#heartbeat-file)
30-
- [Healthz endpoint](#healthz-endpoint)
31-
- [How does the config file work?](#how-does-the-config-file-work)
32-
- [Isn't an install script piped into sh insecure?](#isnt-an-install-script-piped-into-sh-insecure)
33-
- [How do I make my keyboard shortcuts work?](#how-do-i-make-my-keyboard-shortcuts-work)
34-
- [How do I access my Documents/Downloads/Desktop folders in code-server on OSX?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-osx)
35-
- [Differences compared to Theia?](#differences-compared-to-theia)
36-
- [`$HTTP_PROXY`, `$HTTPS_PROXY`, `$NO_PROXY`](#http_proxy-https_proxy-no_proxy)
37-
- [Enterprise](#enterprise)
5+
- [Questions?](#questions)
6+
- [iPad Status?](#ipad-status)
7+
- [Community Projects (awesome-code-server)](#community-projects-awesome-code-server)
8+
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
9+
- [Differences compared to VS Code?](#differences-compared-to-vs-code)
10+
- [Installing an extension](#installing-an-extension)
11+
- [How can I request a missing extension?](#how-can-i-request-a-missing-extension)
12+
- [Installing an extension manually](#installing-an-extension-manually)
13+
- [How do I configure the marketplace URL?](#how-do-i-configure-the-marketplace-url)
14+
- [Where are extensions stored?](#where-are-extensions-stored)
15+
- [How is this different from VS Code Codespaces?](#how-is-this-different-from-vs-code-codespaces)
16+
- [How should I expose code-server to the internet?](#how-should-i-expose-code-server-to-the-internet)
17+
- [Can I store my password hashed?](#can-i-store-my-password-hashed)
18+
- [How do I securely access web services?](#how-do-i-securely-access-web-services)
19+
- [Sub-paths](#sub-paths)
20+
- [Sub-domains](#sub-domains)
21+
- [Why does the code-server proxy strip `/proxy/<port>` from the request path?](#why-does-the-code-server-proxy-strip-proxyport-from-the-request-path)
22+
- [Proxying to Create React App](#proxying-to-create-react-app)
23+
- [Multi-tenancy](#multi-tenancy)
24+
- [Docker in code-server container?](#docker-in-code-server-container)
25+
- [How can I disable telemetry?](#how-can-i-disable-telemetry)
26+
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
27+
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
28+
- [Heartbeat File](#heartbeat-file)
29+
- [Healthz endpoint](#healthz-endpoint)
30+
- [How does the config file work?](#how-does-the-config-file-work)
31+
- [Isn't an install script piped into sh insecure?](#isnt-an-install-script-piped-into-sh-insecure)
32+
- [How do I make my keyboard shortcuts work?](#how-do-i-make-my-keyboard-shortcuts-work)
33+
- [How do I access my Documents/Downloads/Desktop folders in code-server on OSX?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-osx)
34+
- [Differences compared to Theia?](#differences-compared-to-theia)
35+
- [`$HTTP_PROXY`, `$HTTPS_PROXY`, `$NO_PROXY`](#http_proxy-https_proxy-no_proxy)
36+
- [Enterprise](#enterprise)
3837

3938
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
4039

@@ -209,7 +208,6 @@ Yes you can! Set the value of `hashed-password` instead of `password`. Generate
209208
```shell
210209
echo -n "password" | npx argon2-cli -e
211210
$argon2i$v=19$m=4096,t=3,p=1$wst5qhbgk2lu1ih4dmuxvg$ls1alrvdiwtvzhwnzcm1dugg+5dto3dt1d5v9xtlws4
212-
213211
```
214212

215213
Of course replace `thisismypassword` with your actual password and **remember to put it inside quotes**!

‎src/node/cli.ts‎

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,8 @@ export function splitOnFirstEquals(str: string): string[] {
247247
// $argon2i$v=19$m=4096,t=3,p=10ドルqR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY
248248
// 2 means return two items
249249
// Source: https://stackoverflow.com/a/4607799/3015595
250-
const split = str.split(/=(.+)/, 2)
251-
252-
// It should always return two elements
253-
// because it's used in a place where
254-
// it expected two elements
255-
if (split.length === 1) {
256-
split.push("")
257-
}
250+
// We use the ? to say the the substr after the = is optional
251+
const split = str.split(/=(.+)?/, 2)
258252

259253
return split
260254
}
@@ -289,10 +283,11 @@ export const parse = (
289283
let key: keyof Args | undefined
290284
let value: string | undefined
291285
if (arg.startsWith("--")) {
292-
// TODO fix this
293-
const split = arg.replace(/^--/, "").split("=", 2)
286+
const split = splitOnFirstEquals(arg.replace(/^--/, ""))
294287
key = split[0] as keyof Args
295288
value = split[1]
289+
290+
console.log(`Hello key: ${key}, and value: ${value}`)
296291
} else {
297292
const short = arg.replace(/^-/, "")
298293
const pair = Object.entries(options).find(([, v]) => v.short === short)
@@ -301,6 +296,7 @@ export const parse = (
301296
}
302297
}
303298

299+
console.log(`What is key: ${key} and options: ${key ? options[key] : ""}`)
304300
if (!key || !options[key]) {
305301
throw error(`Unknown option ${arg}`)
306302
}
@@ -563,7 +559,6 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA
563559
const config = yaml.load(configFile, {
564560
filename: configPath,
565561
})
566-
console.log("what is this config", config)
567562
if (!config || typeof config === "string") {
568563
throw new Error(`invalid config: ${config}`)
569564
}
@@ -576,11 +571,9 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA
576571
}
577572
return `--${optName}=${opt}`
578573
})
579-
console.log("what are the configFileArgv", configFileArgv)
580574
const args = parse(configFileArgv, {
581575
configFile: configPath,
582576
})
583-
console.log(args, "args")
584577
return {
585578
...args,
586579
config: configPath,

‎src/node/http.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ export const ensureAuthenticated = async (
6363
*/
6464
export const authenticated = async (req: express.Request): Promise<boolean> => {
6565
switch (req.args.auth) {
66-
case AuthType.None:
66+
case AuthType.None:{
6767
return true
68-
case AuthType.Password:
68+
}
69+
case AuthType.Password: {
6970
// The password is stored in the cookie after being hashed.
7071
const hashedPasswordFromArgs = req.args["hashed-password"]
7172
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
@@ -77,8 +78,10 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
7778
}
7879

7980
return await isCookieValid(isCookieValidArgs)
80-
default:
81+
}
82+
default: {
8183
throw new Error(`Unsupported auth type ${req.args.auth}`)
84+
}
8285
}
8386
}
8487

‎src/node/util.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import { logger } from "@coder/logger"
2+
import * as argon2 from "argon2"
13
import * as cp from "child_process"
24
import * as crypto from "crypto"
3-
import * as argon2 from "argon2"
45
import envPaths from "env-paths"
56
import { promises as fs } from "fs"
67
import * as net from "net"
78
import * as os from "os"
89
import * as path from "path"
10+
import safeCompare from "safe-compare"
911
import * as util from "util"
1012
import xdgBasedir from "xdg-basedir"
11-
import safeCompare from "safe-compare"
12-
import { logger } from "@coder/logger"
1313

1414
export interface Paths {
1515
data: string

‎test/package.json‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,5 @@
1818
"resolutions": {
1919
"@playwright/test/playwright": "^1.11.0-next-alpha-apr-13-2021"
2020
},
21-
"dependencies": {
22-
}
21+
"dependencies": {}
2322
}

‎test/unit/cli.test.ts‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,21 @@ describe("parser", () => {
349349
],
350350
})
351351
})
352+
it("should parse options with double-dash and multiple equal signs ", async () => {
353+
const args = parse(
354+
[
355+
"--hashed-password=$argon2i$v=19$m=4096,t=3,p=10ドルqr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
356+
],
357+
{
358+
configFile: "/pathtoconfig",
359+
},
360+
)
361+
expect(args).toEqual({
362+
_: [],
363+
"hashed-password":
364+
"$argon2i$v=19$m=4096,t=3,p=10ドルqr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
365+
})
366+
})
352367
})
353368

354369
describe("cli", () => {
@@ -426,25 +441,25 @@ describe("cli", () => {
426441

427442
describe("splitOnFirstEquals", () => {
428443
it("should split on the first equals", () => {
429-
const testStr = "--enabled-proposed-api=test=value"
444+
const testStr = "enabled-proposed-api=test=value"
430445
const actual = splitOnFirstEquals(testStr)
431-
const expected = ["--enabled-proposed-api", "test=value"]
446+
const expected = ["enabled-proposed-api", "test=value"]
432447
expect(actual).toEqual(expect.arrayContaining(expected))
433448
})
434449
it("should split on first equals regardless of multiple equals signs", () => {
435450
const testStr =
436-
"--hashed-password=$argon2i$v=19$m=4096,t=3,p=10ドルqR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY"
451+
"hashed-password=$argon2i$v=19$m=4096,t=3,p=10ドルqR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY"
437452
const actual = splitOnFirstEquals(testStr)
438453
const expected = [
439-
"--hashed-password",
454+
"hashed-password",
440455
"$argon2i$v=19$m=4096,t=3,p=10ドルqR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
441456
]
442457
expect(actual).toEqual(expect.arrayContaining(expected))
443458
})
444-
it("should always return two elements", () => {
445-
const testStr = ""
459+
it("should always return the first element before an equals", () => {
460+
const testStr = "auth="
446461
const actual = splitOnFirstEquals(testStr)
447-
const expected = ["",""]
462+
const expected = ["auth"]
448463
expect(actual).toEqual(expect.arrayContaining(expected))
449464
})
450465
})

‎typings/pluginapi.d.ts‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ export const proxy: ProxyServer
145145
/**
146146
* Middleware to ensure the user is authenticated. Throws if they are not.
147147
*/
148-
export function ensureAuthenticated(req: express.Request, res?: express.Response, next?: express.NextFunction): Promise<void>
148+
export function ensureAuthenticated(
149+
req: express.Request,
150+
res?: express.Response,
151+
next?: express.NextFunction,
152+
): Promise<void>
149153

150154
/**
151155
* Returns true if the user is authenticated.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /