/** * @license * Copyright 2020 Balena Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Command from '@oclif/command'; import { InsufficientPrivilegesError } from './errors'; export default abstract class BalenaCommand extends Command { /** * When set to true, command will be listed in `help`, * otherwise listed in `help --verbose` with secondary commands. */ public static primary = false; /** * Require elevated privileges to run. * When set to true, command will exit with an error * if executed without root on Mac/Linux * or if executed by non-Administrator on Windows. */ public static root = false; /** * Require authentication to run. * 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'))(); if (!isElevated) { throw new InsufficientPrivilegesError( '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() { 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(); } } }