Compare commits
111 commits
update_set
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf90ab1c24 | ||
|
|
e66281996c | ||
|
|
71486a5054 | ||
|
|
4ba021507d | ||
|
|
192181b444 | ||
|
|
6eae151e02 | ||
|
|
0e8927ed1e | ||
|
|
4f926f571f | ||
|
|
0d5f143068 | ||
|
|
023b56b877 | ||
|
|
ef2fe8f080 | ||
|
|
4bf4796dda | ||
|
|
a45801528f | ||
|
|
bca81a3e59 | ||
|
|
cdee44ff92 | ||
|
|
4270790990 | ||
|
|
ab243a1946 | ||
|
|
f12471a144 | ||
|
|
72e39a0d61 | ||
|
|
e162c195e4 | ||
|
|
3f5a9daf1b | ||
|
|
275d391afe | ||
|
|
2b5dee5081 | ||
|
|
115c14fafb | ||
|
|
63647ff448 | ||
|
|
88477512cd | ||
|
|
ffac7e840c | ||
|
|
67e2f66d0b | ||
|
|
0aac8897f3 | ||
|
|
5c21a9d827 | ||
|
|
1c2097e76b | ||
|
|
0b34446083 | ||
|
|
14c2bd5578 | ||
|
|
de6fafa9ef | ||
|
|
71d095fbb9 | ||
|
|
eab1701259 | ||
|
|
17f123d461 | ||
|
|
a0fb85863c | ||
|
|
c750e7a3c6 | ||
|
|
1c8d83fc4d | ||
|
|
a5f15dd1c5 | ||
|
|
bb66c5fb87 | ||
|
|
8ed034c50c | ||
|
|
739cdad201 | ||
|
|
2a002742c9 | ||
|
|
34f35bc029 | ||
|
|
866cbb0b07 | ||
|
|
c9bee8c65a | ||
|
|
21a71ba103 | ||
|
|
97f3c5a523 | ||
|
|
f133dec99d | ||
|
|
5d2a693929 | ||
|
|
253e929717 | ||
|
|
7339e6caf9 | ||
|
|
ceca5008b2 | ||
|
|
b2b73e8556 | ||
|
|
008e44acaf | ||
|
|
6ae9e9bfc9 | ||
|
|
33be18de0d | ||
|
|
4cdbba68a8 | ||
|
|
a3f1c33eb2 | ||
|
|
2b2f45ea7d | ||
|
|
65efc495d9 | ||
|
|
4377e56e38 | ||
|
|
e68c3e6fad | ||
|
|
529d489b4f | ||
|
|
5291fa0b85 | ||
|
|
72f244304d | ||
|
|
7d906207a2 | ||
|
|
cd79c179cf | ||
|
|
47a7045e07 | ||
|
|
67e3aa4c85 | ||
|
|
beea098827 | ||
|
|
dc05c93b35 | ||
|
|
e542ed3f96 | ||
|
|
865d960e12 | ||
|
|
26e4c37b3e | ||
|
|
b965c171ba | ||
|
|
4b00a4671b | ||
|
|
e0d4bf0847 | ||
|
|
6a951bbd0e | ||
|
|
979e37c4c8 | ||
|
|
1502067f78 | ||
|
|
845d26a341 | ||
|
|
427536debb | ||
|
|
524b3b8401 | ||
|
|
8b324b62d4 | ||
|
|
ff39d5f5cb | ||
|
|
bee24d02be | ||
|
|
f229fcac1c | ||
|
|
ac35b34f35 | ||
|
|
94a9bee913 | ||
|
|
02c238b2b7 | ||
|
|
53084e290b | ||
|
|
f946db7e93 | ||
|
|
e9f9d4d88a | ||
|
|
d0accd7a86 | ||
|
|
935d333a7c | ||
|
|
31f1545311 | ||
|
|
9b2a272189 | ||
|
|
cbab5fdd15 | ||
|
|
62b453334f | ||
|
|
992983838b | ||
|
|
4d61650ef2 | ||
|
|
9aaa89ebb0 | ||
|
|
1d6aab4e8f | ||
|
|
78f052678c | ||
|
|
8eb4205245 | ||
|
|
b238f6e53a | ||
|
|
bc2caa435c | ||
|
|
ac39a871fb |
57 changed files with 4981 additions and 1840 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
repositories
|
repositories
|
||||||
users.db
|
database/webide_data_store
|
||||||
|
|
||||||
/editor.tar.gz
|
/editor.tar.gz
|
||||||
__MACOSX
|
__MACOSX
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- 0.8
|
- 4.8.2
|
||||||
- 0.6
|
|
||||||
|
|
|
||||||
91
README.md
91
README.md
|
|
@ -2,17 +2,24 @@ Adafruit webIDE
|
||||||
================
|
================
|
||||||
This is a simple editor designed to help learn the Raspberry Pi and Beaglebone components, and more. This editor is designed solely for use on your secure private network as of now.
|
This is a simple editor designed to help learn the Raspberry Pi and Beaglebone components, and more. This editor is designed solely for use on your secure private network as of now.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
This guidance and repo are deprecated and no longer supported.
|
||||||
|
It is here for historical purposes only
|
||||||
|
******************************************************************************
|
||||||
|
|
||||||
Debian Installation (Raspberry Pi and BeagleBone Black)
|
Debian Installation (Raspberry Pi and BeagleBone Black)
|
||||||
============
|
============
|
||||||
|
|
||||||
|
The WebIDE installer is currently targeting Debian Stretch (latest Raspbian) installations only.
|
||||||
|
|
||||||
On the Raspberry PI or BeagleBone Black (after expanding the file system):
|
On the Raspberry PI or BeagleBone Black (after expanding the file system):
|
||||||
|
|
||||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh
|
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/scripts/install.sh | sudo sh
|
||||||
|
|
||||||
Alternatively, you can install using the .deb file:
|
Alternatively, you can install using the .deb file:
|
||||||
|
|
||||||
curl -O http://adafruit-download.s3.amazonaws.com/adafruitwebide-0.3.8-Linux.deb
|
curl -O https://adafruit-download.s3.amazonaws.com/adafruitwebide-0.3.12-Linux.deb
|
||||||
sudo dpkg -i adafruitwebide-0.3.8-Linux.deb
|
sudo dpkg -i adafruitwebide-0.3.12-Linux.deb
|
||||||
sudo apt-get -f install
|
sudo apt-get -f install
|
||||||
|
|
||||||
Note: As part of the installation process, the 'webide' user is given access to sudo and sudoers,
|
Note: As part of the installation process, the 'webide' user is given access to sudo and sudoers,
|
||||||
|
|
@ -21,57 +28,24 @@ If you don't need these features, feel free to manually install the editor below
|
||||||
|
|
||||||
Note: This is also the default installation for any Debian or Ubuntu operating systems
|
Note: This is also the default installation for any Debian or Ubuntu operating systems
|
||||||
|
|
||||||
Angstrom Installation (BeagleBone Black)
|
Manual Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
On the Beaglebone (as the default root user), execute each line independently:
|
Follow along in the [installation script][1] and pick and choose
|
||||||
|
the components you'd like to install.
|
||||||
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
|
|
||||||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install-angstrom.sh | sh
|
|
||||||
|
|
||||||
Note: The curl -k command is used due to the Beaglebone not having the github SSL certificate in the default installation.
|
|
||||||
|
|
||||||
Note: If you've replaced the default operating system (Angstrom) with Debian or Ubuntu, use the Raspberry Pi installation instructions.
|
|
||||||
|
|
||||||
Manual Installation (without process monitor)
|
|
||||||
============
|
|
||||||
|
|
||||||
On the Raspberry PI:
|
|
||||||
|
|
||||||
sudo apt-get update && sudo apt-get -y install build-essential nodejs nodejs-legacy npm redis-server git
|
|
||||||
git clone git://github.com/adafruit/Adafruit-WebIDE.git
|
|
||||||
cd Adafruit-WebIDE
|
|
||||||
mkdir tmp
|
|
||||||
npm config set tmp tmp
|
|
||||||
npm install
|
|
||||||
editor config/config.js (change port 80 to your port of choice)
|
|
||||||
nodejs server.js
|
|
||||||
|
|
||||||
You can look at the install.sh script if you'd like a process monitor, and to install it
|
|
||||||
as a daemon.
|
|
||||||
|
|
||||||
Uninstallation
|
Uninstallation
|
||||||
============
|
============
|
||||||
|
|
||||||
Debian (Raspberry PI and BeagleBone Black):
|
Debian (Raspberry PI and BeagleBone Black):
|
||||||
|
|
||||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall.sh | sudo sh
|
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/scripts/uninstall.sh | sudo sh
|
||||||
|
|
||||||
Or if you installed with the .deb file:
|
|
||||||
|
|
||||||
sudo apt-get remove adafruitwebide
|
|
||||||
|
|
||||||
Angstrom (BeagleBone Black, as default root user):
|
|
||||||
|
|
||||||
curl -k https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall-angstrom.sh | sh
|
|
||||||
|
|
||||||
Manual Uninstallation
|
Manual Uninstallation
|
||||||
============
|
============
|
||||||
|
|
||||||
On the Raspberry PI or BeagleBone Black:
|
Follow along in the [uninstallation script][2] and pick and choose
|
||||||
|
the components you'd like to remove.
|
||||||
rm -r Adafruit-WebIDE
|
|
||||||
rm ~/.ssh/id_rsa_bitbucket*
|
|
||||||
|
|
||||||
Running the Editor
|
Running the Editor
|
||||||
============
|
============
|
||||||
|
|
@ -80,7 +54,7 @@ Using Firefox or Chrome (and likely any other webkit browser) on any computer in
|
||||||
|
|
||||||
Raspberry Pi:
|
Raspberry Pi:
|
||||||
|
|
||||||
http://raspberrypi.local
|
http://raspberrypi.local:8080
|
||||||
|
|
||||||
BeagleBone:
|
BeagleBone:
|
||||||
|
|
||||||
|
|
@ -91,35 +65,17 @@ Restart the Editor
|
||||||
|
|
||||||
If for any reason you need to restart the editor, you can execute the following commands in order
|
If for any reason you need to restart the editor, you can execute the following commands in order
|
||||||
|
|
||||||
sudo service adafruit-webide.sh stop
|
sudo systemctl restart adafruit-webide
|
||||||
sudo service adafruit-webide.sh start
|
sudo systemctl start adafruit-webide
|
||||||
|
|
||||||
Sudo is required to restart due to the editor running as the 'webide' user.
|
Sudo is required to restart due to the editor running as the 'webide' user.
|
||||||
|
|
||||||
Advanced Options
|
Status or Logs for the Editor
|
||||||
============
|
============
|
||||||
|
|
||||||
Offline Mode Installation:
|
sudo systemctl status adafruit-webide
|
||||||
|
|
||||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh -s - --offline
|
Logs are in syslog: /var/log/syslog
|
||||||
|
|
||||||
Note: Offline mode does not setup git in any way other than installing it. You'll want to git config your
|
|
||||||
email and name, and setup your ssh keys.
|
|
||||||
|
|
||||||
GitHub Mode Installation:
|
|
||||||
|
|
||||||
curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/install.sh | sudo sh -s - --github
|
|
||||||
|
|
||||||
Note: GitHub mode does not automatically create, and post an ssh key to your GitHub account. It requires
|
|
||||||
a bit more manual setup at this time.
|
|
||||||
|
|
||||||
Enable support for Makefiles (execute on the Pi in the terminal, post-installation):
|
|
||||||
|
|
||||||
redis-cli hmset editor:settings enable_make "on"
|
|
||||||
|
|
||||||
Disable:
|
|
||||||
|
|
||||||
redis-cli hmset editor:settings enable_make "off"
|
|
||||||
|
|
||||||
License
|
License
|
||||||
============
|
============
|
||||||
|
|
@ -130,3 +86,6 @@ http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
SCREENSHOTS
|
SCREENSHOTS
|
||||||
===========
|
===========
|
||||||

|

