|
1 | 1 | import assert from "node:assert/strict"; |
| 2 | +import { spawnSync } from "node:child_process"; |
2 | 3 | import { once } from "node:events"; |
3 | 4 | import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; |
4 | 5 | import { createServer } from "node:net"; |
@@ -492,6 +493,58 @@ test("launches RDP connection files without endpoint fields", async () => { |
492 | 493 | assert.deepEqual(launchedPayload, payload); |
493 | 494 | }); |
494 | 495 |
|
| 496 | +for (const platform of ["macos", "linux"]) { |
| 497 | + test(`${platform}/terminal-db quotes and encodes MongoDB connection values`, async (context) => { |
| 498 | + if (process.platform === "win32") return context.skip("POSIX shell test"); |
| 499 | + const config = JSON.parse( |
| 500 | + await readFile(path.join(projectRoot, "plugins", platform, `${platform}.terminal-db`, "connect.json"), "utf8") |
| 501 | + ); |
| 502 | + const application = { |
| 503 | + name: "terminal-db", |
| 504 | + protocol: ["mongodb"], |
| 505 | + is_set: true, |
| 506 | + match_first: ["mongodb"], |
| 507 | + launch_type: config.launch.type, |
| 508 | + launch_driver: config.launch.driver, |
| 509 | + arg_format: config.launch.template, |
| 510 | + protocol_templates: config.launch.protocol_templates |
| 511 | + }; |
| 512 | + const launcher = new LocalApplicationLauncher( |
| 513 | + { isPackaged: false }, |
| 514 | + projectRoot, |
| 515 | + { getConfig: async () => ({ databases: [application] }) }, |
| 516 | + null |
| 517 | + ); |
| 518 | + const user = "token:id@/"; |
| 519 | + const password = ["space value", "$HOME", "`printf injected`", "'", '"', ";", "&", "/", "\\", "?", "#"].join(""); |
| 520 | + const database = "data /?#"; |
| 521 | + const expectedUri = `mongodb://${encodeURIComponent(user)}:${encodeURIComponent(password)}@gateway.example.com:5525/${encodeURIComponent(database)}?authSource=admin&loadBalanced=true&retryWrites=false`; |
| 522 | + let launched = false; |
| 523 | + launcher.launchTerminal = async (_selected, command) => { |
| 524 | + const result = spawnSync("bash", ["-lc", `mongosh() { printf '%s\\n' "$@"; }\n${command}`], { |
| 525 | + encoding: "utf8" |
| 526 | + }); |
| 527 | + assert.equal(result.status, 0, result.stderr); |
| 528 | + assert.equal(result.stdout, `${expectedUri}\n`); |
| 529 | + const parsed = new URL(expectedUri); |
| 530 | + assert.equal(decodeURIComponent(parsed.username), user); |
| 531 | + assert.equal(decodeURIComponent(parsed.password), password); |
| 532 | + assert.equal(decodeURIComponent(parsed.pathname.slice(1)), database); |
| 533 | + assert.equal(parsed.searchParams.get("authSource"), "admin"); |
| 534 | + launched = true; |
| 535 | + }; |
| 536 | + const payload = { |
| 537 | + protocol: "mongodb", |
| 538 | + name: "MongoDB", |
| 539 | + endpoint: { host: "gateway.example.com", port: 5525 }, |
| 540 | + token: { id: user, value: password }, |
| 541 | + asset: { info: { db_name: database } } |
| 542 | + }; |
| 543 | + await launcher.launch(`jms2://${Buffer.from(JSON.stringify(payload)).toString("base64")}`); |
| 544 | + assert.equal(launched, true); |
| 545 | + }); |
| 546 | +} |
| 547 | + |
495 | 548 | for (const [platform, plugin, expected] of [ |
496 | 549 | ["macos", "dbeaver", "driver=mysql"], |
497 | 550 | ["linux", "dbeaver", "driver=mysql"], |
|
0 commit comments