Coder Social home page Coder Social logo

automation-stack / electron-sudo Goto Github PK

View Code? Open in Web Editor NEW
381.0 10.0 61.0 2.52 MB

Electron subprocesses with administrative privileges, prompting the user with an OS dialog if necessary.

License: MIT License

JavaScript 100.00%
electron sudo privileges elevate prompt uac

electron-sudo's Introduction

Electron subprocess with administrative privileges

Run a subprocess with administrative privileges, prompting the user with a graphical OS dialog if necessary. Useful for background subprocesse which run native Electron apps that need sudo.

  • Windows, uses elevate utility with native User Account Control (UAC) prompt (no PowerShell required)
  • OS X, uses bundled applet (inspired by Joran Dirk Greef)
  • Linux, uses system pkexec or gksudo (system or bundled).

If you don't trust binaries bundled in npm package you can manually build tools and use them instead.

Features

  • Supports spawn and exec subprocess behavior
  • Supports applications packaged as asar archive
  • Separate password prompt for each call (use sh or bat script for single prompt)
  • No external dependencies, does not depend on OS versions

Installation

npm install electron-sudo

Usage

Note: Your command should not start with the sudo prefix.

Version 4.0.*

import Sudoer from 'electron-sudo';

let options = {name: 'electron sudo application'},
    sudoer = new Sudoer(options);

/* Spawn subprocess behavior */
let cp = await sudoer.spawn(
  'echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}
);
cp.on('close', () => {
  /*
    cp.output.stdout (Buffer)
    cp.output.stderr (Buffer)
  */
});

/* Exec subprocess behavior */
let result = await sudoer.exec(
  'echo $PARAM', {env: {PARAM: 'VALUE'}}
);
/* result is Buffer with mixed (both stdout and stderr) output */


/* Usage with Vanila JS */

var Sudoer = require('electron-sudo').default;
var sudoer = new Sudoer(options);
sudoer.spawn('echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}).then(function (cp) {
  /*
    cp.output.stdout (Buffer)
    cp.output.stderr (Buffer)
  */
});

Version 3.0.* (deprecated)

var sudo = require('electron-sudo');
var options = {
  name: 'Your application name',
  icns: '/path/to/icns/file' // (optional, only for MacOS),
  process: {
    options: {
      // Can use custom environment variables for your privileged subprocess
      env: {'VAR': 'VALUE'}
      // ... and all other subprocess options described here
      // https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
    },
    on: function(ps) {
      ps.stdout.on('data', function(data) {});
      setTimeout(function() {
        ps.kill()
      }.bind(ps), 50000);
    }
  }
};
sudo.exec('echo hello', options, function(error) {});

Tests

npm i && npm test

Usage with Webpack

Webpack config should contain __dirname equals true for work properly

let nodeModules = fs.readdirSync('./node_modules')
    .filter((module) => {
        return module !== '.bin';
    })
    .reduce((prev, module) => {
        return Object.assign(prev, {[module]: 'commonjs ' + module});
    }, {});

export default {
    ...
    target: 'electron',
    node: {
        /* http://webpack.github.io/docs/configuration.html#node */
        __dirname: true
    },
    externals: nodeModules
};

electron-sudo's People

Contributors

automation-stack avatar cgalvarez avatar comee avatar creeperyang avatar ecomrobotics avatar facekapow avatar gitter-badger avatar jorangreef avatar kyo-ago avatar peakwinter avatar sbekrin avatar winhowes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

electron-sudo's Issues

Honor the MIT license

electron-sudo is a heavily refactored fork of sudo-prompt and still retains several portions of copyrighted content copied verbatim from there.

electron-sudo used to include the sudo-prompt license, but this has recently been removed, along with all reference to sudo-prompt.

I would appreciate it if you continue to honor the MIT license terms by at least including the sudo-prompt license in your project.

Command Failed on Windows

Hi,

I am trying to update the host files on windows PC (via electron app), statement is pretty straight-forward:

echo 127.0.0.1 mydev.test.com >> <hostFile> // which is correct location

After packing and running the app, it shows me: Command Failed: The system cannot find the path specified.C:\Users\...\AppData\Local\Temp\batch-0.<random_num>.bat.

Any idea why, it works well on unix. Its just windows.

Thank you! :)

_context25.sent.filter is not a function

I have something like following code.

      var sudo = new Sudoer.default({name: 'My App'});

        sudo.spawn("./runasroot.sh", []).then(function(inst) {
            inst.on('close', function(res) {
                console.log("ran successfully");
                next();  
            });
            //not tested..
            inst.on('error', function(err) {
                console.error("ran successfully");
            });
        })

When I run it, I get following error message

