apollo-passport-local-strategy
Version:
Local strategy using email address and hashed, bcrypted password
482 lines (383 loc) • 15.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var resolvers = {
RootMutation: {
apCreateUserEmailPassword: function apCreateUserEmailPassword(root, _ref) {
var input = _ref.input;
var existing, reducedInput, expirationLength, verificationToken, user, userId, onBeforeStoreRegisteredUser, onCreateUserEnd;
return regeneratorRuntime.async(function apCreateUserEmailPassword$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return regeneratorRuntime.awrap(this.db.fetchUserByEmail(input.email));
case 2:
existing = _context.sent;
reducedInput = Object.assign({}, input);
delete reducedInput.email;
delete reducedInput.password;
if (!(existing && existing.services && Object.keys(existing.services).length > 0)) {
_context.next = 8;
break;
}
return _context.abrupt("return", { token: "", error: "E-mail already registered" });
case 8:
expirationLength = this.strategies.local.tokensExpirationLength.verification;
_context.next = 11;
return regeneratorRuntime.awrap(this.generateVerificationToken(expirationLength));
case 11:
verificationToken = _context.sent;
_context.t0 = Object;
_context.t1 = reducedInput;
_context.t2 = [{ value: input.email }];
_context.next = 17;
return regeneratorRuntime.awrap(this.hashPassword(input.password));
case 17:
_context.t3 = _context.sent;
_context.t4 = {
bcrypt: _context.t3
};
_context.t5 = {
password: _context.t4
};
_context.t6 = verificationToken.token;
_context.t7 = verificationToken.expiration;
_context.t8 = {
emails: _context.t2,
services: _context.t5,
verificationToken: _context.t6,
verificationTokenExpiration: _context.t7,
verified: false
};
user = _context.t0.assign.call(_context.t0, _context.t1, _context.t8);
userId = void 0;
onBeforeStoreRegisteredUser = this.onBeforeStoreRegisteredUser;
if (onBeforeStoreRegisteredUser && typeof onBeforeStoreRegisteredUser === 'function') {
onBeforeStoreRegisteredUser(user);
}
_context.prev = 27;
if (existing) {
_context.next = 34;
break;
}
_context.next = 31;
return regeneratorRuntime.awrap(this.createUser(user));
case 31:
userId = _context.sent;
_context.next = 37;
break;
case 34:
userId = existing._id;
user.dateRegistered = new Date();
this.db.updateUser(userId, user);
case 37:
_context.next = 42;
break;
case 39:
_context.prev = 39;
_context.t9 = _context["catch"](27);
return _context.abrupt("return", {
error: _context.t9.message,
token: ""
});
case 42:
// XXX correct id field?
// user.id = userId;
onCreateUserEnd = this.onCreateUserEnd;
if (onCreateUserEnd && typeof onCreateUserEnd === 'function') {
onCreateUserEnd(user);
}
return _context.abrupt("return", {
error: "",
token: ''
});
case 45:
case "end":
return _context.stop();
}
}
}, null, this, [[27, 39]]);
},
apVerifyAccount: function apVerifyAccount(root, _ref2) {
var userId = _ref2.userId,
verificationToken = _ref2.verificationToken;
var user, err, onVerifyAccountEnd;
return regeneratorRuntime.async(function apVerifyAccount$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.next = 2;
return regeneratorRuntime.awrap(this.db.fetchUserById(userId));
case 2:
user = _context2.sent;
err = {};
if (user) {
_context2.next = 6;
break;
}
return _context2.abrupt("return", {
errCode: 'USER_NOT_EXIST',
errMessage: 'No such user id'
});
case 6:
if (!(!user.verificationToken && user.resetPassToken)) {
_context2.next = 8;
break;
}
return _context2.abrupt("return", {
errCode: 'RESET_PASS_IN_PROGRESS',
errMessage: 'Reset password is in progress'
});
case 8:
if (!(user.verificationToken !== verificationToken)) {
_context2.next = 10;
break;
}
return _context2.abrupt("return", {
errCode: 'TOKEN_NOT_VALID',
errMessage: 'Verification token not valid'
});
case 10:
if (!(Date.now() > user.verificationTokenExpiration)) {
_context2.next = 12;
break;
}
return _context2.abrupt("return", {
errCode: 'TOKEN_EXPIRED',
errMessage: 'Verification token expired'
});
case 12:
onVerifyAccountEnd = this.onVerifyAccountEnd;
if (onVerifyAccountEnd && typeof onVerifyAccountEnd === 'function') {
onVerifyAccountEnd(user);
}
this.db.verifyUserAccount(userId);
case 15:
case "end":
return _context2.stop();
}
}
}, null, this);
},
apRecoverPasswordRequest: function apRecoverPasswordRequest(root, _ref3) {
var email = _ref3.email;
var user, expirationLength, _ref4, token, expiration, updatedUser, onRecoverPasswordRequestEnd;
return regeneratorRuntime.async(function apRecoverPasswordRequest$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return regeneratorRuntime.awrap(this.db.fetchUserByEmail(email));
case 2:
user = _context3.sent;
if (user) {
_context3.next = 5;
break;
}
return _context3.abrupt("return", 'No such user email');
case 5:
expirationLength = this.strategies.local.tokensExpirationLength.resetPass;
_context3.next = 8;
return regeneratorRuntime.awrap(this.generateVerificationToken(expirationLength));
case 8:
_ref4 = _context3.sent;
token = _ref4.token;
expiration = _ref4.expiration;
_context3.next = 13;
return regeneratorRuntime.awrap(this.db.addResetPasswordToken(user._id, token, expiration));
case 13:
_context3.next = 15;
return regeneratorRuntime.awrap(this.db.fetchUserById(user._id));
case 15:
updatedUser = _context3.sent;
onRecoverPasswordRequestEnd = this.onRecoverPasswordRequestEnd;
if (onRecoverPasswordRequestEnd && typeof onRecoverPasswordRequestEnd === 'function') {
onRecoverPasswordRequestEnd(updatedUser);
}
return _context3.abrupt("return", '');
case 19:
case "end":
return _context3.stop();
}
}
}, null, this);
},
apRecoverPassword: function apRecoverPassword(root, _ref5, context) {
var userId = _ref5.userId,
token = _ref5.token,
newPassword = _ref5.newPassword;
var user, onRecoverPasswordEnd;
return regeneratorRuntime.async(function apRecoverPassword$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return regeneratorRuntime.awrap(this.db.fetchUserById(userId));
case 2:
user = _context4.sent;
if (user) {
_context4.next = 5;
break;
}
return _context4.abrupt("return", 'No such userId');
case 5:
if (user.resetPassToken) {
_context4.next = 7;
break;
}
return _context4.abrupt("return", 'Password reset has not been initialized');
case 7:
if (!(user.resetPassToken !== token)) {
_context4.next = 9;
break;
}
return _context4.abrupt("return", 'Reset password token not valid');
case 9:
if (!(Date.now() > user.resetPassTokenExpiration)) {
_context4.next = 11;
break;
}
return _context4.abrupt("return", 'Reset password token expired');
case 11:
_context4.prev = 11;
_context4.t0 = regeneratorRuntime;
_context4.t1 = this.db;
_context4.t2 = userId;
_context4.next = 17;
return regeneratorRuntime.awrap(this.hashPassword(newPassword));
case 17:
_context4.t3 = _context4.sent;
_context4.t4 = {
bcrypt: _context4.t3
};
_context4.t5 = _context4.t1.assertUserServiceData.call(_context4.t1, _context4.t2, 'password', _context4.t4);
_context4.next = 22;
return _context4.t0.awrap.call(_context4.t0, _context4.t5);
case 22:
_context4.next = 24;
return regeneratorRuntime.awrap(this.db.verifyUserAccount(userId, 'verified', 'resetPassToken', 'resetPassTokenExpiration'));
case 24:
_context4.next = 29;
break;
case 26:
_context4.prev = 26;
_context4.t6 = _context4["catch"](11);
return _context4.abrupt("return", _context4.t6.message);
case 29:
onRecoverPasswordEnd = this.onRecoverPasswordEnd;
if (onRecoverPasswordEnd && typeof onRecoverPasswordEnd === 'function') {
onRecoverPasswordEnd(user);
}
return _context4.abrupt("return", "");
case 32:
case "end":
return _context4.stop();
}
}
}, null, this, [[11, 26]]);
},
apLoginEmailPassword: function apLoginEmailPassword(root, args) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.passport.authenticate('local', function (err, user, info) {
if (err) return reject(err);
if (!user || info) return resolve({ error: info, token: "" });
var onLoginEnd = _this.onLoginEnd;
if (onLoginEnd && typeof onLoginEnd === 'function') {
onLoginEnd(user);
}
resolve({
error: "",
token: _this.createTokenFromUser(user)
});
})({ query: args }); // fake req.query using args from graphQL
});
},
apUpdateUserPassword: function apUpdateUserPassword(root, _ref6, context) {
var userId = _ref6.userId,
oldPassword = _ref6.oldPassword,
newPassword = _ref6.newPassword;
var user, storedPassword, match, onUpdatePasswordEnd;
return regeneratorRuntime.async(function apUpdateUserPassword$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
if (context && context.auth && context.auth.userId === userId) {
_context5.next = 2;
break;
}
return _context5.abrupt("return", "Not logged in as " + userId);
case 2:
_context5.next = 4;
return regeneratorRuntime.awrap(this.db.fetchUserById(userId));
case 4:
user = _context5.sent;
if (user) {
_context5.next = 7;
break;
}
return _context5.abrupt("return", 'No such userId');
case 7:
console.log(user);
storedPassword = user && user.services && user.services.password && user.services.password.bcrypt;
console.log('storedPassword', storedPassword);
// TODO allow no password only if email set. allow email as part of query?
if (!storedPassword) {
_context5.next = 19;
break;
}
_context5.next = 13;
return regeneratorRuntime.awrap(this.comparePassword(oldPassword, storedPassword));
case 13:
match = _context5.sent;
console.log('match', match);
if (match) {
_context5.next = 17;
break;
}
return _context5.abrupt("return", "Invalid old password");
case 17:
_context5.next = 20;
break;
case 19:
return _context5.abrupt("return", "No old password set");
case 20:
_context5.prev = 20;
_context5.t0 = regeneratorRuntime;
_context5.t1 = this.db;
_context5.t2 = userId;
_context5.next = 26;
return regeneratorRuntime.awrap(this.hashPassword(newPassword));
case 26:
_context5.t3 = _context5.sent;
_context5.t4 = {
bcrypt: _context5.t3
};
_context5.t5 = _context5.t1.assertUserServiceData.call(_context5.t1, _context5.t2, 'password', _context5.t4);
_context5.next = 31;
return _context5.t0.awrap.call(_context5.t0, _context5.t5);
case 31:
_context5.next = 36;
break;
case 33:
_context5.prev = 33;
_context5.t6 = _context5["catch"](20);
return _context5.abrupt("return", _context5.t6.message);
case 36:
onUpdatePasswordEnd = this.onUpdatePasswordEnd;
if (onUpdatePasswordEnd && typeof onUpdatePasswordEnd === 'function') {
onUpdatePasswordEnd(user);
}
return _context5.abrupt("return", "");
case 39:
case "end":
return _context5.stop();
}
}
}, null, this, [[20, 33]]);
}
}
};
exports.default = resolvers;