Skip to content

Commit 87aabf1

Browse files
committed
Upload to GitHub
0 parents  commit 87aabf1

39 files changed

+3402
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
### c9launcher

cloud9.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
module.exports = function (config, db) {
2+
const fs = require('fs');
3+
const path = require('path');
4+
const { exec } = require('child_process');
5+
const kill = require('tree-kill');
6+
const isPortAvailable = require('is-port-available');
7+
const { getPortPromise } = require('portfinder');
8+
9+
class Cloud9 {
10+
constructor(executable,wsd) {
11+
this._executable = path.resolve(executable);
12+
this._wsd = path.resolve(wsd);
13+
this._workspaces = fs.readdirSync(this._wsd);
14+
this._children = {};
15+
}
16+
17+
execute(args = []) {
18+
const child = exec(`node "${this._executable}" ${args.join(' ')}`);
19+
return child;
20+
}
21+
22+
start(id, workspace, port, auth, collab = false, localOnly = false) {
23+
return new Promise(async (resolve,reject) => {
24+
if (port == false || port == 0) {
25+
port = await getPortPromise();
26+
}
27+
if (!await isPortAvailable(port)) return reject('Port is not available');
28+
if (!this._workspaces.includes(workspace)) return reject('Workspace not found');
29+
var args = [
30+
`-p ${port}`,
31+
`-w "${path.resolve(this._wsd,workspace)}"`,
32+
(collab ? '--collab' : ''),
33+
(localOnly ? '--listen localhost' : ''),
34+
(auth && auth.username && auth.password ? `-a ${auth.username}:${auth.password}` : '')
35+
];
36+
var child = this.execute(args);
37+
this._children[id] = {child: child, port: port};
38+
resolve(child);
39+
});
40+
}
41+
42+
kill(id) {
43+
var child = this.getChild(id).child;
44+
if (!child) return false;
45+
if (child.killed) return false;
46+
kill(child.pid);
47+
delete this._children[id];
48+
return true;
49+
}
50+
51+
getChild(id) {
52+
return id in this._children ? this._children[id] : false;
53+
}
54+
}
55+
56+
return function (executable,wsd) {
57+
return new Cloud9(executable,wsd);
58+
}
59+
}

db.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
module.exports = async function (config,cryptr) {
2+
return new Promise((resolve,reject) => {
3+
const bcrypt = require('bcrypt');
4+
const deasync = require('deasync');
5+
const sqlite3 = require('sqlite3po');
6+
const db = new sqlite3.Database(config.database);
7+
8+
class User {
9+
constructor(first,second,third = 0,fourth = 0) {
10+
if (first == undefined) return;
11+
if (first % 1 === 0) {
12+
this._id = first;
13+
this._username = second;
14+
this._password = third;
15+
this._admin = fourth;
16+
} else {
17+
this._username = first;
18+
this._password = second;
19+
this._admin = third;
20+
}
21+
}
22+
23+
deserialize(row) {
24+
return new this.constructor(row.id,row.username,row.password,row.admin);
25+
}
26+
27+
get asObject() {
28+
var obj = {
29+
username: this._username,
30+
password: this._password,
31+
admin: this._admin
32+
};
33+
if (this._id) obj.id = this._id;
34+
return obj;
35+
}
36+
37+
setPassword(password) {
38+
var hash = deasync(bcrypt.hash);
39+
this._password = hash(password, 10);
40+
}
41+
42+
checkPassword(password) {
43+
return new Promise((resolve,reject) => {
44+
bcrypt.compare(password,this._password).then(correct => {
45+
resolve(correct);
46+
});
47+
})
48+
}
49+
50+
serialize() {
51+
if (this._id) {
52+
return {
53+
id: this._id,
54+
username: this._username,
55+
password: this._password,
56+
admin: this._admin
57+
}
58+
} else {
59+
var hash = deasync(bcrypt.hash);
60+
61+
this._password = hash(this._password, 10);
62+
63+
return {
64+
username: this._username,
65+
password: this._password,
66+
admin: this._admin
67+
}
68+
}
69+
}
70+
}
71+
72+
class Config {
73+
constructor(id,key,value) {
74+
this._id = id;
75+
this._key = key;
76+
this._value = value;
77+
}
78+
79+
deserialize(row) {
80+
return new this.constructor(row.id,row.key,row.value);
81+
}
82+
83+
serialize() {
84+
return {
85+
id: this._id,
86+
key: this._key,
87+
value: this._value
88+
}
89+
}
90+
}
91+
92+
class Workspace {
93+
constructor(id,key,workspace,port,username,password) {
94+
this._id = id;
95+
this._key = key;
96+
this._workspace = workspace;
97+
this._port = port;
98+
this._username = username;
99+
this._password = password;
100+
}
101+
deserialize(row) {
102+
return new this.constructor(row.id,row.key,row.workspace,row.port,row.username,cryptr.decrypt(row.password));
103+
}
104+
serialize() {
105+
return {
106+
id: this._id,
107+
key: this._key,
108+
workspace: this._workspace,
109+
port: this._port,
110+
username: this._username,
111+
password: cryptr.encrypt(this._password)
112+
}
113+
}
114+
}
115+
116+
db.on('open', () => {
117+
db.bindSchema(User,'users',{id:'INTEGER PRIMARY KEY AUTOINCREMENT',username: 'TEXT',password: 'TEXT',admin: 'INTEGER'}).then(() => {
118+
User.get('SELECT id FROM users WHERE id = ?',1).then(d => {
119+
if (d == undefined) {
120+
new User('admin','admin',1).save().then(() => {
121+
console.log('Initialized Admin account with username and password as admin.');
122+
});
123+
}
124+
});
125+
});
126+
db.bindSchema(Config,'config',{id:'INTEGER PRIMARY KEY AUTOINCREMENT',key: 'TEXT', value: 'TEXT'}).then(() => {
127+
Config.get('SELECT * FROM config WHERE key = ?','Workspace Directory').then(d => {
128+
if (d == undefined) {
129+
new Config(1,'Workspace Directory','./workspaces').save().then(() => {
130+
console.log('Set config for Server Directory');
131+
new Config(2,'Admins Only','false').save().then(() => {
132+
console.log('Set config for Admins Only');
133+
});
134+
});
135+
}
136+
});
137+
});
138+
db.bindSchema(Workspace,'workspaces',{id:'INTEGER PRIMARY KEY AUTOINCREMENT',key: 'TEXT',workspace: 'TEXT',port: 'INTEGER',username: 'TEXT',password: 'TEXT'}).then();
139+
resolve({User: User, Config: Config, Workspace: Workspace});
140+
});
141+
});
142+
};