Unhandled rejection TypeError: _context25.sent.filter is not a function
    at SudoerLinux._callee25$ (/home/hayashis/git/kdinstaller2/node_modules/electron-sudo/dist/index.js:76:1705)
    at tryCatch (/home/hayashis/git/kdinstaller2/node_modules/regenerator-runtime/runtime.js:62:40)
    at GeneratorFunctionPrototype.invoke [as _invoke] (/home/hayashis/git/kdinstaller2/node_modules/regenerator-runtime/runtime.js:336:22)
    at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (/home/hayashis/git/kdinstaller2/node_modules/regenerator-runtime/runtime.js:95:21)
    at GeneratorFunctionPrototype.tryCatcher (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/util.js:26:23)
    at PromiseSpawn._next (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/generators.js:100:49)
    at Promise._settlePromiseAt (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/promise.js:582:21)
    at Promise._settlePromises (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/promise.js:700:14)
    at Async._drainQueue (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/async.js:123:16)
    at Async._drainQueues (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/async.js:133:10)
    at MutationObserver.Async.drainQueues (/home/hayashis/git/kdinstaller2/node_modules/bluebird/js/main/async.js:15:1

Passing the result of `fs.stat` to `child_process.spawn`

When I run the example in the README (without await) I get the following output:

/bin/sh: 1: [object: not found

ย 
The code in its entirety is:

import ElectronSudo from 'electron-sudo';

const options = {
  name: 'YOLO'
};
const sudo = new ElectronSudo(options);

let p = sudo.spawn(
  'echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}
).then( () => {
  p.on('close', () => {
    console.log('stderr:', p.output.stderr.toString());
  });
});

ย 

After poking around a little in the source code I found that the getBinary method of SudoerLinux returns the result from stat in src/lib/utils.js which is an fs.Stats object. This object is then passed directly to child_process.spawn which would explain the [object part of the error output.

Changing the getBinary method to return the path to the binary instead of the stat object seemed to fix it for me.

Am I using the library wrong?

feature request: fork call and IPC

sometimes we want to execute elevated JavaScript script instead of external process.
if there is something like child_process.fork() call, it will be great.

documents about node.js native fork and ipc:

https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options

note that spawn support IPC too, just specific it in stdio

https://nodejs.org/api/child_process.html#child_process_options_stdio

and in child process
https://nodejs.org/api/process.html#process_process_send_message_sendhandle_options_callback
https://nodejs.org/api/process.html#process_event_message

I've done something to simulate this ipc. it's ugly and not robust, but works for me.

it will break normal stdin/stdout since I'm using this to transfer messages. I don't know what does node.js native child_process ipc implement, maybe unixsock or named pipe?

here is my code:

import {remote} from "electron";

const Sudo = require('electron-sudo').default;

Sudo.prototype.fork = async function (modulePath, args, options) {
    let child = await this.spawn(remote.app.getPath('exe'), ['-e', modulePath].concat(args), options);
    readline.createInterface({input: child.stdout}).on('line', (line) => {
        child.emit('message', JSON.parse(line));
    });
    child.send = (message, sendHandle, options, callback)=> {
        child.stdin.write(JSON.stringify(message) + os.EOL);
        if (callback) {
            callback()
        }
    };
    return child
};

in index.js

function handleElevate() {
    if (process.argv[1] == '-e') {
        app.dock.hide();
        const os = require('os');
        const readline = require('readline');
        process.send = (message, sendHandle, options, callback)=> process.stdout.write(JSON.stringify(message) + os.EOL, callback);
        process.stdin.on('end', ()=> process.emit('disconnect'));
        readline.createInterface({input: process.stdin}).on('line', (line) => process.emit('message', JSON.parse(line)));
        require("./" + process.argv[2]);
        return true;
    }
}

if (handleElevate()) {
    return;
}

in my elevated module maotama.js, I'm using this to send raw-socket

const raw = require("raw-socket");
let socket = raw.createSocket({protocol: raw.Protocol.UDP});

let connect = (local_port, remote_port, remote_address)=> {
    let buffer = new Buffer(9);
    buffer.writeUInt16BE(local_port, 0);
    buffer.writeUInt16BE(remote_port, 2);
    buffer.writeUInt16BE(buffer.length, 4);
    socket.send(buffer, 0, buffer.length, remote_address, (error, bytes) => {
        if (error) {
            throw(error);
        }
    })
};

process.on('message', (message)=> {
    connect(...message.arguments);
});

process.on('disconnect', process.exit);

and calling

let child = await new Sudo({name: 'MyCard'}).fork('maotama')

child.send({
    action: 'connect',
    arguments: [app.network.port, port, address]
})

Path error resulted from webpack bundle

The lib report an error when I use webpack dev and bundle electron app:

Uncaught TypeError: Path must be a string. Received undefined

When I dive in, I found the error is with:

var source = Node.path.join(Node.path.dirname(module.filename), Node.process.platform, 'applet.app');

The module is generated by webpack and has no filename property.

Prompt is giving EISDIR error and Console is giving password required Error

Whenever I try to spawn a command with the sudoer, it gives me an error after I type my password that:
Error: EISDIR: illegal operation on a directory, open '/var/db/sudo/julianknodt'
at Error (native)

but it looks like it spawns the process. It's just frustrating that the error occurs even though it seems to work.

screen shot 2016-10-17 at 12 52 48 am

screen shot 2016-10-17 at 12 51 17 am

screen shot 2016-10-17 at 12 57 02 am

Edit:
Turns out when the child processes closes, it exits with status code 1, so the stdout is not getting anything from the process.

help needed: running a script

Hi!
first of all, thanks a lot for this cool package.
I've been struggling for the past hour over something that I thought would be pretty simple... running a script using electron sudo, rather than just a command.
All of my attempts not only do nothing but the callbacks returns this error:

Unhandled rejection TypeError: cp.output.stdout is not a function
at /Library/WebServer/Documents/Upwork/download_booster/boostum-electron/main.js:158:15
at tryCatcher (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/Library/WebServer/Documents/Upwork/download_booster/boostum-electron/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:789:20)
at tryOnImmediate (timers.js:751:5)
at processImmediate [as _immediateCallback] (timers.js:722:5)

Here's what I tried:

Os: macOS Sierra,
electron version: 2.0.2
electron-sudo version: 4.0.12

//startup code
var Sudoer = require('electron-sudo').default,
    sudo = new Sudoer({}),
    script_path = path.join(__dirname, "external", "shutdown.sh");
//I've also tried: script_path = path.join("external", "shutdown.sh");
//these were some of my attempts. I probably tried a couple others, but can't remember them right now
sudo.spawn('sh', ['$PARAM'], {env: {PARAM: script_path}})
    .then(function (cp) {                                                       //I used the same callback for all of them
        cp.output.stdout (Buffer)                                          //I didn't write it here to keep is concise 
        cp.output.stderr (Buffer)
    });
sudo.spawn('sh', [script_path], {}).then(function (cp) {});
sudo.spawn('sh', [script_path]).then(function (cp) {});
sudo.spawn(script_path, [], {}).then(function (cp) {});

the prompt screen appears and then... nothing. The script is supposed to wait until there is content in a particular file and, when there is, shutdown my computer.
I checked several times after turning the system on and there is content.

I've run the script independently and it works. I'm not sure if it's relevant, but here it is, anyway...

while [  ! -s external/shutdown_commander.txt ]; do
  sleep 5
done
> external/shutdown_commander.txt
shutdown -h now

'Error: Command failed' in Mac and double Dialog

It seems to be related to the the -s flag on the sudo command.

I get an Error: Command failed:

Error: Command failed: /usr/bin/sudo -n -s security find-generic-password -D "AirPort network password" -wa WifiName

Without the -s flag it runs but I get first the Custom Dialog from electron-sudo and then one from the Native one.

Here is my code:

var sudo = require('electron-sudo');
var options = {
  name: 'Your application name',
  //icns: '/path/to/icns/file', // (optional, only for MacOS),
  process: {
    options: {
      // Can use custom environment variables for your privileged subprocess
      // env: {'VAR': 'VALUE'}
      // ... and all other subprocess options described here
      // https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
    },
    on: function(ps) {
      ps.stdout.on('data', function(data) {
        console.log(data);
      });
      setTimeout(function() {
        ps.kill()
      }.bind(ps), 50000);
    }
  }
};
sudo.exec('security find-generic-password -D "AirPort network password" -wa WifiName', options, function(error) {
  console.log(error);
});

I'm probably doing it wrong, apologies

Cannot find module `regenerator-runtime`

When trying to run an Electron app that uses this, it complains about not being able to find regenerator-runtime. Inspecting the code of dist/index.js reveals that this is true, regenerator-runtime is required but not depended upon.

Ok, that's fine, I just installed regenerator-runtime manually. Except, now it's throwing because it can't read Math from null. Once again, inspecting dist/index.js shows that it's trying to get Math from a window global. I'm trying to use electron-sudo in the main process, is this it only supposed to be used in the renderer process?

Windows cannot find...

Thanks for a great project! It works perfectly on OSX, but I can't make it work on windows 10:

screen shot 2016-04-05 at 02 03 32

Same thing happens for echo hello and any other program I'm trying to execute. Calling it directly via child_process.exec works just fine.

Use pkexec as first option instead of gksudo

gksudo is a dead project now....
pkexec shows a nice prompt (which is quite the opposite of what you're saying in the src files and the reason why i didn't create a PR)
pkexec
screenshot from 2017-02-14 01-32-53
gksudo
screenshot from 2017-02-14 01-34-13

Unexpected stderr from sudo command without corresponding error: sudo: a password is required

I'm attempting to run this library on OS X 10.9.5 via an Electron app and am immediately getting the error below without being prompted for my password:

Unexpected stderr from sudo command without corresponding error: sudo: a password is required

Yet it works fine on my MacBook running El Capitan. Any idea what would be causing this? The error message is rather cryptic. I'm able to run sudo from a terminal just fine. I'm just kind of stumped on the possible cause of the error.

Command fails in Ubuntu

This is the error I'm getting:

// Error in the console
{ Error: Command failed: [object Object] undefined ls ~/
/bin/sh: 1: [object: not found

    at ChildProcess.exithandler (child_process.js:282:12)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at maybeClose (internal/child_process.js:921:16)
    at Socket.stream.socket.on (internal/child_process.js:348:11)
    at emitOne (events.js:115:13)
    at Socket.emit (events.js:210:7)
    at Pipe._handle.close [as _onclose] (net.js:549:12)
  killed: false,
  code: 127,
  signal: null,
  cmd: '[object Object] undefined ls ~/' }
(node:31336) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: result is not defined
(node:31336) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

The relevant part is that the command received is literally [object Object] undefined ls ~/, when I'm passing ls ~/. No prompt ever appears.

Minimal example to reproduce:

// index.js in my code
const Sudoer = require('electron-sudo').default;

const options = {name: 'electron sudo application'};
const sudoer = new Sudoer(options);

(async () => {
  try {
    const result = await sudoer.exec('echo "Hello"', {env: {PARAM: 'VALUE'}});
    console.log(result);
  } catch (error) {
    console.log(error);
  }
})();

Digging deeper and into the minified code+correlating it with the unminified code, I added a couple of logs to debug it:

// utils.js lines 19 to 27 (added the console.log):
async function exec(cmd, options={}) {
    return new Promise((resolve, reject) => {
        console.log('COMMAND:', cmd);
        child.exec(cmd, options, (err, stdout, stderr) => {
            if (err) { return reject(err); }
            return resolve({stdout, stderr});
        });
    });
}

// Result: the wrong command as shown previously

Now the interesting part is here:

// sudoer.js lines 307 to 320:
            if (/gksudo/i.test(self.binary)) {
                flags = '--preserve-env --sudo-mode ' +
                    `--description="${self.escapeDoubleQuotes(self.options.name)}"`;
            } else if (/pkexec/i.test(self.binary)) {
                flags = '--disable-internal-agent';
            }
            console.log('BINARY:', self.binary, this.binary, flags);
            command = `${this.binary} ${flags} ${command}`;
            try {
                result = await exec(command, options);
                return resolve(result);
            } catch (err) {
                return reject(err);
            }

And this is the result in the console (note: split in 4 for legibility):

Binary: 

Stats {
  dev: 64513,
  mode: 35309,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: 4096,
  ino: 14812184,
  size: 23376,
  blocks: 48,
  atimeMs: 1525863957752.7988,
  mtimeMs: 1453072407000,
  ctimeMs: 1467329709774.2266,
  birthtimeMs: 1467329709774.2266,
  atime: 2018-05-09T11:05:57.753Z,
  mtime: 2016-01-17T23:13:27.000Z,
  ctime: 2016-06-30T23:35:09.774Z,
  birthtime: 2016-06-30T23:35:09.774Z }

Stats {
  dev: 64513,
  mode: 35309,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: 4096,
  ino: 14812184,
  size: 23376,
  blocks: 48,
  atimeMs: 1525863957752.7988,
  mtimeMs: 1453072407000,
  ctimeMs: 1467329709774.2266,
  birthtimeMs: 1467329709774.2266,
  atime: 2018-05-09T11:05:57.753Z,
  mtime: 2016-01-17T23:13:27.000Z,
  ctime: 2016-06-30T23:35:09.774Z,
  birthtime: 2016-06-30T23:35:09.774Z }

undefined

So, for some reason, instead of the path for sudo we are retrieving the STAT for that path as you can see in the getBinary():

    async getBinary() {
        return (await Promise.all(
            this.paths.map(async (path) => {
                try {
                    path = await stat(path);
                    return path;
                } catch (err) {
                    return null;
                }
            })
        )).filter((v) => v)[0];
    }

Instead of that, it should be changed to this:

    async getBinary() {
        return (await Promise.all(
            this.paths.map(async (path) => {
                try {
                    const exists = await stat(path);
                    return path;
                } catch (err) {
                    return null;
                }
            })
        )).filter((v) => v)[0];
    }

Cannot build with `npm i`

I cloned the repo and run npm i under the project dir. but i got

npm WARN deprecated [email protected]: WARNING: This project has been renamed to babel-plugin-module-resolver. Install babel-plugin-module-resolver for new features
npm WARN deprecated [email protected]: to-iso-string has been deprecated, use @segment/to-iso-string instead.
npm WARN deprecated [email protected]: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue

> [email protected] install /Users/tims/vpn/client/node_modules/electron-sudo/node_modules/fsevents
> node-pre-gyp install --fallback-to-build

[fsevents] Success: "/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/fsevents/lib/binding/Release/node-v48-darwin-x64/fse.node" is installed via remote

> [email protected] prepublish /Users/tims/vpn/client/node_modules/electron-sudo
> npm run test


> [email protected] test /Users/tims/vpn/client/node_modules/electron-sudo
> npm run build && node_modules/mocha/bin/mocha --compilers js:babel-core/register ./tests


> [email protected] build /Users/tims/vpn/client/node_modules/electron-sudo
> node_modules/webpack/bin/webpack.js --config ./webpack/config.babel.js

Executing additional scripts before exit
Hash: 1bc259f4ec85dc49dcc7
Version: webpack 1.14.0
Time: 74ms
                                                     Asset       Size  Chunks             Chunk Names
                                         bin/libgksu2.so.0    69.7 kB          [emitted]
                                                  index.js    2.36 kB       0  [emitted]  main
                                           bin/elevate.exe     108 kB          [emitted]
                                    bin/applet.app/LICENSE    1.08 kB          [emitted]
                           bin/applet.app/Contents/PkgInfo    8 bytes          [emitted]
                                     bin/libgksu2.so.0.0.2    69.7 kB          [emitted]
                                                bin/gksudo    28.2 kB          [emitted]
                        bin/applet.app/Contents/Info.plist  960 bytes          [emitted]
                      bin/applet.app/Contents/MacOS/applet      25 kB          [emitted]
             bin/applet.app/Contents/Resources/applet.rsrc  362 bytes          [emitted]
       bin/applet.app/Contents/Resources/Scripts/main.scpt  526 bytes          [emitted]
bin/applet.app/Contents/Resources/description.rtfd/TXT.rtf  102 bytes          [emitted]
             bin/applet.app/Contents/Resources/applet.icns    56.4 kB          [emitted]
   [0] multi main 28 bytes {0} [built]
    + 1 hidden modules

ERROR in index.js from UglifyJs
SyntaxError: Unexpected token: punc ({) [./src/index.js:1,0]
/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/file/index.js:600
      throw err;
      ^

SyntaxError: /Users/tims/vpn/client/node_modules/electron-sudo/dist/index.js: 'import' and 'export' may only appear at the top level (65:1)
  63 | /***/ function(module, exports) {
  64 |
> 65 | 	import {SudoerDarwin, SudoerWin32, SudoerLinux} from '~/lib/sudoer';
     | 	^
  66 |
  67 | 	export default (() => {
  68 | 	    let {platform} = process;
    at Parser.pp$5.raise (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:4246:13)
    at Parser.pp$1.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1745:16)
    at Parser.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5218:22)
    at Parser.pp$1.parseBlockBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2133:21)
    at Parser.pp$1.parseBlock (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2114:8)
    at Parser.pp$3.parseFunctionBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3998:22)
    at Parser.parseFunctionBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5205:20)
    at Parser.pp$1.parseFunction (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2251:8)
    at Parser.pp$3.parseFunctionExpression (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3596:17)
    at Parser.pp$3.parseExprAtom (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3558:19)
    at Parser.pp$3.parseExprSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3331:19)
    at Parser.pp$3.parseMaybeUnary (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3311:19)
    at Parser.pp$3.parseExprOps (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3241:19)
    at Parser.pp$3.parseMaybeConditional (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3218:19)
    at Parser.pp$3.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3181:19)
    at Parser.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5694:20)
    at Parser.pp$3.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:4101:16)
    at Parser.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5425:24)
    at Parser.pp$3.parseExprList (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:4089:20)
    at Parser.pp$3.parseExprAtom (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3550:28)
    at Parser.pp$3.parseExprSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3331:19)
    at Parser.pp$3.parseMaybeUnary (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3311:19)
    at Parser.pp$3.parseExprOps (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3241:19)
    at Parser.pp$3.parseMaybeConditional (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3218:19)
    at Parser.pp$3.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3181:19)
    at Parser.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5694:20)
    at Parser.pp$3.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:4101:16)
    at Parser.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5425:24)
    at Parser.pp$3.parseCallExpressionArguments (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3410:20)
    at Parser.pp$3.parseSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3370:31)
    at Parser.pp$3.parseExprSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3341:15)
    at Parser.pp$3.parseMaybeUnary (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3311:19)
    at Parser.pp$3.parseExprOps (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3241:19)
    at Parser.pp$3.parseMaybeConditional (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3218:19)
    at Parser.pp$3.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3181:19)
    at Parser.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5694:20)
    at Parser.pp$3.parseExpression (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3143:19)
    at Parser.pp$1.parseReturnStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1945:26)
    at Parser.pp$1.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1716:19)
    at Parser.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5218:22)
    at Parser.pp$1.parseBlockBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2133:21)
    at Parser.pp$1.parseBlock (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2114:8)
    at Parser.pp$3.parseFunctionBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3998:22)
    at Parser.parseFunctionBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5205:20)
    at Parser.pp$1.parseFunction (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2251:8)
    at Parser.pp$3.parseFunctionExpression (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3596:17)
    at Parser.pp$3.parseExprAtom (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3558:19)
    at Parser.pp$3.parseExprSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3331:19)
    at Parser.pp$3.parseMaybeUnary (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3311:19)
    at Parser.pp$3.parseExprOps (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3241:19)
    at Parser.pp$3.parseMaybeConditional (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3218:19)
    at Parser.pp$3.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3181:19)
    at Parser.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5694:20)
    at Parser.pp$3.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:4101:16)
    at Parser.parseExprListItem (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5425:24)
    at Parser.pp$3.parseCallExpressionArguments (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3410:20)
    at Parser.pp$3.parseSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3370:31)
    at Parser.pp$3.parseExprSubscripts (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3341:15)
    at Parser.pp$3.parseMaybeUnary (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3311:19)
    at Parser.pp$3.parseExprOps (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3241:19)
    at Parser.pp$3.parseMaybeConditional (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3218:19)
    at Parser.pp$3.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3181:19)
    at Parser.parseMaybeAssign (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5694:20)
    at Parser.pp$3.parseExpression (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:3143:19)
    at Parser.pp$1.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1774:19)
    at Parser.parseStatement (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:5218:22)
    at Parser.pp$1.parseBlockBody (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:2133:21)
    at Parser.pp$1.parseTopLevel (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1645:8)
    at Parser.parse (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:1537:17)
    at parse$1 (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babylon/lib/index.js:6466:37)
    at File.parse (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/file/index.js:527:15)
    at File.parseCode (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/file/index.js:612:20)
    at /Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/pipeline.js:49:12
    at File.wrap (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/file/index.js:574:16)
    at Pipeline.transform (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/transformation/pipeline.js:47:17)
    at Object.transformFileSync (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-core/lib/api/node.js:138:10)
    at compile (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-register/lib/node.js:118:20)
    at loader (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-register/lib/node.js:144:14)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/tims/vpn/client/node_modules/electron-sudo/tests/index.js:3:1)
    at Module._compile (module.js:570:32)
    at loader (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at /Users/tims/vpn/client/node_modules/electron-sudo/node_modules/mocha/lib/mocha.js:220:27
    at Array.forEach (native)
    at Mocha.loadFiles (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/mocha/lib/mocha.js:217:14)
    at Mocha.run (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/mocha/lib/mocha.js:469:10)
    at Object.<anonymous> (/Users/tims/vpn/client/node_modules/electron-sudo/node_modules/mocha/bin/_mocha:404:18)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

npm ERR! Darwin 15.4.0
npm ERR! argv "/usr/local/bin/node" "/Users/tims/vpn/client/node_modules/.bin/npm" "run" "test"
npm ERR! node v6.9.1
npm ERR! npm  v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] test: `npm run build && node_modules/mocha/bin/mocha --compilers js:babel-core/register ./tests`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test script 'npm run build && node_modules/mocha/bin/mocha --compilers js:babel-core/register ./tests'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the electron-sudo package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     npm run build && node_modules/mocha/bin/mocha --compilers js:babel-core/register ./tests
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs electron-sudo
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls electron-sudo
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/tims/vpn/client/node_modules/electron-sudo/npm-debug.log

