Skip to content

Commit f2505db

Browse files
committed
fix(local-process): error if content folder owned by other user
closes TryGhost#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
1 parent 509aa5a commit f2505db

File tree

2 files changed

+408
-7
lines changed

2 files changed

+408
-7
lines changed

lib/utils/local-process.js

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
const fs = require('fs-extra');
3+
const os = require('os');
34
const path = require('path');
45
const fkill = require('fkill');
56
const spawn = require('child_process').spawn;
@@ -28,6 +29,14 @@ class LocalProcess extends ProcessManager {
2829
* @public
2930
*/
3031
start(cwd, environment) {
32+
const stat = fs.lstatSync(path.join(cwd, 'content'));
33+
34+
// Check that content folder is owned by the current user
35+
if (stat.uid !== process.getuid()) {
36+
return Promise.reject(new errors.SystemError(`The content folder is not owned by the current user.
37+
Please ensure the content folder has correct permissions and try again.`));
38+
}
39+
3140
return new Promise((resolve, reject) => {
3241
const cp = spawn('node', [process.argv[1] , 'run'], {
3342
cwd: cwd,
@@ -39,7 +48,12 @@ class LocalProcess extends ProcessManager {
3948
// Stick the pid into the pidfile so we can stop the process later
4049
fs.writeFileSync(path.join(cwd, PID_FILE), cp.pid);
4150

42-
cp.on('error', reject);
51+
cp.on('error', (error) => {
52+
reject(new errors.CliError({
53+
message: 'An error occurred while starting Ghost.',
54+
err: error
55+
}));
56+
});
4357

4458
cp.on('exit', (code) => {
4559
fs.removeSync(path.join(cwd, PID_FILE));
@@ -50,8 +64,7 @@ class LocalProcess extends ProcessManager {
5064
cp.on('message', (msg) => {
5165
if (msg.error) {
5266
fs.removeSync(path.join(cwd, PID_FILE));
53-
54-
return reject(new errors.GhostError(msg));
67+
return reject(new errors.GhostError(msg.error));
5568
}
5669

5770
if (msg.started) {
@@ -80,18 +93,24 @@ class LocalProcess extends ProcessManager {
8093
} catch (e) {
8194
if (e.code === 'ENOENT') {
8295
// pid was not found, exit
83-
return;
96+
return Promise.resolve();
8497
}
8598

86-
throw e;
99+
return Promise.reject(new errors.CliError({
100+
message: 'An unexpected error occurred when reading the pidfile.',
101+
error: e
102+
}));
87103
}
88104

89-
const isWindows = process.platform === 'win32';
105+
const isWindows = os.platform() === 'win32';
90106

91107
return fkill(pid, {force: isWindows}).catch((error) => {
92108
// TODO: verify windows outputs same error message as mac/linux
93109
if (!error.message.match(/No such process/)) {
94-
throw error;
110+
return Promise.reject(new errors.CliError({
111+
message: 'An unexpected error occurred while stopping Ghost.',
112+
err: error
113+
}));
95114
}
96115
}).then(() => {
97116
fs.removeSync(path.join(cwd, PID_FILE));

0 commit comments

Comments
 (0)