UNPKG

apollo-passport-local-strategy

Version:

Local strategy using email address and hashed, bcrypted password

516 lines (430 loc) 17.9 kB
"use strict"; var _proxyquire = require("proxyquire"); var _proxyquire2 = _interopRequireDefault(_proxyquire); var _chai = require("chai"); var _chai2 = _interopRequireDefault(_chai); var _chaiAsPromised = require("chai-as-promised"); var _chaiAsPromised2 = _interopRequireDefault(_chaiAsPromised); require("regenerator-runtime/runtime"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } _chai2.default.use(_chaiAsPromised2.default); var should = _chai2.default.should(); // might be useful elsewhere too... var passportStub = { authenticate: function authenticate(name, callback) { return function (req) { if (!req) throw new Error("no req"); if (!req.query) throw new Error("no req.query"); var override = req.query.override; if (!override) throw new Error("no req.query.override"); switch (override) { case 'error': return callback(new Error()); case 'user': return callback(null, { id: 1 }); case 'info': return callback(null, null, 'info'); default: throw new Error("Invalid req.query.override: " + override); } }; } }; var context = { passport: passportStub, hashPassword: function hashPassword(pass) { return new Promise(function (resolve) { return resolve("hashed:" + pass); }); } }; var resolvers = (0, _proxyquire2.default)('./resolvers', { passport: passportStub }).default; describe('apollo-passport-local', function () { describe('passportStub', function () { it('throws on missing or invalid values', function () { (function () { passportStub.authenticate()(); }).should.throw(); (function () { passportStub.authenticate()({}); }).should.throw(); (function () { passportStub.authenticate()({ query: {} }); }).should.throw(); (function () { passportStub.authenticate()({ query: { override: 'error' } }); }).should.throw(); (function () { passportStub.authenticate()({ query: { override: 'invalid' } }); }).should.throw(); }); }); describe('resolvers', function () { describe('apCreateUserEmailPassword()', function () { var errMsg = "foo"; var apCreateUserEmailPassword = resolvers.RootMutation.apCreateUserEmailPassword.bind(context); it('returns an error when trying to re-register an existing email', function _callee() { var result; return regeneratorRuntime.async(function _callee$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: context.db = { fetchUserByEmail: function fetchUserByEmail() { return regeneratorRuntime.async(function fetchUserByEmail$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", { userId: 1 }); case 1: case "end": return _context.stop(); } } }, null, undefined); } }; _context2.next = 3; return regeneratorRuntime.awrap(apCreateUserEmailPassword(null, { email: 'email', password: 'password ' })); case 3: result = _context2.sent; result.should.deep.equal({ error: "E-mail already registered", token: "" }); case 5: case "end": return _context2.stop(); } } }, null, undefined); }); it('catches createUser errors', function _callee3() { var result; return regeneratorRuntime.async(function _callee3$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: context.db = { fetchUserByEmail: function fetchUserByEmail() { return regeneratorRuntime.async(function fetchUserByEmail$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: return _context3.abrupt("return", null); case 1: case "end": return _context3.stop(); } } }, null, undefined); } }; context.createUser = function _callee2() { return regeneratorRuntime.async(function _callee2$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: throw new Error(errMsg); case 1: case "end": return _context4.stop(); } } }, null, undefined); }; _context5.next = 4; return regeneratorRuntime.awrap(apCreateUserEmailPassword(null, { email: 'email', password: 'password ' })); case 4: result = _context5.sent; result.should.deep.equal({ error: errMsg, token: "" }); case 6: case "end": return _context5.stop(); } } }, null, undefined); }); it('calls createUser with correct args, logs in user', function _callee5() { var result; return regeneratorRuntime.async(function _callee5$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: context.db = { fetchUserByEmail: function fetchUserByEmail() { return regeneratorRuntime.async(function fetchUserByEmail$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: return _context6.abrupt("return", null); case 1: case "end": return _context6.stop(); } } }, null, undefined); } }; context.createUser = function _callee4(user) { return regeneratorRuntime.async(function _callee4$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: user.should.deep.equal({ emails: [{ value: 'email' }], services: { password: { bcrypt: 'hashed:password ' } } }); return _context7.abrupt("return", 'elizabeth'); case 2: case "end": return _context7.stop(); } } }, null, this); }; context.createTokenFromUser = function () { return 'token'; }; _context8.next = 5; return regeneratorRuntime.awrap(apCreateUserEmailPassword(null, { email: 'email', password: 'password ' })); case 5: result = _context8.sent; result.should.deep.equal({ error: "", token: 'token' }); case 7: case "end": return _context8.stop(); } } }, null, undefined); }); }); describe('apLoginEmailPassword()', function () { var apLoginEmailPassword = resolvers.RootMutation.apLoginEmailPassword.bind(context); it('throws on a real error', function () { // I don't know how to check if an async function throws apLoginEmailPassword(null, { override: 'error' }).should.be.rejected; }); it('passes the user', function _callee6() { var result; return regeneratorRuntime.async(function _callee6$(_context9) { while (1) { switch (_context9.prev = _context9.next) { case 0: _context9.next = 2; return regeneratorRuntime.awrap(apLoginEmailPassword(null, { override: 'user' })); case 2: result = _context9.sent; result.error.should.equal(""); result.token.should.equal('token'); case 5: case "end": return _context9.stop(); } } }, null, undefined); }); it('passes an error string (not a throw)', function _callee7() { var result; return regeneratorRuntime.async(function _callee7$(_context10) { while (1) { switch (_context10.prev = _context10.next) { case 0: _context10.next = 2; return regeneratorRuntime.awrap(apLoginEmailPassword(null, { override: 'info' })); case 2: result = _context10.sent; result.error.should.equal("info"); result.token.should.equal(""); case 5: case "end": return _context10.stop(); } } }, null, undefined); }); }); describe('apUpdateUserPassword', function () { var password = 'password'; var apUpdateUserPassword = resolvers.RootMutation.apUpdateUserPassword.bind(context); it('only works for logged in matching userId', function _callee8() { var result; return regeneratorRuntime.async(function _callee8$(_context12) { while (1) { switch (_context12.prev = _context12.next) { case 0: context.db = { assertUserServiceData: function assertUserServiceData() { return regeneratorRuntime.async(function assertUserServiceData$(_context11) { while (1) { switch (_context11.prev = _context11.next) { case 0: case "end": return _context11.stop(); } } }, null, this); } }; _context12.next = 3; return regeneratorRuntime.awrap(apUpdateUserPassword(null, { userId: 1, password: password }, { auth: { userId: 2 } })); case 3: result = _context12.sent; result.should.equal("Not logged in as 1"); _context12.next = 7; return regeneratorRuntime.awrap(apUpdateUserPassword(null, { userId: 1, password: password }, {})); case 7: result = _context12.sent; result.should.equal("Not logged in as 1"); _context12.next = 11; return regeneratorRuntime.awrap(apUpdateUserPassword(null, { userId: 1, password: password })); case 11: result = _context12.sent; result.should.equal("Not logged in as 1"); case 13: case "end": return _context12.stop(); } } }, null, undefined); }); it('calls db.assertUserServiceData correctly and returns no error', function _callee11() { var result; return regeneratorRuntime.async(function _callee11$(_context17) { while (1) { switch (_context17.prev = _context17.next) { case 0: context.comparePassword = function _callee9() { return regeneratorRuntime.async(function _callee9$(_context13) { while (1) { switch (_context13.prev = _context13.next) { case 0: return _context13.abrupt("return", true); case 1: case "end": return _context13.stop(); } } }, null, undefined); }; context.hashPassword = function _callee10(password) { return regeneratorRuntime.async(function _callee10$(_context14) { while (1) { switch (_context14.prev = _context14.next) { case 0: return _context14.abrupt("return", "hashed:" + password); case 1: case "end": return _context14.stop(); } } }, null, undefined); }; context.db = { fetchUserById: function fetchUserById() { return regeneratorRuntime.async(function fetchUserById$(_context15) { while (1) { switch (_context15.prev = _context15.next) { case 0: return _context15.abrupt("return", { services: { password: { bcrypt: password } } }); case 1: case "end": return _context15.stop(); } } }, null, undefined); }, assertUserServiceData: function assertUserServiceData(userId, service, data) { return regeneratorRuntime.async(function assertUserServiceData$(_context16) { while (1) { switch (_context16.prev = _context16.next) { case 0: should.exist(userId); service.should.equal('password'); data.should.deep.equal({ bcrypt: "hashed:" + password }); case 3: case "end": return _context16.stop(); } } }, null, this); } }; _context17.next = 5; return regeneratorRuntime.awrap(apUpdateUserPassword(null, { userId: 1, oldPassword: password, newPassword: password }, { auth: { userId: 1 } })); case 5: result = _context17.sent; result.should.equal(""); case 7: case "end": return _context17.stop(); } } }, null, undefined); }); it('catches errors from db.assertUserServiceData', function _callee13() { var result; return regeneratorRuntime.async(function _callee13$(_context21) { while (1) { switch (_context21.prev = _context21.next) { case 0: context.comparePassword = function _callee12() { return regeneratorRuntime.async(function _callee12$(_context18) { while (1) { switch (_context18.prev = _context18.next) { case 0: return _context18.abrupt("return", true); case 1: case "end": return _context18.stop(); } } }, null, undefined); }; context.db = { fetchUserById: function fetchUserById() { return regeneratorRuntime.async(function fetchUserById$(_context19) { while (1) { switch (_context19.prev = _context19.next) { case 0: return _context19.abrupt("return", { services: { password: { bcrypt: password } } }); case 1: case "end": return _context19.stop(); } } }, null, undefined); }, assertUserServiceData: function assertUserServiceData() { return regeneratorRuntime.async(function assertUserServiceData$(_context20) { while (1) { switch (_context20.prev = _context20.next) { case 0: throw new Error('foo'); case 1: case "end": return _context20.stop(); } } }, null, this); } }; _context21.next = 4; return regeneratorRuntime.awrap(apUpdateUserPassword(null, { userId: 1, password: password }, { auth: { userId: 1 } })); case 4: result = _context21.sent; result.should.equal('foo'); case 6: case "end": return _context21.stop(); } } }, null, undefined); }); }); }); });