npm ERR! Darwin 15.4.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "i"
npm ERR! node v6.9.1
npm ERR! npm  v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! [email protected] prepublish: `npm run test`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] prepublish script 'npm run test'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the electron-sudo package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     npm run test
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs electron-sudo
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls electron-sudo
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/tims/vpn/client/node_modules/electron-sudo/npm-debug.log

TypeError: Cannot call a class as a function

I have made simple lines of code:

Sudoer = require('electron-sudo').default;

var sudo = Sudoer({name: 'test'});
var result = sudo.spawn('dir').then(function (cp) {
    console.log(cp.output.stdout)
});

And this gave me that kind of error:

D:\Phantasy star\Mobi\Daniars_Project\Node\sudotest\node_modules\electron-sudo\dist\index.js:2
})})}));case 1:case"end":return t.stop()}},t,this)}));return function(e,n){return t.apply(this,arguments)}(),b=function(){var t=(0,p.coroutine)(f.default.mark(function t(e){var n,r;r
eturn f.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return n=u(w.default.stat),t.prev=1,t.next=4,n(e);case 4:return r=t.sent,t.abrupt("return",r);case 8:return t.prev
=8,t.t0=t.catch(1),t.abrupt("return",null);case 11:case"end":return t.stop()}},t,this,[[1,8]])}));return  function(e){return t.apply(this,arguments)}}(),x=n(60),w=r(x),m=n(119),_=r(m),
 g=u(w.default.open),k=u(w.default.mkdir),j=u(w.default.readFile),O=u(w.default.writeFile);e.readFile=j,e.writeFile=O,e.spawn=o,e.exec=y,e.mkdir=k,e.stat=b,e.open=g},function(t,e,n){t.
exports={default:n(76),__esModule:!0}},function(t,e,n){t.exports={default:n(78),__esModule:!0}},function(t,e,n){t.exports={default:n(79),__esModule:!0}},function(t,e,n){t.exports={def
ault:n(80),_

TypeError: Cannot call a class as a function
    at e.default (D:\Phantasy star\Mobi\Daniars_Project\Node\sudotest\node_modules\electron-sudo\dist\index.js:2:1208)
    at e (D:\Phantasy star\Mobi\Daniars_Project\Node\sudotest\node_modules\electron-sudo\dist\index.js:1:26433)
    at Object.<anonymous> (D:\Phantasy star\Mobi\Daniars_Project\Node\sudotest\main.js:6:12)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:425:7)
    at startup (bootstrap_node.js:146:9)
   at bootstrap_node.js:540:3

works with electron-builder

It can't run with electron-builder dist package
Image: Imgur

in fact, this executable is in
/Users/zh99998/mycard/dist/mac/MyCard.app/Contents/Resources/app.asar.unpacked/node_modules/electron-sudo/dist/bin

notice app.asar.unpacked
during packaging, it says:
node_modules/electron-sudo is not packed into asar archive - contains executable code
and then leaves it in app.asar.unpacked under Resources root.

further more, I can't code sign my package (it will automatically done with with electron-builder before)

Signing app (identity: Developer ID Application: XIAOCHI CHEN (ZNVDEVDRX3))
Error: Command failed: codesign --sign Developer ID Application: XIAOCHI CHEN (ZNVDEVDRX3) --force --keychain /var/folders/my/m6ynh3bn6tq06h7xr3js0z7r0000gn/T/electron-builder-eH2lUj/t-d16-0.keychain /Users/travis/build/mycard/mycard/dist/mac/MyCard.app/Contents/Resources/app.asar.unpacked/node_modules/electron-sudo/dist/bin/applet.app/Contents/MacOS/applet
/Users/travis/build/mycard/mycard/dist/mac/MyCard.app/Contents/Resources/app.asar.unpacked/node_modules/electron-sudo/dist/bin/applet.app/Contents/MacOS/applet: unsealed contents present in the bundle root

seems it caused by this executable file and maybe can solved by some manually codesign command call, but I googled it for several hours and can't get it work....
I can provide a apple developer certificate if it helps to debug.

about windows usage

I follow the usage (Version 4.0.*) , and I use [email protected] , my test.js is below:

var Sudoer = require('electron-sudo').default;
let options = {name: 'electron sudo application'};
var sudoer = new Sudoer(options);

sudoer.spawn('cmd.exe', ['echo', 'hello']).then(function (cp) {
cp.stdout.on('data', (msg) => {
console.log('Looks like we have a message on STDOUT');
console.log(err.toString('utf8'));
});

cp.stderr.on('data',(err) => {
console.log('Looks like we have a message on STDERR');
console.log(err.toString('utf8'));
});

cp.on('close',() => {
console.log('Processed Finished!');
});
});

But the result is:
err
err2

Please help me to point out What's wrong with my usage.
Thx

I found some relative issue #47, so closed.

bad touch

just got this error:

bad touch!
/Users/zh99998/mycard/node_modules/touch/bin/touch.js:28
      throw er
      ^

Error: EISDIR: illegal operation on a directory, open '/var/db/sudo/zh99998'
    at Error (native)

my code:

const sudo = new (System._nodeRequire('electron-sudo').default)({name: 'MyCard'});
grant_privilege() {

        sudo.spawn('echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}).then((child) => {
            console.log('success', child);
        }).catch(reason=>console.log('error', reason))
    }

