Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V6.0 #1691

Merged
merged 39 commits into from
Jun 8, 2014
Merged

V6.0 #1691

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
919cd31
Remove internal view require(). Closes #1655
May 18, 2014
0e312e6
#1655
May 18, 2014
6c20786
Remove pack array support. Closes #1652
May 25, 2014
2fcaa6a
Move Composer into Pack.compose(). Closes #1653
May 18, 2014
b4183c5
Remove pack.require(). Closes #1656
May 25, 2014
78a2b37
Partial docs
May 26, 2014
affe9be
Update register plugin format
May 26, 2014
5574cb7
plugin vhost and path prefix override. Closes #981, Closes #1658, Clo…
May 26, 2014
bb0fcb5
Prevent view manager from cloning engines. Closes #1661
May 26, 2014
9b09ec5
Prevent clone from deep copy of unsafe object. Closes #1662
May 26, 2014
3e6dc1d
merge
May 26, 2014
dc3fd91
Server config clone. For #1662
May 26, 2014
474fed5
Apply plugin register route options to child register. For #1658
May 26, 2014
fabebee
Pre-select labels in register. Closes #1663
May 26, 2014
3054058
Cleanup
May 27, 2014
7fee0cb
Merge branch 'master' of github.com:spumko/hapi into v6.0
May 29, 2014
ad11ffa
Merge branch 'v6.0' of github.com:spumko/hapi into v6.0
May 29, 2014
54bdf05
Divider object
May 29, 2014
cf298c1
Move shallow utils to hoek
May 29, 2014
4704971
Merge branch 'master' of github.com:spumko/hapi into v6.0
Jun 1, 2014
dfff9ed
Merge branch 'v6.0' of github.com:spumko/hapi into v6.0
Jun 1, 2014
ca5cd30
Move divider to kilt
Jun 1, 2014
4d58ac7
Make plugin.events to selectable. Closes #1673
Jun 1, 2014
b5a0310
apply preselected plugins to expose. For #1663
Jun 1, 2014
8fc5db8
Remove pack.list. Closes #1675
Jun 1, 2014
384bf6c
Move plugin register and dependency to selectable. Closes #1674
Jun 1, 2014
62bd628
manifest support for plugin select. Closes #1677
Jun 2, 2014
757cb48
Fix test
May 29, 2014
85c3248
Fix pack event emitter. For #1673
Jun 2, 2014
b7c304d
server.location(). Closes #1678
Jun 2, 2014
48511f8
Cookie specific overrides. Closes #1679
Jun 3, 2014
830ddf6
auth non-error log. Closes #1687
Jun 5, 2014
842ce83
reply.redirect(). Closes #1688
Jun 5, 2014
f9e739e
lowercase hapi
Jun 5, 2014
76779aa
auth.test(). Closes #1692
Jun 7, 2014
e5df652
Auth defaults. Closes #1693
Jun 8, 2014
4f90baa
Minor error tweaks
Jun 8, 2014
86eccfb
merge
Jun 8, 2014
e8e5050
Remove unused dep
Jun 8, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ infrastructure. The framework supports a powerful plugin architecture for pain-f

