diff --git a/README.md b/README.md index 5ce703f..d3c20b8 100755 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ export const passport = { secretOrKey: SECRET, issuer: ISSUER, audience: AUDIENCE, - jwtFromRequest: ExtractJwt.fromAuthHeader() + jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme("jwt") } }, diff --git a/lib/api/models/User.ts b/lib/api/models/User.ts index 66e7ba3..94c5ae9 100755 --- a/lib/api/models/User.ts +++ b/lib/api/models/User.ts @@ -1,6 +1,7 @@ import { FabrixApp } from '@fabrix/fabrix' import { FabrixModel as Model } from '@fabrix/fabrix/dist/common' import { SequelizeResolver } from '@fabrix/spool-sequelize' +import { ModelError } from '@fabrix/spool-sequelize/dist/errors' import { UserDefaults } from '../utils/queryDefaults/UserDefaults' import * as shortId from 'shortid' @@ -26,57 +27,135 @@ export class UserResolver extends SequelizeResolver { return this.findOne(options) } - resolve(user, options = {}) { - options = options || {} - if (user instanceof this.sequelizeModel) { - return Promise.resolve(user) - } - else if (user && isObject(user) && user.id) { - return this.findById(user.id, options) - .then(resUser => { - if (!resUser) { - throw Error(`User ${user.id} not found`) - } - return resUser - }) - } - else if (user && isObject(user) && user.email) { - return this.findOne(defaultsDeep({ - where: { - email: user.email + /** + * Resolve by instance Function + * @param user + * @param options + */ + resolveByInstance (user, options: {[key: string]: any} = {}) { + return Promise.resolve(user) + } + /** + * Resolve by id Function + * @param user + * @param options + */ + resolveById (user, options: {[key: string]: any} = {}) { + return this.findById(user.id, options) + .then(resUser => { + if (!resUser && options.reject !== false) { + throw new ModelError('E_NOT_FOUND', `User ${user.id} not found`) } - }, options)) - .then(resUser => { - if (!resUser) { - throw new Error(`User ${user.email} not found`) - } - return resUser - }) - } - else if (user && isNumber(user)) { - return this.findById(user, options) - .then(resUser => { - if (!resUser) { - throw new Error(`User ${user} not found`) - } - return resUser - }) - } - else if (user && isString(user)) { - return this.findOne(defaultsDeep({ - where: { - email: user + return resUser + }) + } + /** + * Resolve by token Function + * @param user + * @param options + */ + resolveByToken (user, options: {[key: string]: any} = {}) { + return this.findOne(defaultsDeep({ + where: { + token: user.token + } + }, options)) + .then(resUser => { + if (!resUser && options.reject !== false) { + throw new ModelError('E_NOT_FOUND', `User token ${user.token} not found`) } - }, options)) - .then(resUser => { - if (!resUser) { - throw new Error(`User ${user} not found`) - } - return resUser - }) + return resUser + }) + } + /** + * Resolve by email Function + * @param user + * @param options + */ + resolveByEmail (user, options: {[key: string]: any} = {}) { + return this.findOne(defaultsDeep({ + where: { + email: user.email + } + }, options)) + .then(resUser => { + if (!resUser && options.reject !== false) { + throw new ModelError('E_NOT_FOUND', `User email ${user.email} not found`) + } + return resUser + }) + } + /** + * Resolve by number Function + * @param user + * @param options + */ + resolveByNumber (user, options: {[key: string]: any} = {}) { + return this.findById(user, options) + .then(resUser => { + if (!resUser && options.reject !== false) { + throw new ModelError('E_NOT_FOUND', `User ${user.token} not found`) + } + return resUser + }) + } + /** + * Resolve by string Function + * @param user + * @param options + */ + resolveByString (user, options: {[key: string]: any} = {}) { + return this.findOne(defaultsDeep({ + where: { + token: user + } + }, options)) + .then(resUser => { + if (!resUser && options.reject !== false) { + throw new ModelError('E_NOT_FOUND', `User ${user} not found`) + } + return resUser + }) + } + /** + * Primary Resolve Function + * @param user + * @param options + */ + resolve(user, options: {[key: string]: any} = {}) { + const resolvers = { + 'instance': user instanceof this.sequelizeModel, + 'id': !!(user && isObject(user) && user.id), + 'token': !!(user && isObject(user) && user.token), + 'number': !!(user && isNumber(user)), + 'string': !!(user && isString(user)) } - else { - throw new Error(`User ${user} not found`) + const type = Object.keys(resolvers).find((key) => resolvers[key]) + + switch (type) { + case 'instance': { + return this.resolveByInstance(user, options) + } + case 'id': { + return this.resolveById(user, options) + } + case 'token': { + return this.resolveByToken(user, options) + } + case 'email': { + return this.resolveByEmail(user, options) + } + case 'number': { + return this.resolveByNumber(user, options) + } + case 'string': { + return this.resolveByString(user, options) + } + default: { + // TODO create proper error + const err = new Error(`Unable to resolve User ${user}`) + return Promise.reject(err) + } } } } @@ -93,12 +172,14 @@ export class User extends Model { options: { underscored: true, hooks: { - beforeCreate: (values, options) => { - // If not token was already created, create it - if (!values.token) { - values.token = `user_${shortId.generate()}` + beforeCreate: [ + (values, options) => { + // If not token was already created, create it + if (!values.token) { + values.token = `user_${shortId.generate()}` + } } - } + ] } } } diff --git a/package-lock.json b/package-lock.json index 89f9e93..686f6da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@fabrix/spool-passport", - "version": "1.1.1", + "version": "1.1.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -158,9 +158,9 @@ } }, "@fabrix/spool-express": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@fabrix/spool-express/-/spool-express-1.1.3.tgz", - "integrity": "sha512-p4GPwfs41o15Y4OO8f5QSrY6UmwaG4d19kld9RhKHKmf5iOAjCa1w9oK6qxHgWOWhTxexM9ROfQ+CzCner+L5g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@fabrix/spool-express/-/spool-express-1.1.4.tgz", + "integrity": "sha512-He4MbJKD/UbzUTpjKj0Ed5TQtJSb/ywXPHaAEjkg/yvhnuanQBp+svaXXaSKQV29jzqNeiJyANTa/399XpO3lA==", "dev": true, "requires": { "body-parser": "1.18.3", @@ -198,9 +198,9 @@ } }, "@fabrix/spool-sequelize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fabrix/spool-sequelize/-/spool-sequelize-1.1.0.tgz", - "integrity": "sha512-lfzhMix0r3aFahemyQMMn35KuvDNk0kQHndWU+K5fRAe344I4SvDOgVNSCm7OJcVBmmYDcwXVAv6aDbg2Qh6Sw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@fabrix/spool-sequelize/-/spool-sequelize-1.1.1.tgz", + "integrity": "sha512-70px0HzxNZ59VG12ZhZyOkBMzZRoOlQ+rfkzbVx26qZicBZCVnOD+xMc++C7R44DZlu+8SLrrGewXaj3VnsWPw==", "dev": true, "requires": { "@types/sequelize": "4.27.24", @@ -1241,46 +1241,19 @@ } }, "jsonwebtoken": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.3.0.tgz", - "integrity": "sha1-hRGNanDj/M3xQ4n056HD+cip+7o=", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz", + "integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==", "requires": { - "joi": "6.10.1", "jws": "3.1.5", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", "lodash.once": "4.1.1", - "ms": "0.7.3", - "xtend": "4.0.1" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" - }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.22.2", - "topo": "1.1.0" - } - }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "requires": { - "hoek": "2.16.3" - } - } + "ms": "2.1.1" } }, "jwa": { @@ -1316,6 +1289,36 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -1480,7 +1483,8 @@ "moment": { "version": "2.22.2", "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=", + "dev": true }, "moment-timezone": { "version": "0.5.21", @@ -1492,9 +1496,9 @@ } }, "ms": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", - "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "nan": { "version": "2.10.0", @@ -1502,6 +1506,11 @@ "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", "dev": true }, + "nanoid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.1.0.tgz", + "integrity": "sha512-iOCqgXieGrk8/wDt1n9rZS2KB1dYVssemY0NTWjfzVr+1t1gAmdTp1u2+YHppKro3Bk5S+Gs+xmYCfpuXauYXQ==" + }, "needle": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", @@ -3964,12 +3973,12 @@ } }, "passport-jwt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-2.2.1.tgz", - "integrity": "sha1-DgBMlAcTGdZz2dm8/RV0qGgBFSc=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", "dev": true, "requires": { - "jsonwebtoken": "7.3.0", + "jsonwebtoken": "8.3.0", "passport-strategy": "1.0.0" } }, @@ -4395,9 +4404,12 @@ "dev": true }, "shortid": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.8.tgz", - "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=" + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.12.tgz", + "integrity": "sha512-sw0knB/ioTu/jVYgJz1IP1b5uhPZtZYwQ9ir/EqXZHI4+Jh8rzzGLM3LKptGHBKoDsgTBDfr4yCRNUX7hEIksQ==", + "requires": { + "nanoid": "1.1.0" + } }, "signal-exit": { "version": "3.0.2", @@ -4797,7 +4809,8 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true }, "yallist": { "version": "3.0.2", diff --git a/package.json b/package.json index c082051..d7a891e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fabrix/spool-passport", - "version": "1.1.1", + "version": "1.1.2", "description": "Spool - To allow passport authentification for a Fabrix application", "homepage": "https://github.com/fabrix-app/spool-passport", "author": { @@ -50,23 +50,23 @@ "dependencies": { "bcryptjs": "2.4.3", "joi": "^13.4.0", - "jsonwebtoken": "7.3.0", + "jsonwebtoken": "8.3.0", "lodash": "^4.17.10", "passport": "^0.4.0", - "shortid": "^2.2.8" + "shortid": "^2.2.12" }, "devDependencies": { "@fabrix/fabrix": "^1.1.1", "@fabrix/lint": "^1.0.0-alpha.3", "@fabrix/spool-email": "^1.1.0", - "@fabrix/spool-express": "^1.1.3", + "@fabrix/spool-express": "^1.1.4", "@fabrix/spool-i18n": "^1.1.0", "@fabrix/spool-router": "^1.1.2", - "@fabrix/spool-sequelize": "^1.1.0", + "@fabrix/spool-sequelize": "^1.1.1", "@types/lodash": "^4.14.109", "@types/node": "~10.3.4", "express": "4.15.2", - "passport-jwt": "^2.1.0", + "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", "pg": "^6.4.2", "mocha": "^5", diff --git a/test/fixtures/app.js b/test/fixtures/app.js index 3059169..cae8bd4 100755 --- a/test/fixtures/app.js +++ b/test/fixtures/app.js @@ -81,7 +81,7 @@ const App = { return Promise.resolve(user) }, onUserRecover: (req, app, user) => { - console.log('THIS RECOVER onUserRecover', user) + // console.log('THIS RECOVER onUserRecover', user) // if (user.recovery) { // delete user.recovery // } @@ -114,7 +114,7 @@ const App = { secretOrKey: SECRET, issuer: ISSUER, audience: AUDIENCE, - jwtFromRequest: ExtractJwt.fromAuthHeader() //Authorization: JWT JSON_WEB_TOKEN_STRING + jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme("jwt") //Authorization: JWT JSON_WEB_TOKEN_STRING } }, local: { diff --git a/test/integration/services/PassportService.test.js b/test/integration/services/PassportService.test.js index 4a71546..8f45140 100755 --- a/test/integration/services/PassportService.test.js +++ b/test/integration/services/PassportService.test.js @@ -152,10 +152,9 @@ describe('PassportService', () => { }) .expect(200) .end((err, res) => { - console.log('THIS RECOVER END', err, res.body) + // console.log('THIS RECOVER END', err, res.body) assert.equal(res.body.redirect, '/') assert.equal(res.body.user.username, 'jim') - assert.equal() done(err) }) })