Comparing version 0.6.5 to 0.6.6
@@ -32,2 +32,3 @@ /* Adapted from http://www.quirksmode.org/js/xmlhttp.html */ | ||
req.open(method,url,true); | ||
req.withCredentials = true; | ||
// req.setRequestHeader('User-Agent','XMLHTTP/1.0'); | ||
@@ -61,3 +62,4 @@ if (data) | ||
function () {return new ActiveXObject("Msxml3.XMLHTTP")}, | ||
function () {return new ActiveXObject("Microsoft.XMLHTTP")} | ||
function () {return new ActiveXObject("Microsoft.XMLHTTP")}, | ||
function () {return new XDomainRequest()} | ||
]; | ||
@@ -64,0 +66,0 @@ |
@@ -1,2 +0,2 @@ | ||
# About Deployd Server | ||
# About Deployd | ||
@@ -3,0 +3,0 @@ We call Deployd a **resource server**. A resource server is not a library, but a complete server that works out of the box, and can be customized to fit the needs of your app by adding resources. Resources are ready-made components that live at a URL and provide functionality to your client app. |
@@ -36,2 +36,7 @@ # Deploying Your App | ||
## Dashboard Accesss | ||
To set up the dashboard on your server, type `dpd keygen` on your server's command line to create a remote access key. Type `dpd showkey` to get the key; you should store this somewhere secure. | ||
You can then go to the `/dashboard` route on the server and type in that key to gain access. | ||
## Server Script | ||
@@ -63,2 +68,3 @@ | ||
}); | ||
server.on('error', function(err) { | ||
@@ -65,0 +71,0 @@ console.error(err); |
# History | ||
## 0.6.6 | ||
- Added CORS support | ||
- Exposed the server object to modules as `process.server` | ||
- Fixed a rare bug where the first request after a login would not be authenticated | ||
- Fixed minor bug when loading only node modules | ||
## 0.6.5 | ||
@@ -4,0 +11,0 @@ |
@@ -70,3 +70,2 @@ var fs = require('fs') | ||
], fn); | ||
} | ||
@@ -73,0 +72,0 @@ |
@@ -5,3 +5,4 @@ var db = require('./db') | ||
, debug = require('debug')('router') | ||
, doh = require('doh'); | ||
, doh = require('doh') | ||
, async = require('async'); | ||
@@ -38,4 +39,3 @@ /** | ||
, resources = this.matchResources(url) | ||
, i = 0 | ||
, globals = 0; | ||
, i = 0; | ||
@@ -48,18 +48,14 @@ if (req._routed) { | ||
function next() { | ||
globals++; | ||
return function() { | ||
globals--; | ||
if(!globals) { nextResource(); } | ||
}; | ||
} | ||
// global hooks | ||
this.resources.forEach(function(resource) { | ||
if(resource.handleSession) { | ||
var ctx = new Context(resource, req, res, server); | ||
process.nextTick(function () { | ||
resource.handleSession(ctx, next()); | ||
}); | ||
} | ||
async.series([function(fn) { | ||
async.forEach(router.resources, function(resource, fn) { | ||
if(resource.handleSession) { | ||
var ctx = new Context(resource, req, res, server); | ||
resource.handleSession(ctx, fn); | ||
} else { | ||
fn(); | ||
} | ||
}, fn); | ||
}], function(err) { | ||
if (err) throw err; | ||
nextResource(); | ||
}); | ||
@@ -98,8 +94,3 @@ | ||
} | ||
// only start if there are no globals remaining | ||
if(!globals) { | ||
globals = -1; | ||
nextResource(); | ||
} | ||
}; | ||
@@ -106,0 +97,0 @@ |
@@ -52,3 +52,3 @@ var http = require('http') | ||
function Server(options) { | ||
var server = this; | ||
var server = process.server = this; | ||
http.Server.call(this); | ||
@@ -55,0 +55,0 @@ |
@@ -193,3 +193,2 @@ var Store = require('./db').Store | ||
Object.keys(object).forEach(function(key) { | ||
@@ -196,0 +195,0 @@ data[key] = object[key]; |
var Cookies = require('cookies') | ||
, qs = require('querystring') | ||
, parseUrl = require('url').parse; | ||
, parseUrl = require('url').parse | ||
, corser = require('corser') | ||
, ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'DELETE']; | ||
/*! | ||
@@ -10,24 +12,36 @@ * A utility for setting up a request and response. | ||
exports.setup = function(req, res, next) { | ||
var mime = req.headers['content-type'] || ''; | ||
mime = mime.split(';')[0]; //Just in case there's multiple mime types, pick the first | ||
var remoteHost = parseUrl(req.headers.referer || '').host | ||
, origins = ['http://' + remoteHost, 'https://' + remoteHost] | ||
, handler = corser.create({supportsCredentials: true, methods: ALLOWED_METHODS, origins: origins}); | ||
handler(req, res, function () { | ||
if (req.method === "OPTIONS") { | ||
// End CORS preflight request. | ||
res.writeHead(204); | ||
res.end(); | ||
} else { | ||
var mime = req.headers['content-type'] || ''; | ||
mime = mime.split(';')[0]; //Just in case there's multiple mime types, pick the first | ||
req.cookies = res.cookies = new Cookies(req, res); | ||
req.cookies = res.cookies = new Cookies(req, res); | ||
if(~req.url.indexOf('?')) { | ||
try { | ||
req.query = parseQuery(req.url); | ||
} catch (ex) { | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.statusCode = 400; | ||
res.end('Failed to parse querystring: ' + ex); | ||
return; | ||
if(~req.url.indexOf('?')) { | ||
try { | ||
req.query = parseQuery(req.url); | ||
} catch (ex) { | ||
res.setHeader('Content-Type', 'text/plain'); | ||
res.statusCode = 400; | ||
res.end('Failed to parse querystring: ' + ex); | ||
return; | ||
} | ||
} | ||
if(autoParse[mime]) { | ||
autoParse[mime](req, res, mime, next); | ||
} else { | ||
if(req.headers['content-length']) req.pause(); | ||
next(); | ||
} | ||
} | ||
} | ||
if(autoParse[mime]) { | ||
autoParse[mime](req, res, mime, next); | ||
} else { | ||
if(req.headers['content-length']) req.pause(); | ||
next(); | ||
} | ||
}); | ||
}; | ||
@@ -34,0 +48,0 @@ |
{ | ||
"author": "Ritchie Martori", | ||
"name": "deployd", | ||
"version": "0.6.5", | ||
"version": "0.6.6", | ||
"description": "the simplest way to build realtime APIs for web and mobile apps", | ||
@@ -38,3 +38,4 @@ "repository": { | ||
"keypress": "~0.1.0", | ||
"opener": "~1.3.0" | ||
"opener": "~1.3.0", | ||
"corser": "~1.1.1" | ||
}, | ||
@@ -41,0 +42,0 @@ "devDependencies": { |
@@ -1,2 +0,2 @@ | ||
# deployd v0.6.5 | ||
# deployd v0.6.6 | ||
@@ -3,0 +3,0 @@ [![Build Status](https://secure.travis-ci.org/deployd/deployd.png)](http://travis-ci.org/deployd/deployd) |
@@ -446,2 +446,53 @@ describe('Collection', function() { | ||
describe('issue 76', function() { | ||
it('should prevent unauthorized post', function(done) { | ||
chain(function(next) { | ||
dpd.todos.post({title: "$REQUIRE_AUTH"}, next); | ||
}).chain(function(next, res, err) { | ||
expect(err).to.exist; | ||
done(); | ||
}); | ||
}); | ||
it('should allow logged in user to post', function(done) { | ||
chain(function(next) { | ||
dpd.users.post({username: 'foo', password: 'bar'}, next); | ||
}).chain(function(next) { | ||
dpd.users.login({username: 'foo', password: 'bar'}, next); | ||
}).chain(function(next) { | ||
dpd.todos.post({title: "$REQUIRE_AUTH"}, next); | ||
}).chain(function(next, res, err) { | ||
expect(err).to.not.exist; | ||
expect(res.title).to.equal("$REQUIRE_AUTH"); | ||
done(); | ||
}); | ||
}); | ||
it('should allow logged in user to post after second try', function(done) { | ||
chain(function(next) { | ||
dpd.users.post({username: 'foo', password: 'bar'}, next); | ||
}).chain(function(next) { | ||
dpd.users.login({username: 'foo', password: 'bar'}, next); | ||
}).chain(function(next) { | ||
dpd.todos.post({title: "$REQUIRE_AUTH"}, next); | ||
}).chain(function(next) { | ||
dpd.todos.post({title: "$REQUIRE_AUTH"}, next); | ||
}).chain(function(next, res, err) { | ||
expect(err).to.not.exist; | ||
expect(res.title).to.equal("$REQUIRE_AUTH"); | ||
done(); | ||
}); | ||
}); | ||
afterEach(function(done) { | ||
this.timeout(10000); | ||
dpd.users.logout(function() { | ||
cleanCollection(dpd.users, function() { | ||
cleanCollection(dpd.todos, done); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('internal cancel()', function(){ | ||
@@ -457,2 +508,4 @@ it('should not cancel the internal call', function(done) { | ||
}); | ||
@@ -459,0 +512,0 @@ afterEach(function (done) { |
@@ -36,3 +36,3 @@ var chain = function(fn) { | ||
var cleanCollection = function(collection, done) { | ||
collection.get(function (items) { | ||
collection.get({clean: true}, function (items) { | ||
var total = items.length; | ||
@@ -39,0 +39,0 @@ if(total === 0) return done(); |
@@ -6,3 +6,3 @@ if (query.title === "$FAIL2") { | ||
if (this.title === "$GET_CANCEL") { | ||
if (this.title === "$GET_CANCEL" && !query.clean) { | ||
cancel("Cancelled"); | ||
@@ -9,0 +9,0 @@ } |
@@ -0,1 +1,5 @@ | ||
if (this.title == "$REQUIRE_AUTH") { | ||
if (!me) cancel("You are not authorized", 401); | ||
} | ||
if (this.title === "$FAIL") { | ||
@@ -2,0 +6,0 @@ var x = null; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1950922
34501
26
+ Addedcorser@~1.1.1
+ Addedcorser@1.1.2(transitive)