For the latest updates and release information follow [@hapijs](https://twitter.com/hapijs) on twitter.

Current version: **5.1.x** ([release notes](https://github.com/spumko/hapi/issues?labels=release+notes&page=1&state=closed))
Current version: **6.0.x** ([release notes](https://github.com/spumko/hapi/issues?labels=release+notes&page=1&state=closed))


[![Build Status](https://secure.travis-ci.org/spumko/hapi.svg)](http://travis-ci.org/spumko/hapi)
Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
## Current Documentation
[v5.1.x](https://github.com/spumko/hapi/blob/master/docs/Reference.md)
[v6.0.x](https://github.com/spumko/hapi/blob/master/docs/Reference.md)

## Previous Documentation
[v5.1.x](https://github.com/spumko/hapi/blob/v5.1.0/docs/Reference.md)
[v5.0.x](https://github.com/spumko/hapi/blob/v5.0.0/docs/Reference.md)
[v4.1.x](https://github.com/spumko/hapi/blob/v4.1.0/docs/Reference.md)
[v4.0.x](https://github.com/spumko/hapi/blob/v4.0.0/docs/Reference.md)
Expand Down
651 changes: 292 additions & 359 deletions docs/Reference.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ internals.handler = function (request, reply) {
internals.main = function () {

var server = new Hapi.Server(8000);
server.pack.require(['hapi-auth-basic', 'hapi-auth-hawk'], function (err) {
server.pack.register([require('hapi-auth-basic'), require('hapi-auth-hawk')], function (err) {

server.auth.strategy('hawk', 'hawk', { getCredentialsFunc: internals.getCredentials });
server.auth.strategy('basic', 'basic', { validateFunc: internals.validate });
Expand Down
120 changes: 71 additions & 49 deletions lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var Boom = require('boom');
var Hoek = require('hoek');
var Semver = require('semver');
var Handler = require('./handler');
var Schema = require('./schema');


// Declare internals
Expand All @@ -16,10 +17,7 @@ exports = module.exports = internals.Auth = function (server) {
this.server = server;
this._schemes = {};
this._strategies = {};
this._defaultStrategy = { // Strategy used as default if route has no auth settings
name: null,
mode: 'required'
};
this._defaultStrategy = null; // Strategy used as default if route has no auth settings
};


Expand All @@ -44,83 +42,106 @@ internals.Auth.prototype.strategy = function (name, scheme /*, mode, options */)
Hoek.assert(!this._strategies[name], 'Authentication strategy name already exists');
Hoek.assert(scheme, 'Authentication strategy', name, 'missing scheme');
Hoek.assert(this._schemes[scheme], 'Authentication strategy', name, 'uses unknown scheme:', scheme);
Hoek.assert(!mode || !this._defaultStrategy.name, 'Cannot set default required strategy more than once:', name, '- already set to:', this._defaultStrategy);

this._strategies[name] = this._schemes[scheme](this.server, options);

if (mode) {
this._defaultStrategy.name = name;
this._defaultStrategy.mode = (typeof mode === 'string' ? mode : 'required');
Hoek.assert(['required', 'optional', 'try'].indexOf(this._defaultStrategy.mode) !== -1, 'Unknown default authentication mode:', this._defaultStrategy.mode);
this.default({ strategies: [name], mode: mode === true ? 'required' : mode });
}
};


internals.Auth.prototype.default = function (options) {

Schema.assert('auth', options, 'default strategy');
Hoek.assert(!this._defaultStrategy, 'Cannot set default strategy more than once');

var settings = Hoek.clone(options); // options can be reused

if (typeof settings === 'string') {
settings = {
strategies: [settings],
mode: 'required'
};
}

if (settings.strategy) {
settings.strategies = [settings.strategy];
delete settings.strategy;
}

Hoek.assert(settings.strategies && settings.strategies.length, 'Default authentication strategy missing strategy name');

this._defaultStrategy = settings;
};


internals.Auth.prototype.test = function (name, request, next) {

Hoek.assert(name, 'Missing authentication strategy name');
var strategy = this._strategies[name];
Hoek.assert(strategy, 'Unknown authentication strategy:', name);

var root = function (err, result) {

return (err ? reply._root(err) : next(err, result.credentials));
};

var reply = Handler.replyInterface(request, next, root);
strategy.authenticate.call(null, request, reply);
};


internals.Auth.prototype._setupRoute = function (options) {
internals.Auth.prototype._setupRoute = function (options, path) {

var self = this;

if (!options) {
return options; // Preseve the difference between undefined and false
}

var names = Object.keys(this._strategies);
var defaultName = (names.length === 1 ? names[0] : null);

if (typeof options === 'string') {
options = { strategies: [options] };
}
else if (options === true) {
Hoek.assert(defaultName, 'Cannot set auth to true when more than one configured');
options = { strategies: [defaultName] };

if (options.strategy) {
options.strategies = [options.strategy];
delete options.strategy;
}

options.mode = options.mode || 'required';
Hoek.assert(['required', 'optional', 'try'].indexOf(options.mode) !== -1, 'Unknown authentication mode:', options.mode);
if (!options.strategies) {
Hoek.assert(this._defaultStrategy, 'Route missing authentication strategy and no default defined:', path);
options = Hoek.applyToDefaults(this._defaultStrategy, options);
}

Hoek.assert(!options.entity || ['user', 'app', 'any'].indexOf(options.entity) !== -1, 'Unknown authentication entity type:', options.entity);
Hoek.assert(!options.payload || ['required', 'optional'].indexOf(options.payload) !== -1, 'Unknown authentication payload mode:', options.entity);
Hoek.assert(!(options.strategy && options.strategies), 'Route can only have a auth.strategy or auth.strategies (or use the default) but not both');
Hoek.assert(!options.strategies || options.strategies.length, 'Cannot have empty auth.strategies array');
Hoek.assert(options.strategies || options.strategy || defaultName, 'Cannot use default strategy when none or more than one configured');
options.strategies = options.strategies || [options.strategy || defaultName];
delete options.strategy;
Hoek.assert(options.strategies.length, 'Route missing authentication strategy:', path);

options.mode = options.mode || 'required';
options.payload = options.payload || false;
var hasAuthenticatePayload = false;
options.strategies.forEach(function (strategy) {

Hoek.assert(self._strategies[strategy], 'Unknown authentication strategy:', strategy);
hasAuthenticatePayload = hasAuthenticatePayload || typeof self._strategies[strategy].payload === 'function';
Hoek.assert(options.payload !== 'required' || hasAuthenticatePayload, 'Payload validation can only be required when all strategies support it');
});
if (options.payload) {
var hasAuthenticatePayload = false;
options.strategies.forEach(function (strategy) {

Hoek.assert(!options.payload || hasAuthenticatePayload, 'Payload authentication requires at least one strategy with payload support');
Hoek.assert(self._strategies[strategy], 'Unknown authentication strategy:', strategy, 'in path:', path);
hasAuthenticatePayload = hasAuthenticatePayload || typeof self._strategies[strategy].payload === 'function';
Hoek.assert(options.payload !== 'required' || hasAuthenticatePayload, 'Payload validation can only be required when all strategies support it in path:', path);
});

Hoek.assert(hasAuthenticatePayload, 'Payload authentication requires at least one strategy with payload support in path:', path);
}

return options;
};


internals.Auth.prototype._routeConfig = function (request) {

if (request.route.auth) {
return request.route.auth;
}

if (request.route.auth === false ||
request.route.auth === null) {

if (request.route.auth === false) {
return false;
}

if (this._defaultStrategy.name) {
return {
mode: this._defaultStrategy.mode,
strategies: [this._defaultStrategy.name]
};
}

return false;
return request.route.auth || this._defaultStrategy;
};


Expand Down Expand Up @@ -185,7 +206,7 @@ internals.Auth.prototype._authenticate = function (request, next) {
});
};

var validate = function (err, strategy, result) {
var validate = function (err, strategy, result) { // err can be Boom, Error, or a valid response object

if (!strategy) {
return next(err);
Expand All @@ -204,7 +225,8 @@ internals.Auth.prototype._authenticate = function (request, next) {
request.log(['hapi', 'auth', 'error', strategy].concat(result.log.tags), result.log.data);
}
else {
request.log(['hapi', 'auth', 'error', 'unauthenticated'], (err.isBoom ? err : err.statusCode));
var tags = err.isBoom ? ['hapi', 'auth', 'error', 'unauthenticated'] : ['hapi', 'auth', 'response', 'unauthenticated'];
request.log(tags, (err.isBoom ? err : err.statusCode));
}

if (err.isMissing) {
Expand All @@ -220,7 +242,7 @@ internals.Auth.prototype._authenticate = function (request, next) {
request.auth.strategy = strategy;
request.auth.credentials = result.credentials;
request.auth.artifacts = result.artifacts;
request.log(['hapi', 'auth', 'error', 'unauthenticated', 'try'], err);
request.log(['hapi', 'auth', 'unauthenticated', 'try'], err);
return next();
}

Expand Down
83 changes: 33 additions & 50 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ internals.loadExtras = function () {
console.error('Unable to require extra file: %s (%s)', extras, err.message);
process.exit(1);
}
};

return;
}

internals.getManifest = function () {

Expand All @@ -72,7 +71,7 @@ internals.getManifest = function () {
}

return manifest;
}
};


internals.loadPacks = function (manifest, callback) {
Expand All @@ -89,71 +88,55 @@ internals.loadPacks = function (manifest, callback) {
return callback(err);
}

options.pack = { requirePath: path };
options = { relativeTo: path };
callback(null, options);
});
}


internals.createComposer = function (manifest, options) {

var attached = !!internals.composer; // When composer exists events are already attached.
internals.composer = new Hapi.Composer(manifest, options);

internals.composer.compose(function (err) {

Hoek.assert(!err, 'Failed loading plugins: ' + (err && err.message));
internals.composer.start(function (err) {

Hoek.assert(!err, 'Failed starting server: ' + (err && err.message));

if (!attached) {
internals.attachEvents();
}
});
});
};


internals.attachEvents = function () {
exports.start = function () {

process.once('SIGQUIT', internals.stop); // Use kill -s QUIT {pid} to kill the servers gracefully
process.on('SIGUSR2', internals.restart); // Use kill -s SIGUSR2 {pid} to restart the servers
};
internals.loadExtras();
Hapi = require('..')
var manifest = internals.getManifest();

internals.loadPacks(manifest, function (err, options) {

if (err) {
console.error(err);
process.exit(1);
}

internals.stop = function () {
Hapi.Pack.compose(manifest, options, function (err, pack) {

internals.composer.stop(function () {
Hoek.assert(!err, 'Failed loading plugins: ' + (err && err.message));

process.exit(0);
});
};
pack.start(function (err) {

Hoek.assert(!err, 'Failed starting server: ' + (err && err.message));

internals.restart = function () {
// Use kill -s QUIT {pid} to kill the servers gracefully

console.log('Stopping...');
internals.composer.stop(function () {
process.once('SIGQUIT', function () {

console.log('Starting...');
internals.start();
});
};
pack.stop(function () {

process.exit(0);
});
});

exports.start = function () {
// Use kill -s SIGUSR2 {pid} to restart the servers

internals.loadExtras();
Hapi = require('..')
var manifest = internals.getManifest();
internals.loadPacks(manifest, function (err, options) {
process.on('SIGUSR2', function () {

if (err) {
console.error(err);
process.exit(1);
}
console.log('Stopping...');
pack.stop(function () {

internals.createComposer(manifest, options);
console.log('Starting...');
internals.start();
});
});
});
});
});
};
Loading