|
||||||
|
|
||||||
|
[1]: https://github.com/adafruit/Adafruit-WebIDE/blob/master/scripts/install.sh
|
||||||
|
[2]: https://github.com/adafruit/Adafruit-WebIDE/blob/master/scripts/uninstall.sh
|
||||||
|
|
|
||||||
BIN
bin/node_hf/node
BIN
bin/node_hf/node
Binary file not shown.
|
|
@ -1 +0,0 @@
|
||||||
node hardfloat v0.8.16
|
|
||||||
BIN
bin/node_sf/node
BIN
bin/node_sf/node
Binary file not shown.
|
|
@ -1 +0,0 @@
|
||||||
node softfloat v0.8.9
|
|
||||||
|
|
@ -7,10 +7,7 @@ project folder, so you can edit, and save them. If you ever need to start
|
||||||
over, just delete your copied project folder, and grab the
|
over, just delete your copied project folder, and grab the
|
||||||
Adafruit libraries again.
|
Adafruit libraries again.
|
||||||
|
|
||||||
We've also created a folder you can start putting your projects into. This
|
We've also created a folder you can start putting your projects into.
|
||||||
is a version-controlled repository stored in your Bitbucket account.
|
|
||||||
Whenever you create projects and files within this folder, they will be
|
|
||||||
versioned and saved at Bitbucket.
|
|
||||||
|
|
||||||
This file was pre-loaded in your projects folder, and is located in the
|
This file was pre-loaded in your projects folder, and is located in the
|
||||||
'my-pi-projects' link to the left.
|
'my-pi-projects' link to the left.
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,9 @@
|
||||||
//Change offline in /config.
|
//Change offline in /config.
|
||||||
//Change github in /config.
|
//Change github in /config.
|
||||||
exports.editor = {
|
exports.editor = {
|
||||||
"port": 80,
|
"port": 3000,
|
||||||
"version": "0.3.8",
|
"version": "0.8.0",
|
||||||
"version_url": "https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/version.txt",
|
"version_url": "https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/master/release/version.txt"
|
||||||
"offline": false,
|
|
||||||
"github": false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.adafruit = {
|
exports.adafruit = {
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,148 @@
|
||||||
var fs_helper = require('../helpers/fs_helper'),
|
var fs_helper = require('../helpers/fs_helper'),
|
||||||
|
winston = require('winston'),
|
||||||
|
editor_setup = require('../helpers/editor_setup'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
redis = require('redis'),
|
|
||||||
client = redis.createClient(),
|
|
||||||
git_helper = require('../helpers/git_helper'),
|
git_helper = require('../helpers/git_helper'),
|
||||||
|
updater = require('../helpers/updater'),
|
||||||
|
scheduler = require('../helpers/scheduler'),
|
||||||
|
debug_helper = require('../helpers/python/debug_helper'),
|
||||||
|
exec_helper = require('../helpers/exec_helper'),
|
||||||
|
scheduler = require('../helpers/scheduler'),
|
||||||
config = require('../config/config'),
|
config = require('../config/config'),
|
||||||
check = require('validator').check,
|
db = require('../models/webideModel'),
|
||||||
sanitize = require('validator').sanitize;
|
sanitize = require('validator');
|
||||||
|
|
||||||
|
var REPOSITORY_PATH = path.resolve(__dirname, "../repositories");
|
||||||
|
|
||||||
//Loads the editor
|
//Loads the editor
|
||||||
exports.index = function(req, res) {
|
exports.index = function(req, res) {
|
||||||
var shown_notification = false;
|
req.session.message = undefined;
|
||||||
client.get('editor:shown_notification', function(err, result) {
|
db.findOne({"type": "user"}, function(err, user) {
|
||||||
if (result) {
|
if (!user) {
|
||||||
shown_notification = result;
|
req.session.message = "Set your name and email prior to continuing to the editor.";
|
||||||
|
res.redirect('/setup');
|
||||||
} else {
|
} else {
|
||||||
client.set('editor:shown_notification', true);
|
res.render('editor/index', {profile: req.user, version: config.editor.version, shown_notification: false});
|
||||||
}
|
}
|
||||||
res.render('editor/index', {profile: req.user, version: config.editor.version, shown_notification: shown_notification});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.create_repository = function(req, res) {
|
exports.editor = function(ws, req) {
|
||||||
var repository_url = sanitize(req.body.repository_url).xss().trim();
|
config.editor_ws = ws;
|
||||||
var retain_remote = sanitize(req.body.retain_remote).xss().trim();
|
winston.debug('socket io connection completed');
|
||||||
|
|
||||||
git_helper.clone_update_remote_push(req.user, repository_url, retain_remote, function(err, status) {
|
function send_message(type, data) {
|
||||||
|
ws.send(JSON.stringify({type: type, data: data}));
|
||||||
|
}
|
||||||
|
|
||||||
|
//emit on first connection
|
||||||
|
send_message('cwd-init', {dirname: REPOSITORY_PATH});
|
||||||
|
scheduler.emit_scheduled_jobs(ws);
|
||||||
|
|
||||||
|
ws.on('message', function(msg) {
|
||||||
|
var message = JSON.parse(msg);
|
||||||
|
var type = message.type;
|
||||||
|
var data = message.data;
|
||||||
|
|
||||||
|
winston.debug("Editor action type: " + type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'self-check-request':
|
||||||
|
winston.debug('self-check-request');
|
||||||
|
editor_setup.health_check(ws);
|
||||||
|
break;
|
||||||
|
case 'git-delete':
|
||||||
|
git_helper.remove_commit_push(data.file, function(err, status) {
|
||||||
|
send_message('git-delete-complete', {err: err, status: status});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'git-pull':
|
||||||
|
var name = data.file ? data.file.name : "";
|
||||||
|
git_helper.pull(name, "origin", "master", function(err, status) {
|
||||||
|
send_message('git-pull-complete', {err: err, status: status});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'git-is-modified':
|
||||||
|
git_helper.is_modified(data.file, function(err, status) {
|
||||||
|
send_message('git-is-modified-complete', {is_modified: status});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'commit-file':
|
||||||
|
var commit_message = "";
|
||||||
|
|
||||||
|
if (data.message) {
|
||||||
|
commit_message = data.message;
|
||||||
|
} else {
|
||||||
|
commit_message = "Modified " + data.file.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_helper.commit_push_and_save(data.file, commit_message, function(err, status) {
|
||||||
|
send_message('commit-file-complete', {err: err, status: status});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'move-file':
|
||||||
|
git_helper.move_commit_push(data.file, function(err) {
|
||||||
|
console.log('move-file', err);
|
||||||
|
send_message('move-file-complete', {err: err});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'editor-check-updates':
|
||||||
|
// TODO: Explore adding auto-updater again
|
||||||
|
// updater.check_for_updates(ws);
|
||||||
|
break;
|
||||||
|
case 'editor-update':
|
||||||
|
updater.update(ws);
|
||||||
|
break;
|
||||||
|
case 'trace-file':
|
||||||
|
exec_helper.trace_program(data.file, ws);
|
||||||
|
break;
|
||||||
|
case 'debug-command':
|
||||||
|
debug_helper.debug_command(data, ws);
|
||||||
|
break;
|
||||||
|
case 'debug-file':
|
||||||
|
debug_helper.start_debug(data.file, ws);
|
||||||
|
break;
|
||||||
|
case 'commit-run-file':
|
||||||
|
exec_helper.execute_program(data.file, false);
|
||||||
|
git_helper.commit_push_and_save(data.file, "Modified " + data.file.name, function(err, status) {
|
||||||
|
send_message('commit-file-complete', {message: "Save was successful"});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'stop-script-execution':
|
||||||
|
exec_helper.stop_program(data.file, false);
|
||||||
|
break;
|
||||||
|
case 'submit-schedule':
|
||||||
|
scheduler.add_schedule(data, ws);
|
||||||
|
break;
|
||||||
|
case 'schedule-delete-job':
|
||||||
|
scheduler.delete_job(data, ws);
|
||||||
|
break;
|
||||||
|
case 'schedule-toggle-job':
|
||||||
|
scheduler.toggle_job(data, ws);
|
||||||
|
break;
|
||||||
|
case 'set-settings':
|
||||||
|
data["type"] = "editor:settings";
|
||||||
|
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||||
|
db.update({type: "editor:settings"}, Object.assign(settings || {}, data || {}), { upsert: true }, function(err) {
|
||||||
|
data["type"] = "editor:settings";
|
||||||
|
if (err) winston.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('disconnect', function() {
|
||||||
|
debug_helper.client_disconnect();
|
||||||
|
debug_helper.kill_debug();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.create_repository = function(req, res) {
|
||||||
|
var repository_url = sanitize.trim(req.body.repository_url);
|
||||||
|
|
||||||
|
git_helper.clone_update_remote_push(req.user, repository_url, function(err, status) {
|
||||||
if (err) res.send(err, 404);
|
if (err) res.send(err, 404);
|
||||||
else res.send(status, 200);
|
else res.send(status, 200);
|
||||||
});
|
});
|
||||||
|
|
@ -32,7 +150,7 @@ exports.create_repository = function(req, res) {
|
||||||
|
|
||||||
//Opens an image clicked from the editor navigator
|
//Opens an image clicked from the editor navigator
|
||||||
exports.image = function(req, res) {
|
exports.image = function(req, res) {
|
||||||
var temp_path = sanitize(req.query.path).xss().trim().replace('/filesystem/', '/repositories/');
|
var temp_path = sanitize(req.query.path).trim().replace('/filesystem/', '/repositories/');
|
||||||
//strip basic attempted path traversals
|
//strip basic attempted path traversals
|
||||||
temp_path = temp_path.replace('..', '');
|
temp_path = temp_path.replace('..', '');
|
||||||
|
|
||||||
|
|
@ -43,12 +161,14 @@ exports.image = function(req, res) {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.upload_file = function(req, res) {
|
exports.upload_file = function(req, res) {
|
||||||
console.log(req.files.files[0]);
|
console.log(req.file);
|
||||||
|
console.log(req.file.originalname);
|
||||||
|
console.log(req.file.path);
|
||||||
|
|
||||||
var temp_path = sanitize(req.files.files[0].path).xss().trim();
|
var temp_path = sanitize.trim(req.file.path);
|
||||||
var file_name = sanitize(req.files.files[0].name).xss().trim();
|
var file_name = sanitize.trim(req.file.originalname);
|
||||||
file_name = file_name.replace(" ", "_");
|
file_name = file_name.replace(" ", "_");
|
||||||
var folder_path = sanitize(req.body.path).xss().trim().replace('filesystem', 'repositories');
|
var folder_path = sanitize.trim(req.body.path).replace('filesystem', 'repositories');
|
||||||
|
|
||||||
var new_path = __dirname + '/..' + folder_path + file_name;
|
var new_path = __dirname + '/..' + folder_path + file_name;
|
||||||
new_path = path.resolve(new_path);
|
new_path = path.resolve(new_path);
|
||||||
|
|
@ -58,7 +178,7 @@ exports.upload_file = function(req, res) {
|
||||||
res.send(false, 200);
|
res.send(false, 200);
|
||||||
} else {
|
} else {
|
||||||
var comment = "Uploaded new File.";
|
var comment = "Uploaded new File.";
|
||||||
git_helper.commit_push_and_save({path: folder_path + file_name}, comment, null, function(err, status) {
|
git_helper.commit_push_and_save({path: folder_path + file_name}, comment, function(err, status) {
|
||||||
res.send(true, 200);
|
res.send(true, 200);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
var request_helper = require('../helpers/request_helper');
|
|
||||||
|
|
||||||
exports.index = function(req, res){
|
exports.index = function(req, res){
|
||||||
if (req.user) {
|
res.redirect('/editor');
|
||||||
res.redirect('/editor');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,68 +1,44 @@
|
||||||
var redis = require("redis"),
|
var path = require('path'),
|
||||||
client = redis.createClient(),
|
db = require('../models/webideModel'),
|
||||||
scripts_helper = require('../helpers/scripts_helper'),
|
scripts_helper = require('../helpers/scripts_helper'),
|
||||||
config = require('../config/config'),
|
config = require('../config/config'),
|
||||||
check = require('validator').check,
|
sanitize = require('validator');
|
||||||
sanitize = require('validator').sanitize;
|
|
||||||
|
|
||||||
exports.login = function(req, res){
|
// Instructional page that displays the setup steps
|
||||||
res.render('users/login', { title: 'test', user: req.user, github: config.editor.github });
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.logout = function(req, res){
|
|
||||||
req.logout();
|
|
||||||
res.redirect('/');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Instructional page that displays the bitbucket setup steps,
|
|
||||||
// and inputs for OAuth and Git config
|
|
||||||
exports.setup = function(req, res) {
|
exports.setup = function(req, res) {
|
||||||
var locals = {
|
var locals = {
|
||||||
consumer_key: "",
|
|
||||||
consumer_secret: "",
|
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
hostname: "",
|
hostname: ""
|
||||||
github: config.editor.github
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.render('users/setup', locals);
|
res.render('users/setup', locals);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Saves the bitbucket and git config setup information in Redis,
|
// Saves the git config setup information in nedb,
|
||||||
// submitted as a post from /setup
|
// submitted as a post from /setup
|
||||||
exports.submit_setup = function(req, res) {
|
exports.submit_setup = function(req, res) {
|
||||||
var key, secret, name, email, message;
|
var name, email, message;
|
||||||
req.session.message = undefined;
|
req.session.message = undefined;
|
||||||
|
|
||||||
function common_setup(name, email) {
|
function common_setup(name, email) {
|
||||||
client.hmset("user", "name", name, "email", email, function() {
|
db.update({"type": "user"}, {"type": "user", "name": name, "email": email}, { upsert: true }, function() {
|
||||||
req.session.message = "Settings Successfully Configured.";
|
req.session.message = "Settings Successfully Configured.";
|
||||||
res.redirect('/login');
|
res.redirect('/editor');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
key = sanitize(req.body.key).xss().trim();
|
name = sanitize.trim(req.body.name);
|
||||||
secret = sanitize(req.body.secret).xss().trim();
|
email = sanitize.trim(req.body.email);
|
||||||
name = sanitize(req.body.name).xss().trim();
|
sanitize.isEmail(email);
|
||||||
email = sanitize(req.body.email).xss().trim();
|
|
||||||
check(email).isEmail();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
req.session.message = e.message;
|
req.session.message = e.message;
|
||||||
console.log(e.message);
|
console.log(e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key && secret && name && email) {
|
if (name && email) {
|
||||||
if (config.editor.github) {
|
common_setup(name, email);
|
||||||
client.hmset("github_oauth", "consumer_key", key, "consumer_secret", secret, function() {
|
|
||||||
common_setup(name, email);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
client.hmset("bitbucket_oauth", "consumer_key", key, "consumer_secret", secret, function() {
|
|
||||||
common_setup(name, email);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!req.session.message) {
|
if (!req.session.message) {
|
||||||
req.session.message = "Please set all fields, at the bottom of this page, in order to continue.";
|
req.session.message = "Please set all fields, at the bottom of this page, in order to continue.";
|
||||||
|
|
@ -73,7 +49,7 @@ exports.submit_setup = function(req, res) {
|
||||||
|
|
||||||
|
|
||||||
exports.config = function(req, res) {
|
exports.config = function(req, res) {
|
||||||
client.hgetall('server', function (err, server) {
|
db.findOne({type: "server"}, function (err, server) {
|
||||||
var locals = {
|
var locals = {
|
||||||
hostname: "",
|
hostname: "",
|
||||||
wifi_ssid: "",
|
wifi_ssid: "",
|
||||||
|
|
@ -85,19 +61,19 @@ exports.config = function(req, res) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Saves the bitbucket and git config setup information in Redis,
|
// Saves the git config setup information in nedb,
|
||||||
// submitted as a post from /setup
|
// submitted as a post from /setup
|
||||||
|
|
||||||
//TODO: Refactor this...it's out of control!
|
//TODO: Refactor this...it's out of control!
|
||||||
exports.submit_config = function(req, res) {
|
exports.submit_config = function(req, res) {
|
||||||
var key, secret, name, email, message;
|
var name, email, message;
|
||||||
req.session.message = undefined;
|
req.session.message = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
hostname = sanitize(req.body.hostname).xss().trim();
|
hostname = sanitize.trim(req.body.hostname);
|
||||||
wifi_ssid = sanitize(req.body.wifi_ssid).xss().trim();
|
wifi_ssid = sanitize.trim(req.body.wifi_ssid);
|
||||||
wifi_password = sanitize(req.body.wifi_password).xss().trim();
|
wifi_password = sanitize.trim(req.body.wifi_password);
|
||||||
port = sanitize(req.body.port).xss().trim();
|
port = sanitize.trim(req.body.port);
|
||||||
if (hostname) {
|
if (hostname) {
|
||||||
check(hostname).len(3, 25);
|
check(hostname).len(3, 25);
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +95,8 @@ exports.submit_config = function(req, res) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (port) {
|
if (port) {
|
||||||
client.hmset("server", "port", port, function() {
|
db.update({type: "server"}, { $set: {"port": port}}, {}, function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
db/.gitignore
vendored
Normal file
4
db/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
||||||
0
error.log
Normal file
0
error.log
Normal file
|
|
@ -1,140 +1,70 @@
|
||||||
var exec = require('child_process').exec,
|
var path = require('path'),
|
||||||
fs = require ('fs'),
|
winston = require('winston'),
|
||||||
path = require('path'),
|
db = require('../models/webideModel'),
|
||||||
git_helper = require('./git_helper'),
|
exec = require('child_process').exec,
|
||||||
fs_helper = require('./fs_helper'),
|
fs = require ('fs'),
|
||||||
redis = require('redis'),
|
git_helper = require('./git_helper.js'),
|
||||||
client = redis.createClient(),
|
fs_helper = require('./fs_helper'),
|
||||||
request_helper = require('./request_helper'),
|
ws_helper = require('./websocket_helper'),
|
||||||
config = require('../config/config');
|
config = require('../config/config');
|
||||||
|
|
||||||
fs.exists || (fs.exists = path.exists);
|
fs.exists || (fs.exists = path.exists);
|
||||||
|
|
||||||
exports.setup_github = function(socket) {
|
exports.setup_adafruit_libraries = function(ws) {
|
||||||
git_helper.set_config(function() {
|
|
||||||
this.setup_adafruit_libraries(socket);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.setup_adafruit_libraries = function(socket) {
|
|
||||||
git_helper.clone_adafruit_libraries(config.adafruit.repository, config.adafruit.remote, function(cloned_libraries) {
|
git_helper.clone_adafruit_libraries(config.adafruit.repository, config.adafruit.remote, function(cloned_libraries) {
|
||||||
socket.emit("self-check-message", "Cloning remote Adafruit repository");
|
ws_helper.send_message(ws, "self-check-message", "Cloning remote Adafruit repository");
|
||||||
//cloned_libraries is false if they already existed...if false, let's pull the latest version of the adafruit libraries
|
//cloned_libraries is false if they already existed...if false, let's pull the latest version of the adafruit libraries
|
||||||
if (!cloned_libraries) {
|
if (!cloned_libraries) {
|
||||||
git_helper.pull(config.adafruit.repository, "origin", "master", function() {
|
git_helper.pull(config.adafruit.repository, "origin", "master", function() {
|
||||||
socket.emit("self-check-message", "Adafruit repository updated");
|
ws_helper.send_message(ws, "self-check-message", "Adafruit repository updated");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.offline_health_check = function(socket) {
|
exports.health_check = function(ws) {
|
||||||
client.hgetall('editor:settings', function(err, settings) {
|
//TODO redis to nedb
|
||||||
|
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||||
|
if (settings) {
|
||||||
|
settings.offline = true;
|
||||||
|
} else {
|
||||||
|
settings = {offline: true};
|
||||||
|
}
|
||||||
|
winston.debug("getting settings", settings);
|
||||||
|
ws_helper.send_message(ws, "self-check-settings", settings);
|
||||||
|
})
|
||||||
|
|
||||||
if (settings) {
|
this.setup_adafruit_libraries(ws);
|
||||||
settings.offline = true;
|
|
||||||
} else {
|
|
||||||
settings = {offline: true};
|
|
||||||
}
|
|
||||||
console.log("getting settings", settings);
|
|
||||||
socket.emit("self-check-settings", settings);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('self-check-complete');
|
|
||||||
socket.emit('self-check-complete');
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO this is a terrible mess..clean this up, no reason to have these big blocks of callbacks...uffda.
|
|
||||||
exports.health_check = function(socket, profile) {
|
|
||||||
var that = this;
|
|
||||||
console.log(config.editor.offline);
|
|
||||||
|
|
||||||
if (config.editor.github) {
|
|
||||||
this.setup_github(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.editor.offline || config.editor.github) {
|
|
||||||
this.offline_health_check(socket);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var project_repository = 'git@bitbucket.org:' + profile.username + '/my-pi-projects.git';
|
|
||||||
console.log(project_repository);
|
|
||||||
|
|
||||||
client.hgetall('editor:settings', function(err, settings) {
|
|
||||||
if (typeof settings === 'undefined' || !settings) {
|
|
||||||
settings = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("getting settings", settings);
|
|
||||||
socket.emit("self-check-settings", settings);
|
|
||||||
});
|
|
||||||
|
|
||||||
//check if the adafruit libraries exist, if not, clone them.
|
|
||||||
request_helper.post_ssh_key(profile, function(err, response) {
|
|
||||||
that.setup_adafruit_libraries(socket);
|
|
||||||
|
|
||||||
git_helper.set_config(function() {
|
git_helper.set_config(function() {
|
||||||
request_helper.list_repositories(profile, function(err, list) {
|
var my_repository = "my-pi-projects";
|
||||||
var exists = list.some(function(repository) {
|
fs_helper.check_for_repository(my_repository, function(err, exists) {
|
||||||
return (repository.name.toLowerCase() === config.defaults.repository.toLowerCase());
|
ws_helper.send_message(ws, "self-check-message", "Validated my-pi-projects");
|
||||||
});
|
winston.debug(exists);
|
||||||
|
if (exists) {
|
||||||
|
git_helper.pull(my_repository, "origin", "master", function(err, status) {
|
||||||
|
ws_helper.send_message(ws, "self-check-message", "Updated my-pi-projects");
|
||||||
|
ws_helper.send_message(ws, 'self-check-complete');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
git_helper.create_local_repository(my_repository, function(err, response) {
|
||||||
|
ws_helper.send_message(ws, "self-check-message", "Cloned my-pi-projects on local system");
|
||||||
|
fs_helper.create_project_gitignore(function(err, file) {
|
||||||
|
ws_helper.send_message(ws, "self-check-message", "Added .gitignore in my-pi-projects");
|
||||||
|
fs_helper.create_project_readme(function(err, file) {
|
||||||
|
ws_helper.send_message(ws, "self-check-message", "Added README.md in my-pi-projects");
|
||||||
|
winston.debug(file);
|
||||||
|
if (err) winston.error(err);
|
||||||
|
|
||||||
if (!exists) {
|
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", function(err, response) {
|
||||||
request_helper.create_repository(profile, config.defaults.repository, function(err, response) {
|
ws_helper.send_message(ws, "self-check-message", "Pushed changes to my-pi-projects");
|
||||||
socket.emit("self-check-message", "Created my-pi-projects in Bitbucket");
|
ws_helper.send_message(ws, 'self-check-complete');
|
||||||
|
|
||||||
git_helper.clone_repository(project_repository, function(err, response) {
|
|
||||||
socket.emit("self-check-message", "Cloned my-pi-projects on local system");
|
|
||||||
fs_helper.create_project_gitignore(function(err, file) {
|
|
||||||
socket.emit("self-check-message", "Added .gitignore in my-pi-projects");
|
|
||||||
fs_helper.create_project_readme(function(err, file) {
|
|
||||||
socket.emit("self-check-message", "Added README.md in my-pi-projects");
|
|
||||||
if (err) console.log(err);
|
|
||||||
console.log(file);
|
|
||||||
|
|
||||||
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", null, function(err, response) {
|
|
||||||
socket.emit("self-check-message", "Pushed changes to my-pi-projects to Bitbucket");
|
|
||||||
socket.emit('self-check-complete');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
//check if repository exists here
|
|
||||||
var my_repository = "my-pi-projects";
|
|
||||||
fs_helper.check_for_repository(my_repository, function(err, exists) {
|
|
||||||
socket.emit("self-check-message", "Validated my-pi-projects");
|
|
||||||
if (exists) {
|
|
||||||
git_helper.pull(my_repository, "origin", "master", function(err, status) {
|
|
||||||
socket.emit("self-check-message", "Updated my-pi-projects");
|
|
||||||
socket.emit('self-check-complete');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
git_helper.clone_repository(project_repository, function(err, response) {
|
|
||||||
socket.emit("self-check-message", "Cloned my-pi-projects on local system");
|
|
||||||
fs_helper.create_project_gitignore(function(err, file) {
|
|
||||||
socket.emit("self-check-message", "Added .gitignore in my-pi-projects");
|
|
||||||
fs_helper.create_project_readme(function(err, file) {
|
|
||||||
socket.emit("self-check-message", "Added README.md in my-pi-projects");
|
|
||||||
console.log(file);
|
|
||||||
if (err) console.log(err);
|
|
||||||
|
|
||||||
git_helper.commit_push_and_save(file, "Added README.md and .gitignore", null, function(err, response) {
|
|
||||||
socket.emit("self-check-message", "Pushed changes to my-pi-projects to Bitbucket");
|
|
||||||
socket.emit('self-check-complete');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
winston.debug("after everything");
|
||||||
}); // end of list repositories
|
});
|
||||||
}); //end of git set config
|
});
|
||||||
}); //end of post ssh key
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
var spawn = require('child_process').spawn,
|
var spawn = require('child_process').spawn,
|
||||||
|
ws_helper = require('./websocket_helper'),
|
||||||
//pty = require('pty.js'),
|
//pty = require('pty.js'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
ipython, spawn_list = [];
|
ipython, spawn_list = [];
|
||||||
|
|
@ -54,12 +55,12 @@ function execute_python_trace(file_path, socket) {
|
||||||
});
|
});
|
||||||
|
|
||||||
prog.stderr.on('data', function(data) {
|
prog.stderr.on('data', function(data) {
|
||||||
socket.emit('trace-program-stderr', {output: data.toString()});
|
ws_helper.send_message(socket, 'trace-program-stderr', {output: data.toString()});
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
prog.on('exit', function(code) {
|
prog.on('exit', function(code) {
|
||||||
socket.emit('trace-program-exit', {output: program_output});
|
ws_helper.send_message(socket, 'trace-program-exit', {output: program_output});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,16 +69,16 @@ function execute_python_trace(file_path, socket) {
|
||||||
ipython.removeAllListeners('data');
|
ipython.removeAllListeners('data');
|
||||||
require('../server').get_socket(file.username, function(socket) {
|
require('../server').get_socket(file.username, function(socket) {
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
socket.emit('scheduler-start', {file: file});
|
ws_helper.send_message(socket, 'scheduler-start', {file: file});
|
||||||
}
|
}
|
||||||
ipython.on('data', function(data) {
|
ipython.on('data', function(data) {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
//data = data.replace(/\[0;.*?In\s\[.*?\[0m/, '~-prompt-~');
|
//data = data.replace(/\[0;.*?In\s\[.*?\[0m/, '~-prompt-~');
|
||||||
//data = data.replace(/In\s\[.*?\]:/, '~-prompt-~');
|
//data = data.replace(/In\s\[.*?\]:/, '~-prompt-~');
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
socket.emit('scheduler-executing', {file: file});
|
ws_helper.send_message(socket, 'scheduler-executing', {file: file});
|
||||||
} else {
|
} else {
|
||||||
socket.emit('program-stdout', {output: data});
|
ws_helper.send_message(socket, 'program-stdout', {output: data});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -104,41 +105,39 @@ function execute_program(file, type, is_job) {
|
||||||
console.log('execute_program');
|
console.log('execute_program');
|
||||||
console.log(file_path);
|
console.log(file_path);
|
||||||
|
|
||||||
require('../server').get_socket(file.username, function(socket) {
|
console.log(file);
|
||||||
console.log(file);
|
var cwd = get_cwd(file_path);
|
||||||
var cwd = get_cwd(file_path);
|
var prog = spawn("sudo", [type, file_path], {cwd: cwd});
|
||||||
var prog = spawn("sudo", [type, file_path], {cwd: cwd});
|
var key = get_key(file);
|
||||||
var key = get_key(file);
|
spawn_list.push({key: key, prog: prog});
|
||||||
spawn_list.push({key: key, prog: prog});
|
if (socket) {
|
||||||
if (socket) {
|
console.log('found socket, executing');
|
||||||
console.log('found socket, executing');
|
handle_output(prog, file, is_job, socket);
|
||||||
handle_output(prog, file, is_job, socket);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_output(prog, file, is_job, socket) {
|
function handle_output(prog, file, is_job, socket) {
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
socket.emit('scheduler-start', {file: file});
|
ws_helper.send_message(socket, 'scheduler-start', {file: file});
|
||||||
}
|
}
|
||||||
|
|
||||||
prog.stdout.on('data', function(data) {
|
prog.stdout.on('data', function(data) {
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
socket.emit('scheduler-executing', {file: file});
|
ws_helper.send_message(socket, 'scheduler-executing', {file: file});
|
||||||
} else {
|
} else {
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
socket.emit('program-stdout', {output: data.toString()});
|
ws_helper.send_message(socket, 'program-stdout', {output: data.toString()});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
prog.stderr.on('data', function(data) {
|
prog.stderr.on('data', function(data) {
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
socket.emit('scheduler-error', {file: file, error: data});
|
ws_helper.send_message(socket, 'scheduler-error', {file: file, error: data});
|
||||||
} else {
|
} else {
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
socket.emit('program-stderr', {output: data.toString()});
|
ws_helper.send_message(socket, 'program-stderr', {output: data.toString()});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -151,9 +150,9 @@ function handle_output(prog, file, is_job, socket) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_job) {
|
if (is_job) {
|
||||||
socket.emit('scheduler-exit', {code: code, file: file});
|
ws_helper.send_message(socket, 'scheduler-exit', {code: code, file: file});
|
||||||
} else {
|
} else {
|
||||||
socket.emit('program-exit', {code: code});
|
ws_helper.send_message(socket, 'program-exit', {code: code});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
var path = require('path'),
|
var path = require('path'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
util = require('util'),
|
config = require('../config/config'),
|
||||||
config = require('../config/config');
|
winston = require('winston'),
|
||||||
exec = require('child_process').exec;
|
exec = require('child_process').exec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks to see if a bitbucket ssh key exists already.
|
* Checks to see if an ssh key exists already.
|
||||||
*/
|
*/
|
||||||
exports.has_ssh_key = function has_ssh_key(cb) {
|
exports.has_ssh_key = function has_ssh_key(key_name, cb) {
|
||||||
path.exists(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', function(exists) {
|
fs.exists(path.resolve(process.env['HOME'], '/.ssh/', key_name), function(exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
cb(true);
|
cb(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -18,15 +18,15 @@ exports.has_ssh_key = function has_ssh_key(cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generates an ssh key for Bitbucket
|
* Generates an ssh key
|
||||||
*/
|
*/
|
||||||
exports.generate_ssh_key = function(cb) {
|
exports.generate_ssh_key = function(key_name, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.has_ssh_key(function(exists) {
|
self.has_ssh_key(key_name, function(exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
cb();
|
cb();
|
||||||
} else {
|
} else {
|
||||||
exec("ssh-keygen -b 2048 -N '' -f ~/.ssh/id_rsa_bitbucket -t rsa -q", function(err, stdout, stderr) {
|
exec("ssh-keygen -b 2048 -N '' -f ~/.ssh/" + key_name + "-t rsa -q", function(err, stdout, stderr) {
|
||||||
//console.log(err, stdout, stderr);
|
//console.log(err, stdout, stderr);
|
||||||
self.append_to_ssh_config(function() {
|
self.append_to_ssh_config(function() {
|
||||||
cb();
|
cb();
|
||||||
|
|
@ -36,46 +36,17 @@ exports.generate_ssh_key = function(cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Append bitbucket.org to the ssh config file to disable StrictHostKeyChecking.
|
|
||||||
* This isn't great, but we need a way for beginners to get past the known_host checks.
|
|
||||||
*/
|
|
||||||
exports.append_to_ssh_config = function append_to_ssh_config(cb) {
|
|
||||||
var ssh_config_file = process.env['HOME'] + '/.ssh/config';
|
|
||||||
var identity_info = "Host bitbucket.org \r\n\tHostName bitbucket.org\r\n\tStrictHostKeyChecking no\r\n\tPreferredAuthentications publickey\r\n\tIdentityFile ~/.ssh/id_rsa_bitbucket";
|
|
||||||
|
|
||||||
path.exists(ssh_config_file, function(exists) {
|
exports.read_or_generate_key = function(key_name, cb) {
|
||||||
if (exists) {
|
|
||||||
//file exists, let's check if it has the bitbucket host in it, otherwise add it
|
|
||||||
fs.readFile(ssh_config_file, 'ascii', function(err, data) {
|
|
||||||
if (data.indexOf('bitbucket.org') !== -1) {
|
|
||||||
cb();
|
|
||||||
} else {
|
|
||||||
var file = fs.createWriteStream(ssh_config_file, {'flags': 'a'});
|
|
||||||
file.write(identity_info, function() {
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
fs.writeFile(ssh_config_file, identity_info, function(err) {
|
|
||||||
if(err) console.log(err);
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.read_or_generate_key = function(cb) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
self.has_ssh_key(function(has_key) {
|
self.has_ssh_key(key_name, function(has_key) {
|
||||||
if (has_key) {
|
if (has_key) {
|
||||||
fs.readFile(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', 'ascii', function(err,data){
|
fs.readFile(process.env['HOME'] + '/.ssh/' + key_name, 'ascii', function(err,data){
|
||||||
cb(data);
|
cb(data);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.generate_ssh_key(function() {
|
self.generate_ssh_key(key_name, function() {
|
||||||
fs.readFile(process.env['HOME'] + '/.ssh/id_rsa_bitbucket.pub', 'ascii', function(err,data){
|
fs.readFile(process.env['HOME'] + '/.ssh/' + key_name, 'ascii', function(err,data){
|
||||||
cb(data);
|
cb(data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -109,9 +80,11 @@ exports.move_uploaded_file = function(temp_path, new_path, cb) {
|
||||||
var is = fs.createReadStream(temp_path);
|
var is = fs.createReadStream(temp_path);
|
||||||
var os = fs.createWriteStream(new_path);
|
var os = fs.createWriteStream(new_path);
|
||||||
|
|
||||||
util.pump(is, os, function() {
|
is.pipe(os);
|
||||||
fs.unlinkSync(temp_path);
|
|
||||||
cb();
|
is.on("close", function() {
|
||||||
|
fs.unlinkSync(temp_path);
|
||||||
|
cb();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -143,9 +116,11 @@ exports.create_project_readme = function(cb) {
|
||||||
|
|
||||||
var is = fs.createReadStream(source);
|
var is = fs.createReadStream(source);
|
||||||
var os = fs.createWriteStream(destination);
|
var os = fs.createWriteStream(destination);
|
||||||
util.pump(is, os, function(err) {
|
|
||||||
console.log(err);
|
is.pipe(os);
|
||||||
cb(err, file);
|
|
||||||
|
is.on("close", function() {
|
||||||
|
cb(null, file);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -164,9 +139,11 @@ exports.create_project_gitignore = function(cb) {
|
||||||
|
|
||||||
var is = fs.createReadStream(source);
|
var is = fs.createReadStream(source);
|
||||||
var os = fs.createWriteStream(destination);
|
var os = fs.createWriteStream(destination);
|
||||||
util.pump(is, os, function(err) {
|
is.pipe(os);
|
||||||
console.log(err);
|
|
||||||
cb(err, file);
|
is.on("close", function() {
|
||||||
|
winston.debug("IN OS END");
|
||||||
|
cb(null, file);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,50 @@
|
||||||
var git = require('gitty'),
|
var path = require('path'),
|
||||||
|
db = require('../models/webideModel'),
|
||||||
|
git = require('gitty'),
|
||||||
|
Command = require('../node_modules/gitty/lib/command'),
|
||||||
url = require('url'),
|
url = require('url'),
|
||||||
path = require('path'),
|
|
||||||
winston = require('winston'),
|
winston = require('winston'),
|
||||||
|
fs = require('fs'),
|
||||||
fs_helper = require('./fs_helper'),
|
fs_helper = require('./fs_helper'),
|
||||||
redis = require("redis"),
|
ws_helper = require('./websocket_helper'),
|
||||||
client = redis.createClient(),
|
|
||||||
request_helper = require('./request_helper'),
|
|
||||||
config = require('../config/config');
|
config = require('../config/config');
|
||||||
|
|
||||||
var REPOSITORY_PATH = path.resolve(__dirname + "/../repositories") + "/";
|
var REPOSITORY_PATH = path.resolve(__dirname + "/../repositories") + "/";
|
||||||
var push_queue = [], pushInterval, PUSH_TIMER = 30000;
|
var push_queue = [], pushInterval, PUSH_TIMER = 30000;
|
||||||
|
|
||||||
|
/* extend gitty */
|
||||||
|
git.prototype.remove_recursive = function(path, callback) {
|
||||||
|
var self = this;
|
||||||
|
var cmd = new Command(self, 'rm', ['-r', '--cached'], path);
|
||||||
|
|
||||||
|
cmd.exec(function(error, stdout, stderr) {
|
||||||
|
callback(error || stderr || null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
git.prototype.move = function(source, destination, callback) {
|
||||||
|
var self = this;
|
||||||
|
var cmd = new Command(self, 'mv', [], source, destination);
|
||||||
|
|
||||||
|
cmd.exec(function(error, stdout, stderr) {
|
||||||
|
callback(error || stderr || null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a simple queue that is used for pushing git changes to the remote repositories.
|
* Creates a simple queue that is used for pushing git changes to the remote repositories.
|
||||||
* The queue is currently set using the PUSH_TIMER to delay the remote pushes.
|
* The queue is currently set using the PUSH_TIMER to delay the remote pushes.
|
||||||
*/
|
*/
|
||||||
function push_queue_interval() {
|
function push_queue_interval() {
|
||||||
console.log('git push queue init');
|
winston.debug('git push queue init');
|
||||||
function push(repository_path, remote, branch, username) {
|
function push(repository_path, remote, branch, username) {
|
||||||
git.push(repository_path, remote, branch, function(obj) {
|
var repo = git(repository_path);
|
||||||
require('../server').get_socket(username, function(socket) {
|
repo.push(remote, branch, function(err) {
|
||||||
if (obj.error) {
|
if (err) {
|
||||||
winston.error(obj);
|
winston.error(err);
|
||||||
socket.emit('git-push-error', {err: "Error: Failure pushing code to remote repository"});
|
ws_helper.send_message(null, 'git-push-error', {err: "Error: Failure pushing code to remote repository"});
|
||||||
}
|
}
|
||||||
//console.log(obj);
|
//winston.debug(obj);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +54,7 @@ function push_queue_interval() {
|
||||||
}
|
}
|
||||||
|
|
||||||
while(push_queue.length > 0) {
|
while(push_queue.length > 0) {
|
||||||
console.log('pushing code to remote repository');
|
winston.debug('pushing code to remote repository');
|
||||||
var element = push_queue.shift();
|
var element = push_queue.shift();
|
||||||
push(element.repository_path, element.remote, element.branch, element.username);
|
push(element.repository_path, element.remote, element.branch, element.username);
|
||||||
}
|
}
|
||||||
|
|
@ -50,8 +69,8 @@ push_queue_interval();
|
||||||
exports.clone_adafruit_libraries = function(adafruit_repository, remote, cb) {
|
exports.clone_adafruit_libraries = function(adafruit_repository, remote, cb) {
|
||||||
fs_helper.check_for_repository(adafruit_repository, function(err, status) {
|
fs_helper.check_for_repository(adafruit_repository, function(err, status) {
|
||||||
if (!err && !status) {
|
if (!err && !status) {
|
||||||
git.clone(REPOSITORY_PATH, remote, function(output) {
|
git.clone(REPOSITORY_PATH, remote, function(err) {
|
||||||
console.log(output);
|
winston.debug(err);
|
||||||
cb(true);
|
cb(true);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -60,75 +79,46 @@ exports.clone_adafruit_libraries = function(adafruit_repository, remote, cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
exports.clone_update_remote_push = function(repository_url, cb) {
|
||||||
* This does a few things in order to clone a repository, and save it to your Bitbucket profile.
|
|
||||||
* This allows you to clone from any remote repository, including Github (it's overly complicated...).
|
|
||||||
* 1. It first checks if the repository already exists in your bitbucket profile.
|
|
||||||
* 2. If not 1, it creates the repository in Bitbucket using the API.
|
|
||||||
* 3. It then clones the remote repository you're interested in.
|
|
||||||
* 4. It then updates the git remote for that repository to your bitbucket repository.
|
|
||||||
* 5. Finally, it pushes the cloned repository to your remote account.
|
|
||||||
*/
|
|
||||||
exports.clone_update_remote_push = function(profile, repository_url, retain_remote, cb) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var repository_name = path.basename(repository_url, '.git');
|
var repository_name = path.basename(repository_url, '.git');
|
||||||
|
|
||||||
if (config.editor.offline || config.editor.github || (retain_remote === 'on')) {
|
self.clone_repository(repository_url, function(err, results) {
|
||||||
self.clone_repository(repository_url, function(err, results) {
|
winston.debug("clone repository locally: " + repository_name);
|
||||||
console.log("clone repository locally: " + repository_name);
|
cb(err, true);
|
||||||
cb(err, true);
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
request_helper.list_repositories(profile, function(err, list) {
|
|
||||||
var exists = list.some(function(repository) {
|
|
||||||
return (repository.name === repository_name);
|
|
||||||
});
|
|
||||||
if (!exists) {
|
|
||||||
//TODO need better error handling eventually
|
|
||||||
request_helper.create_repository(profile, repository_name, function(err, response) {
|
|
||||||
console.log("created repository in bitbucket: " + repository_name);
|
|
||||||
self.clone_repository(repository_url, function(err, results) {
|
|
||||||
console.log("clone repository locally: " + repository_name);
|
|
||||||
self.update_remote(profile, repository_name, function(err, response) {
|
|
||||||
console.log("updated remote for repository: " + repository_name);
|
|
||||||
self.push(repository_name, "origin", "master", profile, function(err, response) {
|
|
||||||
console.log("git push for repository: " + repository_name);
|
|
||||||
cb(err, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (repository_url.toLowerCase().indexOf("bitbucket.org") === -1) {
|
|
||||||
cb("Repository Already Exists in Bitbucket, clone with Bitbucket URL.", false);
|
|
||||||
} else {
|
|
||||||
self.clone_repository(repository_url, function(err, results) {
|
|
||||||
console.log("clone repository locally: " + repository_name);
|
|
||||||
cb(err, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.clone_repository = function(repository_path, cb) {
|
exports.clone_repository = function(repository_path, cb) {
|
||||||
console.log(repository_path);
|
winston.debug("clone_repository", repository_path);
|
||||||
var repository_url = url.parse(repository_path);
|
var repository_url = url.parse(repository_path);
|
||||||
|
|
||||||
console.log("cloning", repository_path);
|
winston.debug("cloning", repository_path);
|
||||||
git.clone(REPOSITORY_PATH, repository_url.href, function(output) {
|
|
||||||
cb(output.error, output.message);
|
git.clone(REPOSITORY_PATH, repository_url.href, function(err, output) {
|
||||||
|
cb(err, output);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.create_local_repository = function(name, cb) {
|
||||||
|
winston.debug("create_repository", name);
|
||||||
|
//create directory
|
||||||
|
var repository_path = REPOSITORY_PATH + name;
|
||||||
|
if (!fs.existsSync(repository_path)){
|
||||||
|
fs.mkdirSync(repository_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
var repo = git(repository_path);
|
||||||
|
repo.init(function(err, output) {
|
||||||
|
cb(err, output);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.validate_config = function validate_config(cb) {
|
exports.validate_config = function validate_config(cb) {
|
||||||
git.config("user.email", null, function(err, email) {
|
git.getConfig("user.email", function(err, email) {
|
||||||
git.config("user.name", null, function(err, name) {
|
git.getConfig("user.name", function(err, name) {
|
||||||
if (err) winston.error("git_helper.validate_config err", err);
|
if (err) winston.error("git_helper.validate_config err", err);
|
||||||
|
|
||||||
if (name && email) {
|
if (name && email) {
|
||||||
cb(true);
|
cb(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -142,15 +132,15 @@ exports.set_config = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.validate_config(function(is_valid) {
|
self.validate_config(function(is_valid) {
|
||||||
if (is_valid) {
|
if (is_valid) {
|
||||||
console.log('git config is valid');
|
winston.debug('git config is valid');
|
||||||
cb();
|
cb();
|
||||||
} else {
|
} else {
|
||||||
winston.error('git config is invalid');
|
winston.error('git config is invalid');
|
||||||
client.hgetall('user', function (err, user) {
|
db.findOne({type: "user"}, function (err, user) {
|
||||||
console.log("set_config user", user);
|
winston.debug("set_config user", user);
|
||||||
git.config("user.email", user.email, function(err, email) {
|
git.setConfig("user.email", user.email, function(err, email) {
|
||||||
git.config("user.name", user.name, function(err, name) {
|
git.setConfig("user.name", user.name, function(err, name) {
|
||||||
console.log("git config set", email, name);
|
winston.debug("git config set", email, name);
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -160,24 +150,14 @@ exports.set_config = function(cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Updates the remote repository to the users bitbucket repository.
|
|
||||||
*/
|
|
||||||
exports.update_remote = function(profile, repository, cb) {
|
|
||||||
var remote_url = "ssh://git@bitbucket.org/" + profile.username + "/" + repository.toLowerCase() + ".git";
|
|
||||||
git.remote.update(REPOSITORY_PATH + repository, "origin", remote_url, function(output) {
|
|
||||||
//console.log(output);
|
|
||||||
cb(output.error, output.message);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds an additional remote to a repository.
|
* Adds an additional remote to a repository.
|
||||||
*/
|
*/
|
||||||
exports.add_remote = function(repository, remote_name, remote_url, cb) {
|
exports.add_remote = function(repository, remote_name, remote_url, cb) {
|
||||||
git.remote.add(REPOSITORY_PATH + repository, remote_name, remote_url, function(output) {
|
var repo = git(REPOSITORY_PATH + repository);
|
||||||
//console.log(output);
|
repo.addRemote(remote_name, remote_url, function(err, message) {
|
||||||
cb(output.error, output.message);
|
winston.debug(err);
|
||||||
|
cb(err, message);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -191,10 +171,10 @@ exports.add = function add(repository, files, cb) {
|
||||||
files = [files];
|
files = [files];
|
||||||
}
|
}
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
git.add(repository_path, files, function(output) {
|
var repo = git(repository_path);
|
||||||
//console.log(output.errors);
|
repo.add(files, function(err, added) {
|
||||||
//console.log(output);
|
winston.debug(err);
|
||||||
cb(output.errors, output.added);
|
cb(err, added);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -208,9 +188,10 @@ exports.remove = function remove(repository, files, cb) {
|
||||||
files = [files];
|
files = [files];
|
||||||
}
|
}
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
git.remove(repository_path, files, function(output) {
|
var repo = git(repository_path);
|
||||||
//console.log(output.errors);
|
repo.remove(files, function(err, added) {
|
||||||
cb(output.errors, output.added);
|
winston.debug(err);
|
||||||
|
cb(err, added);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -222,9 +203,10 @@ exports.remove = function remove(repository, files, cb) {
|
||||||
exports.remove_recursive = function remove_recursive(repository, path, cb) {
|
exports.remove_recursive = function remove_recursive(repository, path, cb) {
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
|
|
||||||
git.remove_recursive(repository_path, path, function(output) {
|
var repo = git(repository_path);
|
||||||
console.log(output);
|
repo.remove_recursive(path, function(err, data) {
|
||||||
cb(output.errors, output.added);
|
winston.debug(err);
|
||||||
|
cb(err, data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -234,9 +216,10 @@ exports.remove_recursive = function remove_recursive(repository, path, cb) {
|
||||||
*/
|
*/
|
||||||
exports.move = function move(repository, source, destination, cb) {
|
exports.move = function move(repository, source, destination, cb) {
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
git.move(repository_path, source, destination, function(obj) {
|
var repo = git(repository_path);
|
||||||
//console.log(obj);
|
repo.move(source, destination, function(err, message) {
|
||||||
cb(obj.error, obj.message);
|
//winston.debug(obj);
|
||||||
|
cb(err, message);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -247,10 +230,11 @@ exports.move = function move(repository, source, destination, cb) {
|
||||||
*/
|
*/
|
||||||
exports.commit = function commit(repository, message, cb) {
|
exports.commit = function commit(repository, message, cb) {
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
console.log(repository_path);
|
winston.debug(repository_path);
|
||||||
git.commit(repository_path, message, function(obj) {
|
var repo = git(repository_path);
|
||||||
//console.log(obj);
|
repo.commit(message, function(err, message) {
|
||||||
cb(obj.error, obj.message);
|
//winston.debug(obj);
|
||||||
|
cb(err, message);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -265,9 +249,10 @@ exports.is_modified = function (file, cb) {
|
||||||
var item_path = path_array.slice(3).join('/');
|
var item_path = path_array.slice(3).join('/');
|
||||||
|
|
||||||
var is_modified = false;
|
var is_modified = false;
|
||||||
git.status(repository_path, function(output) {
|
var repo = git(repository_path);
|
||||||
|
repo.status(function(err, output) {
|
||||||
|
|
||||||
console.log(output);
|
winston.debug(err, output);
|
||||||
|
|
||||||
if (output.not_staged.length > 0) {
|
if (output.not_staged.length > 0) {
|
||||||
output.not_staged.forEach(function(item, index) {
|
output.not_staged.forEach(function(item, index) {
|
||||||
|
|
@ -281,7 +266,7 @@ exports.is_modified = function (file, cb) {
|
||||||
is_modified = true;
|
is_modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(output.errors, is_modified);
|
cb(err, is_modified);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -295,18 +280,19 @@ exports.is_untracked = function (file, cb) {
|
||||||
var repository_path = path.resolve(REPOSITORY_PATH, repository);
|
var repository_path = path.resolve(REPOSITORY_PATH, repository);
|
||||||
var item_path = path_array.slice(3).join('/');
|
var item_path = path_array.slice(3).join('/');
|
||||||
|
|
||||||
console.log(item_path);
|
winston.debug(item_path);
|
||||||
|
|
||||||
var is_untracked = false;
|
var is_untracked = false;
|
||||||
git.status(repository_path, function(output) {
|
var repo = git(repository_path);
|
||||||
|
repo.status(function(err, output) {
|
||||||
|
|
||||||
console.log(output);
|
winston.debug(err, output);
|
||||||
|
|
||||||
if (output.untracked.indexOf(item_path) !== -1) {
|
if (output.untracked.indexOf(item_path) !== -1) {
|
||||||
is_untracked = true;
|
is_untracked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb(output.errors, is_untracked);
|
cb(err, is_untracked);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -314,10 +300,10 @@ exports.is_untracked = function (file, cb) {
|
||||||
* git push the committed changes. Adds it to the push queue.
|
* git push the committed changes. Adds it to the push queue.
|
||||||
* repository: the name of the repository that resides in the repositories folder.
|
* repository: the name of the repository that resides in the repositories folder.
|
||||||
*/
|
*/
|
||||||
exports.push = function push(repository, remote, branch, profile, cb) {
|
exports.push = function push(repository, remote, branch, cb) {
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
var key = repository + remote + branch;
|
var key = repository + remote + branch;
|
||||||
console.log('called push ' + key);
|
winston.debug('called push ' + key);
|
||||||
|
|
||||||
//if the repository, remote and branch are already on the queue, just skip it...otherwise add it to the end
|
//if the repository, remote and branch are already on the queue, just skip it...otherwise add it to the end
|
||||||
if (push_queue.length > 0) {
|
if (push_queue.length > 0) {
|
||||||
|
|
@ -325,14 +311,13 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
||||||
if (push_queue[i].key === key) {
|
if (push_queue[i].key === key) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
console.log('added to queue ' + key);
|
winston.debug('added to queue ' + key);
|
||||||
push_queue.push({
|
push_queue.push({
|
||||||
key: key,
|
key: key,
|
||||||
repository_path: repository_path,
|
repository_path: repository_path,
|
||||||
repository: repository,
|
repository: repository,
|
||||||
remote: remote,
|
remote: remote,
|
||||||
branch: branch,
|
branch: branch
|
||||||
username: profile ? profile.username : ''
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,8 +327,7 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
||||||
repository_path: repository_path,
|
repository_path: repository_path,
|
||||||
repository: repository,
|
repository: repository,
|
||||||
remote: remote,
|
remote: remote,
|
||||||
branch: branch,
|
branch: branch
|
||||||
username: profile ? profile.username : ''
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
|
|
@ -355,13 +339,13 @@ exports.push = function push(repository, remote, branch, profile, cb) {
|
||||||
*/
|
*/
|
||||||
exports.pull = function pull(repository, remote, branch, cb) {
|
exports.pull = function pull(repository, remote, branch, cb) {
|
||||||
var repository_path = REPOSITORY_PATH + repository;
|
var repository_path = REPOSITORY_PATH + repository;
|
||||||
git.pull(repository_path, remote, branch, function(obj) {
|
var repo = git(repository_path);
|
||||||
//console.log(obj);
|
repo.pull(remote, branch, function(err, message) {
|
||||||
if (obj.error) {
|
if (err) {
|
||||||
winston.error(obj.error);
|
winston.error(err);
|
||||||
cb("Error: Failure updating from remote repository", obj.message);
|
cb("Error: Failure updating from remote repository", message);
|
||||||
} else {
|
} else {
|
||||||
cb(null, obj.message);
|
cb(null, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -370,14 +354,14 @@ exports.pull = function pull(repository, remote, branch, cb) {
|
||||||
/*
|
/*
|
||||||
* Simply removes a file or directory, commits it, and pushes it out.
|
* Simply removes a file or directory, commits it, and pushes it out.
|
||||||
*/
|
*/
|
||||||
exports.remove_commit_push = function(item, profile, cb) {
|
exports.remove_commit_push = function(item, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
console.log(item);
|
winston.debug(item);
|
||||||
var path_array = item.path.split('/');
|
var path_array = item.path.split('/');
|
||||||
var repository = path_array[2];
|
var repository = path_array[2];
|
||||||
var item_path = path_array.slice(3).join('/');
|
var item_path = path_array.slice(3).join('/');
|
||||||
console.log(item_path);
|
winston.debug(item_path);
|
||||||
console.log(repository);
|
winston.debug(repository);
|
||||||
|
|
||||||
|
|
||||||
if (item.type === 'directory') {
|
if (item.type === 'directory') {
|
||||||
|
|
@ -392,7 +376,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
||||||
cb("Error: Failure comitting removed folder", status);
|
cb("Error: Failure comitting removed folder", status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.push(repository, "origin", "master", profile, function() {
|
self.push(repository, "origin", "master", function() {
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -409,7 +393,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
||||||
cb("Error: Failure comitting removed file", status);
|
cb("Error: Failure comitting removed file", status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.push(repository, "origin", "master", profile, function() {
|
self.push(repository, "origin", "master", function() {
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -420,7 +404,7 @@ exports.remove_commit_push = function(item, profile, cb) {
|
||||||
/*
|
/*
|
||||||
* Simply moves a file or directory, commits it, and pushes it out.
|
* Simply moves a file or directory, commits it, and pushes it out.
|
||||||
*/
|
*/
|
||||||
exports.move_commit_push = function(item, profile, cb) {
|
exports.move_commit_push = function(item, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var path_array = item.path.split('/');
|
var path_array = item.path.split('/');
|
||||||
var repository = path_array[2];
|
var repository = path_array[2];
|
||||||
|
|
@ -439,18 +423,18 @@ exports.move_commit_push = function(item, profile, cb) {
|
||||||
self.move(repository, item_path, destination_path, function(err, status) {
|
self.move(repository, item_path, destination_path, function(err, status) {
|
||||||
var commit_message = "Moved " + item.name;
|
var commit_message = "Moved " + item.name;
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log ("has error returning");
|
winston.debug ("has error returning");
|
||||||
cb("Error: Failure moving file (renaming)");
|
cb("Error: Failure moving file (renaming)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.commit(repository, commit_message, function(err, status) {
|
self.commit(repository, commit_message, function(err, status) {
|
||||||
console.log("Committed Moved File");
|
winston.debug("Committed Moved File");
|
||||||
if (err) {
|
if (err) {
|
||||||
cb("Error: Failure comitting file into git");
|
cb("Error: Failure comitting file into git");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.push(repository, "origin", "master", profile, function() {
|
self.push(repository, "origin", "master", function() {
|
||||||
console.log("Pushed latest changes");
|
winston.debug("Pushed latest changes");
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -463,7 +447,7 @@ exports.move_commit_push = function(item, profile, cb) {
|
||||||
/*
|
/*
|
||||||
* Simply commits a file or directory, commits it, and pushes it out.
|
* Simply commits a file or directory, commits it, and pushes it out.
|
||||||
*/
|
*/
|
||||||
exports.commit_push_and_save = function(file, commit_message, profile, cb) {
|
exports.commit_push_and_save = function(file, commit_message, cb) {
|
||||||
var self = this,
|
var self = this,
|
||||||
path_array, repository, file_path;
|
path_array, repository, file_path;
|
||||||
if (!file.repository) {
|
if (!file.repository) {
|
||||||
|
|
@ -475,24 +459,24 @@ exports.commit_push_and_save = function(file, commit_message, profile, cb) {
|
||||||
file_path = file.path;
|
file_path = file.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(commit_message);
|
winston.debug(commit_message);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.add(repository, file_path, function(err, status) {
|
self.add(repository, file_path, function(err, status) {
|
||||||
console.log("added", err, status);
|
winston.debug("added", err, status);
|
||||||
if (err && err.length > 0) {
|
if (err && err.length > 0) {
|
||||||
cb("Error: Failure adding file to git", status);
|
cb("Error: Failure adding file to git", status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.commit(repository, commit_message, function(err, status) {
|
self.commit(repository, commit_message, function(err, status) {
|
||||||
console.log("committed", err, status);
|
winston.debug("committed", err, status);
|
||||||
if (err && err.length > 0) {
|
if (err && err.length > 0) {
|
||||||
cb("Error: Failure comitting file into git", status);
|
cb("Error: Failure comitting file into git", status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.push(repository, "origin", "master", profile, function() {
|
self.push(repository, "origin", "master", function() {
|
||||||
console.log("added to push queue");
|
winston.debug("added to push queue");
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
var spawn = require('child_process').spawn,
|
var spawn = require('child_process').spawn,
|
||||||
exec = require('child_process').exec,
|
exec = require('child_process').exec,
|
||||||
|
db = require('../../models/webideModel'),
|
||||||
net = require('net'),
|
net = require('net'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
|
ws_helper = require('../websocket_helper'),
|
||||||
debug_program, debug_client,
|
debug_program, debug_client,
|
||||||
client_connected = false,
|
client_connected = false,
|
||||||
HOST = '127.0.0.1',
|
HOST = '127.0.0.1',
|
||||||
|
|
@ -28,39 +30,46 @@ exports.start_debug = function start_debug(file, socket) {
|
||||||
console.log(!debug_program);
|
console.log(!debug_program);
|
||||||
if (!debug_program) {
|
if (!debug_program) {
|
||||||
console.log('spawn debugger');
|
console.log('spawn debugger');
|
||||||
debug_program = spawn("sudo", ["python", "debugger.py"], {cwd: __dirname});
|
db.findOne({type: "editor:settings"}, function(err, settings) {
|
||||||
var buffer = "";
|
var command = 'python';
|
||||||
debug_program.stdout.on('data', function(data) {
|
if (typeof settings !== 'undefined' && settings.python_version === '3') {
|
||||||
console.log(data.toString());
|
command = 'python3';
|
||||||
|
|
||||||
buffer += data.toString();
|
|
||||||
|
|
||||||
if (buffer.indexOf("DEBUGGER READY") !== -1 && !client_connected) {
|
|
||||||
console.log("DEBUGGER READY");
|
|
||||||
connect_client(file, socket);
|
|
||||||
console.log("after connect_client");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
debug_program = spawn("sudo", [command, "debugger.py"], {cwd: __dirname});
|
||||||
|
var buffer = "";
|
||||||
|
debug_program.stdout.on('data', function(data) {
|
||||||
|
console.log(data.toString());
|
||||||
|
|
||||||
debug_program.stderr.on('data', function(data) {
|
buffer += data.toString();
|
||||||
console.log(data.toString());
|
|
||||||
socket.emit('debug-error', {file: file, error: data});
|
|
||||||
});
|
|
||||||
|
|
||||||
debug_program.on('error', function(data) {
|
if (buffer.indexOf("DEBUGGER READY") !== -1 && !client_connected) {
|
||||||
console.log("DEBUG PROGRAM ERROR:");
|
console.log("DEBUGGER READY");
|
||||||
console.log(data);
|
connect_client(file, socket);
|
||||||
});
|
console.log("after connect_client");
|
||||||
|
}
|
||||||
|
|
||||||
debug_program.on('exit', function(code) {
|
});
|
||||||
console.log('Debug Program Exit');
|
|
||||||
console.log(code);
|
|
||||||
debug_program = null;
|
|
||||||
|
|
||||||
if (enable_debug) {
|
debug_program.stderr.on('data', function(data) {
|
||||||
self.start_debug(file, socket);
|
console.log(data.toString());
|
||||||
}
|
ws_helper.send_message(socket, 'debug-error', {file: file, error: data});
|
||||||
|
});
|
||||||
|
|
||||||
|
debug_program.on('error', function(data) {
|
||||||
|
console.log("DEBUG PROGRAM ERROR:");
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
debug_program.on('exit', function(code) {
|
||||||
|
console.log('Debug Program Exit');
|
||||||
|
console.log(code);
|
||||||
|
debug_program = null;
|
||||||
|
|
||||||
|
if (enable_debug) {
|
||||||
|
self.start_debug(file, socket);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//console.log('resetting debugger');
|
//console.log('resetting debugger');
|
||||||
|
|
@ -82,6 +91,7 @@ function connect_client(file, socket) {
|
||||||
debug_client = new net.Socket();
|
debug_client = new net.Socket();
|
||||||
debug_client.connect(PORT, HOST, function() {
|
debug_client.connect(PORT, HOST, function() {
|
||||||
socket.emit('debug-client-connected');
|
socket.emit('debug-client-connected');
|
||||||
|
ws_helper.send_message(socket, 'debug-client-connected', "");
|
||||||
client_connected = true;
|
client_connected = true;
|
||||||
console.log('connected to python debugger: ' + HOST + ':' + PORT);
|
console.log('connected to python debugger: ' + HOST + ':' + PORT);
|
||||||
console.log(file_path);
|
console.log(file_path);
|
||||||
|
|
@ -95,7 +105,7 @@ function connect_client(file, socket) {
|
||||||
var temp_buff = buffer.split('\n');
|
var temp_buff = buffer.split('\n');
|
||||||
for (var i=0; i<temp_buff.length-1; i++) {
|
for (var i=0; i<temp_buff.length-1; i++) {
|
||||||
console.log(JSON.parse(temp_buff[i]));
|
console.log(JSON.parse(temp_buff[i]));
|
||||||
socket.emit('debug-file-response', JSON.parse(temp_buff[i]));
|
ws_helper.send_message(socket, 'debug-file-response', JSON.parse(temp_buff[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = temp_buff.slice(temp_buff.length);
|
buffer = temp_buff.slice(temp_buff.length);
|
||||||
|
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
var request = require('request'),
|
|
||||||
qs = require('querystring'),
|
|
||||||
fs_helper = require('./fs_helper');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call the Bitbucket OAuth API to post the ssh key to the users profile.
|
|
||||||
*/
|
|
||||||
exports.post_ssh_key = function(profile, cb) {
|
|
||||||
var url = "https://api.bitbucket.org/1.0/ssh-keys/";
|
|
||||||
var oauth = { consumer_key: profile.consumer_key,
|
|
||||||
consumer_secret: profile.consumer_secret,
|
|
||||||
token: profile.token,
|
|
||||||
token_secret: profile.token_secret };
|
|
||||||
|
|
||||||
fs_helper.read_or_generate_key(function(data) {
|
|
||||||
var params = { key: data.trim(), label: 'raspeditor'};
|
|
||||||
|
|
||||||
request.post({
|
|
||||||
url:url,
|
|
||||||
body: qs.stringify(params),
|
|
||||||
oauth:oauth
|
|
||||||
}, function (e, r, body) {
|
|
||||||
console.log(e);
|
|
||||||
console.log(r.statusCode);
|
|
||||||
console.log(body);
|
|
||||||
cb (e, body);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call the Bitbucket OAuth API to createa a repository on the users profile.
|
|
||||||
*/
|
|
||||||
exports.set_repository_private = function set_repository_private(profile, repository_name) {
|
|
||||||
var username = profile.username;
|
|
||||||
//console.log('set_repository_private');
|
|
||||||
//console.log(profile);
|
|
||||||
var url = "https://api.bitbucket.org/1.0/repositories/" + username + "/" + repository_name;
|
|
||||||
var oauth = { consumer_key: profile.consumer_key,
|
|
||||||
consumer_secret: profile.consumer_secret,
|
|
||||||
token: profile.token,
|
|
||||||
token_secret: profile.token_secret };
|
|
||||||
|
|
||||||
|
|
||||||
var params = {is_private: true};
|
|
||||||
|
|
||||||
request.put({
|
|
||||||
url:url,
|
|
||||||
body: qs.stringify(params),
|
|
||||||
oauth:oauth
|
|
||||||
}, function (e, r, body) {
|
|
||||||
//console.log(e);
|
|
||||||
console.log(r.statusCode);
|
|
||||||
if (r.statusCode === 200) {
|
|
||||||
console.log("successfully set repository private");
|
|
||||||
}
|
|
||||||
//console.log(body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call the Bitbucket OAuth API to get a list of the repositories on the users profile.
|
|
||||||
*/
|
|
||||||
exports.list_repositories = function(profile, cb) {
|
|
||||||
var self = this;
|
|
||||||
var url = "https://api.bitbucket.org/1.0/user/repositories/";
|
|
||||||
var oauth = { consumer_key: profile.consumer_key,
|
|
||||||
consumer_secret: profile.consumer_secret,
|
|
||||||
token: profile.token,
|
|
||||||
token_secret: profile.token_secret };
|
|
||||||
|
|
||||||
request.get({
|
|
||||||
url:url,
|
|
||||||
oauth:oauth,
|
|
||||||
json: true
|
|
||||||
}, function (e, r, body) {
|
|
||||||
console.log(e);
|
|
||||||
//console.log(r.statusCode);
|
|
||||||
//console.log(body);
|
|
||||||
cb (e, body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call the Bitbucket OAuth API to createa a repository on the users profile.
|
|
||||||
*/
|
|
||||||
exports.create_repository = function(profile, repository_name, cb) {
|
|
||||||
var url = "https://api.bitbucket.org/1.0/repositories/";
|
|
||||||
var oauth = { consumer_key: profile.consumer_key,
|
|
||||||
consumer_secret: profile.consumer_secret,
|
|
||||||
token: profile.token,
|
|
||||||
token_secret: profile.token_secret };
|
|
||||||
|
|
||||||
|
|
||||||
var params = { name: repository_name, scm: 'git', is_private: true};
|
|
||||||
|
|
||||||
request.post({
|
|
||||||
url:url,
|
|
||||||
body: qs.stringify(params),
|
|
||||||
oauth:oauth
|
|
||||||
}, function (e, r, body) {
|
|
||||||
console.log(e);
|
|
||||||
console.log(r.statusCode);
|
|
||||||
console.log(body);
|
|
||||||
cb (e, body);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
var exec = require('child_process').exec,
|
var path = require('path'),
|
||||||
fs = require ('fs'),
|
db = require('../models/jobModel'),
|
||||||
path = require('path'),
|
exec = require('child_process').exec,
|
||||||
winston = require('winston'),
|
fs = require ('fs'),
|
||||||
exec_helper = require('./exec_helper'),
|
winston = require('winston'),
|
||||||
redis = require('redis'),
|
exec_helper = require('./exec_helper'),
|
||||||
client = redis.createClient(),
|
ws_helper = require('./websocket_helper'),
|
||||||
later = require('later').later;
|
later = require('later'),
|
||||||
enParser = require('later').enParser,
|
job_queue = [];
|
||||||
job_queue = [];
|
|
||||||
|
|
||||||
fs.exists || (fs.exists = path.exists);
|
fs.exists || (fs.exists = path.exists);
|
||||||
|
|
||||||
|
|
@ -20,96 +19,88 @@ function execute_job(file) {
|
||||||
console.log("execute_job");
|
console.log("execute_job");
|
||||||
console.log(file.key);
|
console.log(file.key);
|
||||||
|
|
||||||
client.hmset(file.key, "last_run", new Date(), function() {
|
file.last_run = new Date();
|
||||||
//repopulate the job list in the editor
|
db.update({key: file.key}, file, {upsert: true}, function(err) {
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
winston.info('scheduled job no longer exists, deleting from queue: ' + file_path);
|
winston.info('scheduled job no longer exists, deleting from queue: ' + file_path);
|
||||||
client.del(file.key);
|
//TODO redis to nedb
|
||||||
client.srem("jobs", file.key);
|
db.remove({key: file.key});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function schedule_job(key, job) {
|
function schedule_job(key, job) {
|
||||||
var is_new_job = true,
|
if (!key) {
|
||||||
l = later(60),
|
return;
|
||||||
schedule = enParser().parse(job.text);
|
}
|
||||||
|
|
||||||
l.exec(schedule, new Date(), execute_job, job);
|
var is_new_job = true,
|
||||||
console.log("Job Scheduled: ", schedule);
|
schedule = later.parse.text(job.text);
|
||||||
|
|
||||||
var len = job_queue.length;
|
later.date.localTime();
|
||||||
for (var i=0; i<len; i++) {
|
var job_timer = later.setInterval(execute_job.bind(null, job), schedule);
|
||||||
if (job_queue[i].key === key) {
|
console.log("Job Scheduled: ", schedule);
|
||||||
//job already exists, but has been modified, let's stop the existing one
|
|
||||||
job_queue[i].later.stopExec();
|
|
||||||
|
|
||||||
//replace it in the queue
|
var len = job_queue.length;
|
||||||
job_queue[i] = {key: key, later: l};
|
for (var i=0; i<len; i++) {
|
||||||
|
if (job_queue[i].key === key) {
|
||||||
|
//job already exists, but has been modified, let's stop the existing one
|
||||||
|
job_queue[i].job_timer.clear();
|
||||||
|
|
||||||
is_new_job = false;
|
//replace it in the queue
|
||||||
break;
|
job_queue[i] = {key: key, job_timer: job_timer};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_new_job) {
|
is_new_job = false;
|
||||||
job_queue.push({key: key, later: l});
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//console.log(job_queue);
|
if (is_new_job) {
|
||||||
|
job_queue.push({key: key, job_timer: job_timer});
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(job_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.emit_scheduled_jobs = function emit_scheduled_jobs(username, socket) {
|
exports.emit_scheduled_jobs = function emit_scheduled_jobs(socket) {
|
||||||
var job_list = [];
|
winston.debug("emit_scheduled_jobs");
|
||||||
client.smembers("jobs", function(err, res) {
|
db.find({type: "job"}, function(err, data) {
|
||||||
res.forEach(function(key, i) {
|
ws_helper.send_message(socket, 'scheduled-job-list', data);
|
||||||
client.hgetall(key, function(err, job_data) {
|
|
||||||
if (job_data.username === username) {
|
|
||||||
job_list.push(job_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.length === (i+1)) {
|
|
||||||
socket.emit('scheduled-job-list', job_list);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create new schedule
|
* Create new schedule
|
||||||
*/
|
*/
|
||||||
exports.add_schedule = function(schedule, socket, session) {
|
exports.add_schedule = function(schedule, socket) {
|
||||||
var self = this;
|
var self = this;
|
||||||
schedule.file.username = session.username;
|
|
||||||
var file_path = schedule.file.path.replace('\/filesystem\/', '\/repositories\/');
|
var file_path = schedule.file.path.replace('\/filesystem\/', '\/repositories\/');
|
||||||
var key = "jobs:" + file_path.replace(/\W/g, ''); //keep only alphanumeric for key
|
var key = "jobs:" + file_path.replace(/\W/g, ''); //keep only alphanumeric for key
|
||||||
var job_data = {
|
var job_data = {
|
||||||
|
type: "job",
|
||||||
text: schedule.text,
|
text: schedule.text,
|
||||||
name: schedule.file.name,
|
name: schedule.file.name,
|
||||||
key: key,
|
key: key,
|
||||||
last_run: "",
|
last_run: "",
|
||||||
active: "1",
|
active: "1",
|
||||||
path: file_path,
|
path: file_path,
|
||||||
extension: schedule.file.extension,
|
extension: schedule.file.extension
|
||||||
username: schedule.file.username
|
|
||||||
};
|
};
|
||||||
console.log("add_schedule");
|
console.log("add_schedule");
|
||||||
console.log(job_data);
|
console.log(job_data);
|
||||||
|
|
||||||
client.sadd("jobs", key, function() {
|
db.update({key: key}, job_data, {upsert: true}, function(err, numReplaced, upsert) {
|
||||||
client.hmset(key, job_data, function() {
|
schedule_job(key, job_data);
|
||||||
schedule_job(key, job_data);
|
//repopulate the job list in the editor
|
||||||
//repopulate the job list in the editor
|
self.emit_scheduled_jobs(socket);
|
||||||
self.emit_scheduled_jobs(session.username, socket);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.delete_job = function(key, socket, session) {
|
exports.delete_job = function(key, socket) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var len = job_queue.length;
|
var len = job_queue.length;
|
||||||
for (var i=0; i<len; i++) {
|
for (var i=0; i<len; i++) {
|
||||||
|
|
@ -119,24 +110,21 @@ exports.delete_job = function(key, socket, session) {
|
||||||
//remove from array
|
//remove from array
|
||||||
job_queue.splice(i, 1);
|
job_queue.splice(i, 1);
|
||||||
//remove from redis
|
//remove from redis
|
||||||
client.del(key);
|
db.remove({key: key});
|
||||||
client.srem("jobs", key);
|
|
||||||
//emit change to front-end
|
//emit change to front-end
|
||||||
self.emit_scheduled_jobs(session.username, socket);
|
self.emit_scheduled_jobs(socket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.toggle_job = function(key, socket, session) {
|
exports.toggle_job = function(key, socket) {
|
||||||
var self = this;
|
var self = this;
|
||||||
console.log(key);
|
console.log(key);
|
||||||
client.hgetall(key, function(err, job) {
|
db.findOne({key: key}, function(err, job) {
|
||||||
console.log(job);
|
|
||||||
//toggle status
|
|
||||||
job.active = 1-job.active;
|
job.active = 1-job.active;
|
||||||
|
|
||||||
client.hmset(key, "active", job.active, function() {
|
db.update({key: key}, job, function() {
|
||||||
if (!job.active) {
|
if (!job.active) {
|
||||||
//remove job from queue, but not redis
|
//remove job from queue, but not redis
|
||||||
var len = job_queue.length;
|
var len = job_queue.length;
|
||||||
|
|
@ -147,31 +135,24 @@ exports.toggle_job = function(key, socket, session) {
|
||||||
//remove from array
|
//remove from array
|
||||||
job_queue.splice(i, 1);
|
job_queue.splice(i, 1);
|
||||||
//emit change to front-end
|
//emit change to front-end
|
||||||
self.emit_scheduled_jobs(session.username, socket);
|
self.emit_scheduled_jobs(socket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
schedule_job(key, job);
|
schedule_job(key, job);
|
||||||
//repopulate the job list in the editor
|
//repopulate the job list in the editor
|
||||||
self.emit_scheduled_jobs(session.username, socket);
|
self.emit_scheduled_jobs(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Jobs initialized at server startup
|
* Jobs initialized at server startup
|
||||||
*/
|
*/
|
||||||
exports.initialize_jobs = function() {
|
exports.initialize_jobs = function() {
|
||||||
client.smembers("jobs", function(err, res) {
|
db.find({type: "job"}, function(err, data) {
|
||||||
res.forEach(function(key) {
|
schedule_job(data.key, data);
|
||||||
client.hgetall(key, function(err, job_data) {
|
|
||||||
schedule_job(key, job_data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
8
helpers/websocket_helper.js
Normal file
8
helpers/websocket_helper.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
var config = require('../config/config');
|
||||||
|
|
||||||
|
exports.send_message = function send_message(ws, type, data) {
|
||||||
|
if (!ws) {
|
||||||
|
ws = config.editor_ws;
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify({type: type, data: data}));
|
||||||
|
}
|
||||||
11
models/jobModel.js
Normal file
11
models/jobModel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Datastore = require('nedb'),
|
||||||
|
path = require('path');
|
||||||
|
|
||||||
|
var jobsDb = new Datastore({
|
||||||
|
filename: path.resolve(__dirname, '../db/jobs_data_store'),
|
||||||
|
autoload: true
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = jobsDb;
|
||||||
11
models/webideModel.js
Normal file
11
models/webideModel.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Datastore = require('nedb'),
|
||||||
|
path = require('path');
|
||||||
|
|
||||||
|
var webideDb = new Datastore({
|
||||||
|
filename: path.resolve(__dirname, '../db/webide_data_store'),
|
||||||
|
autoload: true
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = webideDb;
|
||||||
12
monitor.js
Normal file
12
monitor.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
var forever = require('forever-monitor');
|
||||||
|
|
||||||
|
var child = new (forever.Monitor)('server.js', {
|
||||||
|
silent: false,
|
||||||
|
args: []
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('exit', function () {
|
||||||
|
console.log('your-filename.js has exited after 3 restarts');
|
||||||
|
});
|
||||||
|
|
||||||
|
child.start();
|
||||||
0
output.log
Normal file
0
output.log
Normal file
3617
package-lock.json
generated
Normal file
3617
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
39
package.json
39
package.json
|
|
@ -4,21 +4,28 @@
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "3.1.0",
|
"body-parser": "1.18.2",
|
||||||
"passport": "0.1.15",
|
"cookie": "0.2.3",
|
||||||
"passport-bitbucket": "0.1.2",
|
"cookie-parser": "1.4.3",
|
||||||
"passport-github": "0.1.3",
|
"express": "4.16.2",
|
||||||
"jade": "0.28.1",
|
"express-session": "1.12.1",
|
||||||
"request": "2.14.0",
|
"express-ws": "3.0.0",
|
||||||
"socket.io": "0.9.13",
|
"gitty": "^3.6.0",
|
||||||
"gitty": "git://github.com/jwcooper/Gitty.git",
|
"jsDAV": "jwcooper/jsDAV#629ded2",
|
||||||
"jsDAV": "git://github.com/jwcooper/jsDAV.git",
|
"later": "^1.2.0",
|
||||||
"connect": "2.7.3",
|
"method-override": "2.3.10",
|
||||||
"connect-redis": "1.x",
|
"morgan": "1.9.0",
|
||||||
"redis": "0.8.2",
|
"multer": "^1.3.0",
|
||||||
"tty.js": "git://github.com/jwcooper/tty.js.git",
|
"nedb": "1.8.0",
|
||||||
"validator": "0.4.25",
|
"node-pty": "0.7.4",
|
||||||
"winston": "0.6.2",
|
"pug": "2.0.1",
|
||||||
"later": "git://github.com/jwcooper/later.git"
|
"request": "2.83.0",
|
||||||
|
"serve-static": "1.13.1",
|
||||||
|
"validator": "9.4.0",
|
||||||
|
"winston": "2.4.0",
|
||||||
|
"xterm": "3.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"forever-monitor": "^1.7.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 44 KiB |
File diff suppressed because it is too large
Load diff
|
|
@ -6,7 +6,6 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
padding-top: 40px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +174,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
float: right;
|
float: right;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding-right: 15px;
|
padding: 4px 15px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigator-folder .refresh-directory:hover {
|
#navigator-folder .refresh-directory:hover {
|
||||||
|
|
@ -301,6 +300,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
|
|
||||||
#create-modal .modal-body input[type="text"] {
|
#create-modal .modal-body input[type="text"] {
|
||||||
width: 97%;
|
width: 97%;
|
||||||
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirm-modal p {
|
#confirm-modal p {
|
||||||
|
|
@ -345,6 +345,9 @@ a.navigator-settings i.settings-enabled {
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-input-wrapper input[type='text'], .rename-input-wrapper input[type='text'] {
|
.create-input-wrapper input[type='text'], .rename-input-wrapper input[type='text'] {
|
||||||
|
width: 185px;
|
||||||
|
margin: 5px;
|
||||||
|
height: 30px;
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
border: none;
|
border: none;
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
|
|
@ -356,11 +359,6 @@ a.navigator-settings i.settings-enabled {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-input-wrapper input[type='text'] {
|
|
||||||
width: 185px;
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rename-input-wrapper {
|
.rename-input-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: -2px 0 0 0;
|
padding: -2px 0 0 0;
|
||||||
|
|
@ -401,7 +399,8 @@ a.navigator-settings i.settings-enabled {
|
||||||
left: 300px;
|
left: 300px;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 50px;
|
top: 50px;
|
||||||
bottom: 40px;
|
bottom: 0px;
|
||||||
|
margin-bottom: 40px;
|
||||||
border-bottom: 1px solid #EDEDED;
|
border-bottom: 1px solid #EDEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -456,6 +455,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
margin-bottom: -40px;
|
||||||
border-top: 1px solid #EDEDED;
|
border-top: 1px solid #EDEDED;
|
||||||
border-right: 1px solid #EDEDED;
|
border-right: 1px solid #EDEDED;
|
||||||
}
|
}
|
||||||
|
|
@ -530,7 +530,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
margin: 0 1px 0 0;
|
margin: 0 1px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-element .font-size-value, .soft-tab-value, .tab-size-value, .invisibles-value, .manual-git-value {
|
.settings-element .font-size-value, .soft-tab-value, .tab-size-value, .invisibles-value, .manual-git-value, .python-version {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,6 +544,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#editor-output {
|
#editor-output {
|
||||||
|
|
@ -673,10 +674,6 @@ a.navigator-settings i.settings-enabled {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup-content .bitbucket-signup {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#setup-content form {
|
#setup-content form {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -692,6 +689,7 @@ a.navigator-settings i.settings-enabled {
|
||||||
|
|
||||||
#setup-content form input[type='text'], #setup-content form input[type='password'] {
|
#setup-content form input[type='text'], #setup-content form input[type='password'] {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup-content form .skip-button {
|
#setup-content form .skip-button {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,21 @@
|
||||||
|
-0.8.0
|
||||||
|
Add simple python3 support
|
||||||
|
Fix debug populating variables
|
||||||
|
|
||||||
|
-0.7.0
|
||||||
|
Update pug dependency
|
||||||
|
Updates to installer and uninstaller
|
||||||
|
|
||||||
|
-0.6.0
|
||||||
|
Initial pre-release of the simplified webide
|
||||||
|
|
||||||
|
-0.3.12
|
||||||
|
Add missing cookie package
|
||||||
|
|
||||||
|
-0.3.11
|
||||||
|
Fixes for installation errors
|
||||||
|
Fix some deprecated messages
|
||||||
|
|
||||||
-0.3.10
|
-0.3.10
|
||||||
Fix for settings being undefined in offline mode
|
Fix for settings being undefined in offline mode
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
0.3.8
|
0.8.0
|
||||||
http://adafruit-download.s3.amazonaws.com/webide-0.3.8-update.tar.gz
|
https://github.com/adafruit/Adafruit-WebIDE/archive/0.8.0.tar.gz
|
||||||
https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/changelog.txt
|
https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/release/changelog.txt
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
# for examples
|
# for examples
|
||||||
|
|
||||||
# If not running interactively, don't do anything
|
# If not running interactively, don't do anything
|
||||||
[ -z "$PS1" ] && return
|
case $- in
|
||||||
|
*i*) ;;
|
||||||
|
*) return;;
|
||||||
|
esac
|
||||||
|
|
||||||
# don't put duplicate lines or lines starting with space in the history.
|
# don't put duplicate lines or lines starting with space in the history.
|
||||||
# See bash(1) for more options
|
# See bash(1) for more options
|
||||||
|
|
@ -28,13 +31,13 @@ shopt -s checkwinsize
|
||||||
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||||
|
|
||||||
# set variable identifying the chroot you work in (used in the prompt below)
|
# set variable identifying the chroot you work in (used in the prompt below)
|
||||||
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
|
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||||
debian_chroot=$(cat /etc/debian_chroot)
|
debian_chroot=$(cat /etc/debian_chroot)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set a fancy prompt (non-color, unless we know we "want" color)
|
# set a fancy prompt (non-color, unless we know we "want" color)
|
||||||
case "$TERM" in
|
case "$TERM" in
|
||||||
xterm-color) color_prompt=yes;;
|
xterm-color|*-256color) color_prompt=yes;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# uncomment for a colored prompt, if the terminal has the capability; turned
|
# uncomment for a colored prompt, if the terminal has the capability; turned
|
||||||
|
|
@ -44,17 +47,17 @@ force_color_prompt=yes
|
||||||
|
|
||||||
if [ -n "$force_color_prompt" ]; then
|
if [ -n "$force_color_prompt" ]; then
|
||||||
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||||
# We have color support; assume it's compliant with Ecma-48
|
# We have color support; assume it's compliant with Ecma-48
|
||||||
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||||
# a case would tend to support setf rather than setaf.)
|
# a case would tend to support setf rather than setaf.)
|
||||||
color_prompt=yes
|
color_prompt=yes
|
||||||
else
|
else
|
||||||
color_prompt=
|
color_prompt=
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$color_prompt" = yes ]; then
|
if [ "$color_prompt" = yes ]; then
|
||||||
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w \$\[\033[00m\] '
|
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
|
||||||
else
|
else
|
||||||
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
||||||
fi
|
fi
|
||||||
|
|
@ -81,6 +84,9 @@ if [ -x /usr/bin/dircolors ]; then
|
||||||
alias egrep='egrep --color=auto'
|
alias egrep='egrep --color=auto'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# colored GCC warnings and errors
|
||||||
|
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
|
||||||
|
|
||||||
# some more ls aliases
|
# some more ls aliases
|
||||||
#alias ll='ls -l'
|
#alias ll='ls -l'
|
||||||
#alias la='ls -A'
|
#alias la='ls -A'
|
||||||
|
|
@ -98,6 +104,10 @@ fi
|
||||||
# enable programmable completion features (you don't need to enable
|
# enable programmable completion features (you don't need to enable
|
||||||
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
||||||
# sources /etc/bash.bashrc).
|
# sources /etc/bash.bashrc).
|
||||||
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
|
if ! shopt -oq posix; then
|
||||||
|
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||||
|
. /usr/share/bash-completion/bash_completion
|
||||||
|
elif [ -f /etc/bash_completion ]; then
|
||||||
. /etc/bash_completion
|
. /etc/bash_completion
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
22
scripts/.profile
Normal file
22
scripts/.profile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# ~/.profile: executed by the command interpreter for login shells.
|
||||||
|
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
|
||||||
|
# exists.
|
||||||
|
# see /usr/share/doc/bash/examples/startup-files for examples.
|
||||||
|
# the files are located in the bash-doc package.
|
||||||
|
|
||||||
|
# the default umask is set in /etc/profile; for setting the umask
|
||||||
|
# for ssh logins, install and configure the libpam-umask package.
|
||||||
|
#umask 022
|
||||||
|
|
||||||
|
# if running bash
|
||||||
|
if [ -n "$BASH_VERSION" ]; then
|
||||||
|
# include .bashrc if it exists
|
||||||
|
if [ -f "$HOME/.bashrc" ]; then
|
||||||
|
. "$HOME/.bashrc"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set PATH so it includes user's private bin if it exists
|
||||||
|
if [ -d "$HOME/bin" ] ; then
|
||||||
|
PATH="$HOME/bin:$PATH"
|
||||||
|
fi
|
||||||
19
scripts/adafruit-webide.service
Normal file
19
scripts/adafruit-webide.service
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Adafruit-WebIDE
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/node /usr/share/adafruit/webide/server.js
|
||||||
|
WorkingDirectory=/usr/share/adafruit/webide
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=webide
|
||||||
|
# Change to a non-root user
|
||||||
|
User=webide
|
||||||
|
Group=webide
|
||||||
|
# Set environment options
|
||||||
|
Environment=NODE_ENV=production PORT=8080
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -23,8 +23,8 @@ set(CPACK_PACKAGE_CONTACT "support@adafruit.com")
|
||||||
set(CPACK_PACKAGE_VENDOR "Adafruit")
|
set(CPACK_PACKAGE_VENDOR "Adafruit")
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "7")
|
set(CPACK_PACKAGE_VERSION_PATCH "12")
|
||||||
set(CPACK_PACKAGE_VERSION "0.3.7")
|
set(CPACK_PACKAGE_VERSION "0.3.12")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Adafruit WebIDE")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Adafruit WebIDE")
|
||||||
set(CPACK_RESOURCE_FILE_README "${EDITOR_DIR}/README.md")
|
set(CPACK_RESOURCE_FILE_README "${EDITOR_DIR}/README.md")
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${EDITOR_DIR}/GNU-AGPL-3.0")
|
set(CPACK_RESOURCE_FILE_LICENSE "${EDITOR_DIR}/GNU-AGPL-3.0")
|
||||||
|
|
@ -33,7 +33,7 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Adafruit")
|
||||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-ubuntu")
|
set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-ubuntu")
|
||||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "nodejs, nodejs-legacy, redis-server, git, restartd, libcap2-bin, avahi-daemon, i2c-tools, python-smbus")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "nodejs, nodejs-legacy, redis-server, git, avahi-daemon, i2c-tools, python-smbus")
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst;${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm;")
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst;${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm;")
|
||||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,6 @@ echo 'webide "node" "service adafruit-webide.sh restart" ""' >> /etc/restartd.co
|
||||||
|
|
||||||
cd /etc/init.d
|
cd /etc/init.d
|
||||||
|
|
||||||
NODE_PATH=""
|
|
||||||
ARCH=$(dpkg --print-architecture)
|
|
||||||
if [ $ARCH = armhf ]; then
|
|
||||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_hf\/node"
|
|
||||||
chmod +x "$WEBIDE_ROOT/bin/node_hf/node"
|
|
||||||
else
|
|
||||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_sf\/node"
|
|
||||||
chmod +x "$WEBIDE_ROOT/bin/node_sf/node"
|
|
||||||
fi
|
|
||||||
sed -i "s/NODE_PATH/$NODE_PATH/g" adafruit-webide.sh
|
|
||||||
|
|
||||||
update-rc.d adafruit-webide.sh defaults
|
update-rc.d adafruit-webide.sh defaults
|
||||||
|
|
||||||
echo "Attempting to force reload date and time from ntp server"
|
echo "Attempting to force reload date and time from ntp server"
|
||||||
|
|
|
||||||
|
|
@ -68,12 +68,12 @@ echo "Attempting to force reload date and time from ntp server"
|
||||||
/usr/bin/ntpdate -b -s -u pool.ntp.org
|
/usr/bin/ntpdate -b -s -u pool.ntp.org
|
||||||
|
|
||||||
echo "**** Downloading the latest version of the WebIDE ****"
|
echo "**** Downloading the latest version of the WebIDE ****"
|
||||||
curl -L http://adafruit-download.s3.amazonaws.com/webide-0.3.8.tar.gz | tar xzf -
|
curl -L https://adafruit-download.s3.amazonaws.com/webide-0.3.12.tar.gz | tar xzf -
|
||||||
|
|
||||||
echo "**** Installing required libraries ****"
|
echo "**** Installing required libraries ****"
|
||||||
echo "**** (redis-server git avahi-daemon i2c-tools python-smbus openssh-keygen) ****"
|
echo "**** (redis-server git avahi-daemon i2c-tools python-smbus openssh-keygen) ****"
|
||||||
opkg update
|
opkg update
|
||||||
opkg install nodejs git avahi-daemon i2c-tools python-smbus libcap2 libcap-bin openssh-keygen
|
opkg install nodejs git avahi-daemon i2c-tools python-smbus openssh-keygen
|
||||||
|
|
||||||
if ! redis-cli PING
|
if ! redis-cli PING
|
||||||
then
|
then
|
||||||
|
|
|
||||||
|
|
@ -53,29 +53,25 @@ WEBIDE_ROOT="/usr/share/adafruit/webide"
|
||||||
#needed for SSH key and config access at this point.
|
#needed for SSH key and config access at this point.
|
||||||
WEBIDE_HOME="/home/webide"
|
WEBIDE_HOME="/home/webide"
|
||||||
|
|
||||||
#NODE_PATH="/usr/local/lib/node"
|
|
||||||
|
|
||||||
#if [ ! -d "$NODE_PATH" ]; then
|
|
||||||
# mkdir -p "$NODE_PATH"
|
|
||||||
# # Control will enter here if $DIRECTORY doesn't exist.
|
|
||||||
#fi
|
|
||||||
|
|
||||||
mkdir -p "$WEBIDE_ROOT"
|
mkdir -p "$WEBIDE_ROOT"
|
||||||
mkdir -p "$WEBIDE_HOME"
|
mkdir -p "$WEBIDE_HOME/tmp"
|
||||||
cd "$WEBIDE_ROOT"
|
cd "$WEBIDE_ROOT"
|
||||||
|
|
||||||
echo "**** Downloading the latest version of the WebIDE ****"
|
echo "**** Downloading the latest version of the WebIDE ****"
|
||||||
curl -L http://adafruit-download.s3.amazonaws.com/webide-0.3.8.tar.gz | tar xzf -
|
curl -L https://github.com/adafruit/Adafruit-WebIDE/archive/0.8.0.tar.gz | tar xzf - --strip-components=1
|
||||||
|
|
||||||
echo "**** Installing required libraries ****"
|
echo "**** Installing required libraries ****"
|
||||||
echo "**** (redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus) ****"
|
echo "**** (nodejs-legacy npm git i2c-tools python-smbus ntp libkrb5-dev) ****"
|
||||||
|
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install nodejs nodejs-legacy redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus ntp -y
|
apt-get install nodejs git i2c-tools python-smbus ntp libkrb5-dev -y
|
||||||
|
npm install -g npm
|
||||||
|
|
||||||
echo "**** Create webide user and group ****"
|
echo "**** Create webide user and group ****"
|
||||||
groupadd webide || true
|
groupadd webide || true
|
||||||
useradd -g webide webide || true
|
useradd -g webide webide || true
|
||||||
usermod -a -G i2c,sudo webide || true
|
usermod -a -G i2c,sudo webide || true
|
||||||
|
chsh -s /bin/bash webide
|
||||||
|
|
||||||
echo "**** Adding webide user to sudoers ****"
|
echo "**** Adding webide user to sudoers ****"
|
||||||
if [ -f "/etc/sudoers.tmp" ]; then
|
if [ -f "/etc/sudoers.tmp" ]; then
|
||||||
|
|
@ -93,75 +89,28 @@ chown -R webide:webide "$WEBIDE_HOME"
|
||||||
chown -R webide:webide "$WEBIDE_ROOT"
|
chown -R webide:webide "$WEBIDE_ROOT"
|
||||||
chmod 775 "$WEBIDE_ROOT"
|
chmod 775 "$WEBIDE_ROOT"
|
||||||
|
|
||||||
|
echo "**** Installing webide dependencies ****"
|
||||||
|
sudo -u webide npm install
|
||||||
|
|
||||||
echo "**** Adding default .bashrc file for webide user ****"
|
echo "**** Adding default .bashrc file for webide user ****"
|
||||||
cp "$WEBIDE_ROOT/scripts/.bashrc" "$WEBIDE_HOME"
|
cp "$WEBIDE_ROOT/scripts/.bashrc" "$WEBIDE_HOME"
|
||||||
|
|
||||||
echo "**** Installing the WebIDE as a service ****"
|
|
||||||
echo "**** (to uninstall service, execute: 'sudo update-rc.d -f adafruit-webide.sh remove') ****"
|
|
||||||
cp "$WEBIDE_ROOT/scripts/adafruit-webide.sh" "/etc/init.d"
|
|
||||||
cd /etc/init.d
|
|
||||||
chmod 755 adafruit-webide.sh
|
|
||||||
|
|
||||||
NODE_PATH=""
|
|
||||||
ARCH=$(dpkg --print-architecture)
|
|
||||||
if [ $ARCH = armhf ]; then
|
|
||||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_hf\/node"
|
|
||||||
chmod +x "$WEBIDE_ROOT/bin/node_hf/node"
|
|
||||||
else
|
|
||||||
NODE_PATH="\/usr\/share\/adafruit\/webide\/bin\/node_sf\/node"
|
|
||||||
chmod +x "$WEBIDE_ROOT/bin/node_sf/node"
|
|
||||||
fi
|
|
||||||
sed -i "s/NODE_PATH/$NODE_PATH/g" adafruit-webide.sh
|
|
||||||
|
|
||||||
update-rc.d adafruit-webide.sh defaults
|
|
||||||
|
|
||||||
#set binaries as executable
|
|
||||||
|
|
||||||
echo "Attempting to force reload date and time from ntp server"
|
echo "Attempting to force reload date and time from ntp server"
|
||||||
/etc/init.d/ntp force-reload
|
/etc/init.d/ntp force-reload
|
||||||
|
|
||||||
#Check if port 80 is in use, use 8080 if so.
|
# echo "**** Installing the WebIDE as a service ****"
|
||||||
PORT_USED=""
|
# echo "**** (to uninstall service, execute: 'sudo update-rc.d -f adafruit-webide.sh remove') ****"
|
||||||
if netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".80"' | grep -q "LISTEN"
|
cp "$WEBIDE_ROOT/scripts/adafruit-webide.service" "/etc/systemd/system/adafruit-webide.service"
|
||||||
then
|
systemctl enable adafruit-webide.service
|
||||||
redis-cli HMSET server port 8090
|
systemctl start adafruit-webide.service
|
||||||
PORT_USED=":8090"
|
|
||||||
echo "**** WARNING: PORT 80 IN USE. FALLING BACK TO 8090. ****"
|
|
||||||
echo "**** TO CHOOSE A DIFFERENT PORT USE THE FOLLOWING COMMAND: ****"
|
|
||||||
echo "**** redis-cli HMSET server port 8090 ****"
|
|
||||||
echo "**** AND RESTART THE SERVER ****"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $OFFLINE
|
|
||||||
then
|
|
||||||
redis-cli HMSET server offline 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $GITHUB
|
|
||||||
then
|
|
||||||
redis-cli HMSET server github 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
service adafruit-webide.sh start
|
|
||||||
|
|
||||||
if grep -q adafruit-webide.sh /etc/restartd.conf
|
|
||||||
then
|
|
||||||
echo "restartd already configured"
|
|
||||||
else
|
|
||||||
echo 'webide "node" "service adafruit-webide.sh restart" ""' >> /etc/restartd.conf
|
|
||||||
fi
|
|
||||||
|
|
||||||
#kill all restartd processes, and restart one
|
|
||||||
pkill -f restartd || true
|
|
||||||
sleep 5s
|
|
||||||
restartd
|
|
||||||
|
|
||||||
echo "**** Starting the server...(please wait) ****"
|
echo "**** Starting the server...(please wait) ****"
|
||||||
sleep 20s
|
sleep 20s
|
||||||
|
|
||||||
echo "**** The Adafruit WebIDE is installed and running! ****"
|
echo "**** The Adafruit WebIDE is installed and running! ****"
|
||||||
echo "**** Commands: sudo service adafruit-webide.sh {start,stop,restart} ****"
|
echo "**** Commands: sudo systemctl {start,stop,restart} adafruit-webide ****"
|
||||||
echo "**** Navigate to http://$(hostname).local$PORT_USED to use the WebIDE"
|
echo "**** Navigate to http://$(hostname).local:8080 to use the WebIDE"
|
||||||
#echo "**** To run the editor: ****"
|
#echo "**** To run the editor: ****"
|
||||||
#echo "**** cd ~/Adafruit/WebIDE ****"
|
#echo "**** cd ~/Adafruit/WebIDE ****"
|
||||||
#echo "**** node webide ****"
|
#echo "**** node webide ****"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
cd ~
|
cd ~
|
||||||
git clone git://github.com/adafruit/Adafruit-WebIDE.git
|
git clone git://github.com/adafruit/Adafruit-WebIDE.git
|
||||||
cd Adafruit-WebIDE
|
cd Adafruit-WebIDE
|
||||||
chmod +x bin/node_hf/node
|
|
||||||
sudo ln -s /home/pi/Adafruit-WebIDE/bin/node_hf/node /usr/bin/node
|
|
||||||
sudo ln -s /home/pi/Adafruit-WebIDE/bin/node_hf/node /usr/lib/node
|
|
||||||
curl -L https://npmjs.org/install.sh | sudo sh
|
curl -L https://npmjs.org/install.sh | sudo sh
|
||||||
npm install
|
npm install
|
||||||
cd ..
|
cd ..
|
||||||
cp -r Adafruit-WebIDE Adafruit-WebIDE-Update
|
cp -r Adafruit-WebIDE Adafruit-WebIDE-Update
|
||||||
cd Adafruit-WebIDE-Update/node_modules
|
cd Adafruit-WebIDE-Update/node_modules
|
||||||
rm -rf winston passport-bitbucket socket.io jsDAV connect-redis request connect passport express gitty jade redis validator
|
rm -rf winston socket.io jsDAV connect-redis request connect express gitty jade redis validator
|
||||||
|
|
|
||||||
|
|
@ -42,4 +42,4 @@ echo "**** libraries installed that we did not uninstall as ****"
|
||||||
echo "**** we're not able to determine if other applications are dependent ****"
|
echo "**** we're not able to determine if other applications are dependent ****"
|
||||||
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
||||||
echo "**** the following command: ****"
|
echo "**** the following command: ****"
|
||||||
echo "**** opkg remove nodejs git avahi-daemon i2c-tools python-smbus libcap2 libcap-bin ****"
|
echo "**** opkg remove nodejs git avahi-daemon i2c-tools python-smbus ****"
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,10 @@
|
||||||
# curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall.sh | sudo sh
|
# curl https://raw.githubusercontent.com/adafruit/Adafruit-WebIDE/alpha/scripts/uninstall.sh | sudo sh
|
||||||
|
|
||||||
|
|
||||||
WEBIDE_ROOT="/usr/share/adafruit"
|
WEBIDE_ROOT="/usr/share/adafruit/webide"
|
||||||
WEBIDE_HOME="/home/webide"
|
WEBIDE_HOME="/home/webide"
|
||||||
NODE_PATH=""
|
NODE_PATH=""
|
||||||
|
|
||||||
echo "**** Removing restartd WebIDE configuration ****"
|
|
||||||
sed -i '/adafruit-webide.sh/ d' /etc/restartd.conf
|
|
||||||
#kill all restartd processes, and restart one
|
|
||||||
pkill -f restartd || true
|
|
||||||
sleep 5s
|
|
||||||
restartd
|
|
||||||
|
|
||||||
echo "**** Removing webide user from sudoers ****"
|
echo "**** Removing webide user from sudoers ****"
|
||||||
if [ -f "/etc/sudoers.tmp" ]; then
|
if [ -f "/etc/sudoers.tmp" ]; then
|
||||||
rm /etc/sudoers.tmp
|
rm /etc/sudoers.tmp
|
||||||
|
|
@ -26,35 +19,28 @@ if [ "$?" -eq "0" ]; then
|
||||||
fi
|
fi
|
||||||
rm /etc/sudoers.tmp
|
rm /etc/sudoers.tmp
|
||||||
|
|
||||||
echo "**** Removing access to port 80 for node ****"
|
|
||||||
NODE_PATH=""
|
|
||||||
ARCH=$(dpkg --print-architecture)
|
|
||||||
if [ $ARCH = armhf ]; then
|
|
||||||
NODE_PATH="/usr/share/adafruit/webide/bin/node_hf/node"
|
|
||||||
else
|
|
||||||
NODE_PATH="/usr/share/adafruit/webide/bin/node_sf/node"
|
|
||||||
fi
|
|
||||||
setcap -r "$NODE_PATH"
|
|
||||||
|
|
||||||
echo "**** Stopping the Adafruit WebIDE ****"
|
echo "**** Stopping the Adafruit WebIDE ****"
|
||||||
service adafruit-webide.sh stop
|
service adafruit-webide.sh stop
|
||||||
sleep 5s
|
sleep 5s
|
||||||
|
|
||||||
echo "**** Removing update-rc.d service ****"
|
echo "**** Removing systemd service ****"
|
||||||
update-rc.d -f adafruit-webide.sh remove
|
systemctl stop adafruit-webide
|
||||||
rm /etc/init.d/adafruit-webide.sh
|
systemctl disable adafruit-webide
|
||||||
|
rm /etc/systemd/system/adafruit-webide.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl reset-failed
|
||||||
|
|
||||||
echo "**** Removing the WebIDE Folder ****"
|
echo "**** Removing the WebIDE Folder ****"
|
||||||
rm -rf "$WEBIDE_ROOT"
|
shopt -s extglob
|
||||||
|
rm -rf "$WEBIDE_ROOT"/!(repositories)
|
||||||
echo "**** Removing webide user ****"
|
echo "**** Removing webide user ****"
|
||||||
userdel -r webide
|
userdel -r webide
|
||||||
|
|
||||||
echo "**** Removing redis server setting ****"
|
|
||||||
redis-cli del server
|
|
||||||
|
|
||||||
echo "**** The Adafruit WebIDE is now uninstalled! ****"
|
echo "**** The Adafruit WebIDE is now uninstalled! ****"
|
||||||
|
echo "**** Your code and repositories remain at $WEBIDE_ROOT ****"
|
||||||
echo "**** During the installation process, there were a few ****"
|
echo "**** During the installation process, there were a few ****"
|
||||||
echo "**** libraries installed that we did not uninstall as ****"
|
echo "**** libraries installed that we did not uninstall as ****"
|
||||||
echo "**** we're not able to determine if other applications are dependent ****"
|
echo "**** we're not able to determine if other applications are dependent ****"
|
||||||
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
echo "**** on them. If you are not using them, you can uninstall by executing ****"
|
||||||
echo "**** the following command: ****"
|
echo "**** the following command: ****"
|
||||||
echo "**** sudo apt-get remove nodejs npm redis-server git restartd libcap2-bin avahi-daemon i2c-tools python-smbus ****"
|
echo "**** sudo apt-get remove nodejs-legacy yarn git i2c-tools python-smbus ntp libkrb5-dev ****"
|
||||||
|
|
|
||||||
549
server.js
549
server.js
|
|
@ -1,124 +1,52 @@
|
||||||
var express = require('express'),
|
var express = require('express'),
|
||||||
tty = require('tty.js'),
|
session = require('express-session'),
|
||||||
|
bodyParser = require('body-parser'),
|
||||||
|
methodOverride = require('method-override'),
|
||||||
|
cookieParser = require('cookie-parser'),
|
||||||
|
serveStatic = require('serve-static'),
|
||||||
|
morgan = require('morgan'),
|
||||||
app = express(),
|
app = express(),
|
||||||
|
expressWs = require('express-ws')(app),
|
||||||
|
multer = require('multer'),
|
||||||
|
upload = multer({ dest: './uploads' }),
|
||||||
util = require('util'),
|
util = require('util'),
|
||||||
io = require('socket.io'),
|
|
||||||
passport = require('passport'),
|
|
||||||
util = require('util'),
|
util = require('util'),
|
||||||
BitbucketStrategy = require('passport-bitbucket').Strategy,
|
|
||||||
GitHubStrategy = require('passport-github').Strategy,
|
|
||||||
site = require('./controllers/site'),
|
site = require('./controllers/site'),
|
||||||
editor = require('./controllers/editor'),
|
editor = require('./controllers/editor'),
|
||||||
user = require('./controllers/user'),
|
user = require('./controllers/user'),
|
||||||
jsDAV = require("jsDAV/lib/jsdav"),
|
jsDAV = require("jsDAV/lib/jsdav"),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
updater = require('./helpers/updater'),
|
|
||||||
scheduler = require('./helpers/scheduler'),
|
scheduler = require('./helpers/scheduler'),
|
||||||
editor_setup = require('./helpers/editor_setup'),
|
|
||||||
git_helper = require('./helpers/git_helper'),
|
|
||||||
exec_helper = require('./helpers/exec_helper'),
|
|
||||||
fs_helper = require('./helpers/fs_helper'),
|
fs_helper = require('./helpers/fs_helper'),
|
||||||
exec_helper = require('./helpers/exec_helper'),
|
|
||||||
request_helper = require('./helpers/request_helper'),
|
|
||||||
debug_helper = require('./helpers/python/debug_helper'),
|
debug_helper = require('./helpers/python/debug_helper'),
|
||||||
RedisStore = require('connect-redis')(express),
|
|
||||||
redis = require("redis"),
|
|
||||||
client = redis.createClient(),
|
|
||||||
config = require('./config/config'),
|
config = require('./config/config'),
|
||||||
winston = require('winston');
|
winston = require('winston'),
|
||||||
|
db = require('./models/webideModel'),
|
||||||
|
pty = require('node-pty');
|
||||||
|
|
||||||
var davServer,
|
var davServer,
|
||||||
HOSTNAME,
|
HOSTNAME,
|
||||||
IS_PASSPORT_SETUP = false,
|
|
||||||
REPOSITORY_PATH = path.resolve(__dirname + "/repositories");
|
REPOSITORY_PATH = path.resolve(__dirname + "/repositories");
|
||||||
|
|
||||||
winston.info("REPOSITORY_PATH", REPOSITORY_PATH);
|
|
||||||
|
|
||||||
//exec_helper.spawn_ipython();
|
|
||||||
|
var terminals = {}, logs = {};
|
||||||
|
|
||||||
//check for the existence of the logs directory, if it doesn't
|
//check for the existence of the logs directory, if it doesn't
|
||||||
//exist, create it prior to starting the child process.
|
//exist, create it prior to starting the child process.
|
||||||
var exists = path.existsSync(__dirname + '/logs');
|
var exists = fs.existsSync(__dirname + '/logs');
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
fs.mkdirSync(__dirname + '/logs', 0755);
|
fs.mkdirSync(__dirname + '/logs', 0755);
|
||||||
winston.info('created logs folder');
|
winston.info('created logs folder');
|
||||||
}
|
}
|
||||||
|
|
||||||
winston.add(winston.transports.File, { filename: __dirname + '/logs/output.log', json: false });
|
//winston.add(winston.transports.File, { filename: __dirname + '/logs/output.log', json: false });
|
||||||
winston.handleExceptions(new winston.transports.File({ filename: __dirname + '/logs/errors.log', json: false }));
|
//winston.handleExceptions(new winston.transports.File({ filename: __dirname + '/logs/errors.log', json: false }));
|
||||||
winston.remove(winston.transports.Console);
|
//winston.remove(winston.transports.Console);
|
||||||
|
|
||||||
// Passport session setup.
|
|
||||||
// To support persistent login sessions, Passport needs to be able to
|
|
||||||
// serialize users into and deserialize users out of the session. Typically,
|
|
||||||
// this will be as simple as storing the user ID when serializing, and finding
|
|
||||||
// the user by ID when deserializing. However, since this example does not
|
|
||||||
// have a database of user records, the complete Bitbucket profile is
|
|
||||||
// serialized and deserialized.
|
|
||||||
|
|
||||||
|
|
||||||
// Use the BitbucketStrategy within Passport.
|
winston.info("REPOSITORY_PATH", REPOSITORY_PATH);
|
||||||
// Strategies in passport require a `verify` function, which accept
|
|
||||||
// credentials (in this case, a token, tokenSecret, and Bitbucket profile),
|
|
||||||
// and invoke a callback with a user object.
|
|
||||||
function setup_bitbucket_passport(consumer_key, consumer_secret) {
|
|
||||||
winston.info("http://" + HOSTNAME + "/auth/bitbucket/callback");
|
|
||||||
passport.use(new BitbucketStrategy({
|
|
||||||
consumerKey: consumer_key,
|
|
||||||
consumerSecret: consumer_secret,
|
|
||||||
callbackURL: "http://" + HOSTNAME + "/auth/bitbucket/callback"
|
|
||||||
},
|
|
||||||
function(token, tokenSecret, profile, done) {
|
|
||||||
// asynchronous verification, for effect...
|
|
||||||
process.nextTick(function () {
|
|
||||||
profile.token = token;
|
|
||||||
profile.token_secret = tokenSecret;
|
|
||||||
profile.consumer_key = consumer_key;
|
|
||||||
profile.consumer_secret = consumer_secret;
|
|
||||||
|
|
||||||
return done(null, profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the GitHubStrategy within Passport.
|
|
||||||
// Strategies in passport require a `verify` function, which accept
|
|
||||||
// credentials (in this case, a token, tokenSecret, and Github profile),
|
|
||||||
// and invoke a callback with a user object.
|
|
||||||
function setup_github_passport(consumer_key, consumer_secret) {
|
|
||||||
winston.info("http://" + HOSTNAME + "/auth/github/callback");
|
|
||||||
passport.use(new GitHubStrategy({
|
|
||||||
clientID: consumer_key,
|
|
||||||
clientSecret: consumer_secret,
|
|
||||||
callbackURL: "http://" + HOSTNAME + "/auth/github/callback",
|
|
||||||
userAgent: HOSTNAME
|
|
||||||
},
|
|
||||||
function(accessToken, refreshToken, profile, done) {
|
|
||||||
// asynchronous verification, for effect...
|
|
||||||
process.nextTick(function () {
|
|
||||||
profile.token = accessToken;
|
|
||||||
profile.refresh_token = refreshToken;
|
|
||||||
profile.consumer_key = consumer_key;
|
|
||||||
profile.consumer_secret = consumer_secret;
|
|
||||||
|
|
||||||
return done(null, profile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
passport.serializeUser(function(user, done) {
|
|
||||||
client.set(user.username, JSON.stringify(user));
|
|
||||||
done(null, user.username);
|
|
||||||
});
|
|
||||||
|
|
||||||
passport.deserializeUser(function(obj, done) {
|
|
||||||
client.get(obj, function(err, reply) {
|
|
||||||
done(null, JSON.parse(reply));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//redirect anything with /filesystem in the url to the WebDav server.
|
//redirect anything with /filesystem in the url to the WebDav server.
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
|
|
@ -130,91 +58,118 @@ app.use(function(req, res, next) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var sessionStore = new RedisStore();
|
app.set('view engine', 'pug');
|
||||||
app.set('view engine', 'jade');
|
|
||||||
app.set('views', __dirname + '/views');
|
app.set('views', __dirname + '/views');
|
||||||
app.use(express.logger());
|
//logging
|
||||||
//app.use(express.logger("dev"));
|
app.use(morgan('tiny'));
|
||||||
app.use(express.static(__dirname + '/public'));
|
app.use(serveStatic(__dirname + '/public'));
|
||||||
app.use(express.static(__dirname + '/node_modules/tty.js/static'));
|
app.use(serveStatic(__dirname + '/node_modules/xterm/dist'));
|
||||||
app.use(express.cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.session({
|
var sessionMiddleware = session({
|
||||||
store: sessionStore,
|
|
||||||
key: 'sid',
|
key: 'sid',
|
||||||
secret: 'cat nap'
|
secret: 'cat nap',
|
||||||
}));
|
resave: true,
|
||||||
app.use(express.bodyParser());
|
saveUninitialized: true
|
||||||
app.use(express.methodOverride());
|
});
|
||||||
app.use(passport.initialize());
|
app.use(sessionMiddleware);
|
||||||
app.use(passport.session());
|
app.use(bodyParser.json())
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true }))
|
||||||
|
app.use(methodOverride());
|
||||||
|
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
res.locals.session = req.session;
|
res.locals.session = req.session;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(app.router);
|
app.get('/', site.index);
|
||||||
|
|
||||||
app.use(errorHandler);
|
app.get('/editor', editor.index);
|
||||||
|
app.get('/editor/image', editor.image);
|
||||||
|
|
||||||
|
app.post('/editor/upload', upload.single('obj'), editor.upload_file);
|
||||||
|
|
||||||
app.get('/', ensureAuthenticated, site.index);
|
app.post('/create/repository', editor.create_repository);
|
||||||
|
|
||||||
app.get('/editor', ensureAuthenticated, editor.index);
|
|
||||||
app.get('/editor/image', ensureAuthenticated, editor.image);
|
|
||||||
app.post('/editor/upload', ensureAuthenticated, editor.upload_file);
|
|
||||||
|
|
||||||
app.post('/create/repository', ensureAuthenticated, editor.create_repository);
|
|
||||||
|
|
||||||
app.get('/setup', user.setup);
|
app.get('/setup', user.setup);
|
||||||
app.post('/setup', user.submit_setup);
|
app.post('/setup', user.submit_setup);
|
||||||
app.get('/config', user.config);
|
app.get('/config', user.config);
|
||||||
app.post('/config', user.submit_config);
|
app.post('/config', user.submit_config);
|
||||||
app.get('/set-datetime', user.set_datetime);
|
app.get('/set-datetime', user.set_datetime);
|
||||||
app.get('/login', ensureOauth, user.login);
|
|
||||||
app.get('/logout', user.logout);
|
|
||||||
|
|
||||||
// GET /auth/bitbucket
|
app.post('/terminals', function (req, res) {
|
||||||
// Use passport.authenticate() as route middleware to authenticate the
|
var cols = parseInt(req.query.cols),
|
||||||
// request. The first step in Bitbucket authentication will involve redirecting
|
rows = parseInt(req.query.rows),
|
||||||
// the user to bitbucket.org. After authorization, Bitbucket will redirect the user
|
cwd = req.query.cwd;
|
||||||
// back to this application at /auth/bitbucket/callback
|
|
||||||
app.get('/auth/bitbucket',
|
|
||||||
passport.authenticate('bitbucket'),
|
|
||||||
function(req, res){
|
|
||||||
// The request will be redirected to Bitbucket for authentication, so this
|
|
||||||
// function will not be called.
|
|
||||||
});
|
|
||||||
|
|
||||||
// GET /auth/bitbucket/callback
|
var term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
|
||||||
// Use passport.authenticate() as route middleware to authenticate the
|
name: 'xterm-color',
|
||||||
// request. If authentication fails, the user will be redirected back to the
|
cols: cols || 80,
|
||||||
// login page. Otherwise, the primary route function function will be calsled,
|
rows: rows || 24,
|
||||||
// which, in this example, will redirect the user to the home page.
|
cwd: path.resolve(cwd),
|
||||||
app.get('/auth/bitbucket/callback',
|
env: process.env
|
||||||
passport.authenticate('bitbucket', { failureRedirect: '/login' }),
|
});
|
||||||
function(req, res) {
|
|
||||||
res.redirect('/editor');
|
|
||||||
});
|
|
||||||
|
|
||||||
// GET /auth/github
|
console.log('Created terminal with PID: ' + term.pid);
|
||||||
app.get('/auth/github',
|
terminals[term.pid] = term;
|
||||||
passport.authenticate('github'),
|
logs[term.pid] = '';
|
||||||
function(req, res){
|
term.on('data', function(data) {
|
||||||
// The request will be redirected to Github for authentication, so this
|
logs[term.pid] += data;
|
||||||
// function will not be called.
|
|
||||||
});
|
});
|
||||||
|
res.send(term.pid.toString());
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
// GET /auth/github/callback
|
app.post('/terminals/:pid/size', function (req, res) {
|
||||||
app.get('/auth/github/callback',
|
var pid = parseInt(req.params.pid),
|
||||||
passport.authenticate('github', { failureRedirect: '/login' }),
|
cols = parseInt(req.query.cols),
|
||||||
function(req, res) {
|
rows = parseInt(req.query.rows),
|
||||||
res.redirect('/editor');
|
term = terminals[pid];
|
||||||
|
|
||||||
|
term.resize(cols, rows);
|
||||||
|
console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.ws('/terminals/:pid', function (ws, req) {
|
||||||
|
var term = terminals[parseInt(req.params.pid)];
|
||||||
|
console.log('Connected to terminal ' + term.pid);
|
||||||
|
ws.send(logs[term.pid]);
|
||||||
|
|
||||||
|
term.on('data', function(data) {
|
||||||
|
try {
|
||||||
|
ws.send(data);
|
||||||
|
} catch (ex) {
|
||||||
|
// The WebSocket is not open, ignore
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
ws.on('message', function(msg) {
|
||||||
|
try {
|
||||||
|
msg = JSON.parse(msg);
|
||||||
|
} catch (e) {
|
||||||
|
//not json, just a string...
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.type === 'input') {
|
||||||
|
term.write(msg.data.toString() + '\r');
|
||||||
|
} else {
|
||||||
|
term.write(msg.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ws.on('close', function () {
|
||||||
|
term.kill();
|
||||||
|
console.log('Closed terminal ' + term.pid);
|
||||||
|
// Clean things up
|
||||||
|
delete terminals[term.pid];
|
||||||
|
delete logs[term.pid];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.ws('/editor', editor.editor);
|
||||||
|
|
||||||
|
app.use(errorHandler);
|
||||||
|
|
||||||
serverInitialization(app);
|
serverInitialization(app);
|
||||||
|
|
||||||
|
|
||||||
function errorHandler(err, req, res, next) {
|
function errorHandler(err, req, res, next) {
|
||||||
winston.error(err);
|
winston.error(err);
|
||||||
if (err.name === "InternalOAuthError") {
|
if (err.name === "InternalOAuthError") {
|
||||||
|
|
@ -226,93 +181,6 @@ function errorHandler(err, req, res, next) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple route middleware to ensure user is authenticated.
|
|
||||||
// Use this route middleware on any resource that needs to be protected. If
|
|
||||||
// the request is authenticated (typically via a persistent login session),
|
|
||||||
// the request will proceed. Otherwise, the user will be redirected to the
|
|
||||||
// login page.
|
|
||||||
function ensureAuthenticated(req, res, next) {
|
|
||||||
setHostName(req);
|
|
||||||
|
|
||||||
if (config.editor.offline) {
|
|
||||||
req.user = { provider: 'offline',
|
|
||||||
username: 'offline user' };
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function authRoute(req, res, next) {
|
|
||||||
if (req.isAuthenticated()) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_PASSPORT_SETUP) {
|
|
||||||
res.redirect('/setup');
|
|
||||||
} else {
|
|
||||||
res.redirect('/login');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//use the correct key for redis, either github or bitbucket
|
|
||||||
var oauth_key = 'bitbucket_oauth';
|
|
||||||
if (config.editor.github) {
|
|
||||||
oauth_key = 'github_oauth';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_PASSPORT_SETUP) {
|
|
||||||
//need to setup passport on server startup, if the oauth is already setup
|
|
||||||
client.hgetall(oauth_key, function (err, oauth) {
|
|
||||||
if (oauth) {
|
|
||||||
if (config.editor.github) {
|
|
||||||
setup_github_passport(oauth.consumer_key, oauth.consumer_secret);
|
|
||||||
} else {
|
|
||||||
setup_bitbucket_passport(oauth.consumer_key, oauth.consumer_secret);
|
|
||||||
}
|
|
||||||
IS_PASSPORT_SETUP = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
authRoute(req, res, next);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
authRoute(req, res, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureOauth(req, res, next) {
|
|
||||||
setHostName(req);
|
|
||||||
|
|
||||||
if (config.editor.offline) {
|
|
||||||
req.user = { provider: 'offline',
|
|
||||||
username: 'offline user' };
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
//use the correct key for redis, either github or bitbucket
|
|
||||||
var oauth_key = 'bitbucket_oauth';
|
|
||||||
if (config.editor.github) {
|
|
||||||
oauth_key = 'github_oauth';
|
|
||||||
}
|
|
||||||
|
|
||||||
client.hgetall(oauth_key, function (err, oauth) {
|
|
||||||
if (!oauth) {
|
|
||||||
res.redirect('/setup');
|
|
||||||
} else {
|
|
||||||
if (config.editor.github) {
|
|
||||||
setup_github_passport(oauth.consumer_key, oauth.consumer_secret);
|
|
||||||
} else {
|
|
||||||
setup_bitbucket_passport(oauth.consumer_key, oauth.consumer_secret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IS_PASSPORT_SETUP) {
|
|
||||||
IS_PASSPORT_SETUP = true;
|
|
||||||
res.redirect('/login');
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setHostName(req) {
|
function setHostName(req) {
|
||||||
//set it each time, it's quick, and hostname may change (internal IP vs external IP).
|
//set it each time, it's quick, and hostname may change (internal IP vs external IP).
|
||||||
HOSTNAME = req.headers.host;
|
HOSTNAME = req.headers.host;
|
||||||
|
|
@ -321,18 +189,18 @@ function setHostName(req) {
|
||||||
function serverInitialization(app) {
|
function serverInitialization(app) {
|
||||||
|
|
||||||
//setup repositories path
|
//setup repositories path
|
||||||
var exists = path.existsSync(REPOSITORY_PATH);
|
var exists = fs.existsSync(REPOSITORY_PATH);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
fs.mkdirSync(REPOSITORY_PATH, 0777);
|
fs.mkdirSync(REPOSITORY_PATH, 0777);
|
||||||
winston.info('created repositories folder');
|
winston.info('created repositories folder');
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup symlink to webide home, if it exists:
|
//setup symlink to webide home, if it exists:
|
||||||
var has_webide_path = path.existsSync("/home/webide");
|
var has_webide_path = fs.existsSync("/home/webide");
|
||||||
if (has_webide_path) {
|
if (has_webide_path) {
|
||||||
//Creating symbolic link to repositories path
|
//Creating symbolic link to repositories path
|
||||||
winston.info('Linked repository paths: /home/webide/repositories');
|
winston.info('Linked repository paths: /home/webide/repositories');
|
||||||
if (!path.existsSync("/home/webide/repositories")) {
|
if (!fs.existsSync("/home/webide/repositories")) {
|
||||||
fs.symlinkSync(REPOSITORY_PATH, "/home/webide/repositories", 'dir');
|
fs.symlinkSync(REPOSITORY_PATH, "/home/webide/repositories", 'dir');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -340,189 +208,31 @@ function serverInitialization(app) {
|
||||||
scheduler.initialize_jobs();
|
scheduler.initialize_jobs();
|
||||||
|
|
||||||
start_server(function(server) {
|
start_server(function(server) {
|
||||||
socket_listeners();
|
|
||||||
mount_dav(server);
|
mount_dav(server);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_server(cb) {
|
function start_server(cb) {
|
||||||
server = require('http').createServer(app);
|
db.find('server', function (err, server_data) {
|
||||||
io = io.listen(server);
|
|
||||||
io.configure(function() {
|
|
||||||
io.enable('browser client minification');
|
|
||||||
io.enable('browser client etag');
|
|
||||||
io.set('transports', ['websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling']);
|
|
||||||
});
|
|
||||||
|
|
||||||
new tty.Server(config.term, app, server, io);
|
|
||||||
|
|
||||||
client.hgetall('server', function (err, server_data) {
|
|
||||||
var port;
|
var port;
|
||||||
|
|
||||||
if (server_data && server_data.port) {
|
if (server_data && server_data.port) {
|
||||||
port = server_data.port;
|
port = server_data.port;
|
||||||
|
} else if (process.env.PORT) {
|
||||||
|
port = process.env.PORT
|
||||||
} else {
|
} else {
|
||||||
port = config.editor.port;
|
port = config.editor.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_data && server_data.offline) {
|
|
||||||
config.editor.offline = (server_data.offline == 1) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server_data && server_data.github) {
|
|
||||||
config.editor.github = (server_data.github == 1) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
winston.info('listening on port ' + port);
|
winston.info('listening on port ' + port);
|
||||||
cb(server.listen(port));
|
cb(app.listen(port));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function socket_listeners() {
|
|
||||||
io.sockets.authorization(function(handshakeData, callback) {
|
|
||||||
if (!handshakeData.headers.cookie) return callback('socket.io: cookie not found.', false);
|
|
||||||
var signedCookies = require('express/node_modules/cookie').parse(handshakeData.headers.cookie);
|
|
||||||
handshakeData.cookies = require('connect/lib/utils').parseSignedCookies(signedCookies, 'cat nap');
|
|
||||||
|
|
||||||
sessionStore.get(handshakeData.cookies['sid'], function(err, session) {
|
|
||||||
if (config.editor.offline) {
|
|
||||||
handshakeData.session = { provider: 'offline', username: 'offline user' };
|
|
||||||
return callback(null, true);
|
|
||||||
} else {
|
|
||||||
client.get(session.passport.user, function(err, user) {
|
|
||||||
if (err || !session) return callback('socket.io: session not found.', false);
|
|
||||||
handshakeData.session = JSON.parse(user);
|
|
||||||
if (handshakeData.session) {
|
|
||||||
return callback(null, true);
|
|
||||||
} else {
|
|
||||||
return callback('socket.io: session user not found', false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
io.sockets.on('connection', function (socket) {
|
|
||||||
socket.set('username', socket.handshake.session.username);
|
|
||||||
|
|
||||||
//emit on first connection
|
|
||||||
socket.emit('cwd-init', {dirname: REPOSITORY_PATH});
|
|
||||||
scheduler.emit_scheduled_jobs(socket.handshake.session.username, socket);
|
|
||||||
|
|
||||||
socket.on('disconnect', function() {
|
|
||||||
debug_helper.client_disconnect();
|
|
||||||
debug_helper.kill_debug();
|
|
||||||
});
|
|
||||||
|
|
||||||
//listen for events
|
|
||||||
socket.on('git-delete', function(data) {
|
|
||||||
git_helper.remove_commit_push(data.file, socket.handshake.session, function(err, status) {
|
|
||||||
socket.emit('git-delete-complete', {err: err, status: status});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//listen for events
|
|
||||||
socket.on('git-pull', function(data) {
|
|
||||||
console.log(data);
|
|
||||||
var name = data.file ? data.file.name : "";
|
|
||||||
git_helper.pull(name, "origin", "master", function(err, status) {
|
|
||||||
socket.emit('git-pull-complete', {err: err, status: status});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//listen for events
|
|
||||||
socket.on('git-is-modified', function(data) {
|
|
||||||
git_helper.is_modified(data.file, function(err, status) {
|
|
||||||
socket.emit('git-is-modified-complete', {is_modified: status});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('commit-file', function (data) {
|
|
||||||
var commit_message = "";
|
|
||||||
|
|
||||||
if (data.message) {
|
|
||||||
commit_message = data.message;
|
|
||||||
} else {
|
|
||||||
commit_message = "Modified " + data.file.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_helper.commit_push_and_save(data.file, commit_message, socket.handshake.session, function(err, status) {
|
|
||||||
socket.emit('commit-file-complete', {err: err, status: status});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('move-file', function (data) {
|
|
||||||
git_helper.move_commit_push(data.file, socket.handshake.session, function(err) {
|
|
||||||
console.log('move-file', err);
|
|
||||||
socket.emit('move-file-complete', {err: err});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('self-check-request', function() {
|
|
||||||
editor_setup.health_check(socket, socket.handshake.session);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('editor-check-updates', function() {
|
|
||||||
updater.check_for_updates(socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('editor-update', function() {
|
|
||||||
updater.update(socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('trace-file', function(data) {
|
|
||||||
exec_helper.trace_program(data.file, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('debug-command', function(data) {
|
|
||||||
debug_helper.debug_command(data, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('debug-file', function(data) {
|
|
||||||
debug_helper.start_debug(data.file, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('commit-run-file', function(data) {
|
|
||||||
if (data && data.file) {
|
|
||||||
data.file.username = socket.handshake.session.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
exec_helper.execute_program(data.file, false);
|
|
||||||
git_helper.commit_push_and_save(data.file, "Modified " + data.file.name, socket.handshake.session, function(err, status) {
|
|
||||||
socket.emit('commit-file-complete', {message: "Save was successful"});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('stop-script-execution', function(data) {
|
|
||||||
exec_helper.stop_program(data.file, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('submit-schedule', function(schedule) {
|
|
||||||
scheduler.add_schedule(schedule, socket, socket.handshake.session);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('schedule-delete-job', function(key) {
|
|
||||||
scheduler.delete_job(key, socket, socket.handshake.session);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('schedule-toggle-job', function(key) {
|
|
||||||
scheduler.toggle_job(key, socket, socket.handshake.session);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('set-settings', function(value) {
|
|
||||||
client.hmset("editor:settings", value, function(err) {
|
|
||||||
if (err) winston.error(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
io.sockets.on('disconnect', function(socket) {
|
|
||||||
exec_helper.set_sockets(io.sockets.sockets);
|
|
||||||
});
|
|
||||||
|
|
||||||
function mount_dav(server) {
|
function mount_dav(server) {
|
||||||
var jsDAV_Tree_Filesystem = require("jsDAV/lib/DAV/tree/filesystem").jsDAV_Tree_Filesystem;
|
var jsDAV_FS_Tree = require("jsDAV/lib/DAV/backends/fs/tree");
|
||||||
//jsDAV.debugMode = true;
|
//jsDAV.debugMode = true;
|
||||||
davServer = jsDAV.mount({
|
davServer = jsDAV.mount({
|
||||||
path: REPOSITORY_PATH,
|
path: REPOSITORY_PATH,
|
||||||
|
|
@ -530,32 +240,33 @@ function mount_dav(server) {
|
||||||
plugins: ["codesearch", "tree", "filelist", "filesearch", "locks", "mount", "temporaryfilefilter"],
|
plugins: ["codesearch", "tree", "filelist", "filesearch", "locks", "mount", "temporaryfilefilter"],
|
||||||
server: server,
|
server: server,
|
||||||
standalone: false,
|
standalone: false,
|
||||||
tree: new jsDAV_Tree_Filesystem(REPOSITORY_PATH)
|
tree: jsDAV_FS_Tree.new(REPOSITORY_PATH)
|
||||||
});
|
});
|
||||||
winston.info('webdav filesystem mounted');
|
winston.info('webdav filesystem mounted');
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.get_socket = function (username, cb) {
|
function cleanup() {
|
||||||
for (var socketId in io.sockets.sockets) {
|
winston.info("process and worker cleanup");
|
||||||
io.sockets.sockets[socketId].get('username', function(err, sock_username) {
|
Object.keys(terminals).forEach(function (pid) {
|
||||||
if (username === sock_username) {
|
var term = terminals[pid];
|
||||||
cb(io.sockets.sockets[socketId]);
|
console.log('Closed terminal ' + term.pid);
|
||||||
}
|
term.kill();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.on('SIGINT', function() {
|
|
||||||
winston.info("\nShutting down from SIGINT");
|
|
||||||
// some other closing procedures go here
|
|
||||||
debug_helper.kill_debug(false, function() {
|
debug_helper.kill_debug(false, function() {
|
||||||
//no need to wait for this
|
//no need to wait for this
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', function() {
|
||||||
|
winston.info("Shutting down from SIGINT");
|
||||||
|
cleanup();
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('uncaughtException', function(err) {
|
process.on('uncaughtException', function(err) {
|
||||||
debug_helper.kill_debug(false, function() {
|
winston.error("Shutting down from uncaughtException");
|
||||||
//no need to wait for this
|
winston.error(err.stack);
|
||||||
});
|
cleanup();
|
||||||
|
process.exit();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
3
uploads/.gitignore
vendored
Normal file
3
uploads/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
!.gitignore
|
||||||
|
|
@ -28,21 +28,21 @@ block content
|
||||||
form(method="post", action="/editor/settings")
|
form(method="post", action="/editor/settings")
|
||||||
.settings-element
|
.settings-element
|
||||||
span Select Font Size (px):
|
span Select Font Size (px):
|
||||||
span.font-size-value.10px 10
|
span.font-size-value._10px 10
|
||||||
span.font-size-value.12px 12
|
span.font-size-value._12px 12
|
||||||
span.font-size-value.14px 14
|
span.font-size-value._14px 14
|
||||||
span.font-size-value.16px 16
|
span.font-size-value._16px 16
|
||||||
span.font-size-value.20px 20
|
span.font-size-value._20px 20
|
||||||
.settings-element
|
.settings-element
|
||||||
span Use Soft Tabs:
|
span Use Soft Tabs:
|
||||||
span.soft-tab-value.on On
|
span.soft-tab-value.on On
|
||||||
span.soft-tab-value.off Off
|
span.soft-tab-value.off Off
|
||||||
.settings-element
|
.settings-element
|
||||||
span Tab Size:
|
span Tab Size:
|
||||||
span.tab-size-value.2-value 2
|
span.tab-size-value._2-value 2
|
||||||
span.tab-size-value.4-value 4
|
span.tab-size-value._4-value 4
|
||||||
span.tab-size-value.6-value 6
|
span.tab-size-value._6-value 6
|
||||||
span.tab-size-value.8-value 8
|
span.tab-size-value._8-value 8
|
||||||
.settings-element
|
.settings-element
|
||||||
span Show Invisibles:
|
span Show Invisibles:
|
||||||
span.invisibles-value.on On
|
span.invisibles-value.on On
|
||||||
|
|
@ -51,6 +51,10 @@ block content
|
||||||
span Manual Git commit and push (advanced)
|
span Manual Git commit and push (advanced)
|
||||||
span.manual-git-value.on On
|
span.manual-git-value.on On
|
||||||
span.manual-git-value.off Off
|
span.manual-git-value.off Off
|
||||||
|
.settings-element
|
||||||
|
span Python Version:
|
||||||
|
span.python-version._2 2
|
||||||
|
span.python-version._3 3
|
||||||
#editor
|
#editor
|
||||||
#editor-output-wrapper
|
#editor-output-wrapper
|
||||||
.dragbar
|
.dragbar
|
||||||
|
|
@ -78,7 +82,7 @@ block content
|
||||||
button.btn.modal-cancel Cancel
|
button.btn.modal-cancel Cancel
|
||||||
#manual-git-modal(class="modal hide fade")
|
#manual-git-modal(class="modal hide fade")
|
||||||
.modal-header
|
.modal-header
|
||||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||||
h3#create-modal-label Git Commit and Push
|
h3#create-modal-label Git Commit and Push
|
||||||
.modal-body
|
.modal-body
|
||||||
p Add a comment to your edited filed, and click Commit and Push.
|
p Add a comment to your edited filed, and click Commit and Push.
|
||||||
|
|
@ -90,7 +94,7 @@ block content
|
||||||
button.btn.btn-primary.modal-submit Commit and Push
|
button.btn.btn-primary.modal-submit Commit and Push
|
||||||
#create-modal(class="modal hide fade")
|
#create-modal(class="modal hide fade")
|
||||||
.modal-header
|
.modal-header
|
||||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||||
h3#create-modal-label
|
h3#create-modal-label
|
||||||
.modal-body
|
.modal-body
|
||||||
p
|
p
|
||||||
|
|
@ -99,7 +103,7 @@ block content
|
||||||
button.btn.btn-primary.modal-submit Save
|
button.btn.btn-primary.modal-submit Save
|
||||||
#schedule-modal(class="modal hide fade")
|
#schedule-modal(class="modal hide fade")
|
||||||
.modal-header
|
.modal-header
|
||||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
button.close(type="button", data-dismiss="modal", aria-hidden="true") ×
|
||||||
h3#create-modal-label Job Scheduler
|
h3#create-modal-label Job Scheduler
|
||||||
.modal-body
|
.modal-body
|
||||||
p Schedule your script to run at specific time periods. There are many combinations you can use to schedule.
|
p Schedule your script to run at specific time periods. There are many combinations you can use to schedule.
|
||||||
|
|
@ -125,33 +129,7 @@ block content
|
||||||
.modal-footer
|
.modal-footer
|
||||||
button.btn(data-dismiss="modal", aria-hidden="true") Close
|
button.btn(data-dismiss="modal", aria-hidden="true") Close
|
||||||
button.btn.btn-primary.modal-submit Submit
|
button.btn.btn-primary.modal-submit Submit
|
||||||
#notification-modal(class="modal hide fade")
|
|
||||||
.modal-header
|
|
||||||
button.close(type="button", data-dismiss-"modal", aria-hidden="true") ×
|
|
||||||
h3#create-modal-label WebIDE Message
|
|
||||||
.modal-body
|
|
||||||
p Please ensure your repositories are listed private or public at Bitbucket based on your preferences.
|
|
||||||
p You can validate them by viewing your <a href="https://bitbucket.org" target="_blank">bitbucket profile page</a>
|
|
||||||
| , and looking for the padlock to the left of the repository
|
|
||||||
| name in the "Repositories" sidebar.
|
|
||||||
p To make the repository private or public, click the repository name, and then the gear in the header on the
|
|
||||||
| the repository page. Then click the checkbox in the form to make the repository private or public,
|
|
||||||
| and click submit.
|
|
||||||
p This particular notification will only display one time. Thank you!
|
|
||||||
.modal-footer
|
|
||||||
button.btn(data-dismiss="modal", aria-hidden="true") Dismiss
|
|
||||||
script(type="text/javascript")
|
|
||||||
if(!#{shown_notification}) {
|
|
||||||
setTimeout(function() {
|
|
||||||
$('#notification-modal').modal({show: true, backdrop: 'static'});
|
|
||||||
}, 20000);
|
|
||||||
|
|
||||||
}
|
|
||||||
script(src="/javascripts/ace/ace.js")
|
script(src="/javascripts/ace/ace.js")
|
||||||
script(src="/socket.io/socket.io.js")
|
|
||||||
script(src="/term.js")
|
|
||||||
script(src="/options.js")
|
|
||||||
script(src="/tty.js")
|
|
||||||
script(src="/javascripts/trace/d3.v2.min.js")
|
script(src="/javascripts/trace/d3.v2.min.js")
|
||||||
script(src="/javascripts/trace/jquery.ba-bbq.min.js")
|
script(src="/javascripts/trace/jquery.ba-bbq.min.js")
|
||||||
script(src="/javascripts/trace/jquery.jsPlumb-1.3.10-all-min.js")
|
script(src="/javascripts/trace/jquery.jsPlumb-1.3.10-all-min.js")
|
||||||
|
|
@ -160,9 +138,12 @@ block content
|
||||||
script(src="/javascripts/fileupload/js/jquery.fileupload.js")
|
script(src="/javascripts/fileupload/js/jquery.fileupload.js")
|
||||||
script(src="/javascripts/fileupload/js/jquery.fileupload-ui.js")
|
script(src="/javascripts/fileupload/js/jquery.fileupload-ui.js")
|
||||||
script(src="/javascripts/davFS.js")
|
script(src="/javascripts/davFS.js")
|
||||||
|
script(src="/xterm.js")
|
||||||
|
script(src="/addons/fit/fit.js")
|
||||||
|
script(src="/addons/attach/attach.js")
|
||||||
script(src="/javascripts/later/later-recur.min.js")
|
script(src="/javascripts/later/later-recur.min.js")
|
||||||
script(src="/javascripts/later/later.min.js")
|
script(src="/javascripts/later/later.min.js")
|
||||||
script(src="/javascripts/jquery.colorbox-min.js")
|
script(src="/javascripts/jquery.colorbox-min.js")
|
||||||
script(src="/javascripts/context_menu.js")
|
script(src="/javascripts/context_menu.js")
|
||||||
script(src="/javascripts/webide_utils.js")
|
script(src="/javascripts/webide_utils.js")
|
||||||
script(src="/javascripts/occ_editor.js")
|
script(src="/javascripts/editor.js")
|
||||||
|
|
@ -5,5 +5,4 @@ block content
|
||||||
#login-content
|
#login-content
|
||||||
p There was an error with your request. Please try again, or visit
|
p There was an error with your request. Please try again, or visit
|
||||||
a(href="http://learn.adafruit.com/webide/faq") the FAQ for assistance
|
a(href="http://learn.adafruit.com/webide/faq") the FAQ for assistance
|
||||||
| .
|
|
||||||
p #{error}
|
p #{error}
|
||||||
|
|
@ -6,6 +6,6 @@ head
|
||||||
link(rel="stylesheet", href="/javascripts/fileupload/css/jquery.fileupload-ui.css")
|
link(rel="stylesheet", href="/javascripts/fileupload/css/jquery.fileupload-ui.css")
|
||||||
link(rel="stylesheet", href="/stylesheets/colorbox.css")
|
link(rel="stylesheet", href="/stylesheets/colorbox.css")
|
||||||
link(rel="stylesheet", href="/stylesheets/app.css")
|
link(rel="stylesheet", href="/stylesheets/app.css")
|
||||||
link(rel="stylesheet", href="/style.css")
|
link(rel="stylesheet", href="/xterm.css")
|
||||||
link(rel="stylesheet", href="/stylesheets/pytutor.css")
|
link(rel="stylesheet", href="/stylesheets/pytutor.css")
|
||||||
script(src='/javascripts/jquery.min.js')
|
script(src='/javascripts/jquery.min.js')
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
extends layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
- if (!user)
|
|
||||||
h4 Welcome! Please log in.
|
|
||||||
a(href="/auth/bitbucket") Login with Bitbucket
|
|
||||||
- else
|
|
||||||
h4 Hello, #{user.username}
|
|
||||||
p Please choose a repository
|
|
||||||
for repository in user._json.repositories
|
|
||||||
.repository
|
|
||||||
a(href="/editor/#{repository.name}") #{repository.name}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
!!! 5
|
|
||||||
html
|
html
|
||||||
include header
|
include header
|
||||||
body
|
body
|
||||||
|
|
@ -7,9 +6,6 @@ html
|
||||||
.container-fluid
|
.container-fluid
|
||||||
a.brand(href="/")
|
a.brand(href="/")
|
||||||
img(src="/images/WebIDE_Logo_Beta@2x.png", style="height:30px;")
|
img(src="/images/WebIDE_Logo_Beta@2x.png", style="height:30px;")
|
||||||
p.logout-wrapper
|
|
||||||
- if (typeof profile !== "undefined")
|
|
||||||
a(href="/logout") Log out
|
|
||||||
p.update-wrapper
|
p.update-wrapper
|
||||||
div.connection-state
|
div.connection-state
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
extends layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
#login-wrapper
|
|
||||||
#login-content
|
|
||||||
p There was an error signing in. It could be any number of reasons, but first ensure that your date/time is set accurately on your Pi.
|
|
||||||
| For More help, visit
|
|
||||||
a(href="http://learn.adafruit.com/webide/faq") the FAQ for assistance
|
|
||||||
| .
|
|
||||||
p To try and repair the error, by setting your date and time, click the below link. You will be redirected to the login page after 5-10 seconds to try login in again.
|
|
||||||
p
|
|
||||||
a(href="/set-datetime") Set the Date and Time
|
|
||||||
p #{error}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
extends ../layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
#login-wrapper
|
|
||||||
#login-content
|
|
||||||
if (typeof(session.message) != 'undefined')
|
|
||||||
div.login-info
|
|
||||||
div.alert.alert-info
|
|
||||||
p #{session.message}
|
|
||||||
#{session.message = undefined}
|
|
||||||
if !github
|
|
||||||
img(src="/images/login/login2_logos.jpg")
|
|
||||||
if github
|
|
||||||
a(href="/auth/github", rel="external", class="btn btn-large") Click here to log in to your Github Account
|
|
||||||
else
|
|
||||||
a(href="/auth/bitbucket", rel="external", class="btn btn-large") Click here to log in to your Bitbucket Account
|
|
||||||
.login-help
|
|
||||||
b Need Help?
|
|
||||||
a(href="http://learn.adafruit.com/webide", target="_blank") Learn how to use the Adafruit webIDE here.
|
|
||||||
0
views/users/repositories.pug
Normal file
0
views/users/repositories.pug
Normal file
|
|
@ -1,59 +0,0 @@
|
||||||
extends ../layout
|
|
||||||
|
|
||||||
block content
|
|
||||||
#setup-wrapper
|
|
||||||
#setup-content
|
|
||||||
h3 Welcome to the Adafruit webIDE powered by the Adafruit Learning System
|
|
||||||
if (typeof(session.message) != 'undefined')
|
|
||||||
div.alert.alert-error
|
|
||||||
p #{session.message}
|
|
||||||
p Setting up your Raspberry Pi or Beaglebone will only take a few minutes. Let's get started.
|
|
||||||
p Are you setting up more than one Raspberry Pi or Beaglebone? Visit the config to
|
|
||||||
a(href="/config") change hostname and WiFi.
|
|
||||||
if !github
|
|
||||||
p One of the many useful features of the webIDE is that all of your code will be
|
|
||||||
| stored in the cloud over at bitbucket.org. So, before we can go any further, you
|
|
||||||
| will want to create your free Bitbucket account. If you already have one, you can use
|
|
||||||
| your existing account, or create one specifically for the webIDE.
|
|
||||||
p
|
|
||||||
a.btn.btn-large.btn-info.bitbucket-signup(href="https://bitbucket.org/account/signup/", target="_blank") Click here to create your free bitbucket account
|
|
||||||
p
|
|
||||||
img(src="/images/setup/step1.png")
|
|
||||||
p In your Account page, click on the Integrated Applications link in the left column:
|
|
||||||
p
|
|
||||||
img(src="/images/setup/step2.png")
|
|
||||||
p Now, click on the '+ Add consumer' button:
|
|
||||||
p
|
|
||||||
img(src="/images/setup/step3.png")
|
|
||||||
p For the name, type in Adafruit webIDE, then click the 'Add consumer' button:
|
|
||||||
p
|
|
||||||
img(src="/images/setup/step4.png")
|
|
||||||
p What we are after is the Key, and the Secret text. Copy each of those and paste in the boxes below.
|
|
||||||
p
|
|
||||||
img(src="/images/setup/step5.png")
|
|
||||||
p Copy the key and Secret codes into these text boxes, and then click submit:
|
|
||||||
if github
|
|
||||||
p Enter your Github OAuth Consumer Key and Secret here:
|
|
||||||
form(method="post", action="/setup", class="form-horizontal")
|
|
||||||
div.control-group
|
|
||||||
label(for="key", class="control-label") Key:
|
|
||||||
div.controls
|
|
||||||
input(type="text", name="key", value=consumer_key)
|
|
||||||
div.control-group
|
|
||||||
label(for="secret", class="control-label") Secret:
|
|
||||||
div.controls
|
|
||||||
input(type="text", name="secret", value=consumer_secret)
|
|
||||||
if github
|
|
||||||
p Add your Full Name and Email to attach to saved files at Github (git config)
|
|
||||||
else
|
|
||||||
p Add your Full Name and Email to attach to saved files at Bitbucket (git config)
|
|
||||||
div.control-group
|
|
||||||
label(for="name", class="control-label") Full Name:
|
|
||||||
div.controls
|
|
||||||
input(type="text", name="name", value=name)
|
|
||||||
div.control-group
|
|
||||||
label(for="email", class="control-label") Email:
|
|
||||||
div.controls
|
|
||||||
input(type="text", name="email", value=email)
|
|
||||||
p
|
|
||||||
input(type="submit", class="btn btn-primary btn-large", name="Submit")
|
|
||||||
24
views/users/setup.pug
Normal file
24
views/users/setup.pug
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
extends ../layout
|
||||||
|
|
||||||
|
block content
|
||||||
|
#setup-wrapper
|
||||||
|
#setup-content
|
||||||
|
h3 Welcome to the Adafruit webIDE powered by the Adafruit Learning System
|
||||||
|
if (typeof(session.message) != 'undefined')
|
||||||
|
div.alert.alert-error
|
||||||
|
p #{session.message}
|
||||||
|
p Setting up your Raspberry Pi or Beaglebone will only take a few minutes. Let's get started.
|
||||||
|
p Are you setting up more than one Raspberry Pi or Beaglebone? Visit the config to
|
||||||
|
a(href="/config") change hostname and WiFi.
|
||||||
|
form(method="post", action="/setup", class="form-horizontal")
|
||||||
|
p Add your Name and Email for git config
|
||||||
|
div.control-group
|
||||||
|
label(for="name", class="control-label") Full Name:
|
||||||
|
div.controls
|
||||||
|
input(type="text", name="name", value=name)
|
||||||
|
div.control-group
|
||||||
|
label(for="email", class="control-label") Email:
|
||||||
|
div.controls
|
||||||
|
input(type="text", name="email", value=email)
|
||||||
|
p
|
||||||
|
input(type="submit", class="btn btn-primary btn-large", name="Submit")
|
||||||
Loading…
Reference in a new issue