Skip to content

Commit

Permalink
fix(local-process): error if content folder owned by other user
Browse files Browse the repository at this point in the history
closes #501
- if the content folder is owned by a separate user, the local process manager will fail
- improve local process manager errors
- add local process manager tests
  • Loading branch information
acburdine committed Feb 3, 2018
1 parent 3db21d6 commit 707ce6a
Show file tree
Hide file tree
Showing 2 changed files with 418 additions and 9 deletions.
50 changes: 41 additions & 9 deletions lib/utils/local-process.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';
const fs = require('fs-extra');
const os = require('os');
const path = require('path');
const fkill = require('fkill');
const spawn = require('child_process').spawn;
const childProcess = require('child_process');
const isRunning = require('is-running');

const errors = require('../errors');
Expand All @@ -28,8 +29,14 @@ class LocalProcess extends ProcessManager {
* @public
*/
start(cwd, environment) {
// Check that content folder is owned by the current user
if (!this._checkContentFolder(cwd)) {
return Promise.reject(new errors.SystemError(`The content folder is not owned by the current user.
Please ensure the content folder has correct permissions and try again.`));
}

return new Promise((resolve, reject) => {
const cp = spawn('node', [process.argv[1] , 'run'], {
const cp = childProcess.spawn('node', [process.argv[1] , 'run'], {
cwd: cwd,
detached: true,
stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
Expand All @@ -39,7 +46,12 @@ class LocalProcess extends ProcessManager {
// Stick the pid into the pidfile so we can stop the process later
fs.writeFileSync(path.join(cwd, PID_FILE), cp.pid);

cp.on('error', reject);
cp.on('error', (error) => {
reject(new errors.CliError({
message: 'An error occurred while starting Ghost.',
err: error
}));
});

cp.on('exit', (code) => {
fs.removeSync(path.join(cwd, PID_FILE));
Expand All @@ -50,8 +62,7 @@ class LocalProcess extends ProcessManager {
cp.on('message', (msg) => {
if (msg.error) {
fs.removeSync(path.join(cwd, PID_FILE));

return reject(new errors.GhostError(msg));
return reject(new errors.GhostError(msg.error));
}

if (msg.started) {
Expand Down Expand Up @@ -80,18 +91,24 @@ class LocalProcess extends ProcessManager {
} catch (e) {
if (e.code === 'ENOENT') {
// pid was not found, exit
return;
return Promise.resolve();
}

throw e;
return Promise.reject(new errors.CliError({
message: 'An unexpected error occurred when reading the pidfile.',
error: e
}));
}

const isWindows = process.platform === 'win32';
const isWindows = os.platform() === 'win32';

return fkill(pid, {force: isWindows}).catch((error) => {
// TODO: verify windows outputs same error message as mac/linux
if (!error.message.match(/No such process/)) {
throw error;
return Promise.reject(new errors.CliError({
message: 'An unexpected error occurred while stopping Ghost.',
err: error
}));
}
}).then(() => {
fs.removeSync(path.join(cwd, PID_FILE));
Expand Down Expand Up @@ -151,6 +168,21 @@ class LocalProcess extends ProcessManager {
return running;
}

/**
* Check that the content folder is owned by the current user
*
* @param {String} cwd current working directory
* @return {Boolean} true if ownership is correct, otherwise false
*/
_checkContentFolder(cwd) {
if (os.platform() === 'win32') {
return true;
}

const stat = fs.lstatSync(path.join(cwd, 'content'));
return stat.uid === process.getuid();
}

/**
* Because this process manager should work on every system,
* just return true here
Expand Down
Loading

0 comments on commit 707ce6a

Please sign in to comment.