import crypto from "node:crypto"; import path from "node:path"; import { password as promptPassword } from "@inquirer/prompts"; import { stringify } from "yaml"; import { hashPassword } from "../../lib/auth/password"; import { upsertEnvVar } from "../lib/env-file"; import { resolveConfigPath } from "../lib/paths"; import { slug } from "../lib/slug"; export interface UsersOptions { config?: string; inline?: boolean; } function printSnippet(heading: string, entry: Record): void { console.log(`\n${heading}\n`); console.log(stringify([entry])); } async function promptNewPassword(): Promise { for (;;) { const first = await promptPassword({ message: "Password", mask: true }); const second = await promptPassword({ message: "Confirm password", mask: true, }); if (first === second) return first; console.error("Passwords did not match, try again.\n"); } } export async function usersAddCommand( username: string, opts: UsersOptions, ): Promise { const password = await promptNewPassword(); const passwordHash = await hashPassword(password); if (opts.inline) { printSnippet("Add this under `auth.users:` in your config file:", { username, passwordHash, }); return; } const configPath = resolveConfigPath(opts.config); const envPath = path.join(path.dirname(configPath), ".env"); const varName = `TRIGGERSHELL_USER_${slug(username)}_PASSWORD_HASH`; upsertEnvVar(envPath, varName, passwordHash); console.log(`Stored ${varName} in ${envPath}`); printSnippet("Add this under `auth.users:` in your config file:", { username, passwordHash: `\${${varName}}`, }); } export async function usersAddTokenCommand( name: string, opts: UsersOptions, ): Promise { const token = crypto.randomBytes(32).toString("hex"); const tokenHash = `sha256:${crypto.createHash("sha256").update(token).digest("hex")}`; console.log("\nSave this token now - it will not be shown again:"); console.log(` ${token}`); console.log(`Use it as: Authorization: Bearer ${token}`); if (opts.inline) { printSnippet("Add this under `auth.tokens:` in your config file:", { name, tokenHash, }); return; } const configPath = resolveConfigPath(opts.config); const envPath = path.join(path.dirname(configPath), ".env"); const varName = `TRIGGERSHELL_TOKEN_${slug(name)}_HASH`; upsertEnvVar(envPath, varName, tokenHash); console.log(`Stored ${varName} in ${envPath}`); printSnippet("Add this under `auth.tokens:` in your config file:", { name, tokenHash: `\${${varName}}`, }); }