Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/v21'
Browse files Browse the repository at this point in the history
  • Loading branch information
devinivy committed Nov 7, 2022
2 parents 8540cd3 + 923491b commit 06beb0f
Show file tree
Hide file tree
Showing 31 changed files with 576 additions and 600 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci-module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ name: ci
on:
push:
branches:
- v21
- master
pull_request:
workflow_dispatch:

jobs:
test:
uses: hapijs/.github/.github/workflows/ci-module.yml@master
with:
min-node-version: 14
74 changes: 31 additions & 43 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ All options are optionals.

#### <a name="server.options.address" /> `server.options.address`

Default value: `'0.0.0.0'` (all available network interfaces).
Default value: `'::'` if IPv6 is available, otherwise `'0.0.0.0'` (i.e. all available network interfaces).

Sets the hostname or IP address the server will listen on. If not configured, defaults to
[`host`](#server.options.host) if present, otherwise to all available network interfaces. Set to
`'127.0.0.1'` or `'localhost'` to restrict the server to only those coming from the same host.
`'127.0.0.1'`, `'::1'`, or `'localhost'` to restrict the server to only those coming from the same host.

#### <a name="server.options.app" /> `server.options.app`

Expand Down Expand Up @@ -1539,11 +1539,11 @@ async function example() {
const server = Hapi.server({ port: 80 });
server.event('test');
server.events.on('test', (update) => console.log(update));
await server.events.emit('test', 'hello');
await server.events.gauge('test', 'hello');
}
```

### <a name="server.events.emit()" /> `await server.events.emit(criteria, data)`
### <a name="server.events.emit()" /> `server.events.emit(criteria, data)`

Emits a custom application event to all the subscribed listeners where:

Expand All @@ -1569,7 +1569,7 @@ async function example() {
const server = Hapi.server({ port: 80 });
server.event('test');
server.events.on('test', (update) => console.log(update));
await server.events.emit('test', 'hello'); // await is optional
server.events.emit('test', 'hello');
}
```

Expand Down Expand Up @@ -1634,7 +1634,7 @@ async function example() {
const server = Hapi.server({ port: 80 });
server.event('test');
server.events.on('test', (update) => console.log(update));
await server.events.emit('test', 'hello');
server.events.emit('test', 'hello');
}
```

Expand All @@ -1652,8 +1652,8 @@ async function example() {
const server = Hapi.server({ port: 80 });
server.event('test');
server.events.once('test', (update) => console.log(update));
await server.events.emit('test', 'hello');
await server.events.emit('test', 'hello'); // Ignored
server.events.emit('test', 'hello');
server.events.emit('test', 'hello'); // Ignored
}
```

Expand All @@ -1671,11 +1671,17 @@ async function example() {
const server = Hapi.server({ port: 80 });
server.event('test');
const pending = server.events.once('test');
await server.events.emit('test', 'hello');
server.events.emit('test', 'hello');
const update = await pending;
}
```

### <a name="server.events.gauge()" /> `await server.events.gauge(criteria, data)`

Behaves identically to [`server.events.emit()`](#server.events.emit()), but also returns an array of the results of all the event listeners that run. The return value is that of `Promise.allSettled()`, where each item in the resulting array is `{ status: 'fulfilled', value }` in the case of a successful handler, or `{ status: 'rejected', reason }` in the case of a handler that throws.

Please note that system errors such as a `TypeError` are not handled specially, and it's recommended to scrutinize any rejections using something like [bounce](https://hapi.dev/module/bounce/).

### <a name="server.expose()" /> `server.expose(key, value, [options])`

Used within a plugin to expose a property via [`server.plugins[name]`](#server.plugins) where:
Expand Down Expand Up @@ -2895,6 +2901,9 @@ object with the following options:
- `credentials` - if `true`, allows user credentials to be sent
('Access-Control-Allow-Credentials'). Defaults to `false`.

- `preflightStatusCode` - the status code used for CORS preflight responses, either `200` or `204`.
Defaults to `200`.

### <a name="route.options.description" /> `route.options.description`

Default value: none.
Expand Down Expand Up @@ -2974,21 +2983,6 @@ string payload or escaping it after stringification. Supports the following:
- `escape` - calls [`Hoek.jsonEscape()`](https://hapi.dev/family/hoek/api/#escapejsonstring)
after conversion to JSON string. Defaults to `false`.

### <a name="route.options.jsonp" /> `route.options.jsonp`

Default value: none.

Enables JSONP support by setting the value to the query parameter name containing the function name
used to wrap the response payload.

For example, if the value is `'callback'`, a request comes in with `'callback=me'`, and the JSON
response is `'{ "a":"b" }'`, the payload will be `'me({ "a":"b" });'`. Cannot be used with stream
responses.

The 'Content-Type' response header is set to `'text/javascript'` and the 'X-Content-Type-Options'
response header is set to `'nosniff'`, and will override those headers even if explicitly set by
[`response.type()`](#response.type()).

### <a name="route.options.log" /> `route.options.log`

Default value: `{ collect: false }`.
Expand Down Expand Up @@ -3361,13 +3355,17 @@ following options:
otherwise this field is ignored. If `rule` is `'allow-from'` but `source` is unset, the
rule will be automatically changed to `'sameorigin'`.

- `xss` - boolean that controls the 'X-XSS-PROTECTION' header for Internet Explorer. Defaults to
`true` which sets the header to equal `'1; mode=block'`.
- Note: this setting can create a security vulnerability in versions of Internet Exploere below
8, as well as unpatched versions of IE8. See [here](https://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/)
and [here](https://technet.microsoft.com/library/security/ms10-002) for more information. If
you actively support old versions of IE, it may be wise to explicitly set this flag to
`false`.
- `xss` - controls the 'X-XSS-Protection' header, where:

- `'disable'` - the header will be set to `'0'`. This is the default value.
- `'enable'` - the header will be set to `'1; mode=block'`.
- `false` - the header will be omitted.

Note: when enabled, this setting can create a security vulnerabilities in versions of Internet Explorer
below 8, unpatched versions of IE8, and browsers that employ an XSS filter/auditor. See
[here](https://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities/),
[here](https://technet.microsoft.com/library/security/ms10-002), and
[here](https://blog.innerht.ml/the-misunderstood-x-xss-protection/) for more information.

- `noOpen` - boolean controlling the 'X-Download-Options' header for Internet Explorer, preventing
downloads from executing in your context. Defaults to `true` setting the header to `'noopen'`.
Expand Down Expand Up @@ -3448,7 +3446,8 @@ Default value: `'error'` (return a Bad Request (400) error response).

A [`failAction` value](#lifecycle-failAction) which determines how to handle failed validations.
When set to a function, the `err` argument includes the type of validation error under
`err.output.payload.validation.source`.
`err.output.payload.validation.source`. The default error that would otherwise have been logged
or returned can be accessed under `err.data.defaultError`.

#### <a name="route.options.validate.headers" /> `route.options.validate.headers`

Expand Down Expand Up @@ -3616,19 +3615,12 @@ the same. The following is the complete list of steps a request can go through:
- [`request.route`](#request.route) is unassigned.
- [`request.url`](#request.url) can be `null` if the incoming request path is invalid.
- [`request.path`](#request.path) can be an invalid path.
- JSONP configuration is ignored for any response returned from the extension point since no
route is matched yet and the JSONP configuration is unavailable.

- _**Route lookup**_
- lookup based on `request.path` and `request.method`.
- skips to _**onPreResponse**_ if no route is found or if the path violates the HTTP
specification.

- _**JSONP processing**_
- based on the route [`jsonp`](#route.options.jsonp) option.
- parses JSONP parameter from [`request.query`](#request.query).
- skips to _**Response validation**_ on error.

- _**Cookies processing**_
- based on the route [`state`](#route.options.state) option.
- error handling based on [`failAction`](#route.options.state.failAction).
Expand Down Expand Up @@ -3663,10 +3655,6 @@ the same. The following is the complete list of steps a request can go through:
- based on the route [`validate.params`](#route.options.validate.params) option.
- error handling based on [`failAction`](#route.options.validate.failAction).

- _**JSONP cleanup**_
- based on the route [`jsonp`](#route.options.jsonp) option.
- remove the JSONP parameter from [`request.query`](#request.query).

- _**Query validation**_
- based on the route [`validate.query`](#route.options.validate.query) option.
- error handling based on [`failAction`](#route.options.validate.failAction).
Expand Down
14 changes: 8 additions & 6 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Copyright (c) 2011-2020, Sideway Inc, and project contributors
Copyright (c) 2011-2014, Walmart
Copyright (c) 2011, Yahoo Inc.
Copyright (c) 2011-2022, Project contributors
Copyright (c) 2011-2020, Sideway Inc
Copyright (c) 2011-2014, Walmart
Copyright (c) 2011, Yahoo Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 changes: 10 additions & 12 deletions lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ exports = module.exports = internals.Auth = class {
Hoek.assert(typeof strategy.authenticate === 'function', 'Invalid scheme:', name, 'invalid authenticate() method');
Hoek.assert(!strategy.payload || typeof strategy.payload === 'function', 'Invalid scheme:', name, 'invalid payload() method');
Hoek.assert(!strategy.response || typeof strategy.response === 'function', 'Invalid scheme:', name, 'invalid response() method');
strategy.options = strategy.options || {};
strategy.options = strategy.options ?? {};
Hoek.assert(strategy.payload || !strategy.options.payload, 'Cannot require payload validation without a payload method');

this.#strategies[name] = {
Expand Down Expand Up @@ -171,10 +171,10 @@ exports = module.exports = internals.Auth = class {
options = Hoek.applyToDefaults(this.settings.default, options);
}

path = path || 'default strategy';
Hoek.assert(options.strategies && options.strategies.length, 'Missing authentication strategy:', path);
path = path ?? 'default strategy';
Hoek.assert(options.strategies?.length, 'Missing authentication strategy:', path);

options.mode = options.mode || 'required';
options.mode = options.mode ?? 'required';

if (options.entity !== undefined || // Backwards compatibility with <= 11.x.x
options.scope !== undefined) {
Expand Down Expand Up @@ -304,9 +304,7 @@ exports = module.exports = internals.Auth = class {
_access(request, route) {

const config = this.lookup(route || request.route);
if (!config ||
!config.access) {

if (!config?.access) {
return true;
}

Expand Down Expand Up @@ -389,7 +387,7 @@ exports = module.exports = internals.Auth = class {
}

const config = auth.lookup(request.route);
const setting = config.payload || (strategy.methods.options.payload ? 'required' : false);
const setting = config.payload ?? (strategy.methods.options.payload ? 'required' : false);
if (!setting) {
return;
}
Expand Down Expand Up @@ -451,13 +449,13 @@ internals.setupScope = function (access) {
const prefix = value[0];
const type = prefix === '+' ? 'required' : (prefix === '!' ? 'forbidden' : 'selection');
const clean = type === 'selection' ? value : value.slice(1);
scope[type] = scope[type] || [];
scope[type] = scope[type] ?? [];
scope[type].push(clean);

if ((!scope._hasParameters || !scope._hasParameters[type]) &&
if ((!scope._hasParameters?.[type]) &&
/{([^}]+)}/.test(clean)) {

scope._hasParameters = scope._hasParameters || {};
scope._hasParameters = scope._hasParameters ?? {};
scope._hasParameters[type] = true;
}
}
Expand All @@ -468,7 +466,7 @@ internals.setupScope = function (access) {

internals.validate = function (err, result, name, config, request, errors) { // err can be Boom, Error, or a valid response object

result = result || {};
result = result ?? {};
request.auth.isAuthenticated = !err;

if (err) {
Expand Down
8 changes: 5 additions & 3 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const Os = require('os');

const Somever = require('@hapi/somever');
const Validate = require('@hapi/validate');


Expand Down Expand Up @@ -38,6 +39,7 @@ exports.enable = function (options) {
return settings;
};

exports.versionMatch = (version, range) => Somever.match(version, range, { includePrerelease: true });

internals.access = Validate.object({
entity: Validate.valid('user', 'app', 'any'),
Expand Down Expand Up @@ -109,7 +111,8 @@ internals.routeBase = Validate.object({
additionalHeaders: Validate.array().items(Validate.string()).default([]),
exposedHeaders: Validate.array().items(Validate.string()).default(['WWW-Authenticate', 'Server-Authorization']),
additionalExposedHeaders: Validate.array().items(Validate.string()).default([]),
credentials: Validate.boolean().when('origin', { is: 'ignore', then: false }).default(false)
credentials: Validate.boolean().when('origin', { is: 'ignore', then: false }).default(false),
preflightStatusCode: Validate.valid(200, 204).default(200)
})
.allow(false, true)
.default(false),
Expand All @@ -134,7 +137,6 @@ internals.routeBase = Validate.object({
escape: Validate.boolean().default(false)
})
.default(),
jsonp: Validate.string(),
log: Validate.object({
collect: Validate.boolean().default(false)
})
Expand Down Expand Up @@ -194,7 +196,7 @@ internals.routeBase = Validate.object({
})
])
.default('deny'),
xss: Validate.boolean().default(true),
xss: Validate.valid('enabled', 'disabled', false).default('disabled'),
noOpen: Validate.boolean().default(true),
noSniff: Validate.boolean().default(true),
referrer: Validate.alternatives([
Expand Down
Loading

0 comments on commit 06beb0f

Please # to comment.