From 96e3a9be23fe5c8a8f094dd628e4efeab86ef8ab Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Sat, 26 Nov 2011 14:43:47 -0800 Subject: [PATCH] renamed plugins --- lib/plugins/apps/app.js | 54 ++++++++++++++++++++ lib/plugins/apps/apps.js | 9 ++++ lib/plugins/apps/balancer.js | 74 +++++++++++++++++++++++++++ lib/plugins/apps/index.js | 49 ++++++++++++++++++ lib/plugins/apps/views/index.ejs | 29 +++++++++++ lib/plugins/apps/views/layout.ejs | 26 ++++++++++ lib/plugins/apps/views/login.ejs | 37 ++++++++++++++ lib/plugins/models/index.js | 32 ++++++++++++ lib/plugins/users/group.js | 34 +++++++++++++ lib/plugins/users/groups.js | 9 ++++ lib/plugins/users/index.js | 83 +++++++++++++++++++++++++++++++ lib/plugins/users/user.js | 62 +++++++++++++++++++++++ lib/plugins/users/users.js | 9 ++++ 13 files changed, 507 insertions(+) create mode 100644 lib/plugins/apps/app.js create mode 100644 lib/plugins/apps/apps.js create mode 100644 lib/plugins/apps/balancer.js create mode 100644 lib/plugins/apps/index.js create mode 100644 lib/plugins/apps/views/index.ejs create mode 100644 lib/plugins/apps/views/layout.ejs create mode 100644 lib/plugins/apps/views/login.ejs create mode 100644 lib/plugins/models/index.js create mode 100644 lib/plugins/users/group.js create mode 100644 lib/plugins/users/groups.js create mode 100644 lib/plugins/users/index.js create mode 100644 lib/plugins/users/user.js create mode 100644 lib/plugins/users/users.js diff --git a/lib/plugins/apps/app.js b/lib/plugins/apps/app.js new file mode 100644 index 0000000..d2997cd --- /dev/null +++ b/lib/plugins/apps/app.js @@ -0,0 +1,54 @@ +var Model = require('../../model'); + +module.exports = Model.spawn({ + + collection: 'apps', + plugin: 'apps', + + description: { + name: {type: 'string', unique: true}, + creator: 'string', + db: 'string', + host: 'string' + }, + + allowed: { + read: 'creator', + write: 'creator', + remove: 'creator', + create: 'user' + }, + + save: function() { + var name = this.get('name') + , host = this.toHostName() + , creator = this.get('creator') + ; + + if(!creator) this.error('Must be logged in to create an app.', 'App'); + + if(host && creator) { + if(this.isNew()) { + this.set({name: name, host: host, db: this.toDatabaseName(), creator: creator}); + } else { + this.restart(host); + } + } + + Model.save.apply(this, arguments); + }, + + toHostName: function() { + var name = this.get('name') + , app = name && name.replace(/ /g, '-') + , creator = this.get('creator') + ; + + return app.toLowerCase(); + }, + + toDatabaseName: function() { + return this.toHostName().replace(/\./g, ':').toLowerCase(); + } + +}); \ No newline at end of file diff --git a/lib/plugins/apps/apps.js b/lib/plugins/apps/apps.js new file mode 100644 index 0000000..565a9e2 --- /dev/null +++ b/lib/plugins/apps/apps.js @@ -0,0 +1,9 @@ +var Collection = require('../../collection') + , App = require('./app') +; + +module.exports = Collection.spawn({ + collection: 'apps', + plugin: 'apps', + model: App +}); \ No newline at end of file diff --git a/lib/plugins/apps/balancer.js b/lib/plugins/apps/balancer.js new file mode 100644 index 0000000..d16405a --- /dev/null +++ b/lib/plugins/apps/balancer.js @@ -0,0 +1,74 @@ +// Balancer tells requests where to go +// - If a internal host (ihost) is not found within its cache, it boots a deployd +// app at a new ihost and saves this location to the central deployd db +// - Subsequent requests should be mapped from host to ihost and routed + +var bouncy = require('bouncy') + , apps = {} + , exec = require('child_process').exec + , ERROR = '

Not Found

