mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 08:03:50 +00:00
* fix: prevent variable push from corrupting is_secret variables Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(cli): unit-test looksLikeWorkspaceCiphertext shape detection Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): scope is_secret downgrade to single-file push, not sync push Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): warn when variable push stores a secret value as already-encrypted Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): route workspace-resolution and auth diagnostics to stderr Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): rephrase comments to describe current behavior, not history Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
104 lines
2.5 KiB
TypeScript
104 lines
2.5 KiB
TypeScript
import { GlobalOptions } from "../types.ts";
|
|
import { colors } from "@cliffy/ansi/colors";
|
|
import * as getPort from "get-port";
|
|
import * as log from "./log.ts";
|
|
import * as open from "open";
|
|
import { Secret } from "@cliffy/prompt/secret";
|
|
import { Select } from "@cliffy/prompt/select";
|
|
import * as http from "node:http";
|
|
|
|
export async function loginInteractive(remote: string) {
|
|
let token: string | undefined;
|
|
if (!process.stdin.isTTY) {
|
|
log.infoStderr("Not a TTY, can't login interactively.");
|
|
return undefined;
|
|
}
|
|
if (
|
|
(await Select.prompt({
|
|
message: "How do you want to login",
|
|
options: [
|
|
{
|
|
name: "Browser",
|
|
value: "b",
|
|
},
|
|
{
|
|
name: "Token",
|
|
value: "t",
|
|
},
|
|
],
|
|
})) === "b"
|
|
) {
|
|
token = await browserLogin(remote);
|
|
} else {
|
|
token = await Secret.prompt("Enter your token");
|
|
}
|
|
return token;
|
|
}
|
|
|
|
export async function tryGetLoginInfo(
|
|
opts: GlobalOptions
|
|
): Promise<string | undefined> {
|
|
if (opts.token) {
|
|
return opts.token;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
export async function browserLogin(
|
|
baseUrl: string
|
|
): Promise<string | undefined> {
|
|
const env =
|
|
process.env["TOKEN_PORT"] != undefined
|
|
? parseInt(process.env["TOKEN_PORT"]!)
|
|
: undefined;
|
|
const port = await getPort.default({ port: env });
|
|
|
|
if (port == undefined) {
|
|
log.infoStderr(colors.red.underline("failed to aquire port"));
|
|
return undefined;
|
|
}
|
|
|
|
return new Promise((resolve) => {
|
|
const server = http.createServer((req, res) => {
|
|
const params = new URL(req.url!, `http://${req.headers.host}`)
|
|
.searchParams;
|
|
const token = params.get("token");
|
|
|
|
// Redirect the user to the success page
|
|
res.writeHead(302, { Location: `${baseUrl}user/cli-success` });
|
|
res.end();
|
|
|
|
// Close the server after a short delay
|
|
setTimeout(() => {
|
|
server.close();
|
|
}, 10);
|
|
|
|
// Resolve the promise with the token
|
|
resolve(token ?? undefined);
|
|
});
|
|
|
|
const url = `${baseUrl}user/cli?port=${port}`;
|
|
log.infoStderr(`Login by going to ${url}`);
|
|
|
|
try {
|
|
open.default(url).catch((error) => {
|
|
console.error(
|
|
`Failed to open browser, please navigate to ${url}, error: ${error}`
|
|
);
|
|
});
|
|
|
|
log.infoStderr("Opened browser for you");
|
|
} catch (error) {
|
|
console.error(
|
|
`Failed to open browser, please navigate to ${url}, error: ${error}`
|
|
);
|
|
}
|
|
|
|
// Start the server
|
|
server.listen(port, () => {
|
|
console.log(`Listening on port ${port}`);
|
|
});
|
|
});
|
|
}
|