Integrated stackedit-ssh-proxy service

This commit is contained in:
benweet 2014-08-20 00:25:22 +01:00
parent 3952ab6af1
commit d1b0b86fbe
5 changed files with 144 additions and 92 deletions

62
app/ssh.js Normal file
View File

@ -0,0 +1,62 @@
var ssh2 = require('ssh2');
exports.publish = function(req, res) {
var done;
function sendResult(result) {
if(!done) {
res.json(result);
}
done = true;
}
function sendError(error) {
sendResult({error: error});
}
var conn = new ssh2();
conn.on('ready', function() {
conn.sftp(function(err, sftp) {
if(err) {
return sendError('Unable to establish SFTP connection');
}
var writeStream = sftp.createWriteStream(req.query.path);
writeStream.on('close', function() {
sftp.end();
conn.end();
});
writeStream.on('error', function() {
sendError('Unable to write "' + req.query.path + '"');
sftp.end();
conn.end();
});
req.pipe(writeStream);
});
});
conn.on('error', function(err) {
if(err.level == "authentication") {
return sendError('Authentication failure');
}
if(err.code == "ENOTFOUND") {
return sendError('Host not found');
}
if(err.code == "ETIMEDOUT") {
return sendError('Connection timeout');
}
sendError(err);
});
conn.on('end', function() {
sendResult({});
});
conn.connect({
host: req.query.host,
port: req.query.port || 22,
username: req.query.username,
password: req.query.password
});
};

View File

@ -25,8 +25,6 @@ Getting started
(export PORT=80 && node server.js)
> **NOTE:** StackEdit project itself has no back end. It can run on any apache server.
- Run Chrome without application cache:
chrome --disable-application-cache

View File

@ -1,93 +1,88 @@
define([
"jquery",
"constants",
"core",
"logger",
"eventMgr",
"settings",
"classes/AsyncTask"
"jquery",
"constants",
"core",
"logger",
"eventMgr",
"settings",
"classes/AsyncTask"
], function($, constants, core, logger, eventMgr, settings, AsyncTask) {
var sshHelper = {};
var sshHelper = {};
// Listen to offline status changes
var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam;
});
// Listen to offline status changes
var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam;
});
// Only used to check the offline status
function connect(task) {
task.onRun(function() {
if(isOffline === true) {
task.error(new Error("Operation not available in offline mode.|stopPublish"));
return;
}
task.chain();
});
}
// Only used to check the offline status
function connect(task) {
task.onRun(function() {
if(isOffline === true) {
return task.error(new Error("Operation not available in offline mode.|stopPublish"));
}
task.chain();
});
}
sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
var task = new AsyncTask();
connect(task);
task.onRun(function() {
var url = settings.sshProxy + "upload";
var data = {
host: host,
port: port,
username: username,
password: password,
path: path,
title: title,
content: content
};
$.ajax({
url: url,
data: data,
type: "POST",
dataType: "json",
timeout: constants.AJAX_TIMEOUT
}).done(function(response) {
if(response.error === undefined) {
task.chain();
return;
}
handleError(response.error, task);
}).fail(function(jqXHR) {
var error = {
code: jqXHR.status,
message: jqXHR.statusText
};
handleError(error, task);
});
});
task.onSuccess(function() {
callback();
});
task.onError(function(error) {
callback(error);
});
task.enqueue();
};
sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
var task = new AsyncTask();
connect(task);
task.onRun(function() {
var url = constants.SSH_PUBLISH_URL + '?' + $.param({
host: host,
port: port,
username: username,
password: password,
path: path,
title: title
});
$.ajax({
url: url,
data: content,
type: "POST",
timeout: constants.AJAX_TIMEOUT
}).done(function(response) {
if(response.error === undefined) {
return task.chain();
}
handleError(response.error, task);
}).fail(function(jqXHR) {
var error = {
code: jqXHR.status,
message: jqXHR.statusText
};
handleError(error, task);
});
});
task.onSuccess(function() {
callback();
});
task.onError(function(error) {
callback(error);
});
task.enqueue();
};
function handleError(error, task) {
var errorMsg;
if(error) {
logger.error(error);
// Try to analyze the error
if(typeof error === "string") {
errorMsg = "SSH error: " + error + ".";
}
else {
errorMsg = "Could not publish on SSH server.";
if(error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}
}
}
task.error(new Error(errorMsg));
}
function handleError(error, task) {
var errorMsg;
if(error) {
logger.error(error);
// Try to analyze the error
if(typeof error === "string") {
errorMsg = "SSH error: " + error + ".";
}
else {
errorMsg = "Could not publish on SSH server.";
if(error.code <= 0) {
core.setOffline();
errorMsg = "|stopPublish";
}
}
}
task.error(new Error(errorMsg));
}
return sshHelper;
return sshHelper;
});

View File

@ -590,11 +590,9 @@
<label class="col-sm-4 control-label" for="input-publish-ssh-host">Host</label>
<div class="col-sm-7">
<input type="text" id="input-publish-ssh-host"
placeholder="host.name.or.ip" class="form-control"> <span
placeholder="hostname.or.ip" class="form-control"> <span
class="help-block"> Host must be accessible publicly,
unless you are hosting your own <a target="_blank"
href="https://github.com/benweet/stackedit-ssh-proxy">SSH
proxy</a>.
unless you're hosting your own StackEdit instance.
</span>
</div>
</div>
@ -1310,7 +1308,7 @@
</div>
<div class="modal-body">
<p>This feature is restricted to sponsor users as it's a web service hosted on Amazon EC2.
Note that sponsoring StackEdit would cost you only <b>$5/year</b>.</p>
Note that sponsoring StackEdit would cost you only $5/year.</p>
<p>To see how a PDF looks like <a target="_blank" href="/Welcome%20document.pdf">click here</a>.</p>
<blockquote><b>Tip:</b> PDFs are fully customizable via Settings>Advanced>PDF template/options.</blockquote>
</div>

View File

@ -56,7 +56,6 @@ define([
' "pageSize": "A4"',
'}'
].join('\n'),
sshProxy: constants.SSH_PROXY_URL,
extensionSettings: {}
};