index.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const http = require('http');
2+
const express = require('express');
3+
const bodyParser = require('body-parser');
4+
const helmet = require('helmet');
5+
const session = require('express-session');
6+
const store = require('connect-sqlite3')(session);
7+
const deasync = require('deasync');
8+
const app = express();
9+
const server = http.createServer(app);
10+
const Cryptr = require('cryptr');
11+
const path = require('path');
12+
const port = process.env.PORT || 8080;
13+
const ip = process.env.IP || '0.0.0.0';
14+
const config = require('./config.json');
15+
const cryptr = new Cryptr(config.crypto);
16+
const database = require('./db.js')(config,cryptr);
17+
database.then(async db => {
18+
const cloud9 = require('./cloud9')(config,db);
19+
const c9 = cloud9(path.resolve('/home/c9/c9sdk/','server.js'),(await db.Config.get('SELECT * FROM config WHERE key = ?','Workspace Directory'))._value);
20+
const proxy = require('http-proxy').createProxyServer({ws:true});
21+
const fs = require('fs');
22+
23+
// Start a workspace named Testing, with the folder as test, port as 8083, and collaboration enabled, then output to console
24+
// var workspace = c9.start('Testing','test',8083,{username: 'sirhypernova', password: 'test'},true);
25+
// Same as above, but first open port
26+
// var workspace = c9.start('Testing','test',false,{username: 'sirhypernova', password: 'test'},true);
27+
// workspace.then((child) => {
28+
// child.stdout.pipe(process.stdout);
29+
// }).catch(err => {
30+
// console.log(err);
31+
// });
32+
33+
app.set('view engine', 'ejs');
34+
35+
// Helmet
36+
app.use(helmet());
37+
// Session
38+
app.use(session({
39+
store: new store({
40+
db: config.session
41+
}),
42+
name: 'rvsess',
43+
resave: true,
44+
saveUninitialized: false,
45+
secret: '3348227453261949266283369121938267059251'
46+
}));
47+
48+
// Initialize Routes
49+
50+
require('./routes')(app,config,db,proxy,c9,cryptr)(config.routes).then(() => {
51+
console.log('Loaded routes successfully.');
52+
53+
// Register 404 Page
54+
app.use((req,res) => {
55+
res.render('404',{name: config.name, page: '404'});
56+
});
57+
58+
// Configure static directory
59+
app.use(express.static('static'));
60+
});
61+
62+
app.listen(port,ip, () => {
63+
console.log(`Server listening at ${ip}:${port}`);
64+
});
65+
});

0 commit comments

Comments
 (0)