diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 0000000..cae63e3 --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,5 @@ +version: 1 +update_configs: + - package_manager: "javascript" + directory: "/" + update_schedule: "daily" diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..98d9555 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,29 @@ +name: Node CI + +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ${{ matrix.os }} + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x] + os: [ubuntu-latest, macOS-latest, windows-latest] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + - name: Install + run: | + npm install + + - name: Test + run: | + npm test diff --git a/README.md b/README.md index 52bf1b9..155d2a1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # fastify-basic-auth -[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) - [![Build Status](https://dev.azure.com/fastify/fastify/_apis/build/status/fastify.fastify-basic-auth?branchName=master)](https://dev.azure.com/fastify/fastify/_build/latest?definitionId=7&branchName=master) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) ![Node CI](https://github.com/fastify/fastify-basic-auth/workflows/Node%20CI/badge.svg) A simple basic auth plugin for Fastify. @@ -10,7 +9,7 @@ npm i fastify-basic-auth ``` ## Usage -This plugin decorates the fastify instance with a `basicAuth` function, which you can use inside a `preHandler` hook, in a `beforeHandler` or with [`fastify-auth`](https://github.com/fastify/fastify-auth). +This plugin decorates the fastify instance with a `basicAuth` function, which you can use inside any hook before your route handler, or with [`fastify-auth`](https://github.com/fastify/fastify-auth). ```js const fastify = require('fastify')() @@ -26,7 +25,7 @@ function validate (username, password, req, reply, done) { } fastify.after(() => { - fastify.addHook('preHandler', fastify.basicAuth) + fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/', (req, reply) => { reply.send({ hello: 'world' }) @@ -46,7 +45,7 @@ async function validate (username, password, req, reply) { } ``` -Use with `preHandler`: +Use with `onRequest`: ```js const fastify = require('fastify')() const authenticate = {realm: 'Westeros'} @@ -61,7 +60,7 @@ fastify.after(() => { fastify.route({ method: 'GET', url: '/', - preHandler: fastify.basicAuth, + onRequest: fastify.basicAuth, handler: async (req, reply) => { return { hello: 'world' } } @@ -88,8 +87,8 @@ fastify.after(() => { fastify.route({ method: 'GET', url: '/', - // use beforeHanderto authenticatejust this one - preHandler: fastify.auth([fastify.basicAuth]), + // use onRequest to authenticate just this one + onRequest: fastify.auth([fastify.basicAuth]), handler: async (req, reply) => { return { hello: 'world' } } @@ -121,12 +120,12 @@ fastify.setErrorHandler(function (err, req, reply) { ### `validate` (required) -The `validate` function is called on each request made, -and is passed the `username`, `password`, `req` and `reply` +The `validate` function is called on each request made, +and is passed the `username`, `password`, `req` and `reply` parameters in that order. An optional fifth parameter, `done` may be -used to signify a valid request when called with no arguments, -or an invalid request when called with an `Error` object. Alternatively, -the `validate` function may return a promise, resolving for valid +used to signify a valid request when called with no arguments, +or an invalid request when called with an `Error` object. Alternatively, +the `validate` function may return a promise, resolving for valid requests and rejecting for invalid. This can also be achieved using an `async/await` function, and throwing for invalid requests. @@ -134,7 +133,7 @@ See code above for examples. ### `authenticate` (optional, default: false) -When supplied, the `authenticate` option will cause the +When supplied, the `authenticate` option will cause the [`WWW-Authenticate` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate) to be added. It may also be used to set the `realm` value. This can be useful in situations where we want to trigger client-side authentication interfaces - for instance the browser authentication dialog. @@ -142,13 +141,13 @@ This can be useful in situations where we want to trigger client-side authentica As a boolean setting `authenticate` to `true` will set a header like so: `WWW-Authenticate: Basic`. When `false`, no header is added. This is the default. ```js -fastify.register(require('fastify-basic-auth'), { - validate, +fastify.register(require('fastify-basic-auth'), { + validate, authenticate: true // WWW-Authenticate: Basic }) -fastify.register(require('fastify-basic-auth'), { - validate, +fastify.register(require('fastify-basic-auth'), { + validate, authenticate: false // no authenticate header, same as omitting authenticate option }) ``` @@ -158,8 +157,8 @@ When supplied as an object the `authenticate` option may have a `realm` key. If the `realm` key is supplied, it will be appended to the header value: ```js -fastify.register(require('fastify-basic-auth'), { - validate, +fastify.register(require('fastify-basic-auth'), { + validate, authenticate: {realm: 'example'} // WWW-Authenticate: Basic realm="example" }) ``` diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 5d771db..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,25 +0,0 @@ -pool: - vmImage: 'ubuntu-16.04' - -strategy: - matrix: - node_6_x: - node_version: 6.x - node_8_x: - node_version: 8.x - node_10_x: - node_version: 10.x - node_11_x: - node_version: 11.x - -steps: - - task: NodeTool@0 - inputs: - versionSpec: $(node_version) - displayName: Install Node.js - - - bash: npm install - displayName: Install dependencies - - - bash: npm run test - displayName: Test \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index 11470da..2940f37 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,27 +1,32 @@ -import fastify = require('fastify'); - -import { Server, IncomingMessage, ServerResponse } from 'http'; +import { + FastifyRequest, + FastifyPlugin, + FastifyReply, + onRequestHookHandler, + preParsingHookHandler, + preValidationHookHandler, + preHandlerHookHandler +} from 'fastify' declare module 'fastify' { - interface FastifyInstance { - basicAuth: FastifyMiddleware; + interface FastifyInstance { + basicAuth: onRequestHookHandler | + preParsingHookHandler | + preValidationHookHandler | + preHandlerHookHandler } } -declare const fastifyBasicAuth: fastify.Plugin< - Server, - IncomingMessage, - ServerResponse, - { - validate: ( - username: string, - password: string, - req: fastify.FastifyRequest, - reply: fastify.FastifyReply, - done: (err?: Error) => void - ) => void; - authenticate?: boolean | { realm: string }; - } ->; +export interface FastifyBasicAuthOptions { + validate( + username: string, + password: string, + req: FastifyRequest, + reply: FastifyReply, + done: (err?: Error) => void + ): void | Promise; + authenticate?: boolean | { realm: string }; +} -export = fastifyBasicAuth; +declare const fastifyBasicAuth: FastifyPlugin +export default fastifyBasicAuth; diff --git a/index.js b/index.js index 710a899..73d07ae 100644 --- a/index.js +++ b/index.js @@ -64,6 +64,6 @@ function getAuthenticateHeader (authenticate) { } module.exports = fp(basicPlugin, { - fastify: '>=1.0.0', + fastify: '3.x', name: 'fastify-basic-auth' }) diff --git a/index.test-d.ts b/index.test-d.ts new file mode 100644 index 0000000..2493fd1 --- /dev/null +++ b/index.test-d.ts @@ -0,0 +1,36 @@ +import { expectType, expectAssignable } from 'tsd' +import fastify, { + FastifyRequest, + FastifyReply, + onRequestHookHandler, + preParsingHookHandler, + preValidationHookHandler, + preHandlerHookHandler +} from 'fastify' +import fastifyBasicAuth from '.' + +const app = fastify() + +app.register(fastifyBasicAuth, { + validate: async function validatePromise (username, password, req, reply) { + expectType(username) + expectType(password) + expectType(req) + expectType(reply) + } +}) + +app.register(fastifyBasicAuth, { + validate: function validateCallback (username, password, req, reply, done) { + expectType(username) + expectType(password) + expectType(req) + expectType(reply) + expectAssignable<(err?: Error) => void>(done) + } +}) + +expectAssignable(app.basicAuth) +expectAssignable(app.basicAuth) +expectAssignable(app.basicAuth) +expectAssignable(app.basicAuth) \ No newline at end of file diff --git a/package.json b/package.json index 2e2ef7d..786523e 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "main": "index.js", "types": "index.d.ts", "scripts": { - "typescript": "tsc --project ./test/types/tsconfig.json", - "test": "standard && tap test/*.test.js && npm run typescript" + "test": "standard && tap test.js && tsd" }, "repository": { "type": "git", @@ -26,15 +25,18 @@ }, "homepage": "https://github.com/fastify/fastify-basic-auth#readme", "devDependencies": { - "@types/node": "^12.7.12", - "fastify": "^2.0.0", - "fastify-auth": "^0.3.0", - "standard": "^11.0.1", - "tap": "^12.0.1" + "fastify": "^3.0.0-rc.1", + "fastify-auth": "^1.0.0", + "standard": "^14.3.3", + "tap": "^14.10.7", + "tsd": "^0.11.0" }, "dependencies": { - "basic-auth": "^2.0.0", - "fastify-plugin": "^1.0.1", - "http-errors": "^1.7.2" + "basic-auth": "^2.0.1", + "fastify-plugin": "^2.0.0", + "http-errors": "^1.7.3" + }, + "engines": { + "node": ">=10.0.0" } } diff --git a/test/test.js b/test.js similarity index 96% rename from test/test.js rename to test.js index bd5ca5c..17a2821 100644 --- a/test/test.js +++ b/test.js @@ -24,7 +24,7 @@ test('Basic', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -61,7 +61,7 @@ test('Basic - 401', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -103,7 +103,7 @@ test('Basic with promises', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -140,7 +140,7 @@ test('Basic with promises - 401', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -183,7 +183,7 @@ test('WWW-Authenticate (authenticate: true)', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -207,7 +207,7 @@ test('WWW-Authenticate Realm (authenticate: {realm: "example"})', t => { t.plan(3) const fastify = Fastify() - const authenticate = {realm: 'example'} + const authenticate = { realm: 'example' } fastify.register(basicAuth, { validate, authenticate }) function validate (username, password, req, res, done) { @@ -222,7 +222,7 @@ test('WWW-Authenticate Realm (authenticate: {realm: "example"})', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -316,7 +316,7 @@ test('With fastify-auth - 401', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.auth([fastify.basicAuth]), + preHandler: fastify.auth([fastify.basicAuth]), handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -402,7 +402,7 @@ test('Missing header', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -443,7 +443,7 @@ test('Fastify context', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } @@ -525,7 +525,7 @@ test('Missing header and custom error handler', t => { fastify.route({ method: 'GET', url: '/', - beforeHandler: fastify.basicAuth, + preHandler: fastify.basicAuth, handler: (req, reply) => { reply.send({ hello: 'world' }) } diff --git a/test/types/index.ts b/test/types/index.ts deleted file mode 100644 index 77f5435..0000000 --- a/test/types/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as Fastify from 'fastify'; -import * as fastifyBasicAuth from '../..'; - -const app = Fastify(); - -const authenticate = { realm: 'Westeros' }; -app.register(fastifyBasicAuth, { - validate: function validate(username, password, req, reply, done) { - if (username === 'Tyrion' && password === 'wine') { - done(); - } else { - done(new Error('Winter is coming')); - } - }, - authenticate -}); - -app.after(() => { - app.addHook('preHandler', app.basicAuth); - - app.get('/', (req, reply) => { - reply.send({ hello: 'world' }); - }); - - app.route({ - method: 'GET', - url: '/', - preHandler: app.basicAuth, - handler: async (req, reply) => { - return { hello: 'world' }; - } - }); -}); diff --git a/test/types/tsconfig.json b/test/types/tsconfig.json deleted file mode 100644 index b170f36..0000000 --- a/test/types/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "noEmit": true, - "strict": true - }, - "files": ["./index.ts"] -}