mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 07:17:18 +00:00
fix(GUI): provide a friendly message when no polkit agent is available (#1221)
`sudo-prompt`, the module we use to provide elevation for GNU/Linux, relies on polkit to show the elevation dialog. Polkit implements a "backend" to control privileges, but relies on different packages to provide a GUI frontend. If no GUI frontend can be found on the system, then `sudo-prompt` will fail with a `No polkit authentication agent found.` In this case, we shouldn't present a scary stack trace to the user, and we should also not send this error to TrackJS. As a solution, we intercept such error in `lib/child-writer/writer-proxy.js`, and convert it into a human readable user error using `errors.createUserError()`, which is passed to the Etcher GUI using the "robot" mechanism. Fixes: https://github.com/resin-io/etcher/issues/1179 Change-Type: patch Changelog-Entry: Provide a user friendly error message when no polkit authentication agent is available on the system. Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
parent
e7f0613d82
commit
0e8dee0506
@ -113,25 +113,43 @@ exports.write = (image, drive, options) => {
|
||||
emitter.emit('error', error);
|
||||
};
|
||||
|
||||
ipc.server.on('error', emitError);
|
||||
ipc.server.on('message', (data) => {
|
||||
let message = null;
|
||||
|
||||
/**
|
||||
* @summary Bridge robot message to the child writer caller
|
||||
* @function
|
||||
* @private
|
||||
*
|
||||
* @param {String} message - robot message
|
||||
*
|
||||
* @example
|
||||
* bridgeRobotMessage(robot.buildMessage('foo', {
|
||||
* bar: 'baz'
|
||||
* }));
|
||||
*/
|
||||
const bridgeRobotMessage = (message) => {
|
||||
try {
|
||||
message = robot.parseMessage(data);
|
||||
const parsedMessage = robot.parseMessage(message);
|
||||
|
||||
// These are lighweight accessor methods for
|
||||
// the properties of the parsed message
|
||||
const messageCommand = robot.getCommand(parsedMessage);
|
||||
const messageData = robot.getData(parsedMessage);
|
||||
|
||||
// The error object is decomposed by the CLI for serialisation
|
||||
// purposes. We compose it back to an `Error` here in order
|
||||
// to provide better encapsulation.
|
||||
if (messageCommand === 'error') {
|
||||
emitError(robot.recomposeErrorMessage(parsedMessage));
|
||||
} else {
|
||||
emitter.emit(messageCommand, messageData);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return emitError(error);
|
||||
emitError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// The error object is decomposed by the CLI for serialisation
|
||||
// purposes. We compose it back to an `Error` here in order
|
||||
// to provide better encapsulation.
|
||||
if (robot.getCommand(message) === 'error') {
|
||||
return emitError(robot.recomposeErrorMessage(message));
|
||||
}
|
||||
|
||||
return emitter.emit(robot.getCommand(message), robot.getData(message));
|
||||
});
|
||||
ipc.server.on('error', emitError);
|
||||
ipc.server.on('message', bridgeRobotMessage);
|
||||
|
||||
ipc.server.on('start', () => {
|
||||
const child = childProcess.fork(CONSTANTS.WRITER_PROXY_SCRIPT, argv, {
|
||||
@ -144,7 +162,7 @@ exports.write = (image, drive, options) => {
|
||||
});
|
||||
|
||||
child.stderr.on('data', (data) => {
|
||||
emitError(new Error(data.toString()));
|
||||
bridgeRobotMessage(data.toString());
|
||||
|
||||
// This function causes the `close` event to be emitted
|
||||
child.kill();
|
||||
|
@ -28,6 +28,7 @@ const sudoPrompt = Bluebird.promisifyAll(require('sudo-prompt'));
|
||||
const utils = require('./utils');
|
||||
const EXIT_CODES = require('../shared/exit-codes');
|
||||
const errors = require('../shared/errors');
|
||||
const robot = require('../shared/robot');
|
||||
const packageJSON = require('../../package.json');
|
||||
|
||||
// This script is in charge of spawning the writer process and
|
||||
@ -153,10 +154,23 @@ return isElevated().then((elevated) => {
|
||||
if (!_.isEmpty(stderr)) {
|
||||
throw errors.createError(stderr);
|
||||
}
|
||||
|
||||
// We're hardcoding internal error messages declared by `sudo-prompt`.
|
||||
// There doesn't seem to be a better way to handle these errors, so
|
||||
// for now, we should make sure we double check if the error messages
|
||||
// have changed every time we upgrade `sudo-prompt`.
|
||||
|
||||
}).catch({
|
||||
message: 'User did not grant permission.'
|
||||
}, () => {
|
||||
process.exit(EXIT_CODES.CANCELLED);
|
||||
}).catch({
|
||||
message: 'No polkit authentication agent found.'
|
||||
}, () => {
|
||||
throw errors.createUserError(
|
||||
'No polkit authentication agent found',
|
||||
'Please install a polkit authentication agent for your desktop environment of choice to continue'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -226,6 +240,6 @@ return isElevated().then((elevated) => {
|
||||
process.exit(exitCode);
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
robot.printError(error);
|
||||
process.exit(EXIT_CODES.GENERAL_ERROR);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user