mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
overhaul identity file detection and resolution
This commit is contained in:
parent
7ce1b9e2b7
commit
f452e8324f
3 changed files with 64 additions and 17 deletions
|
|
@ -7,18 +7,19 @@ async function main() {
|
||||||
.subcommand(tribe)
|
.subcommand(tribe)
|
||||||
.subcommand(remote)
|
.subcommand(remote)
|
||||||
.option('-i --identity-file', {
|
.option('-i --identity-file', {
|
||||||
description: 'The ssh identity file to use. Defaults to ~/.ssh/id_rsa.',
|
description: 'The ssh identity file to use. You will be prompted if this is not supplied.',
|
||||||
default: await defaultIdentityFile(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { parsed } = tribes.parse(Deno.args);
|
const { parsed } = tribes.parse(Deno.args);
|
||||||
|
parsed['identity-file'] = await defaultIdentityFile(parsed['identity-file'] as string);
|
||||||
|
|
||||||
const [s, v] = parsed._.slice(1);
|
const [s, v] = parsed._.slice(1);
|
||||||
|
|
||||||
let cmd = tribes;
|
let cmd = tribes;
|
||||||
if (s) cmd = tribes.getSubcommand(s);
|
if (s) cmd = tribes.getSubcommand(s);
|
||||||
if (v) cmd = cmd.getSubcommand(v);
|
if (v) cmd = cmd.getSubcommand(v);
|
||||||
|
|
||||||
await cmd.action(parsed);
|
await cmd.doAction(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.main) {
|
if (import.meta.main) {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,7 @@
|
||||||
import { join } from '@std/path';
|
|
||||||
import { ParsedArgs } from './parsing.ts';
|
import { ParsedArgs } from './parsing.ts';
|
||||||
import { Command } from './command.ts';
|
import { Command } from './command.ts';
|
||||||
|
import { defaultIdentityFile } from './ssh/identity.ts';
|
||||||
export const defaultIdentityFile = async () => {
|
import { connect } from './ssh/mod.ts';
|
||||||
const home = Deno.env.get('HOME');
|
|
||||||
if (!home) throw new Error('tribes-cli: unable to find default identity file');
|
|
||||||
const path = join(home, '.ssh', 'id_rsa');
|
|
||||||
try {
|
|
||||||
await Deno.stat(path);
|
|
||||||
return path;
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
throw new Error('tribes-cli: unable to find default identity file.');
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Option =
|
export type Option =
|
||||||
& { description: string }
|
& { description: string }
|
||||||
|
|
@ -27,5 +16,5 @@ export const cleanArg = (arg: string) => {
|
||||||
return arg.replace(/^--?/g, '');
|
return arg.replace(/^--?/g, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Command };
|
export { Command, connect, defaultIdentityFile };
|
||||||
export type { ParsedArgs };
|
export type { ParsedArgs };
|
||||||
|
|
|
||||||
57
tribes-cli/utils/ssh/identity.ts
Normal file
57
tribes-cli/utils/ssh/identity.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { join } from '@std/path';
|
||||||
|
import { expandGlob } from '@std/fs/expand-glob';
|
||||||
|
import question from 'question-deno';
|
||||||
|
|
||||||
|
const resolveIdentityFile = async () => {
|
||||||
|
const home = Deno.env.get('HOME');
|
||||||
|
if (!home) throw new Error('tribes-cli: unable to find default identity file');
|
||||||
|
const path = join(home, '.ssh', '*.pub');
|
||||||
|
const found: string[] = [];
|
||||||
|
for await (const file of expandGlob(path)) {
|
||||||
|
try {
|
||||||
|
const pkey = file.path.replace(/.pub$/, '');
|
||||||
|
const info = await Deno.stat(pkey);
|
||||||
|
if (info.isFile) found.push(pkey);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
if (found.length) {
|
||||||
|
const chosen = await question('list', 'There were multiple ssh keys found. Which do you want to use?', [
|
||||||
|
...found,
|
||||||
|
'Something else',
|
||||||
|
]);
|
||||||
|
if (chosen?.startsWith('/')) return chosen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = await question('input', 'Enter the path of the ssh identity file to use.');
|
||||||
|
try {
|
||||||
|
const stat = await Deno.stat(input || '');
|
||||||
|
if (stat.isFile) return input!;
|
||||||
|
} catch {
|
||||||
|
throw new Error(`tribes-cli: could not stat "${input}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('tribes-cli: unable to find valid identity file, or selected path is a directory');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const defaultIdentityFile = async (supplied?: string) => {
|
||||||
|
const cached = localStorage.getItem('identity-file-path');
|
||||||
|
if (cached && cached !== supplied && await question('confirm', `Found identity file ${cached}. Use it?`)) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
let identityFile = '';
|
||||||
|
|
||||||
|
if (supplied) {
|
||||||
|
try {
|
||||||
|
const stat = await Deno.stat(supplied);
|
||||||
|
if (stat.isFile) identityFile = supplied;
|
||||||
|
} catch {
|
||||||
|
throw new Error(`tribes-cli: supplied identity file ${supplied} does not exist or is not a file.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!identityFile) identityFile = await resolveIdentityFile();
|
||||||
|
localStorage.setItem('identity-file-path', identityFile);
|
||||||
|
|
||||||
|
return identityFile;
|
||||||
|
};
|
||||||
Loading…
Add table
Reference in a new issue