mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: create key cli command logic and add to index command list
This commit is contained in:
117
api/src/cli/commands/key.ts
Normal file
117
api/src/cli/commands/key.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { ArgumentConfig, parse } from 'ts-command-line-args';
|
||||
|
||||
import { cliLogger } from '@app/core/log';
|
||||
import { Role } from '@app/graphql/generated/api/types';
|
||||
import { ApiKeyService } from '@app/unraid-api/auth/api-key.service';
|
||||
|
||||
enum Command {
|
||||
Get = 'get',
|
||||
Create = 'create',
|
||||
}
|
||||
|
||||
type KeyFlags = {
|
||||
command: string;
|
||||
name: string;
|
||||
create?: boolean;
|
||||
roles?: string;
|
||||
permissions?: string;
|
||||
};
|
||||
|
||||
const validRoles: Set<Role> = new Set(Object.values(Role));
|
||||
|
||||
const validateRoles = (rolesStr?: string): Role[] => {
|
||||
if (!rolesStr) return [Role.GUEST];
|
||||
|
||||
const requestedRoles = rolesStr.split(',').map((role) => role.trim().toUpperCase() as Role);
|
||||
const validRequestedRoles = requestedRoles.filter((role) => validRoles.has(role));
|
||||
|
||||
if (validRequestedRoles.length === 0) {
|
||||
throw new Error(`Invalid roles. Valid options are: ${Array.from(validRoles).join(', ')}`);
|
||||
}
|
||||
|
||||
const invalidRoles = requestedRoles.filter((role) => !validRoles.has(role));
|
||||
|
||||
if (invalidRoles.length > 0) {
|
||||
cliLogger.warn(`Ignoring invalid roles: ${invalidRoles.join(', ')}`);
|
||||
}
|
||||
|
||||
return validRequestedRoles;
|
||||
};
|
||||
|
||||
const keyOptions: ArgumentConfig<KeyFlags> = {
|
||||
command: { type: String, description: 'get or create' },
|
||||
name: { type: String, description: 'Name of the API key', typeLabel: '{underline name}' },
|
||||
create: { type: Boolean, optional: true, description: "Create the key if it doesn't exist" },
|
||||
roles: {
|
||||
type: String,
|
||||
optional: true,
|
||||
description: `Comma-separated list of roles (${Object.values(Role).join(', ')})`,
|
||||
typeLabel: '{underline role1,role2}',
|
||||
},
|
||||
permissions: {
|
||||
type: String,
|
||||
optional: true,
|
||||
description: 'Comma-separated list of permissions',
|
||||
typeLabel: '{underline perm1,perm2}',
|
||||
},
|
||||
};
|
||||
|
||||
export const key = async (...argv: string[]) => {
|
||||
try {
|
||||
const options = parse<KeyFlags>(keyOptions, { argv });
|
||||
const apiKeyService = new ApiKeyService();
|
||||
|
||||
if (!options.name) {
|
||||
throw new Error('Name is required');
|
||||
}
|
||||
|
||||
switch (options.command) {
|
||||
case Command.Create: {
|
||||
const roles = validateRoles(options.roles);
|
||||
const key = await apiKeyService.create(
|
||||
options.name,
|
||||
`CLI generated key: ${options.name}`,
|
||||
roles,
|
||||
true
|
||||
);
|
||||
|
||||
console.log('API Key: ', key);
|
||||
cliLogger.info('API key created successfully');
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Command.Get: {
|
||||
const key = await apiKeyService.findByField('name', options.name);
|
||||
|
||||
if (!key && options.create) {
|
||||
const roles = validateRoles(options.roles);
|
||||
const newKey = await apiKeyService.create(
|
||||
options.name,
|
||||
`CLI generated key: ${options.name}`,
|
||||
roles,
|
||||
true
|
||||
);
|
||||
|
||||
console.log('New API Key: ', newKey);
|
||||
cliLogger.info('API key created successfully');
|
||||
} else if (key) {
|
||||
console.log('API Key: ', key);
|
||||
} else {
|
||||
throw new Error(`No API key found with name: ${options.name}`);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Invalid command. Use: ${Object.values(Command).join(' or ')}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
cliLogger.error(`Failed to process API key: ${error.message}`);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
@@ -30,6 +30,7 @@ export const main = async (...argv: string[]) => {
|
||||
|
||||
// Only import the command we need when we use it
|
||||
const commands = {
|
||||
key: import('@app/cli/commands/key').then((pkg) => pkg.key),
|
||||
start: import('@app/cli/commands/start').then((pkg) => pkg.start),
|
||||
stop: import('@app/cli/commands/stop').then((pkg) => pkg.stop),
|
||||
restart: import('@app/cli/commands/restart').then((pkg) => pkg.restart),
|
||||
|
||||
Reference in New Issue
Block a user