apollo-passport-local-strategy
Version:
Local strategy using email address and hashed, bcrypted password
516 lines (430 loc) • 17.9 kB
JavaScript
;
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);
});
});
});
});