... NetGet Documentation src/modules/utils/handlePermissions.js

Source

src/modules/utils/handlePermissions.js

// netget/src/modules/utils/handlePermissions.js
import { exec } from 'child_process';
import fs from 'fs';
import inquirer from 'inquirer';
import chalk from 'chalk';

/**
 * Handles permission errors generically.
 * @param {string} taskDescription - Description of the task that requires permission.
 * @param {string} autoCommand - Command to execute for automatic resolution with elevated privileges.
 * @param {string} manualInstructions - Manual instructions for the user to resolve permission issues.
 * @category Utils
 * @subcategory General
 * @module handlePermissions
*/
const handlePermission = async (taskDescription, autoCommand, manualInstructions) => {
    const choices = [
        { name: 'Retry with elevated privileges', value: 'sudo' },
        { name: 'Display manual configuration instructions', value: 'manual' },
        { name: 'Try to change file permissions', value: 'changePermissions' },
        { name: 'Cancel operation', value: 'cancel' }
    ];

    const { action } = await inquirer.prompt({
        type: 'list',
        name: 'action',
        message: `Permission denied for ${taskDescription}. How would you like to proceed?`,
        choices: choices
    });

    switch (action) {
        case 'sudo':
            await tryElevatedPrivileges(autoCommand, manualInstructions);
            break;
        case 'manual':
            displayManualInstructions(manualInstructions);
            break;
        case 'changePermissions':
            const { filePath, requiredPermissions } = await inquirer.prompt([
                {
                    type: 'input',
                    name: 'filePath',
                    message: 'Enter the path of the file to change permissions:'
                },
                {
                    type: 'input',
                    name: 'requiredPermissions',
                    message: 'Enter the required permissions (e.g., 755) [default: 755]:',
                    default: '755'
                }
            ]);
            if (requiredPermissions) {
                await checkAndSetFilePermissions(filePath, requiredPermissions);
            } else {
                console.log(chalk.red('Permissions value is required.'));
            }
            break;
        case 'cancel':
            console.log(chalk.blue('Operation canceled by the user.'));
            break;
    }
};

/**
 * Tries to execute a command with elevated privileges.
 * @param {string} command - Command to execute with elevated privileges.
 * @param {string} manualInstructions - Instructions for manual permission resolution.
 * @category Utils
 * @subcategory General
 * @module handlePermissions
*/
const tryElevatedPrivileges = async (command, manualInstructions) => {
    try {
        const result = await execShellCommand(`sudo ${command}`);
        console.log(chalk.green('Command executed with elevated privileges.'));
        console.log(result);
    } catch (error) {
        console.error(chalk.red(`Failed with elevated privileges: ${error.message}`));
        displayManualInstructions(manualInstructions);
    }
};

/**
 * Displays manual configuration instructions.
 * @param {string} instructions - Instructions for manual permission resolution.
 * @category Utils
 * @subcategory General
 * @module handlePermissions
*/
const displayManualInstructions = (instructions) => {
    console.log(chalk.yellow('To manually configure, follow these instructions:'));
    console.info(chalk.cyan(instructions));
};

/**
 * Executes a shell command.
 * @param {string} cmd - Command to execute.
 * @returns {Promise<string>} - A promise that resolves with the command output.
 * @category Utils
 * @subcategory General
 * @module handlePermissions
*/
const execShellCommand = (cmd) => {
    return new Promise((resolve, reject) => {
        exec(cmd, (error, stdout, stderr) => {
            if (error) {
                reject(error);
            } else {
                resolve(stdout ? stdout : stderr);
            }
        });
    });
};

/**
 * Checks and sets file permissions if necessary.
 * @param {string} filePath - Path to the file to check permissions for.
 * @param {string} requiredPermissions - The permissions required (e.g., '755').
 * @category Utils
 * @subcategory General
 * @module handlePermissions 
*/
const checkAndSetFilePermissions = async (filePath, requiredPermissions) => {
    try {
        const stats = fs.statSync(filePath);
        const currentPermissions = `0${(stats.mode & 0o777).toString(8)}`;
        
        if (currentPermissions !== requiredPermissions) {
            await execShellCommand(`sudo chmod ${requiredPermissions} ${filePath}`);
            console.log(chalk.green(`Permissions for ${filePath} set to ${requiredPermissions}.`));
        } else {
            console.log(chalk.green(`Permissions for ${filePath} are already set to ${requiredPermissions}.`));
        }
    } catch (error) {
        console.error(chalk.red(`Failed to check/set permissions for ${filePath}: ${error.message}`));
    }
};

export { handlePermission, checkAndSetFilePermissions };

Witness our Seal.
neurons.me