mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-18 02:39:49 +00:00
Add support for authentication checking to oclif
Change-type: patch Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
parent
6ec8bcddaa
commit
8658104647
3
lib/actions-oclif/env/add.ts
vendored
3
lib/actions-oclif/env/add.ts
vendored
@ -105,7 +105,6 @@ export default class EnvAddCmd extends Command {
|
|||||||
EnvAddCmd,
|
EnvAddCmd,
|
||||||
);
|
);
|
||||||
const cmd = this;
|
const cmd = this;
|
||||||
const { checkLoggedIn } = await import('../../utils/patterns');
|
|
||||||
|
|
||||||
if (!options.application && !options.device) {
|
if (!options.application && !options.device) {
|
||||||
throw new ExpectedError(
|
throw new ExpectedError(
|
||||||
@ -113,7 +112,7 @@ export default class EnvAddCmd extends Command {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await checkLoggedIn();
|
await Command.checkLoggedIn();
|
||||||
|
|
||||||
if (params.value == null) {
|
if (params.value == null) {
|
||||||
params.value = process.env[params.name];
|
params.value = process.env[params.name];
|
||||||
|
3
lib/actions-oclif/env/rename.ts
vendored
3
lib/actions-oclif/env/rename.ts
vendored
@ -85,9 +85,8 @@ export default class EnvRenameCmd extends Command {
|
|||||||
const { args: params, flags: opt } = this.parse<FlagsDef, ArgsDef>(
|
const { args: params, flags: opt } = this.parse<FlagsDef, ArgsDef>(
|
||||||
EnvRenameCmd,
|
EnvRenameCmd,
|
||||||
);
|
);
|
||||||
const { checkLoggedIn } = await import('../../utils/patterns');
|
|
||||||
|
|
||||||
await checkLoggedIn();
|
await Command.checkLoggedIn();
|
||||||
|
|
||||||
await getBalenaSdk().pine.patch({
|
await getBalenaSdk().pine.patch({
|
||||||
resource: ec.getVarResourceName(opt.config, opt.device, opt.service),
|
resource: ec.getVarResourceName(opt.config, opt.device, opt.service),
|
||||||
|
4
lib/actions-oclif/env/rm.ts
vendored
4
lib/actions-oclif/env/rm.ts
vendored
@ -88,9 +88,9 @@ export default class EnvRmCmd extends Command {
|
|||||||
EnvRmCmd,
|
EnvRmCmd,
|
||||||
);
|
);
|
||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
const { checkLoggedIn, confirm } = await import('../../utils/patterns');
|
const { confirm } = await import('../../utils/patterns');
|
||||||
|
|
||||||
await checkLoggedIn();
|
await Command.checkLoggedIn();
|
||||||
|
|
||||||
await confirm(
|
await confirm(
|
||||||
opt.yes || false,
|
opt.yes || false,
|
||||||
|
@ -133,10 +133,9 @@ export default class EnvsCmd extends Command {
|
|||||||
|
|
||||||
public async run() {
|
public async run() {
|
||||||
const { flags: options } = this.parse<FlagsDef, {}>(EnvsCmd);
|
const { flags: options } = this.parse<FlagsDef, {}>(EnvsCmd);
|
||||||
const { checkLoggedIn } = await import('../utils/patterns');
|
|
||||||
const variables: EnvironmentVariableInfo[] = [];
|
const variables: EnvironmentVariableInfo[] = [];
|
||||||
|
|
||||||
await checkLoggedIn();
|
await Command.checkLoggedIn();
|
||||||
|
|
||||||
if (!options.application && !options.device) {
|
if (!options.application && !options.device) {
|
||||||
throw new ExpectedError('You must specify an application or device');
|
throw new ExpectedError('You must specify an application or device');
|
||||||
|
@ -308,8 +308,8 @@ async function validateOptions(options: FlagsDef) {
|
|||||||
-------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
const { checkLoggedIn } = await import('../../utils/patterns');
|
|
||||||
await checkLoggedIn();
|
await Command.checkLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Command from '@oclif/command';
|
import Command from '@oclif/command';
|
||||||
import { ExpectedError } from './errors';
|
import { InsufficientPrivilegesError } from './errors';
|
||||||
|
|
||||||
export default abstract class BalenaCommand extends Command {
|
export default abstract class BalenaCommand extends Command {
|
||||||
/**
|
/**
|
||||||
@ -33,19 +33,59 @@ export default abstract class BalenaCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
public static root = false;
|
public static root = false;
|
||||||
|
|
||||||
protected async checkElevatedPrivileges() {
|
/**
|
||||||
const root = (this.constructor as typeof BalenaCommand).root;
|
* Require authentication to run.
|
||||||
if (root) {
|
* When set to true, command will exit with an error
|
||||||
|
* if user is not already logged in.
|
||||||
|
*/
|
||||||
|
public static authenticated = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw InsufficientPrivilegesError if not root on Mac/Linux
|
||||||
|
* or non-Administrator on Windows.
|
||||||
|
*
|
||||||
|
* Called automatically if `root=true`.
|
||||||
|
* Can be called explicitly by command implementation, if e.g.:
|
||||||
|
* - check should only be done conditionally
|
||||||
|
* - other code needs to execute before check
|
||||||
|
*/
|
||||||
|
protected static async checkElevatedPrivileges() {
|
||||||
const isElevated = await (await import('is-elevated'))();
|
const isElevated = await (await import('is-elevated'))();
|
||||||
if (!isElevated) {
|
if (!isElevated) {
|
||||||
throw new ExpectedError(
|
throw new InsufficientPrivilegesError(
|
||||||
'You need admin privileges to run this command',
|
'You need root/admin privileges to run this command',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw NotLoggedInError if not logged in.
|
||||||
|
*
|
||||||
|
* Called automatically if `authenticated=true`.
|
||||||
|
* Can be called explicitly by command implementation, if e.g.:
|
||||||
|
* - check should only be done conditionally
|
||||||
|
* - other code needs to execute before check
|
||||||
|
*
|
||||||
|
* Note, currently public to allow use outside of derived commands
|
||||||
|
* (as some command implementations require this. Can be made protected
|
||||||
|
* if this changes).
|
||||||
|
*/
|
||||||
|
public static async checkLoggedIn() {
|
||||||
|
await (await import('./utils/patterns')).checkLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async init() {
|
protected async init() {
|
||||||
await this.checkElevatedPrivileges();
|
const requireElevatedPrivileges = (this.constructor as typeof BalenaCommand)
|
||||||
|
.root;
|
||||||
|
const requireAuthentication = (this.constructor as typeof BalenaCommand)
|
||||||
|
.authenticated;
|
||||||
|
|
||||||
|
if (requireElevatedPrivileges) {
|
||||||
|
await BalenaCommand.checkElevatedPrivileges();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requireAuthentication) {
|
||||||
|
await BalenaCommand.checkLoggedIn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ export class ExpectedError extends TypedError {}
|
|||||||
|
|
||||||
export class NotLoggedInError extends ExpectedError {}
|
export class NotLoggedInError extends ExpectedError {}
|
||||||
|
|
||||||
|
export class InsufficientPrivilegesError extends ExpectedError {}
|
||||||
|
|
||||||
function hasCode(error: any): error is Error & { code: string } {
|
function hasCode(error: any): error is Error & { code: string } {
|
||||||
return error.code != null;
|
return error.code != null;
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,10 @@ export function authenticate(options: {}): Bluebird<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if logged in, and throw `NotLoggedInError` if not.
|
||||||
|
* Note: `NotLoggedInError` is an `ExpectedError`.
|
||||||
|
*/
|
||||||
export async function checkLoggedIn(): Promise<void> {
|
export async function checkLoggedIn(): Promise<void> {
|
||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
if (!(await balena.auth.isLoggedIn())) {
|
if (!(await balena.auth.isLoggedIn())) {
|
||||||
@ -84,6 +88,10 @@ export async function checkLoggedIn(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if logged in, and call `exitWithExpectedError()` if not.
|
||||||
|
* DEPRECATED: Use checkLoggedIn() instead.
|
||||||
|
*/
|
||||||
export async function exitIfNotLoggedIn(): Promise<void> {
|
export async function exitIfNotLoggedIn(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await checkLoggedIn();
|
await checkLoggedIn();
|
||||||
|
Loading…
Reference in New Issue
Block a user