Skip to content

Commit

Permalink
Add standalone option
Browse files Browse the repository at this point in the history
  • Loading branch information
wiltsecarpenter committed Oct 28, 2023
1 parent cec312a commit 673f118
Show file tree
Hide file tree
Showing 8 changed files with 773 additions and 44 deletions.
19 changes: 0 additions & 19 deletions .eslintrc.js

This file was deleted.

13 changes: 11 additions & 2 deletions bin/observable-database-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ argv
name,
start
)
.command(`add <name>`, `Add a new database proxy configuration`, name, add)
.command(
`add <name> [--standalone]`,
`Add a new database proxy configuration`,
name,
add
)
.command(
`remove <name>`,
`Remove an existing database proxy configuration`,
name,
remove
)
.command(
`reset <name>`,
`reset <name> [--standalone]`,
`Reset the shared secret for an existing database proxy configuration`,
name,
reset
Expand All @@ -40,6 +45,10 @@ argv
`sslkey`,
`Set the SSL private key location for an HTTPS database proxy`
)
.describe(
`standalone`,
`Standalone mode: create secret configuration for standalone client`
)
.example(`$0 start localdb`, `Run an HTTP database proxy named "localdb"`)
.example(
`$0 start localssl --sslkey ../ssl/localhost.key --sslcert ../ssl/localhost.crt`,
Expand Down
62 changes: 57 additions & 5 deletions lib/commands.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/* eslint-disable no-console */

import {randomBytes} from "crypto";
import {createInterface} from "readline";
import open from "open";
import {
readConfig,
readDecodedConfig,
writeConfig,
decodeSecret,
encodeSecret,
} from "./config.js";
import {server} from "./server.js";
import {server, types} from "./server.js";
import {exit} from "./errors.js";

export function start(argv) {
Expand All @@ -17,7 +19,7 @@ export function start(argv) {
}

export async function add(argv, reset = false) {
const {name, sslkey, sslcert} = argv;
const {name, sslkey, sslcert, standalone} = argv;
let config = readConfig();
let url;
let token;
Expand All @@ -39,7 +41,12 @@ export async function add(argv, reset = false) {
if (reset) {
if (!config[name]) exit(`No configuration found for "${name}"`);
url = config[name].url;
} else {
token = config[name].token;
server_host = config[name].server_host;
path = config[name].path;
username = config[name].username;
password = config[name].password;
} else if (!standalone) {
const wantsSSL = sslkey || sslcert;
// open browser
const observable =
Expand All @@ -53,8 +60,51 @@ export async function add(argv, reset = false) {
);
}

// paste secret (secret, origin, name, type, host, port, ssl)
const secret = await question("Secret: ");
let secret;
if (standalone) {
let {type, host, origin, port, ssl} = config[name]
? decodeSecret(config[name].secret)
: {};
if (!type) {
for (;;) {
type = await question("Database type: ");
if (types.includes(type)) break;
console.log(`Invalid type, should be one of: ${types.join(", ")}`);
}
} else if (!types.includes(type)) {
exit(`Invalid type, should be one of: ${type.join(", ")}`);
}
if (!host || !port || !ssl) {
const proxyUrl = new URL(
(await question(
"Observable database proxy Url [http://127.0.0.1:2899]:"
)) || "http://127.0.0.1:2899"
);
host = proxyUrl.hostname;
port = proxyUrl.port;
ssl = proxyUrl.protocol !== "https" ? "disabled" : "required";
}
if (!origin) {
origin =
(await question(
"Observable CLI server origin [http://127.0.0.1:3000]:"
)) || "http://127.0.0.1:3000";
}

const secretPayload = {
name,
type,
host,
port,
ssl,
origin,
secret: randomBytes(32).toString("hex"),
};
secret = encodeSecret(secretPayload);
} else {
// paste secret (secret, origin, name, type, host, port, ssl)
secret = await question("Secret: ");
}
const decoded = decodeSecret(secret);
if (decoded.name !== name)
return exit(`Name mismatch: "${decoded.name}" (server), "${name} (proxy)"`);
Expand Down Expand Up @@ -104,6 +154,8 @@ export async function add(argv, reset = false) {
writeConfig(config);

console.log(`Configuration ${reset ? `reset` : `added`} for "${name}"`);
if (standalone)
console.log(`Secret for DabaseClient("${name}"):\ndb:${name}:${secret}`);
}

export function reset(argv) {
Expand Down
5 changes: 5 additions & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ export function decodeSecret(secret) {
exit(error);
}
}

export function encodeSecret(arg) {
const buffer = Buffer.from(JSON.stringify(arg)).toString("base64");
return buffer;
}
10 changes: 10 additions & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ import oracle from "./oracle.js";
import databricks from "./databricks.js";
import logger from "../middleware/logger.js";

export const types = [
"databricks",
"mysql",
"mssql",
"postgres",
"snowflake",
"oracle",
"mongosql",
];

export async function server(config, argv) {
const development = process.env.NODE_ENV === "development";
const developmentOrigin = "https://worker.test:5000";
Expand Down
2 changes: 1 addition & 1 deletion lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const validateQueryPayload = ajv.compile({
required: ["sql"],
properties: {
sql: {type: "string", minLength: 1, maxLength: 32 * 1000},
params: {type: ["object", "array"]},
params: {anyOf: [{type: ["object"]}, {type: ["array"]}]}
},
});
export const validateDescribeColumnsPayload = ajv.compile({
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@
"@babel/preset-env": "^7.19.4",
"@babel/register": "^7.18.9",
"chai": "^4.3.6",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"mocha": "^10.1.0",
"mock-req": "^0.2.0",
"mock-res": "^0.6.0",
"nodemon": "^1.19.1",
"prettier": "^3.0.3",
"wait-on": "^6.0.1"
},
"peerDependencies": {
Expand Down
Loading

0 comments on commit 673f118

Please sign in to comment.