There is no app configured to listen to this host. Perhaps you mistyped the url?\n' + , App = require('./app') +; + +bouncy(function (req, bounce) { + var host = req.headers.host + , app = App.spawn() + ; + + if(apps[host]) { + bounce(apps[host].ihost || currentHost(), apps[host].port); + return; + } + + app.query = {host: host.replace('.deploydapp.com', '')}; + app + .notify(function(json) { + apps[host] = json; + if(json.ihost && json.port) { + bounce(app.ihost, json.port); + } else if(json._id) { + // app exists, but not on any internal hosts + // set the internal host to the machine that spawned it + json.ihost = currentHost(); + json.port = nextPort(); + + console.log(['deployd', "'" + JSON.stringify(json) + "'"].join(' ')); + + // then boot + var d = exec(['deployd', "'" + JSON.stringify(json) + "'"].join(' ')); + + d.stdout + .on('data', function(data) { + console.log(data.toString()); + if(data.toString().indexOf('listening') > -1) { + bounce(json.port); + } + }); + + d.stderr.on('data', function(data) { + console.log(data.toString()); + }); + + + app.set(json).save(); + } else { + var res = bounce.respond(); + res.writeHead(500, { + 'Content-Length': ERROR.length, + 'Content-Type': 'text/html' + }); + res.end(ERROR); + } + }) + .fetch() + ; +}).listen(80); + +function nextPort() { + process.last = (3001 || process.last); + return process.last++; +} + +function currentHost() { + return 'localhost'; +} \ No newline at end of file diff --git a/lib/plugins/apps/index.js b/lib/plugins/apps/index.js new file mode 100644 index 0000000..03802b5 --- /dev/null +++ b/lib/plugins/apps/index.js @@ -0,0 +1,49 @@ +var app = require('../../app') + , App = require('./app') +; + +if(process.argv.length < 3) { + require('./balancer'); +} + +app.post('/app', function(req, res) { + var session = req.session + , me = session && session.user && session.user.email + ; + + App + .spawn() + .for(req) + .set({name: req.param('name'), creator: me}) + .notify(res) + .save() + ; +}); + +app.get('/app/:id', function(req, res) { + App + .spawn() + .for(req) + .set({_id: req.param('id')}) + .notify(res) + .fetch() + ; +}); + +app.del('/app/:id', function(req, res) { + App + .spawn() + .for(req) + .notify(res) + .remove() + ; +}); + +// views +app.get('/my/apps', function(req, res) { + res.render(__dirname + '/views/index.ejs'); +}); + +app.get('/login', function(req, res) { + res.render(__dirname + '/views/login.ejs'); +}); \ No newline at end of file diff --git a/lib/plugins/apps/views/index.ejs b/lib/plugins/apps/views/index.ejs new file mode 100644 index 0000000..5f28a6b --- /dev/null +++ b/lib/plugins/apps/views/index.ejs @@ -0,0 +1,29 @@ +
+

My Apps

+

alpha!

+ +

Create an app...

+ + +
+ + + + diff --git a/lib/plugins/apps/views/layout.ejs b/lib/plugins/apps/views/layout.ejs new file mode 100644 index 0000000..34a69d8 --- /dev/null +++ b/lib/plugins/apps/views/layout.ejs @@ -0,0 +1,26 @@ + + + + + + index + + + + + + + + +

Deployd

