mirror of
https://github.com/zhigang1992/deployd.git
synced 2026-05-28 16:45:11 +08:00
passing 11/11 0.3.0-pre
This commit is contained in:
@@ -1 +1,12 @@
|
||||
module.exports = require('mdoq').require('mdoq-http');
|
||||
module.exports = require('mdoq')
|
||||
.require('mdoq-http')
|
||||
.use(function (req, res, next) {
|
||||
if(res.statusCode >= 400) {
|
||||
var err = res.data;
|
||||
res.data = undefined;
|
||||
next(err);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
})
|
||||
;
|
||||
8
lib/collections/resources.js
Normal file
8
lib/collections/resources.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = require('../types/collection')
|
||||
.use('/resources')
|
||||
;
|
||||
|
||||
// TODO
|
||||
// - Run migration on PUT (when name is deleted remove property)
|
||||
// - PUT requests come back {task: {$renameFrom: 'title'}}
|
||||
// - or
|
||||
4
lib/collections/sessions.js
Normal file
4
lib/collections/sessions.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = require('../types/collection')
|
||||
.use('/sessions')
|
||||
;
|
||||
|
||||
4
lib/collections/types.js
Normal file
4
lib/collections/types.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = function (req, res, next) {
|
||||
res.data = require('../types');
|
||||
next();
|
||||
};
|
||||
8
lib/db.js
Normal file
8
lib/db.js
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* The unrestriced / private interface to the database.
|
||||
*/
|
||||
|
||||
module.exports = require('mdoq')
|
||||
.require('mdoq-mongodb')
|
||||
.use('localhost')
|
||||
;
|
||||
@@ -1,15 +1,41 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* Extend a basic mdoq object
|
||||
*/
|
||||
|
||||
var express = require('express')
|
||||
, storage = require('./storage')
|
||||
;
|
||||
var dpd = require('mdoq')
|
||||
|
||||
/**
|
||||
* Export the deployd constructor.
|
||||
* Export the dpd mdoq object as the public interface.
|
||||
*/
|
||||
|
||||
module.exports = dpd
|
||||
|
||||
/**
|
||||
* Provide optional network access via an http server.
|
||||
*/
|
||||
|
||||
.use(require('./server'))
|
||||
|
||||
/**
|
||||
* Every request will try to establish a session.
|
||||
*/
|
||||
|
||||
module.exports = function (name) {
|
||||
return require('./server')(name);
|
||||
}
|
||||
.use(require('./session'))
|
||||
|
||||
/**
|
||||
* If a session was established, continue to the router.
|
||||
*/
|
||||
|
||||
.use(require('./router'))
|
||||
|
||||
/**
|
||||
* If the router finds a resource, continue to validation.
|
||||
*/
|
||||
|
||||
.use(require('./validation'))
|
||||
|
||||
/**
|
||||
* If the request passes validation, continue to the requested resource.
|
||||
*/
|
||||
|
||||
.use(require('./resource'))
|
||||
43
lib/resource.js
Normal file
43
lib/resource.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var types = require('./types');
|
||||
|
||||
/**
|
||||
* Execute the request against the provided resource.
|
||||
*/
|
||||
|
||||
module.exports = function (req, res, next, end) {
|
||||
// skip without a resource
|
||||
if(!req.resource) return next(new Error('404'));
|
||||
|
||||
// use type's require if provided
|
||||
var modulePath = (types[req.resource.type] || req.resource).require;
|
||||
|
||||
// skip without a module path
|
||||
if(!modulePath) return next(new Error('Resource does not have a require property.'));
|
||||
|
||||
// require module
|
||||
var module = require(modulePath);
|
||||
|
||||
// end with the module as the finalware
|
||||
if(module.middleware || typeof module == 'function') {
|
||||
end(function (req, res, next) {
|
||||
if(typeof module == 'function') {
|
||||
module(req, res, next);
|
||||
} else{
|
||||
module.exec(req, function (err, data) {
|
||||
res.data = data;
|
||||
next();
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
return next(new Error('The provided module is not supported'));
|
||||
}
|
||||
|
||||
// continue
|
||||
next();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
var debug = require('mdoq').util.debug;
|
||||
|
||||
module.exports = require('./storage')
|
||||
.use('/resources')
|
||||
;
|
||||
@@ -2,43 +2,50 @@
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var storage = require('./storage')
|
||||
, resources = require('./resources')
|
||||
var resources = require('./collections/resources')
|
||||
, revalidator = require('revalidator')
|
||||
;
|
||||
|
||||
module.exports = function (req, res, next) {
|
||||
var path = req.url.split('?')[0];
|
||||
|
||||
resources.get({path: path}, function (err, resource) {
|
||||
|
||||
// HACK - REMOVE ONCE `first()` LANDS IN MDOQ-MONGODB
|
||||
|
||||
resource = resource && resource[0] || resource;
|
||||
|
||||
if(resource && tryingToModify(req)) {
|
||||
if(resource.settings) {
|
||||
var result = revalidator.validate(req.body, {properties: resource.settings});
|
||||
|
||||
if(result.valid) {
|
||||
storage.proxy().call(this, req, res, next);
|
||||
} else {
|
||||
res.send(result);
|
||||
}
|
||||
} else {
|
||||
storage.proxy().call(this, req, res, next);
|
||||
}
|
||||
} else if(resource) {
|
||||
storage.exec(req, function (err, r) {
|
||||
res.send(err || r);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Attach the requested resource definition.
|
||||
*/
|
||||
|
||||
function tryingToModify(req) {
|
||||
var method = req.method;
|
||||
return method === 'POST' || method === 'PUT';
|
||||
}
|
||||
module.exports = function (req, res, next) {
|
||||
var parsed = req.url.split('?')[0].replace('/', '').split('/')
|
||||
, collections = req.collections = []
|
||||
, references = req.references = []
|
||||
, internals = {'/types': './collections/types', '/resources': './collections/resources'}
|
||||
, method = req.method
|
||||
, path = '/'
|
||||
;
|
||||
|
||||
// parse url into references and collections
|
||||
parsed.forEach(function (part, i) {
|
||||
(i % 2 ? references : collections).push(part);
|
||||
});
|
||||
|
||||
path += collections[0];
|
||||
|
||||
// route to the first collection
|
||||
resources.get({path: path}).first(function (err, resource) {
|
||||
|
||||
// TODO only allow root
|
||||
if(!resource && internals[path]) {
|
||||
resource = {
|
||||
require: internals[path],
|
||||
path: path
|
||||
}
|
||||
}
|
||||
|
||||
// for future reference
|
||||
req.resource = resource;
|
||||
|
||||
if(!resource) {
|
||||
console.log(req.method, req.url, 404);
|
||||
err = new Error('404');
|
||||
}
|
||||
|
||||
// continue
|
||||
next(err);
|
||||
});
|
||||
}
|
||||
@@ -1,37 +1,63 @@
|
||||
var dpd = require('./deployd')
|
||||
, name = dpd.name
|
||||
, express = require('express')
|
||||
, server = express.createServer(express.bodyParser())
|
||||
, resources = require('./resources')
|
||||
, router = require('./router')
|
||||
, types = require('./types')
|
||||
;
|
||||
|
||||
/**
|
||||
* Serve storage at each resource route.
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
server.use(router);
|
||||
var express = require('express')
|
||||
, parse = require('url').parse;
|
||||
|
||||
/**
|
||||
* Serve resources over http.
|
||||
* Http server as a middleware
|
||||
*/
|
||||
|
||||
server.use('/resources', resources.proxy());
|
||||
var middleware = function (req, res, next) {
|
||||
next();
|
||||
};
|
||||
|
||||
/**
|
||||
* Serve resource types over http.
|
||||
* Expose the mdoq object over http.
|
||||
*/
|
||||
|
||||
server.get('/types', function (req, res) {
|
||||
res.send(types);
|
||||
});
|
||||
middleware.listen = function (callback) {
|
||||
var server = this.server = express.createServer(express.bodyParser(), express.cookieParser())
|
||||
, url = parse(this.url || 'http://localhost:2304');
|
||||
|
||||
// port
|
||||
var port = url.port || 2304;
|
||||
// host
|
||||
var hostname = url.hostname || 'localhost';
|
||||
|
||||
// proxy requests into the current mdoq stack
|
||||
// executing the stack when a request comes in
|
||||
server.use(this.proxy());
|
||||
|
||||
// error handling
|
||||
server.error(function (err, req, res, next) {
|
||||
if(typeof err == 'object' && !(err instanceof Error)) {
|
||||
res.statusCode = 400;
|
||||
res.send(err);
|
||||
} else {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
// start the server
|
||||
server.listen(port, hostname, callback);
|
||||
|
||||
// chainable
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Export a function to mount the new server to a name.
|
||||
* Stop the server from accepting new connections.
|
||||
*/
|
||||
|
||||
module.exports = function (name) {
|
||||
server.name = name || 'deployd';
|
||||
return server;
|
||||
};
|
||||
middleware.close = function () {
|
||||
this.server.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the middleware
|
||||
*/
|
||||
|
||||
module.exports = middleware;
|
||||
|
||||
|
||||
6
lib/session.js
Normal file
6
lib/session.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function (req, res, next) {
|
||||
|
||||
|
||||
|
||||
next();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = require('mdoq')
|
||||
.require('mdoq-mongodb')
|
||||
.use('mongodb://localhost/dpd-testing')
|
||||
;
|
||||
24
lib/types.js
24
lib/types.js
@@ -1,12 +1,32 @@
|
||||
module.exports = {
|
||||
|
||||
Collection: {
|
||||
defaultPath: '/my-objects'
|
||||
defaultPath: '/my-objects',
|
||||
require: './types/collection'
|
||||
},
|
||||
|
||||
UserCollection: {
|
||||
label: 'Users Collection',
|
||||
defaultPath: '/users'
|
||||
defaultPath: '/users',
|
||||
require: './types/user-collection',
|
||||
settings: {
|
||||
email: {
|
||||
description: 'the unique email of the user',
|
||||
type: 'string',
|
||||
pattern: "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
|
||||
required: true,
|
||||
unique: true,
|
||||
minLength: 5,
|
||||
order: 0
|
||||
},
|
||||
password: {
|
||||
description: "the user's password",
|
||||
type: 'string',
|
||||
required: true,
|
||||
minLength: 5,
|
||||
order: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
13
lib/types/collection.js
Normal file
13
lib/types/collection.js
Normal file
@@ -0,0 +1,13 @@
|
||||
function format(name) {
|
||||
name = name.toLowerCase().replace(/\W/g, '-').replace(/--+/g, '');
|
||||
return '/' + name;
|
||||
}
|
||||
|
||||
module.exports = require('mdoq')
|
||||
.use(function (req, res, next) {
|
||||
var path = req.resource && req.resource.path;
|
||||
this.url = 'localhost/deployd' + (path || this.url);
|
||||
next();
|
||||
})
|
||||
.require('mdoq-mongodb')
|
||||
;
|
||||
40
lib/types/user-collection.js
Normal file
40
lib/types/user-collection.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var sessions = require('../collections/sessions');
|
||||
|
||||
/**
|
||||
* A collection of user objects with login/out support.
|
||||
*/
|
||||
|
||||
module.exports = function (req, res, next) {
|
||||
var col = require('./collection').use('/users');
|
||||
|
||||
if(~req.url.indexOf('/login')) {
|
||||
console.log(req.url, req.data, 'trying to login');
|
||||
col.get(req.data).first(function (err, user) {
|
||||
if(user) {
|
||||
// login successful - create session
|
||||
sessions.post({user: user}, function (e, session) {
|
||||
console.log('created session id', session._id);
|
||||
res.data = session;
|
||||
console.log(res.cookie);
|
||||
next(e || err);
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if(~req.url.indexOf('/logout')) {
|
||||
if(req.session) {
|
||||
|
||||
} else {
|
||||
next(new Error('Session not found.'));
|
||||
}
|
||||
} else {
|
||||
col.exec(req, function (err, docs) {
|
||||
res.data = docs;
|
||||
|
||||
next(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
32
lib/validation.js
Normal file
32
lib/validation.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var revalidator = require('revalidator');
|
||||
|
||||
/**
|
||||
* Validate the attached resource and request.
|
||||
*/
|
||||
|
||||
module.exports = function (req, res, next) {
|
||||
var method = req.method
|
||||
, resource = req.resource
|
||||
, validation
|
||||
, err
|
||||
;
|
||||
|
||||
// skip without a resource
|
||||
if(!resource) return next(new Error('validation 404'));
|
||||
|
||||
// if trying to write data
|
||||
if((method === 'POST' || method === 'PUT') && resource && resource.settings) {
|
||||
|
||||
// validate
|
||||
validation = revalidator.validate(req.body, {properties: resource.settings});
|
||||
console.log(validation);
|
||||
err = validation.valid ? err : validation;
|
||||
}
|
||||
|
||||
// continue
|
||||
next(err);
|
||||
}
|
||||
Reference in New Issue
Block a user