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) (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: - Run Chrome without application cache:
chrome --disable-application-cache chrome --disable-application-cache

View File

@ -1,93 +1,88 @@
define([ define([
"jquery", "jquery",
"constants", "constants",
"core", "core",
"logger", "logger",
"eventMgr", "eventMgr",
"settings", "settings",
"classes/AsyncTask" "classes/AsyncTask"
], function($, constants, core, logger, eventMgr, settings, AsyncTask) { ], function($, constants, core, logger, eventMgr, settings, AsyncTask) {
var sshHelper = {}; var sshHelper = {};
// Listen to offline status changes // Listen to offline status changes
var isOffline = false; var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) { eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam; isOffline = isOfflineParam;
}); });
// Only used to check the offline status // Only used to check the offline status
function connect(task) { function connect(task) {
task.onRun(function() { task.onRun(function() {
if(isOffline === true) { if(isOffline === true) {
task.error(new Error("Operation not available in offline mode.|stopPublish")); return task.error(new Error("Operation not available in offline mode.|stopPublish"));
return; }
} task.chain();
task.chain(); });
}); }
}
sshHelper.upload = function(host, port, username, password, path, title, content, callback) { sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
var task = new AsyncTask(); var task = new AsyncTask();
connect(task); connect(task);
task.onRun(function() { task.onRun(function() {
var url = settings.sshProxy + "upload"; var url = constants.SSH_PUBLISH_URL + '?' + $.param({
var data = { host: host,
host: host, port: port,
port: port, username: username,
username: username, password: password,
password: password, path: path,
path: path, title: title
title: title, });
content: content $.ajax({
}; url: url,
$.ajax({ data: content,
url: url, type: "POST",
data: data, timeout: constants.AJAX_TIMEOUT
type: "POST", }).done(function(response) {
dataType: "json", if(response.error === undefined) {
timeout: constants.AJAX_TIMEOUT return task.chain();
}).done(function(response) { }
if(response.error === undefined) { handleError(response.error, task);
task.chain(); }).fail(function(jqXHR) {
return; var error = {
} code: jqXHR.status,
handleError(response.error, task); message: jqXHR.statusText
}).fail(function(jqXHR) { };
var error = { handleError(error, task);
code: jqXHR.status, });
message: jqXHR.statusText });
}; task.onSuccess(function() {
handleError(error, task); callback();
}); });
}); task.onError(function(error) {
task.onSuccess(function() { callback(error);
callback(); });
}); task.enqueue();
task.onError(function(error) { };
callback(error);
});
task.enqueue();
};
function handleError(error, task) { function handleError(error, task) {
var errorMsg; var errorMsg;
if(error) { if(error) {
logger.error(error); logger.error(error);
// Try to analyze the error // Try to analyze the error
if(typeof error === "string") { if(typeof error === "string") {
errorMsg = "SSH error: " + error + "."; errorMsg = "SSH error: " + error + ".";
} }
else { else {
errorMsg = "Could not publish on SSH server."; errorMsg = "Could not publish on SSH server.";
if(error.code <= 0) { if(error.code <= 0) {
core.setOffline(); core.setOffline();
errorMsg = "|stopPublish"; errorMsg = "|stopPublish";
} }
} }
} }
task.error(new Error(errorMsg)); 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> <label class="col-sm-4 control-label" for="input-publish-ssh-host">Host</label>
<div class="col-sm-7"> <div class="col-sm-7">
<input type="text" id="input-publish-ssh-host" <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, class="help-block"> Host must be accessible publicly,
unless you are hosting your own <a target="_blank" unless you're hosting your own StackEdit instance.
href="https://github.com/benweet/stackedit-ssh-proxy">SSH
proxy</a>.
</span> </span>
</div> </div>
</div> </div>
@ -1310,7 +1308,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>This feature is restricted to sponsor users as it's a web service hosted on Amazon EC2. <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> <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> <blockquote><b>Tip:</b> PDFs are fully customizable via Settings>Advanced>PDF template/options.</blockquote>
</div> </div>

View File

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