mirror of
https://github.com/zhigang1992/deployd.git
synced 2026-05-23 21:35:38 +08:00
renamed plugins
This commit is contained in:
54
lib/plugins/apps/app.js
Normal file
54
lib/plugins/apps/app.js
Normal file
@@ -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();
|
||||
}
|
||||
|
||||
});
|
||||
9
lib/plugins/apps/apps.js
Normal file
9
lib/plugins/apps/apps.js
Normal file
@@ -0,0 +1,9 @@
|
||||
var Collection = require('../../collection')
|
||||
, App = require('./app')
|
||||
;
|
||||
|
||||
module.exports = Collection.spawn({
|
||||
collection: 'apps',
|
||||
plugin: 'apps',
|
||||
model: App
|
||||
});
|
||||
74
lib/plugins/apps/balancer.js
Normal file
74
lib/plugins/apps/balancer.js
Normal file
@@ -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 = '<h1>Not Found</h1>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';
|
||||
}
|
||||
49
lib/plugins/apps/index.js
Normal file
49
lib/plugins/apps/index.js
Normal file
@@ -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');
|
||||
});
|
||||
29
lib/plugins/apps/views/index.ejs
Normal file
29
lib/plugins/apps/views/index.ejs
Normal file
@@ -0,0 +1,29 @@
|
||||
<div class="authed">
|
||||
<h2>My Apps</h2>
|
||||
<h3>alpha!</h3>
|
||||
<ul id="apps">
|
||||
</ul>
|
||||
<h4>Create an app...</h4>
|
||||
<input type="text" id="name" />
|
||||
<button id="create">create new</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
d('/search/apps', {creator: 'skawful@gmail.com'}, function(res) {
|
||||
$.each(res.results, function(i, item) {
|
||||
$('#apps').append(
|
||||
$('<li />').text(item.name + ' @ ' + item.host + '.deploydapp.com')
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
$('#create').click(function() {
|
||||
var name = $('#name').val();
|
||||
d('/app', {name: name}, function(res) {
|
||||
console.log(res);
|
||||
if(res._id) window.location.reload();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
26
lib/plugins/apps/views/layout.ejs
Normal file
26
lib/plugins/apps/views/layout.ejs
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>index</title>
|
||||
<meta name="generator" content="TextMate http://macromates.com/">
|
||||
<meta name="author" content="ritchie">
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
|
||||
<script src="/deployd.js"></script>
|
||||
<script src="/libs/jquery.cookie.js"></script>
|
||||
<style>
|
||||
.authed, .not-authed {display: none;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Deployd</h1>
|
||||
<%- body %>
|
||||
<script>
|
||||
var active = $.cookie('deployd.sid') ? '.authed' : '.not-authed';
|
||||
console.log(active);
|
||||
$(active).show();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
37
lib/plugins/apps/views/login.ejs
Normal file
37
lib/plugins/apps/views/login.ejs
Normal file
@@ -0,0 +1,37 @@
|
||||
<div id="login-form">
|
||||
Username
|
||||
<input id="uid" type="text" />
|
||||
Password
|
||||
<input id="password" type="password" />
|
||||
<button id="login">login</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
d('/me', function(res) {
|
||||
if(res && res.uid)
|
||||
$('#login-form').html('Logged in as ' + res.uid);
|
||||
})
|
||||
|
||||
$('#login').click(function() {
|
||||
var info = {
|
||||
email: $('#uid').val(),
|
||||
password: $('#password').val()
|
||||
};
|
||||
|
||||
d('/user/login', info, function(res) {
|
||||
if(res.auth) {
|
||||
window.location = '/my/apps';
|
||||
} else {
|
||||
alert('login failed...');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#logout').click(function() {
|
||||
d('/user/logout', function() {
|
||||
window.location.reload();
|
||||
});
|
||||
})
|
||||
|
||||
</script>
|
||||
32
lib/plugins/models/index.js
Normal file
32
lib/plugins/models/index.js
Normal file
@@ -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()
|
||||
;
|
||||
|
||||
|
||||
34
lib/plugins/users/group.js
Normal file
34
lib/plugins/users/group.js
Normal file
@@ -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()
|
||||
;
|
||||
});
|
||||
9
lib/plugins/users/groups.js
Normal file
9
lib/plugins/users/groups.js
Normal file
@@ -0,0 +1,9 @@
|
||||
var Collection = require('../../collection')
|
||||
, Group = require('./group')
|
||||
;
|
||||
|
||||
module.exports = Collection.spawn({
|
||||
collection: 'groups',
|
||||
plugin: 'users',
|
||||
model: Group
|
||||
});
|
||||
83
lib/plugins/users/index.js
Normal file
83
lib/plugins/users/index.js
Normal file
@@ -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()
|
||||
;
|
||||
});
|
||||
62
lib/plugins/users/user.js
Normal file
62
lib/plugins/users/user.js
Normal file
@@ -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
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
9
lib/plugins/users/users.js
Normal file
9
lib/plugins/users/users.js
Normal file
@@ -0,0 +1,9 @@
|
||||
var Collection = require('../../collection')
|
||||
, User = require('./user')
|
||||
;
|
||||
|
||||
module.exports = Collection.spawn({
|
||||
collection: 'users',
|
||||
plugin: 'users',
|
||||
model: User
|
||||
});
|
||||
Reference in New Issue
Block a user