+ <%- body %> + + + diff --git a/lib/plugins/apps/views/login.ejs b/lib/plugins/apps/views/login.ejs new file mode 100644 index 0000000..1634309 --- /dev/null +++ b/lib/plugins/apps/views/login.ejs @@ -0,0 +1,37 @@ +
+ Username + + Password + + +
+ + \ No newline at end of file diff --git a/lib/plugins/models/index.js b/lib/plugins/models/index.js new file mode 100644 index 0000000..77d4797 --- /dev/null +++ b/lib/plugins/models/index.js @@ -0,0 +1,32 @@ +var Settings = require('../settings/settings') + , Setting = require('../settings/settings') + , Model = require('../../model') +; + +var models = module.exports.models = {}; +var refresh = module.exports.refresh = function() { + Settings + .spawn() + .find({plugin: 'models'}) + .notify(function(model) { + var m = models[model.name] = Model.spawn(); + m.description = model.description; + m.allowed = model.allowed; + m.collection = model.collection; + m.plugin = model.plugin; + }) + .fetch() + ; +} + +// initial refresh +refresh(); + +// create or update general graph settings +Setting + .spawn() + .set({plugin: 'models', name: 'models'}) + .save() +; + + diff --git a/lib/plugins/users/group.js b/lib/plugins/users/group.js new file mode 100644 index 0000000..24b7928 --- /dev/null +++ b/lib/plugins/users/group.js @@ -0,0 +1,34 @@ +var Model = require('../../model'); + +var Group = module.exports = Model.spawn({ + + collection: 'groups', + plugin: 'users', + + description: { + name: {type: 'string', unique: true}, + creator: 'string' + }, + + allowed: { + read: 'root', + write: 'creator', + remove: 'creator', + create: 'root' + } + +}); + +var defaults = ['root', 'admin', 'public']; + +defaults.forEach(function(group) { + var g = {name: group, creator: 'root'}; + + Group + .spawn() + .unlock() + .find(g) + .set(g) + .save() + ; +}); \ No newline at end of file diff --git a/lib/plugins/users/groups.js b/lib/plugins/users/groups.js new file mode 100644 index 0000000..ce61a9d --- /dev/null +++ b/lib/plugins/users/groups.js @@ -0,0 +1,9 @@ +var Collection = require('../../collection') + , Group = require('./group') +; + +module.exports = Collection.spawn({ + collection: 'groups', + plugin: 'users', + model: Group +}); \ No newline at end of file diff --git a/lib/plugins/users/index.js b/lib/plugins/users/index.js new file mode 100644 index 0000000..b2874b0 --- /dev/null +++ b/lib/plugins/users/index.js @@ -0,0 +1,83 @@ +var app = require('../../app') + , Group = require('./group') + , Groups = require('./groups') + , User = require('./user') + , Users = require('./users') + , ObjectID = require('mongodb').BSON +; + +function user(action, params, req, res) { + User + .spawn() + .for(req) + .set(params) + .notify(res) + [action]() + ; +} + +app.post('/users', function(req, res) { + user('save', req.body, req, res); +}); + +app.post('/users/login', function(req, res) { + user('login', req.body, req, { + send: function(u) { + u.auth = req.sessionID; + res.send(req.session.user = u); + } + }); +}); + +app.get('/users/logout', function(req, res) { + req.session.destroy(function() { + res.send({auth: null}); + }); +}); + +app.get('/me', function(req, res) { + user('fetch', {email: req.session.user && req.session.user.email}, req, res); +}); + +app.del('/me', function(req, res) { + var u = req.session.user; + if(u) user('remove', u, req, res); +}); + +app.get('/users/:id', function(req, res) { + User + .spawn() + .for(req) + .find({_id: req.param('id')}) + .notify(res) + .fetch() + ; +}); + +app.post('/users/:email/group', function(req, res) { + var changes = {} + , group = req.body && req.body.group + ; + + // TODO validate group + changes['groups.' + group] = 1; + User + .spawn() + .for(req) + .find({email: req.param('email')}) + .set({$set: changes}) + .notify(res) + .save() + ; +}); + +app.get('/users', function(req, res) { + Users + .spawn({ + query: req.params + }) + .for(req) + .notify(res) + .fetch() + ; +}); diff --git a/lib/plugins/users/user.js b/lib/plugins/users/user.js new file mode 100644 index 0000000..2c86817 --- /dev/null +++ b/lib/plugins/users/user.js @@ -0,0 +1,62 @@ +var Model = require('../../model') + , ObjectID = require('mongodb').BSONPure.ObjectID + , _ = require('underscore') +; + +module.exports = Model.spawn({ + + collection: 'users', + plugin: 'users', + + description: { + email: {type: 'email', unique: true}, + password: 'password', + name: 'string', + auth: 'string', + removed: 'boolean', + groups: 'object' + }, + + allowed: { + read: 'public', + write: 'creator', + remove: 'creator', + create: 'public', + special: { + groups: {read: 'public', write: 'root'}, + email: {read: 'creator'} + } + }, + + toJSON: function() { + var j = Model.toJSON.apply(this, arguments); + + // remove password before sending to clients + delete j.password; + + return j; + }, + + set: function(changes) { + // prevent ever storing a real password + changes.password && (changes.password = this.hash(changes.password)); + + return Model.set.apply(this, arguments); + }, + + login: function() { + if(!this.get('email') || !this.get('password')) this.error('User email and password are required', 'Required Field'); + + return this.fetch(); + }, + + hash: function(password) { + return password + 'hash!'; + }, + + defineRoutes: function() { + // routes in ./index.js + } + +}); + diff --git a/lib/plugins/users/users.js b/lib/plugins/users/users.js new file mode 100644 index 0000000..dcc3bb4 --- /dev/null +++ b/lib/plugins/users/users.js @@ -0,0 +1,9 @@ +var Collection = require('../../collection') + , User = require('./user') +; + +module.exports = Collection.spawn({ + collection: 'users', + plugin: 'users', + model: User +}); \ No newline at end of file