and I got a "success" and a child_process instance (with exit code=1 and stderr "sudo: a password is required" ).

/var/db/sudo/zh99998 is exists and it's a empty directory

macOS Sirra 10.12.1
npm 3.10.7
node v6.6.0

Version 4 example in ES5

Hello, I try to convert your example from ES6 to ES5, but it's not work.

import Sudoer from 'electron-sudo';

let options = {name: 'electron sudo application'},
    sudoer = new Sudoer(options);

/* Spawn subprocess behavior */
let cp = await sudoer.spawn(
  'echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}
);
cp.on('close', () => {
  /*
    cp.output.stdout (Buffer)
    cp.output.stderr (Buffer)
  */
});

/* Exec subprocess behavior */
let result = await sudoer.exec(
  'echo $PARAM', {env: {PARAM: 'VALUE'}}
);
/* result is Buffer with mixed (both stdout

And I tried with Vanila JS also

  var Sudoer = require('electron-sudo').default;
  let options = {name: 'electron sudo application'};
  var sudoer = new Sudoer(options);
  sudoer.spawn('echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}).then(function (cp) {

      cp.output.stdout (Buffer)
      cp.output.stderr (Buffer)

  });

But got error Unhandled rejection TypeError: cp.output.stdout is not a function

Thanks

Module Not-found when build release version

I use electron-sudo to my project, it work fine when start app on dev with command npm start.
But when I use npm run release to build release version (OSX) DMG file, when open app (after install) have error: Module electron-sudo not found. Another module was work fine.
Please support me, thank so much!

Error message not corresponding to real error

Here inside the linuxExecute function, the launched error message (User did not grant permission) may has nothing to do with the real error.

I'm using electron-sudo to request user permissions before installing a .deb package. Due to some errors from mine, when trying to execute the command "/usr/bin/pkexec" --disable-internal-agent dpkg -i /tmp/app.deb, I was getting always that error message, but the real error was that the .deb package was corrupt, so dpkg was failing. This was driving me crazy for a long time.

I think it's better to simply use something like error = new Error(error.message || error);.

I can make a pull request if you find this reasonable enough (I do!!).

Problem (+ solution) when signing electron app using electron-sudo

I've had problems when signing my electron app for distribution in macOS. App signing and distribution is still a new world to me, so I will try my best to explain what was happening and how I fixed it.

I was using electron-builder to build my app for macOS. electron-builder needs to pack the app as an .asar file, files inside the .asar package are not a problem. The thing is it needs to smartUnpack folders in the project that have binaries in them in order for them to work. That means, getting those files outside the .asar package and placing them in other folder. node_modules/electron-sudo happen to be a folder that needs to be unpacked because it contains binaries.

Now, electron-builder goes ahead and tries to codesign everything that's outside the .asar file, and encounters with node_modules/electron-sudo/dist/bin/applet.app/Contents/MacOS/applet and node_modules/electron-sudo/dist/src/bin/applet.app/Contents/MacOS/applet and tries to codesign them, and throws the following error: myApp.app/Contents/Resources/app.asar.unpacked/node_modules/electron-sudo/dist/bin/applet.app/Contents/MacOS/applet: unsealed contents present in the bundle root.

After a little bit of research, I found that codesign does not like at all any files in the same folder level as the Contents folder. Aaaand that's where LICENSE lives. Tried to place LICENSE inside Contents, got the following error: myApp.app/Contents/Resources/app.asar.unpacked/node_modules/electron-sudo/dist/bin/applet.app/Contents/MacOS/applet: code object is not signed at all.

And the only thing that worked was removing both LICENSE files, after that electron-builder and codesign worked as expected.


TL;DR: the LICENSE files under dist/bin/applet.app and dist/src/bin/applet.app cause errors when trying to sign an app that uses electron-sudo as a dependency, please consider removing both files.

End process

Is it possible to end the spawned process?

Cannot find module 'regenerator-runtime'

I use Sudoer with Vanila JS, but it will report error Cannot find module 'regenerator-runtime', when I install this package, it running normal.

I find in dist/index.js, require("regenerator-runtime") in secod line.

The "file" argument must be of type string. Received type object

    sudoer.spawn(
        'resolvconf -u'
    )
        .catch(err => {
            console.error(err);
        });

Throws this error

TypeError [ERR_INVALID_ARG_TYPE]: The "file" argument must be of type string. Received type object
    at validateString (internal/validators.js:112:11)
    at normalizeSpawnArguments (child_process.js:407:3)
    at Object.spawn (child_process.js:543:16)

Using

    sudoer.spawn(
        'resolvconf', ['-u']
    )
        .catch(err => {
            console.error(err);
        });

does not solve the problem ๐Ÿ›

Path must be a string error

Hello there. Thanks for the package!

I'm running into an issue when I package my electron application where this error shows:
image

The prompt works fine in dev mode but when packaging this Path error shows.

Any ideas what could be going on here?

Thanks

DEP0005: Buffer() constructor

The Buffer() function and new Buffer() constructor are deprecated due to API usability issues that can potentially lead to accidental security issues.

Support for spawn

Instead of exec, some people (including me) would like to use spawn. Can you please add support for spawn too?

Thanks for the nice project! โœจ

Sudo: no tty present

Hi @automation-stack,

I am having the following error:

sudo: no tty present and no askpass program specified
a password is required

Image of Yaktocat

Can you please guide me ?

Thank you.

Usage without transpiler and or es7 support

So I got it working like this, but is this even supported or did I hack something togheter? :)
I'm not really into this new stuff..
If it's ok to do it like that maybe add it to the docs?

var Sudoer = require('electron-sudo');
var sudoer = new Sudoer.default(options);
sudoer.spawn('sh path/to/script.sh' , ['arg1']).then(function (data) {
    data.on('close', function (res) {
        data.output.stdout && console.log('output: ', data.output.stdout.toString('utf8'));
        data.output.stderr && console.log('error: ', data.output.stderr.toString('utf8'));
    });
});

[question] How to kill spawned process

Consider this code snippet:

const sudoReqest = sudoer.spawn('npm', [ 'run-script', someScript ], { cwd: somePath });

sudoReqest.then(childProcess => {
    /* ... */

    process.kill(-childProcess.pid, 'SIGTERM');
});

Since sudoer.spawn spawns new process under root, above code will cause EPERM error.
So, is it possible to kill that process without re-prompting password?

sudo: a password is required

Running example code doesn't work

index.js

var Sudoer = require('electron-sudo').default;

var options = {name: 'electron sudo application'};
var sudoer = new Sudoer(options);

sudoer.spawn(
  'echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}
)
.then(cp => {
  cp.on('close', () => {
    console.log(cp.output.stdout.toString())
    console.log(cp.output.stderr.toString())
  });
})

output

$ node index.js

sudo: a password is required

Would appreciate it if someone can point me in the right direction.

Thanks!

electron-sudo fails to copy applet.app to tmp directory on macOS

Full error:

Unhandled rejection Error: Command failed: /bin/cp -R -p "src/bin/applet.app" "..."
cp: src/bin/applet.app: No such file or directory

    at ChildProcess.exithandler (child_process.js:214:12)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:852:16)
    at Socket.<anonymous> (internal/child_process.js:323:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:492:12)

I guess this happens because of non-absolute path to applet.app executable.

Error Uncaught Exception: TypeError: Sudoer is not a constructor

I use example code on Electron main thread but get back error
Uncaught Exception: TypeError: Sudoer is not a constructor

const {Sudoer} = require('electron-sudo')

let options = {name: 'electron sudo application'},
    sudoer = new Sudoer(options);

/* Spawn subprocess behavior */
let cp = await sudoer.spawn(
  'echo', ['$PARAM'], {env: {PARAM: 'VALUE'}}
);
cp.on('close', () => {
  /*
    cp.output.stdout (Buffer)
    cp.output.stderr (Buffer)
  */
});

Please help figure out where is problem. thanks

How to read & update source

[edit] At first I was confused about how to see what was happening in each platform-specific binary. After some poking, I see the "binaries" are stupidly simple.

Feel like it's worth a short section describing how to edit/update those that are in immediately unreadable formats.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.