Skip to content

Instantly share code, notes, and snippets.

@raid5
Created July 15, 2011 18:48
Show Gist options
  • Save raid5/9022490fd5e98d2cf98d to your computer and use it in GitHub Desktop.
Save raid5/9022490fd5e98d2cf98d to your computer and use it in GitHub Desktop.
module.exports = function Server(serverName,servicesConfig) {
serverName= serverName||'NoName';
var HTTPServer = require('http');
var Express = require('express');
var ExpressResource = require('express-resource'); // included here so that it can monkey-patch express
var Path = require('path');
var Util = require('util');
var fs = require('fs');
var _= require('underscore');
var app = Express.createServer();
app.use(Express.logger());
app.use(Express.bodyParser());
process.env.NODE_ENV= process.env.NODE_ENV||'development';
var root= Path.resolve();
app.configure('development', 'test', function(){
app.use(Express.errorHandler({ dumpExceptions: true, showStack: true }));
// statically serve the client (for development purposes)
app.use(Express.cookieParser());
app.use(Express.session({secret: 'a1b2c3d4e5f60000000000000'}));
// JCM this should be serving from views?
app.use('/'+options.client,
Express.static(Path.join(__dirname, '..', 'client')));
});
app.use(app.router);
app.get('/',function (request,response){
response.send("<p>"+serverName+" Server</p>\n");
});
// service registry map. Stores name of service : singleton instance of service
var serviceRegistry = {};
// The server API. We only expose functions we want to expose, so that services cannot touch
// other parts of the running server.
var server = {
getService: function(serviceName) {
// at a later point, we could do lazy init here
return serviceRegistry[serviceName];
}
};
// messaging-server comes inbuilt into the framework
//servicesConfig.unshift({name:'messaging-server', service:require('messaging-server')});
// expose the app's services
for(var i in servicesConfig) {
var serviceConfig = servicesConfig[i];
var serviceName = serviceConfig.name;
console.log("Starting Service: " + serviceName);
// create an instance of the service and put in registry
var serviceOptions = _.defaults(loadConfig(serviceName),options); // load service specific config, if any
var serviceInstance = new serviceConfig.service(server, app, serviceOptions); // create the singleton instance
serviceInstance.start(server, app, serviceOptions); // start the instance. we could add lazy initialization here at a later point
serviceRegistry[serviceName] = serviceInstance;
}
app.listen(options.port, options.host);
console.log(serverName+" Server listening on http://"+options.host+":"+options.port+"/");
return (function () {
console.log("Shutting down");
app.close();
});
};
//var resource = require('express-resource');
var express = require('express');
var everyauth = require('everyauth');
var crypto = require('crypto');
var util = require('util');
var _ = require('underscore');
// everyauth.debug = true;
// Registration validation bounds
var USERNAME_MIN = 2;
var USERNAME_MAX = 32;
var PASSWORD_MIN = 6;
var PASSWORD_MAX = 32;
// Index and db-driven validations occur in registerUser()
function validateRegistration(newUserAttrs, errors) {
// Validate login
var login = newUserAttrs.login;
if (login.length < USERNAME_MIN) errors.push('Login is too short');
if (login.length > USERNAME_MAX) errors.push('Login is too long');
// Validate password(_confirmation)
var password = newUserAttrs.password;
if (password.length < PASSWORD_MIN) errors.push('Password is too short');
if (password.length > PASSWORD_MAX) errors.push('Password is too long');
var password_confirmation = newUserAttrs.password_confirmation;
if (!password_confirmation) errors.push('Missing password confirmation');
if (password != password_confirmation) errors.push('Password and confirmation do not match');
return errors;
}
var AuthorizationService = module.exports = function Service(server, app, options) {
this.server = server;
this.app = app;
this.options = options;
}
AuthorizationService.prototype.start = function(server, app, options) {
// Setup view rendering
this.app.set('view engine', 'jade');
this.app.set('views', __dirname + '/../../views');
this.app.use(express.static(__dirname + '/../../public'));
this.app.get('/hello', function(req, res) {
console.log('get /hello, req.user: ' + util.inspect(req.user));
res.render('index', { title: 'Hello' });
});
// everyauth setup
// username/password
everyauth
.password
.loginWith('login')
.getLoginPath('/login')
.postLoginPath('/login')
.loginView('login.jade')
.authenticate( function (login, password) {
// Sync checks
var errors = [];
if (!login) errors.push('Missing login');
if (!password) errors.push('Missing password');
if (errors.length) return errors;
// Async checks
var promise = this.Promise();
// test communicating with naming-server
var NamingService = server.getService('naming');
NamingService.lookup('somekey', { login: login }, [], function(err,docs) {
var user = docs[0];
if (typeof(user) == 'undefined') {
// No user
console.log('NamingService: login - no user found');
promise.fulfill(['Login failed']);
} else {
console.log('user: ' + util.inspect(user));
// User found
// hash password and compare
var shasum = crypto.createHash('sha1');
shasum.update(password + login);
var passwordHash = shasum.digest('hex');
if (user.password !== passwordHash) return promise.fulfill(['Login failed']);
promise.fulfill(user);
}
});
return promise;
})
.loginSuccessRedirect('/hello')
.getRegisterPath('/register')
.postRegisterPath('/register')
.registerView('register.jade')
.extractExtraRegistrationParams( function (req) {
return {
'password_confirmation': req.body.password_confirmation
};
})
.validateRegistration( function (newUserAttrs, errors) {
return validateRegistration(newUserAttrs, errors);
})
.registerUser( function (newUserAttrs) {
var login = newUserAttrs[this.loginKey()];
var password = newUserAttrs.password;
// remove confirmation
delete newUserAttrs.password_confirmation;
// hash password and store
var shasum = crypto.createHash('sha1');
shasum.update(password + login);
newUserAttrs.password = shasum.digest('hex');
// Async checks
var promise = this.Promise();
// Check naming server if user already exists. If not, store the user.
var NamingService = server.getService('naming');
NamingService.lookup('somekey', { login: login }, [], function(err,docs) {
var existingUser = docs[0];
if (typeof(existingUser) == 'undefined') {
// No user
NamingService.add('somekey', newUserAttrs, function(err,docs) {
var newUser = docs[0];
promise.fulfill(newUser);
});
} else {
// User found, return error
promise.fulfill(['Login already taken']);
}
});
return promise;
})
.registerSuccessRedirect('/hello');
// logout
everyauth.everymodule.logoutRedirectPath('/hello');
// everyauth middleware and view helpers
this.app.use(everyauth.middleware());
everyauth.helpExpress(this.app);
}
@raid5
Copy link
Author

raid5 commented Jul 15, 2011

I should note that server.js starts up many servics (service.js).

@bnoguchi
Copy link

options appears to be undefined

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment