From 7747200d09127a8c14f80f6a0d492c1b5e5634cf Mon Sep 17 00:00:00 2001 From: Jonah Werre Date: Tue, 13 Jul 2021 15:51:05 -0600 Subject: [PATCH 1/2] modernizing --- index.js | 334 ++-- package-lock.json | 1374 +++++++++++++++++ .../{index_test.js => index.test.js} | 10 +- test/unit/{index_test.js => index.test.js} | 26 +- 4 files changed, 1565 insertions(+), 179 deletions(-) create mode 100644 package-lock.json rename test/integration/{index_test.js => index.test.js} (97%) rename test/unit/{index_test.js => index.test.js} (91%) diff --git a/index.js b/index.js index 1ab2b9a..451d890 100644 --- a/index.js +++ b/index.js @@ -1,173 +1,173 @@ 'use strict'; -/** - * Module dependencies. - */ +const NodeOAuthServer = require('oauth2-server'); +const { + Request, + Response, + InvalidArgumentError, + UnauthorizedRequestError, +} = require('oauth2-server'); + + +class ExpressOAuthServer { + + constructor(options = {}) { + + if (!options.model) { + throw new InvalidArgumentError('Missing parameter: `model`'); + } + + this.useErrorHandler = options.useErrorHandler ? true : false; + delete options.useErrorHandler; + + this.continueMiddleware = options.continueMiddleware ? true : false; + delete options.continueMiddleware; + + this.server = new NodeOAuthServer(options); + } + + /** + * Authentication Middleware. + * + * Returns a middleware that will validate a token. + * + * (See: https://tools.ietf.org/html/rfc6749#section-7) + */ + authenticate(options) { + + console.log('ExpressOAuthServer::authenticate', options); + + return (req, res, next) => { + + const request = new Request(req); + const response = new Response(res); + + return this.server.authenticate(request, response, options) + .then( (token) => { + res.locals.oauth = { + token: token + }; + return next(); + }) .catch( (err) => { + return this.errorHandler(err, req, res, null, next); + }); + }; + + } + + /** + * Authorization Middleware. + * + * Returns a middleware that will authorize a client to request tokens. + * + * (See: https://tools.ietf.org/html/rfc6749#section-3.1) + */ + + authorize(options) { + + + return (req, res, next) => { + + const request = new Request(req); + const response = new Response(res); + + return this.server.authorize(request, response, options) + .then( (code) => { + res.locals.oauth = { + code: code + }; + + if (this.continueMiddleware) { + next(); + } + }) + .then( () => { + return this.responseHandler(req, res, response); + }) + .catch( (e) => { + return this.errorHandler(e, req, res, response, next); + }); + }; + } + + /** + * Grant Middleware. + * + * Returns middleware that will grant tokens to valid requests. + * + * (See: https://tools.ietf.org/html/rfc6749#section-3.2) + */ + token(options) { + + return (req, res, next) => { + + const request = new Request(req); + const response = new Response(res); + + return this.server.token(request, response, options) + .then( (token) => { + res.locals.oauth = { + token: token + }; + if (this.continueMiddleware) + { + next(); + } + }) + .then( () => { + return this.responseHandler(req, res, response); + }) + .catch( (e) => { + return this.errorHandler(e, req, res, response, next); + }); + }; + } + + /** + * Response handler. + */ + responseHandler (req, res, response) { + + if (response.status === 302) { + let location = response.headers.location; + delete response.headers.location; + res.set(response.headers); + return res.redirect(location); + } + + res.set(response.headers); + res.status(response.status) + .send(response.body); + + } + + /** + * Error handler. + */ + errorHandler (error, req, res, response, next) { + + if (this.useErrorHandler === true) { + return next(error); + } + + if (response) { + res.set(response.headers); + } + + res.status(error.code); + + if (error instanceof UnauthorizedRequestError) { + return res.send(); + } + + res.send({ + error: error.name, + error_description: error.message + }); + + } -var InvalidArgumentError = require('oauth2-server/lib/errors/invalid-argument-error'); -var NodeOAuthServer = require('oauth2-server'); -var Promise = require('bluebird'); -var Request = require('oauth2-server').Request; -var Response = require('oauth2-server').Response; -var UnauthorizedRequestError = require('oauth2-server/lib/errors/unauthorized-request-error'); -/** - * Constructor. - */ - -function ExpressOAuthServer(options) { - options = options || {}; - - if (!options.model) { - throw new InvalidArgumentError('Missing parameter: `model`'); - } - - this.useErrorHandler = options.useErrorHandler ? true : false; - delete options.useErrorHandler; - - this.continueMiddleware = options.continueMiddleware ? true : false; - delete options.continueMiddleware; - - this.server = new NodeOAuthServer(options); } -/** - * Authentication Middleware. - * - * Returns a middleware that will validate a token. - * - * (See: https://tools.ietf.org/html/rfc6749#section-7) - */ - -ExpressOAuthServer.prototype.authenticate = function(options) { - var that = this; - - return function(req, res, next) { - var request = new Request(req); - var response = new Response(res); - return Promise.bind(that) - .then(function() { - return this.server.authenticate(request, response, options); - }) - .tap(function(token) { - res.locals.oauth = { token: token }; - next(); - }) - .catch(function(e) { - return handleError.call(this, e, req, res, null, next); - }); - }; -}; - -/** - * Authorization Middleware. - * - * Returns a middleware that will authorize a client to request tokens. - * - * (See: https://tools.ietf.org/html/rfc6749#section-3.1) - */ - -ExpressOAuthServer.prototype.authorize = function(options) { - var that = this; - - return function(req, res, next) { - var request = new Request(req); - var response = new Response(res); - - return Promise.bind(that) - .then(function() { - return this.server.authorize(request, response, options); - }) - .tap(function(code) { - res.locals.oauth = { code: code }; - if (this.continueMiddleware) { - next(); - } - }) - .then(function() { - return handleResponse.call(this, req, res, response); - }) - .catch(function(e) { - return handleError.call(this, e, req, res, response, next); - }); - }; -}; - -/** - * Grant Middleware. - * - * Returns middleware that will grant tokens to valid requests. - * - * (See: https://tools.ietf.org/html/rfc6749#section-3.2) - */ - -ExpressOAuthServer.prototype.token = function(options) { - var that = this; - - return function(req, res, next) { - var request = new Request(req); - var response = new Response(res); - - return Promise.bind(that) - .then(function() { - return this.server.token(request, response, options); - }) - .tap(function(token) { - res.locals.oauth = { token: token }; - if (this.continueMiddleware) { - next(); - } - }) - .then(function() { - return handleResponse.call(this, req, res, response); - }) - .catch(function(e) { - return handleError.call(this, e, req, res, response, next); - }); - }; -}; - -/** - * Handle response. - */ -var handleResponse = function(req, res, response) { - - if (response.status === 302) { - var location = response.headers.location; - delete response.headers.location; - res.set(response.headers); - res.redirect(location); - } else { - res.set(response.headers); - res.status(response.status).send(response.body); - } -}; - -/** - * Handle error. - */ - -var handleError = function(e, req, res, response, next) { - - if (this.useErrorHandler === true) { - next(e); - } else { - if (response) { - res.set(response.headers); - } - - res.status(e.code); - - if (e instanceof UnauthorizedRequestError) { - return res.send(); - } - - res.send({ error: e.name, error_description: e.message }); - } -}; - -/** - * Export constructor. - */ - -module.exports = ExpressOAuthServer; +module.exports = ExpressOAuthServer; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..daa1a7c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1374 @@ +{ + "name": "express-oauth-server", + "version": "2.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", + "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, + "co-bluebird": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/co-bluebird/-/co-bluebird-1.1.0.tgz", + "integrity": "sha1-yLnzqTIKftMJh9zKGlw8/1llXHw=", + "requires": { + "bluebird": "^2.10.0", + "co-use": "^1.1.0" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + } + } + }, + "co-use": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/co-use/-/co-use-1.1.0.tgz", + "integrity": "sha1-xrs83xDLc17Kqdru2kbXJclKTmI=" + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "component-emitter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "cookiejar": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.1.tgz", + "integrity": "sha1-PRJ1L2rfaKiS8zJDNJK9WBK7Zo8=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", + "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=", + "dev": true + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "form-data": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.3.tgz", + "integrity": "sha1-TuQ0bm61Ni6DRKAgdb2NvYxzc+o=", + "dev": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + }, + "dependencies": { + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + } + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "~1.1" + } + }, + "formidable": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", + "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=" + }, + "is-generator-function": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "jshint": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.0.tgz", + "integrity": "sha512-Nd+md9wIeyfDK+RGrbOBzwLONSTdihGMtyGYU/t7zYcN2EgUa4iuY3VK2oxtPYrW5ycTj18iC+UbhNTxe4C66g==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" + }, + "mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "requires": { + "mime-db": "1.48.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "oauth2-server": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oauth2-server/-/oauth2-server-3.1.1.tgz", + "integrity": "sha512-4dv+fE9hrK+xTaCygOLh/kQeFzbFr7UqSyHvBDbrQq8Hg52sAkV2vTsyH3Z42hoeaKpbhM7udhL8Y4GYbl6TGQ==", + "requires": { + "basic-auth": "2.0.1", + "bluebird": "3.7.2", + "lodash": "4.17.19", + "promisify-any": "2.0.1", + "statuses": "1.5.0", + "type-is": "1.6.18" + } + }, + "object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "promisify-any": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promisify-any/-/promisify-any-2.0.1.tgz", + "integrity": "sha1-QD4AqIE/F1JCq1D+M6afjuzkcwU=", + "requires": { + "bluebird": "^2.10.0", + "co-bluebird": "^1.1.0", + "is-generator": "^1.0.2" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + } + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "reduce-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz", + "integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "should": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/should/-/should-7.1.1.tgz", + "integrity": "sha1-ZGTEi298Hh8YrASDV4+i3VXCxuA=", + "dev": true, + "requires": { + "should-equal": "0.5.0", + "should-format": "0.3.1", + "should-type": "0.2.0" + } + }, + "should-equal": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.5.0.tgz", + "integrity": "sha1-x5fxNfMGf+tp6+zbMGscP+IbPm8=", + "dev": true, + "requires": { + "should-type": "0.2.0" + } + }, + "should-format": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.1.tgz", + "integrity": "sha1-LLt4JGFnCs5CkrKx7EaNuM+Z4zA=", + "dev": true, + "requires": { + "should-type": "0.2.0" + } + }, + "should-type": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz", + "integrity": "sha1-ZwfvlVKdmJ3MCY/gdTqx+RNrt/Y=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "superagent": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-0.21.0.tgz", + "integrity": "sha1-+xUCeYR1HucVIgDmzSHNbhml3oc=", + "dev": true, + "requires": { + "component-emitter": "1.1.2", + "cookiejar": "2.0.1", + "debug": "2", + "extend": "~1.2.1", + "form-data": "0.1.3", + "formidable": "1.0.14", + "methods": "1.0.1", + "mime": "1.2.11", + "qs": "1.2.0", + "readable-stream": "1.0.27-1", + "reduce-component": "1.0.1" + }, + "dependencies": { + "methods": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz", + "integrity": "sha1-dbyRlD3/19oDfPPusO1zoAN80Us=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "qs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.0.tgz", + "integrity": "sha1-7Qeb4oaCFH5v2aNMwrDB4OxkU+4=", + "dev": true + }, + "readable-stream": { + "version": "1.0.27-1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz", + "integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "supertest": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-0.15.0.tgz", + "integrity": "sha1-hhGGld5L5Yhps+6UxF4dCEyn+sU=", + "dev": true, + "requires": { + "methods": "1.x", + "superagent": "~0.21.0" + } + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/test/integration/index_test.js b/test/integration/index.test.js similarity index 97% rename from test/integration/index_test.js rename to test/integration/index.test.js index 91f91b7..56bb749 100644 --- a/test/integration/index_test.js +++ b/test/integration/index.test.js @@ -47,15 +47,19 @@ describe('ExpressOAuthServer', function() { }); describe('authenticate()', function() { - it('should return an error if `model` is empty', function(done) { + + it.only('should return an error if `model` is empty', function(done) { var oauth = new ExpressOAuthServer({ model: {} }); app.use(oauth.authenticate()); request(app.listen()) .get('/') - .expect({ error: 'invalid_argument', error_description: 'Invalid argument: model does not implement `getAccessToken()`' }) - .end(done); + .end(function(err, res) { + console.log(res); + + done(); + }); }); it('should authenticate the request', function(done) { diff --git a/test/unit/index_test.js b/test/unit/index.test.js similarity index 91% rename from test/unit/index_test.js rename to test/unit/index.test.js index d06e11d..3c3568a 100644 --- a/test/unit/index_test.js +++ b/test/unit/index.test.js @@ -24,10 +24,12 @@ describe('ExpressOAuthServer', function() { }); describe('authenticate()', function() { + it('should call `authenticate()`', function(done) { var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'authenticate').returns({}); + sinon.stub(oauth.server, 'authenticate') + .returns( Promise.resolve({}) ); app.use(oauth.authenticate()); @@ -40,7 +42,6 @@ describe('ExpressOAuthServer', function() { oauth.server.authenticate.firstCall.args[1].should.be.an.instanceOf(Response); should.not.exist(oauth.server.authenticate.firstCall.args[2]) oauth.server.authenticate.restore(); - done(); }); }); @@ -48,7 +49,8 @@ describe('ExpressOAuthServer', function() { it('should call `authenticate()` with options', function(done) { var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'authenticate').returns({}); + sinon.stub(oauth.server, 'authenticate') + .returns( Promise.resolve({}) ); app.use(oauth.authenticate({options: true})); @@ -71,7 +73,8 @@ describe('ExpressOAuthServer', function() { var nextMiddleware = sinon.spy() var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'authorize').returns({}); + sinon.stub(oauth.server, 'authorize') + .returns( Promise.resolve({}) ); app.use(oauth.authorize()); app.use(nextMiddleware); @@ -94,7 +97,8 @@ describe('ExpressOAuthServer', function() { var nextMiddleware = sinon.spy() var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); - sinon.stub(oauth.server, 'authorize').returns({}); + sinon.stub(oauth.server, 'authorize') + .returns( Promise.resolve({}) ); app.use(oauth.authorize()); app.use(nextMiddleware); @@ -117,7 +121,8 @@ describe('ExpressOAuthServer', function() { it('should call `authorize()` with options', function(done) { var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'authorize').returns({}); + sinon.stub(oauth.server, 'authorize') + .returns(Promise.resolve({})); app.use(oauth.authorize({options: true})); @@ -140,7 +145,8 @@ describe('ExpressOAuthServer', function() { var nextMiddleware = sinon.spy() var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'token').returns({}); + sinon.stub(oauth.server, 'token') + .returns(Promise.resolve({})); app.use(oauth.token()); app.use(nextMiddleware); @@ -163,7 +169,8 @@ describe('ExpressOAuthServer', function() { var nextMiddleware = sinon.spy() var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); - sinon.stub(oauth.server, 'token').returns({}); + sinon.stub(oauth.server, 'token') + .returns(Promise.resolve({})); app.use(oauth.token()); app.use(nextMiddleware); @@ -186,7 +193,8 @@ describe('ExpressOAuthServer', function() { it('should call `token()` with options', function(done) { var oauth = new ExpressOAuthServer({ model: {} }); - sinon.stub(oauth.server, 'token').returns({}); + sinon.stub(oauth.server, 'token') + .returns(Promise.resolve({})); app.use(oauth.token({options: true})); From 711002b355e1a7e7e016ff1ed616ecdb184a2fe0 Mon Sep 17 00:00:00 2001 From: Jonah Werre Date: Wed, 14 Jul 2021 10:51:57 -0600 Subject: [PATCH 2/2] Modernize Convert to ES6 style class Removed bluebird in favor of native Node.js Promise document functions Fixed test so they exit properly --- Readme.md | 10 +-- index.js | 138 ++++++++++++++++++++++----------- package-lock.json | 64 +++++++++------ package.json | 3 +- test/integration/index.test.js | 134 +++++++++++++++++++------------- test/unit/index.test.js | 74 +++++++++++------- 6 files changed, 260 insertions(+), 163 deletions(-) diff --git a/Readme.md b/Readme.md index e3ab76e..8ff7299 100644 --- a/Readme.md +++ b/Readme.md @@ -14,11 +14,11 @@ The module provides two middlewares - one for granting tokens and another to aut The following example uses `body-parser` but you may opt for an alternative library. ```js -var bodyParser = require('body-parser'); -var express = require('express'); -var OAuthServer = require('express-oauth-server'); +const bodyParser = require('body-parser'); +const express = require('express'); +const OAuthServer = require('express-oauth-server'); -var app = express(); +const app = express(); app.oauth = new OAuthServer({ model: {}, // See https://github.com/oauthjs/node-oauth2-server for specification @@ -38,7 +38,7 @@ app.listen(3000); ## Options ``` -var options = { +let options = { useErrorHandler: false, continueMiddleware: false, } diff --git a/index.js b/index.js index 451d890..ef2090d 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,24 @@ const { UnauthorizedRequestError, } = require('oauth2-server'); - +/** + * @class ExpressOAuthServer + * Complete, compliant and well tested module for implementing an OAuth2 + * Server/Provider with Express in Node.js. + * + * @see https://oauth2-server.readthedocs.io/en/latest/api/oauth2-server.html#new-oauth2server-options + * @param {Object} options Middleware options + * @param {Boolean} options.useErrorHandler If false, an error response will be + * rendered by this component. Set this value to true to allow your own express + * error handler to handle the error. + * @param {Boolean} options.continueMiddleware The `authorize()` and token() + * middlewares will both render their result to the response and end the pipeline. + * `next()` will only be called if this is set to true. Note: You cannot modify the + * response since the headers have already been sent. `authenticate()` does not + * modify the response and will always call `next()`. + * @param {Object} options.model a model object through which some aspects of + * storage, retrieval and custom validation are abstracted. + */ class ExpressOAuthServer { constructor(options = {}) { @@ -26,53 +43,66 @@ class ExpressOAuthServer { this.server = new NodeOAuthServer(options); } - /** - * Authentication Middleware. - * - * Returns a middleware that will validate a token. - * - * (See: https://tools.ietf.org/html/rfc6749#section-7) - */ - authenticate(options) { - - console.log('ExpressOAuthServer::authenticate', options); - - return (req, res, next) => { + /** + * Authenticates a request. + * + * @method authenticate + * @see https://oauth2-server.readthedocs.io/en/latest/api/oauth2-server.html#authenticate-request-response-options-callback + * @param {Object} options Handler options. + * @param {String} options.scope The scope(s) to authenticate. + * @param {Boolean} options.addAcceptedScopesHeader Set the X-Accepted-OAuth-Scopes HTTP header on response objects. + * @param {Boolean} options.addAuthorizedScopesHeader Set the X-OAuth-Scopes HTTP header on response objects. + * @param {Boolean} options.allowBearerTokensInQueryString Allow clients to pass bearer tokens in the query string of a request. + * @return {Function} + */ + authenticate(options) { + + + return (req, res, next) => { + // console.log('ExpressOAuthServer::authenticate', options); const request = new Request(req); const response = new Response(res); - - return this.server.authenticate(request, response, options) + return new Promise( (resolve, reject) => { + return resolve( this.server.authenticate(request, response, options) ); + }) .then( (token) => { res.locals.oauth = { token: token }; return next(); - }) .catch( (err) => { + }) + .catch( (err) => { return this.errorHandler(err, req, res, null, next); }); }; } - /** - * Authorization Middleware. - * - * Returns a middleware that will authorize a client to request tokens. - * - * (See: https://tools.ietf.org/html/rfc6749#section-3.1) - */ - - authorize(options) { - - - return (req, res, next) => { + /** + * Authorizes a token request. + * + * @method authorize + * @see https://oauth2-server.readthedocs.io/en/latest/api/oauth2-server.html#authorize-request-response-options-callback + * @param {Object} options Handler options. + * @param {{Funtion}} options.authenticateHandler The authenticate handler. + * @param {Boolean} options.allowEmptyState Allow clients to specify an empty state. + * @param {Number} options.authorizationCodeLifetime Lifetime of generated authorization codes in seconds (default = 5 minutes). + * @param {Number} options.accessTokenLifetime Lifetime of generated implicit grant access token in seconds (default = 1 hr). + * @return {Function} + */ + authorize(options) { + + return (req, res, next) => { + // console.log('ExpressOAuthServer::authorize', options); const request = new Request(req); const response = new Response(res); - return this.server.authorize(request, response, options) - .then( (code) => { + return new Promise( (resolve, reject) => { + return resolve(this.server.authorize(request, response, options)) + }) + .then( (code) => { res.locals.oauth = { code: code }; @@ -84,47 +114,58 @@ class ExpressOAuthServer { .then( () => { return this.responseHandler(req, res, response); }) - .catch( (e) => { - return this.errorHandler(e, req, res, response, next); + .catch( (err) => { + return this.errorHandler(err, req, res, response, next); }); }; } - /** - * Grant Middleware. - * - * Returns middleware that will grant tokens to valid requests. - * - * (See: https://tools.ietf.org/html/rfc6749#section-3.2) - */ - token(options) { + /** + * Retrieves a new token for an authorized token request. + * + * @method token + * @see https://oauth2-server.readthedocs.io/en/latest/api/oauth2-server.html#token-request-response-options-callback + * @param {Object} options Handler options. + * @param { Number} options.accessTokenLifetime Lifetime of generated access tokens in seconds (default = 1 hour). + * @param { Number} options.refreshTokenLifetime Lifetime of generated refresh tokens in seconds (default = 2 weeks). + * @param { Boolean} options.allowExtendedTokenAttributes Allow extended attributes to be set on the returned token. + * @param {Object} options.requireClientAuthentication Require a client secret. Defaults to true for all grant types. + * @param { Boolean} options.alwaysIssueNewRefreshToken Always revoke the used refresh token and issue a new one for the refresh_token grant. + * @param {Object} options.extendedGrantTypes Additional supported grant types. + * @return {Function} + */ + token(options) { return (req, res, next) => { const request = new Request(req); const response = new Response(res); - - return this.server.token(request, response, options) + + return new Promise( (resolve, reject) => { + return resolve(this.server.token(request, response, options)) + }) .then( (token) => { res.locals.oauth = { token: token }; - if (this.continueMiddleware) - { + if (this.continueMiddleware) { next(); } }) .then( () => { return this.responseHandler(req, res, response); }) - .catch( (e) => { - return this.errorHandler(e, req, res, response, next); + .catch( (err) => { + return this.errorHandler(err, req, res, response, next); }); }; } /** * Response handler. + * + * @method responseHandler + * @private */ responseHandler (req, res, response) { @@ -143,9 +184,14 @@ class ExpressOAuthServer { /** * Error handler. + * + * @method errorHandler + * @private */ errorHandler (error, req, res, response, next) { + // console.log('ExpressOAuthServer::errorHandler', error); + if (this.useErrorHandler === true) { return next(error); } diff --git a/package-lock.json b/package-lock.json index daa1a7c..c5891f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,17 +39,9 @@ "dev": true }, "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" }, "body-parser": { "version": "1.19.0", @@ -759,9 +751,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "lolex": { "version": "1.3.2", @@ -903,16 +895,37 @@ "dev": true }, "oauth2-server": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/oauth2-server/-/oauth2-server-3.1.1.tgz", - "integrity": "sha512-4dv+fE9hrK+xTaCygOLh/kQeFzbFr7UqSyHvBDbrQq8Hg52sAkV2vTsyH3Z42hoeaKpbhM7udhL8Y4GYbl6TGQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/oauth2-server/-/oauth2-server-3.0.0.tgz", + "integrity": "sha1-xGJ2t0w9KGNNWe6YH3a1imRZzCg=", "requires": { - "basic-auth": "2.0.1", - "bluebird": "3.7.2", - "lodash": "4.17.19", + "basic-auth": "1.1.0", + "bluebird": "3.5.0", + "lodash": "4.17.4", "promisify-any": "2.0.1", - "statuses": "1.5.0", - "type-is": "1.6.18" + "statuses": "1.3.1", + "type-is": "1.6.15" + }, + "dependencies": { + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.15" + } + } } }, "object-inspect": { @@ -1047,7 +1060,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -1170,7 +1184,8 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true }, "string.prototype.trimend": { "version": "1.0.4", @@ -1287,6 +1302,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" diff --git a/package.json b/package.json index 67a6106..d16d36d 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,11 @@ }, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "bluebird": "^3.0.5", - "express": "^4.13.3", "oauth2-server": "3.0.0" }, "devDependencies": { "body-parser": "^1.14.1", + "express": "^4.17.1", "jshint": "^2.8.0", "mocha": "^2.3.3", "should": "^7.1.0", diff --git a/test/integration/index.test.js b/test/integration/index.test.js index 56bb749..8ad68f2 100644 --- a/test/integration/index.test.js +++ b/test/integration/index.test.js @@ -4,29 +4,35 @@ * Module dependencies. */ -var ExpressOAuthServer = require('../../'); -var InvalidArgumentError = require('oauth2-server/lib/errors/invalid-argument-error'); -var NodeOAuthServer = require('oauth2-server'); -var bodyparser = require('body-parser'); -var express = require('express'); -var request = require('supertest'); -var should = require('should'); -var sinon = require('sinon'); +const ExpressOAuthServer = require('../../'); +const InvalidArgumentError = require('oauth2-server/lib/errors/invalid-argument-error'); +const NodeOAuthServer = require('oauth2-server'); +const bodyparser = require('body-parser'); +const express = require('express'); +const request = require('supertest'); +const should = require('should'); +const sinon = require('sinon'); /** * Test `ExpressOAuthServer`. */ describe('ExpressOAuthServer', function() { - var app; + + let app, server; beforeEach(function() { app = express(); - app.use(bodyparser.json()); app.use(bodyparser.urlencoded({ extended: false })); }); + afterEach(function() { + if(server){ + server.close(); + } + }); + describe('constructor()', function() { it('should throw an error if `model` is missing', function() { try { @@ -40,7 +46,7 @@ describe('ExpressOAuthServer', function() { }); it('should set the `server`', function() { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); oauth.server.should.be.an.instanceOf(NodeOAuthServer); }); @@ -48,31 +54,36 @@ describe('ExpressOAuthServer', function() { describe('authenticate()', function() { - it.only('should return an error if `model` is empty', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + it('should return an error if `model` is empty', function(done) { + let oauth = new ExpressOAuthServer({ model: {} }); app.use(oauth.authenticate()); - - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function(err, res) { - console.log(res); - + res.should.have.property('body'); + res.body.should.have.properties([ + 'error', + 'error_description' + ]); + res.body.error.should.eql('invalid_argument') + res.body.error_description.should.eql('Invalid argument: model does not implement `getAccessToken()`'); done(); }); }); it('should authenticate the request', function(done) { - var tokenExpires = new Date(); + let tokenExpires = new Date(); tokenExpires.setDate(tokenExpires.getDate() + 1); - var token = { user: {}, accessTokenExpiresAt: tokenExpires }; - var model = { + let token = { user: {}, accessTokenExpiresAt: tokenExpires }; + let model = { getAccessToken: function() { return token; } }; - var oauth = new ExpressOAuthServer({ model: model }); + let oauth = new ExpressOAuthServer({ model: model }); app.use(oauth.authenticate()); @@ -82,7 +93,8 @@ describe('ExpressOAuthServer', function() { next(); }); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .set('Authorization', 'Bearer foobar') .expect(200) @@ -90,26 +102,27 @@ describe('ExpressOAuthServer', function() { }); it('should cache the authorization token', function(done) { - var tokenExpires = new Date(); + let tokenExpires = new Date(); tokenExpires.setDate(tokenExpires.getDate() + 1); - var token = { user: {}, accessTokenExpiresAt: tokenExpires }; - var model = { + let token = { user: {}, accessTokenExpiresAt: tokenExpires }; + let model = { getAccessToken: function() { return token; } }; - var oauth = new ExpressOAuthServer({ model: model }); + let oauth = new ExpressOAuthServer({ model: model }); app.use(oauth.authenticate()); - var spy = sinon.spy(function(req, res, next) { + let spy = sinon.spy(function(req, res, next) { res.locals.oauth.token.should.equal(token); res.send(token); next(); }); app.use(spy); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .set('Authorization', 'Bearer foobar') .expect(200, function(err, res){ @@ -121,11 +134,11 @@ describe('ExpressOAuthServer', function() { describe('authorize()', function() { it('should cache the authorization code', function(done) { - var tokenExpires = new Date(); + let tokenExpires = new Date(); tokenExpires.setDate(tokenExpires.getDate() + 1); - var code = { authorizationCode: 123 }; - var model = { + let code = { authorizationCode: 123 }; + let model = { getAccessToken: function() { return { user: {}, accessTokenExpiresAt: tokenExpires }; }, @@ -136,17 +149,18 @@ describe('ExpressOAuthServer', function() { return code; } }; - var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); + let oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); app.use(oauth.authorize()); - var spy = sinon.spy(function(req, res, next) { + let spy = sinon.spy(function(req, res, next) { res.locals.oauth.code.should.equal(code); next(); }); app.use(spy); - request(app.listen()) + server = app.listen(); + request(server) .post('/?state=foobiz') .set('Authorization', 'Bearer foobar') .send({ client_id: 12345, response_type: 'code' }) @@ -157,7 +171,7 @@ describe('ExpressOAuthServer', function() { }); it('should return an error', function(done) { - var model = { + let model = { getAccessToken: function() { return { user: {}, accessTokenExpiresAt: new Date() }; }, @@ -168,11 +182,12 @@ describe('ExpressOAuthServer', function() { return {}; } }; - var oauth = new ExpressOAuthServer({ model: model }); + let oauth = new ExpressOAuthServer({ model: model }); app.use(oauth.authorize()); - request(app.listen()) + server = app.listen(); + request(server) .post('/?state=foobiz') .set('Authorization', 'Bearer foobar') .send({ client_id: 12345 }) @@ -184,7 +199,7 @@ describe('ExpressOAuthServer', function() { }); it('should return a `location` header with the code', function(done) { - var model = { + let model = { getAccessToken: function() { return { user: {}, accessTokenExpiresAt: new Date() }; }, @@ -195,11 +210,12 @@ describe('ExpressOAuthServer', function() { return { authorizationCode: 123 }; } }; - var oauth = new ExpressOAuthServer({ model: model }); + let oauth = new ExpressOAuthServer({ model: model }); app.use(oauth.authorize()); - request(app.listen()) + server = app.listen(); + request(server) .post('/?state=foobiz') .set('Authorization', 'Bearer foobar') .send({ client_id: 12345, response_type: 'code' }) @@ -208,11 +224,12 @@ describe('ExpressOAuthServer', function() { }); it('should return an error if `model` is empty', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); app.use(oauth.authorize()); - request(app) + server = app.listen(); + request(server) .post('/') .expect({ error: 'invalid_argument', error_description: 'Invalid argument: model does not implement `getClient()`' }) .end(done); @@ -221,8 +238,8 @@ describe('ExpressOAuthServer', function() { describe('token()', function() { it('should cache the authorization token', function(done) { - var token = { accessToken: 'foobar', client: {}, user: {} }; - var model = { + let token = { accessToken: 'foobar', client: {}, user: {} }; + let model = { getClient: function() { return { grants: ['password'] }; }, @@ -233,17 +250,18 @@ describe('ExpressOAuthServer', function() { return token; } }; - var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); + let oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); app.use(oauth.token()); - var spy = sinon.spy(function(req, res, next) { + let spy = sinon.spy(function(req, res, next) { res.locals.oauth.token.should.equal(token); next(); }); app.use(spy); - request(app.listen()) + server = app.listen(); + request(server) .post('/') .send('client_id=foo&client_secret=bar&grant_type=password&username=qux&password=biz') .expect({ access_token: 'foobar', token_type: 'Bearer' }) @@ -254,7 +272,7 @@ describe('ExpressOAuthServer', function() { }); it('should return an `access_token`', function(done) { - var model = { + let model = { getClient: function() { return { grants: ['password'] }; }, @@ -265,11 +283,13 @@ describe('ExpressOAuthServer', function() { return { accessToken: 'foobar', client: {}, user: {} }; } }; - var spy = sinon.spy(); - var oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); + let spy = sinon.spy(); + let oauth = new ExpressOAuthServer({ model: model, continueMiddleware: true }); app.use(oauth.token()); - request(app.listen()) + + server = app.listen(); + request(server) .post('/') .send('client_id=foo&client_secret=bar&grant_type=password&username=qux&password=biz') .expect({ access_token: 'foobar', token_type: 'Bearer' }) @@ -277,7 +297,7 @@ describe('ExpressOAuthServer', function() { }); it('should return a `refresh_token`', function(done) { - var model = { + let model = { getClient: function() { return { grants: ['password'] }; }, @@ -288,11 +308,12 @@ describe('ExpressOAuthServer', function() { return { accessToken: 'foobar', client: {}, refreshToken: 'foobiz', user: {} }; } }; - var oauth = new ExpressOAuthServer({ model: model }); + let oauth = new ExpressOAuthServer({ model: model }); app.use(oauth.token()); - request(app.listen()) + server = app.listen(); + request(server) .post('/') .send('client_id=foo&client_secret=bar&grant_type=password&username=qux&password=biz') .expect({ access_token: 'foobar', refresh_token: 'foobiz', token_type: 'Bearer' }) @@ -300,11 +321,12 @@ describe('ExpressOAuthServer', function() { }); it('should return an error if `model` is empty', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); app.use(oauth.token()); - request(app.listen()) + server = app.listen(); + request(server) .post('/') .expect({ error: 'invalid_argument', error_description: 'Invalid argument: model does not implement `getClient()`' }) .end(done); diff --git a/test/unit/index.test.js b/test/unit/index.test.js index 3c3568a..24a90db 100644 --- a/test/unit/index.test.js +++ b/test/unit/index.test.js @@ -3,37 +3,44 @@ /** * Module dependencies. */ - -var ExpressOAuthServer = require('../../'); -var Request = require('oauth2-server').Request; -var Response = require('oauth2-server').Response; -var express = require('express'); -var request = require('supertest'); -var sinon = require('sinon'); -var should = require('should'); +const ExpressOAuthServer = require('../../'); +const Request = require('oauth2-server').Request; +const Response = require('oauth2-server').Response; +const express = require('express'); +const request = require('supertest'); +const sinon = require('sinon'); +const should = require('should'); /** * Test `ExpressOAuthServer`. */ - describe('ExpressOAuthServer', function() { - var app; + + let app, server; beforeEach(function() { app = express(); }); + afterEach(function() { + if(server){ + server.close(); + } + }); + + describe('authenticate()', function() { it('should call `authenticate()`', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'authenticate') .returns( Promise.resolve({}) ); app.use(oauth.authenticate()); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.authenticate.callCount.should.equal(1); @@ -47,14 +54,15 @@ describe('ExpressOAuthServer', function() { }); it('should call `authenticate()` with options', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'authenticate') .returns( Promise.resolve({}) ); app.use(oauth.authenticate({options: true})); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.authenticate.callCount.should.equal(1); @@ -70,8 +78,8 @@ describe('ExpressOAuthServer', function() { describe('authorize()', function() { it('should call `authorize()` and end middleware execution', function(done) { - var nextMiddleware = sinon.spy() - var oauth = new ExpressOAuthServer({ model: {} }); + let nextMiddleware = sinon.spy() + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'authorize') .returns( Promise.resolve({}) ); @@ -79,7 +87,8 @@ describe('ExpressOAuthServer', function() { app.use(oauth.authorize()); app.use(nextMiddleware); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.authorize.callCount.should.equal(1); @@ -94,8 +103,8 @@ describe('ExpressOAuthServer', function() { }); it('should call `authorize()` and continue middleware chain', function(done) { - var nextMiddleware = sinon.spy() - var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); + let nextMiddleware = sinon.spy() + let oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); sinon.stub(oauth.server, 'authorize') .returns( Promise.resolve({}) ); @@ -103,7 +112,8 @@ describe('ExpressOAuthServer', function() { app.use(oauth.authorize()); app.use(nextMiddleware); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.authorize.callCount.should.equal(1); @@ -119,14 +129,15 @@ describe('ExpressOAuthServer', function() { }); it('should call `authorize()` with options', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'authorize') .returns(Promise.resolve({})); app.use(oauth.authorize({options: true})); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.authorize.callCount.should.equal(1); @@ -142,8 +153,8 @@ describe('ExpressOAuthServer', function() { describe('token()', function() { it('should call `token()` and end middleware chain', function(done) { - var nextMiddleware = sinon.spy() - var oauth = new ExpressOAuthServer({ model: {} }); + let nextMiddleware = sinon.spy() + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'token') .returns(Promise.resolve({})); @@ -151,7 +162,8 @@ describe('ExpressOAuthServer', function() { app.use(oauth.token()); app.use(nextMiddleware); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.token.callCount.should.equal(1); @@ -166,8 +178,8 @@ describe('ExpressOAuthServer', function() { }); it('should call `token()` and continue middleware chain', function(done) { - var nextMiddleware = sinon.spy() - var oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); + let nextMiddleware = sinon.spy() + let oauth = new ExpressOAuthServer({ model: {}, continueMiddleware: true }); sinon.stub(oauth.server, 'token') .returns(Promise.resolve({})); @@ -175,7 +187,8 @@ describe('ExpressOAuthServer', function() { app.use(oauth.token()); app.use(nextMiddleware); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.token.callCount.should.equal(1); @@ -191,14 +204,15 @@ describe('ExpressOAuthServer', function() { }); it('should call `token()` with options', function(done) { - var oauth = new ExpressOAuthServer({ model: {} }); + let oauth = new ExpressOAuthServer({ model: {} }); sinon.stub(oauth.server, 'token') .returns(Promise.resolve({})); app.use(oauth.token({options: true})); - request(app.listen()) + server = app.listen(); + request(server) .get('/') .end(function() { oauth.server.token.callCount.should.equal(1);