forked from idflood/ThreeNodes.js
-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.js
406 lines (356 loc) · 12.4 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/**
* Load all dependencies, install them via npm
*/
var express = require('express');
var http = require('http');
var sys = require('util');
var exec = require('child_process').exec;
var url = require("url");
var conf = require("./conf.js");
/***************************************************************************************
* Database management
***************************************************************************************/
/**
* We need a database to store information about our users. We use a mongodb.
*/
var mongoose = require('mongoose')
, Schema = mongoose.Schema
, mongooseAuth = require('mongoose-auth');
var UserSchema = new Schema({})
, User;
/*
* User schema augmentation
*/
// STEP 1: Schema Decoration and Configuration for the Routing
UserSchema.plugin(mongooseAuth, {
// Here, we attach your User model to every module
everymodule: {
everyauth: {
User: function () {
return User;
}
}
}
, facebook: {
everyauth: {
myHostname: conf.server.full_server_name
, appId: conf.fb.appId
, appSecret: conf.fb.appSecret
, redirectPath: '/gui'
, findOrCreateUser: function (sess, accessTok, accessTokExtra, fbUser) {
var promise = this.Promise()
, User = this.User()();
// TODO Check user in session or request helper first
// e.g., req.user or sess.auth.userId
User.findOne({'fb.id': fbUser.id}, function (err, foundUser) {
if (foundUser) {
console.log("Yes, we found you; your gender is:"+foundUser.fb.gender);
return promise.fulfill(foundUser);
}
console.log("We didn't find the user, so we are CREATING your profile...");
User.createWithFB(fbUser, accessTok, accessTokExtra.expires, function (err, createdUser) {
if (err) return promise.fail(err);
return promise.fulfill(createdUser);
}
);
}
);
return promise;
}
}
}
, twitter: {
everyauth: {
myHostname: conf.server.full_server_name
, consumerKey: conf.twit.consumerKey
, consumerSecret: conf.twit.consumerSecret
, redirectPath: '/gui'
, findOrCreateUser: function (sess, accessTok, accessTokSecret, twitterUser) {
var promise = this.Promise()
, self = this;
this.User()().findOne({'twit.id': twitterUser.id}, function (err, foundUser) {
if (err) return promise.fail(err);
if (foundUser) {
console.log("Yes, we found you");
return promise.fulfill(foundUser);
}
console.log("We didn't find the user, so we are CREATING your profile...");
self.User()().createWithTwitter(twitterUser, accessTok, accessTokSecret, function (err, createdUser) {
if (err) return promise.fail(err);
return promise.fulfill(createdUser);
});
});
return promise;
}
}
}
});
UserSchema.add(
{
token: String
, secret: String
}
);
// create the UserSchema Model of mongodb
mongoose.model('User', UserSchema);
mongoose.connect('mongodb://' + conf.server.server_name + '/example');
User = mongoose.model('User');
/***************************************************************************************
* Main routing function
***************************************************************************************/
/**
* The router function. This needs to be "upgraded"... Things to do:
* 1.) make it an actual router file!!!
* 2.) update it to coffeescript
* Remark: if you add things here to the if-else statements, make sure you also add them
* as app.get() targets, or you won't be able to "GET" them.
*/
function respondFunction(req,res){
var query = url.parse(req.url).query;
var pathname = url.parse(req.url).pathname;
console.log("Request for " + pathname + " " + query + " received.");
if (query == "List") {
if (req.user.token){
User.findOne({'token': req.user.token},function (err, token) {
if (token){
console.log('MongoDB detects you and lists your available CS modules here');
mode = 1;
exec("aimlist "+mode, function (error, stdout, stderr) {
res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
res.write(stdout);
res.end();
});
console.log(mode);
console.log(token.secret);
}
else{
console.log('MongoDB does not detect you and only lists your available AI modules here');
mode = 0;
exec("aimlist "+mode, function (error, stdout, stderr) {
res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
res.write(stdout);
res.end();
});
}
}
)
}
else{
console.log('Please log in via Edit-> CommonSense Login');
mode = 0;
exec("aimlist "+mode, function (error, stdout, stderr) {
res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
res.write(stdout);
res.end();
});
}
}
else if (pathname == "/aimports") {
console.log("I am in aimports")
exec("aimports " + query, function (error, stdout, stderr) {
res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
res.write(stdout);
res.end();
});
}
else if (pathname == "/cslogin2") {
var oauth_symbols = query.split("&");
var token = ''; var verifier = '';
for (var i = 0; i < oauth_symbols.length; i++) {
var str = oauth_symbols[i].split("=");
// get second part of string after the = sign and sanitize it
if (i == 0) token = str[1].replace(/[^a-z 0-9]+/gi,'');
if (i == 1) verifier = str[1].replace(/[^a-z 0-9]+/gi,'');
}
// warning: this secret can be temporarily stored, but subsequent token and secret need to go in user db
var secret = req.session.oauthsecret.replace(/[^a-z 0-9]+/gi,'');
if ((token == "") || (secret == "")) {
console.log("Not successful login for CommonSense");
res.render('gui', {title: 'AIM GUI', layout: false });
}
console.log("aimlogin oauth1 " + token + " " + secret + " " + verifier);
exec("aimlogin oauth1 " + token + " " + secret + " " + verifier, function (error, stdout, stderr) {
var vars = stdout.split("\n");
//var instance = new User();
for (var i = 0; i < vars.length-1; i++) {
console.log("t:" + vars[i]);
// store oauthtoken and oauthsecret
if (i == 0) req.user.token = vars[i];
if (i == 1) req.user.secret = vars[i];
}
req.user.save(function (err) { } );
res.render('gui', {title: 'AIM GUI', layout: false });
// res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
// res.write(stdout);
// res.end();
});
}
// the /cslogin command comes from CSLoginCommand
else if (pathname == "/cslogin") {
var param = 'id=123'
// this will return a oauth token but should also return a secret
console.log("I am in cslogin and will execute 'aimlogin oauth0 " + param + "'");
exec("aimlogin oauth0 " + param, function (error, stdout, stderr) {
res.writeHead(200, {"Content-Type": "text/plain", "Access-Control-Allow-Origin": "*"});
var vars = stdout.split("\n");
for (var i = 0; i < vars.length-1; i++) {
console.log("t:" + vars[i]);
if (i == 0) var token = vars[i];
if (i == 1) req.session.oauthsecret = vars[i];
}
res.write(token);
res.end();
});
}
else {
console.log("Very dangerous code... we can run anything we want...");
var body = '';
req.on('data', function (data) {
body += data;
console.log(data.toString());
});
console.log("body"+body);
req.on('end', function () {
var body_split=body.split("\n");
//console.log(body_split[0]);
for (var i = 0; i<body_split.length-1;i++){
console.log(body_split[i]);
// sanitizing
// first check if it starts with "aim"...
// aimrun arg0 arg1
// aimconnect arg0 arg1 arg2 arg3
var aimcmd = body_split[i].replace(/[^a-z 0-9]+/gi,'');
//check for CS....Module
// and append token and secret to argument list
// execute aimrun, aimconnect etc.
exec(aimcmd, function (error, stdout, stderr) {
console.log(stdout);
});
}
});
}
}
/***************************************************************************************
* Create expressjs server
***************************************************************************************/
/**
* Standard server started. It starts the mongoose-auth middleware with many many other configurations such as routing (very important).
*/
var app = express.createServer();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.configure(function(){
console.log('Configuring the express server');
app.use(express.bodyParser());
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.use(express.cookieParser());
app.use(express.session({secret:'whodunnit'}));
// STEP 2: Add in the Routing: the use of mongoose-auth middleware
app.use(mongooseAuth.middleware());
app.use(express.methodOverride());
app.use(app.router);
app.use(express['static'](__dirname + '/public'));
});
/**
* all the the below functions are for different server responses according to different "PATH"
*/
/**
* The root response: the entry point for the routing, we just render view/home.jade which shows a
* login window for OpenID via Facebook/Google.
*/
app.get('/', function (req, res) {
res.render('home', { layout: false} );
});
/**
* We reached the GUI. We have to check if the login procedure was actually successful.
* Notice that rendering the GUI is separated from listing the CommonSense modules. We
* have a two-stage process. The first time we only list the modules the user has access
* to by default. After login via oauth the user can also see CommonSense modules.
*/
app.get('/gui',function(req,res){
if(req.session.auth && req.session.auth.loggedIn){
console.log('Rendering gui');
res.render('gui', {title: 'AIM GUI', layout: false });
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
/**
* This is the first login step if people want to log in to CommonSense. This is not
* mandatory, we might provide other ways of having data input (for example from the web).
* This route is initiated when the user manualyl clicks on Login for CommonSense in
* the menu bar.
*/
app.get('/cslogin',function(req,res) {
if(req.session.auth && req.session.auth.loggedIn){
console.log('Logging in');
respondFunction(req,res);
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
/**
* The second step of logging in. This is when the CommonSense server returns a URL
* with temporary key and secret tokens which subsequently needs to be used by the modules
* started by the user to access the data from that user.
*/
app.get('/cslogin2',function(req,res) {
if(req.session.auth && req.session.auth.loggedIn){
console.log('Logging in, 2nd stage');
respondFunction(req,res);
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
/**
* Let's for now redirect to aimlist.
*/
app.get('/aimlist',function(req,res){
if(req.session.auth && req.session.auth.loggedIn){
console.log('I am in /aimlist');
respondFunction(req,res);
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
app.get('/aimports',function(req,res){
if(req.session.auth && req.session.auth.loggedIn){
console.log('I am in /aimports');
respondFunction(req,res);
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
/**
* Captures GET and POST requests (because of app.all).
*/
app.all('/aimrun',function(req,res){
if(req.session.auth && req.session.auth.loggedIn){
console.log('I am in /aimrun');
respondFunction(req,res);
} else{
console.log("The user is NOT logged in");
res.redirect('/');
}
});
/**
* Only capture GET requests, else way the GUI is not rendered. :-)
*/
app.get('/:id?', function(req,res) {
if(req.session.auth && req.session.auth.loggedIn){
res.redirect('/');
} else{
//console.log("The user is NOT logged in!!!");
res.redirect('/');
}
});
//STEP 3: Add in Dynamic View Helpers (only if you are using express)
mongooseAuth.helpExpress(app);
app.listen(conf.server.port_id);
//console.log(conf.server.server_name);
console.log("ready: http://%s:%d/", conf.server.server_name, app.address().port);