{"version":3,"sources":["meteor://💻app/packages/accounts-password/email_templates.js","meteor://💻app/packages/accounts-password/password_server.js"],"names":["greet","welcomeMsg","user","url","greeting","profile","name","Accounts","emailTemplates","from","siteName","Meteor","absoluteUrl","replace","resetPassword","subject","text","verifyEmail","enrollAccount","bcrypt","NpmModuleBcrypt","bcryptHash","wrapAsync","hash","bcryptCompare","compare","getUserById","id","users","findOne","_bcryptRounds","_options","bcryptRounds","getPasswordString","password","SHA256","algorithm","Error","digest","hashPassword","getRoundsFromBcryptHash","rounds","hashSegments","split","length","parseInt","_checkPassword","result","userId","_id","formattedPassword","services","hashRounds","error","handleError","defer","update","$set","checkPassword","msg","throwError","ambiguousErrorMessages","_findUserByQuery","query","fieldName","fieldValue","username","email","selector","selectorForFastCaseInsensitiveLookup","candidateUsers","find","fetch","findUserByUsername","findUserByEmail","string","prefix","substring","Math","min","orClause","generateCasePermutationsForString","map","prefixPermutation","RegExp","_escapeRegExp","caseInsensitiveClause","$and","$or","permutations","i","ch","charAt","concat","lowerCaseChar","toLowerCase","upperCaseChar","toUpperCase","checkForCaseInsensitiveDuplicates","displayName","ownUserId","skipCheck","Object","prototype","hasOwnProperty","call","_skipCaseInsensitiveChecksForTest","matchedUsers","NonEmptyString","Match","Where","x","check","String","userQueryValidator","Optional","keys","passwordValidator","OneOf","registerLoginHandler","options","srp","undefined","verifier","newVerifier","SRP","generateVerifier","identity","salt","EJSON","stringify","format","v1","v2","hashedIdentityAndPassword","salted","$unset","setUsername","newUsername","oldUsername","ex","methods","changePassword","oldPassword","newPassword","hashed","currentToken","_getLoginToken","connection","$pull","hashedToken","$ne","passwordChanged","setPassword","newPlaintextPassword","logout","pluckAddresses","emails","address","forgotPassword","caseSensitiveEmail","sendResetPasswordEmail","generateResetToken","reason","extraTokenData","includes","token","Random","secret","tokenRecord","when","Date","assign","_ensure","reset","generateVerificationToken","emailRecord","e","verified","$push","verificationTokens","push","generateOptionsForEmail","to","html","headers","realEmail","urls","Email","send","sendEnrollmentEmail","args","_loginMethod","tokenLifetimeMs","_getPasswordResetTokenLifetimeMs","_getPasswordEnrollTokenLifetimeMs","currentTimeMs","now","oldToken","_setLoginToken","resetToOldToken","affectedRecords","err","_clearAllLoginTokens","sendVerificationEmail","t","emailsRecord","addEmail","newEmail","Boolean","caseInsensitiveRegExp","didUpdateOwnEmail","reduce","prev","test","$addToSet","removeEmail","createUser","ObjectIncluding","insertUserDoc","remove","forbidClientAccountCreation","callback","_ensureIndex","unique","sparse"],"mappings":"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","file":"/packages/accounts-password.js","sourcesContent":["const greet = welcomeMsg => (user, url) => {\n const greeting = (user.profile && user.profile.name) ?\n (`Hello ${user.profile.name},`) : \"Hello,\";\n return `${greeting}\n\n${welcomeMsg}, simply click the link below.\n\n${url}\n\nThanks.\n`;\n};\n\n/**\n * @summary Options to customize emails sent from the Accounts system.\n * @locus Server\n * @importFromPackage accounts-base\n */\nAccounts.emailTemplates = {\n from: \"Accounts Example \",\n siteName: Meteor.absoluteUrl().replace(/^https?:\\/\\//, '').replace(/\\/$/, ''),\n\n resetPassword: {\n subject: () => `How to reset your password on ${Accounts.emailTemplates.siteName}`,\n text: greet(\"To reset your password\"),\n },\n verifyEmail: {\n subject: () => `How to verify email address on ${Accounts.emailTemplates.siteName}`,\n text: greet(\"To verify your account email\"),\n },\n enrollAccount: {\n subject: () => `An account has been created for you on ${Accounts.emailTemplates.siteName}`,\n text: greet(\"To start using the service\"),\n },\n};\n","/// BCRYPT\n\nconst bcrypt = NpmModuleBcrypt;\nconst bcryptHash = Meteor.wrapAsync(bcrypt.hash);\nconst bcryptCompare = Meteor.wrapAsync(bcrypt.compare);\n\n// Utility for grabbing user\nconst getUserById = id => Meteor.users.findOne(id);\n\n// User records have a 'services.password.bcrypt' field on them to hold\n// their hashed passwords (unless they have a 'services.password.srp'\n// field, in which case they will be upgraded to bcrypt the next time\n// they log in).\n//\n// When the client sends a password to the server, it can either be a\n// string (the plaintext password) or an object with keys 'digest' and\n// 'algorithm' (must be \"sha-256\" for now). The Meteor client always sends\n// password objects { digest: *, algorithm: \"sha-256\" }, but DDP clients\n// that don't have access to SHA can just send plaintext passwords as\n// strings.\n//\n// When the server receives a plaintext password as a string, it always\n// hashes it with SHA256 before passing it into bcrypt. When the server\n// receives a password as an object, it asserts that the algorithm is\n// \"sha-256\" and then passes the digest to bcrypt.\n\n\nAccounts._bcryptRounds = () => Accounts._options.bcryptRounds || 10;\n\n// Given a 'password' from the client, extract the string that we should\n// bcrypt. 'password' can be one of:\n// - String (the plaintext password)\n// - Object with 'digest' and 'algorithm' keys. 'algorithm' must be \"sha-256\".\n//\nconst getPasswordString = password => {\n if (typeof password === \"string\") {\n password = SHA256(password);\n } else { // 'password' is an object\n if (password.algorithm !== \"sha-256\") {\n throw new Error(\"Invalid password hash algorithm. \" +\n \"Only 'sha-256' is allowed.\");\n }\n password = password.digest;\n }\n return password;\n};\n\n// Use bcrypt to hash the password for storage in the database.\n// `password` can be a string (in which case it will be run through\n// SHA256 before bcrypt) or an object with properties `digest` and\n// `algorithm` (in which case we bcrypt `password.digest`).\n//\nconst hashPassword = password => {\n password = getPasswordString(password);\n return bcryptHash(password, Accounts._bcryptRounds());\n};\n\n// Extract the number of rounds used in the specified bcrypt hash.\nconst getRoundsFromBcryptHash = hash => {\n let rounds;\n if (hash) {\n const hashSegments = hash.split('$');\n if (hashSegments.length > 2) {\n rounds = parseInt(hashSegments[2], 10);\n }\n }\n return rounds;\n};\n\n// Check whether the provided password matches the bcrypt'ed password in\n// the database user record. `password` can be a string (in which case\n// it will be run through SHA256 before bcrypt) or an object with\n// properties `digest` and `algorithm` (in which case we bcrypt\n// `password.digest`).\n//\nAccounts._checkPassword = (user, password) => {\n const result = {\n userId: user._id\n };\n\n const formattedPassword = getPasswordString(password);\n const hash = user.services.password.bcrypt;\n const hashRounds = getRoundsFromBcryptHash(hash);\n\n if (! bcryptCompare(formattedPassword, hash)) {\n result.error = handleError(\"Incorrect password\", false);\n } else if (hash && Accounts._bcryptRounds() != hashRounds) {\n // The password checks out, but the user's bcrypt hash needs to be updated.\n Meteor.defer(() => {\n Meteor.users.update({ _id: user._id }, {\n $set: {\n 'services.password.bcrypt':\n bcryptHash(formattedPassword, Accounts._bcryptRounds())\n }\n });\n });\n }\n\n return result;\n};\nconst checkPassword = Accounts._checkPassword;\n\n///\n/// ERROR HANDLER\n///\nconst handleError = (msg, throwError = true) => {\n const error = new Meteor.Error(\n 403,\n Accounts._options.ambiguousErrorMessages\n ? \"Something went wrong. Please check your credentials.\"\n : msg\n );\n if (throwError) {\n throw error;\n }\n return error;\n};\n\n///\n/// LOGIN\n///\n\nAccounts._findUserByQuery = query => {\n let user = null;\n\n if (query.id) {\n user = getUserById(query.id);\n } else {\n let fieldName;\n let fieldValue;\n if (query.username) {\n fieldName = 'username';\n fieldValue = query.username;\n } else if (query.email) {\n fieldName = 'emails.address';\n fieldValue = query.email;\n } else {\n throw new Error(\"shouldn't happen (validation missed something)\");\n }\n let selector = {};\n selector[fieldName] = fieldValue;\n user = Meteor.users.findOne(selector);\n // If user is not found, try a case insensitive lookup\n if (!user) {\n selector = selectorForFastCaseInsensitiveLookup(fieldName, fieldValue);\n const candidateUsers = Meteor.users.find(selector).fetch();\n // No match if multiple candidates are found\n if (candidateUsers.length === 1) {\n user = candidateUsers[0];\n }\n }\n }\n\n return user;\n};\n\n/**\n * @summary Finds the user with the specified username.\n * First tries to match username case sensitively; if that fails, it\n * tries case insensitively; but if more than one user matches the case\n * insensitive search, it returns null.\n * @locus Server\n * @param {String} username The username to look for\n * @returns {Object} A user if found, else null\n * @importFromPackage accounts-base\n */\nAccounts.findUserByUsername = \n username => Accounts._findUserByQuery({ username });\n\n/**\n * @summary Finds the user with the specified email.\n * First tries to match email case sensitively; if that fails, it\n * tries case insensitively; but if more than one user matches the case\n * insensitive search, it returns null.\n * @locus Server\n * @param {String} email The email address to look for\n * @returns {Object} A user if found, else null\n * @importFromPackage accounts-base\n */\nAccounts.findUserByEmail = email => Accounts._findUserByQuery({ email });\n\n// Generates a MongoDB selector that can be used to perform a fast case\n// insensitive lookup for the given fieldName and string. Since MongoDB does\n// not support case insensitive indexes, and case insensitive regex queries\n// are slow, we construct a set of prefix selectors for all permutations of\n// the first 4 characters ourselves. We first attempt to matching against\n// these, and because 'prefix expression' regex queries do use indexes (see\n// http://docs.mongodb.org/v2.6/reference/operator/query/regex/#index-use),\n// this has been found to greatly improve performance (from 1200ms to 5ms in a\n// test with 1.000.000 users).\nconst selectorForFastCaseInsensitiveLookup = (fieldName, string) => {\n // Performance seems to improve up to 4 prefix characters\n const prefix = string.substring(0, Math.min(string.length, 4));\n const orClause = generateCasePermutationsForString(prefix).map(\n prefixPermutation => {\n const selector = {};\n selector[fieldName] =\n new RegExp(`^${Meteor._escapeRegExp(prefixPermutation)}`);\n return selector;\n });\n const caseInsensitiveClause = {};\n caseInsensitiveClause[fieldName] =\n new RegExp(`^${Meteor._escapeRegExp(string)}$`, 'i')\n return {$and: [{$or: orClause}, caseInsensitiveClause]};\n}\n\n// Generates permutations of all case variations of a given string.\nconst generateCasePermutationsForString = string => {\n let permutations = [''];\n for (let i = 0; i < string.length; i++) {\n const ch = string.charAt(i);\n permutations = [].concat(...(permutations.map(prefix => {\n const lowerCaseChar = ch.toLowerCase();\n const upperCaseChar = ch.toUpperCase();\n // Don't add unneccesary permutations when ch is not a letter\n if (lowerCaseChar === upperCaseChar) {\n return [prefix + ch];\n } else {\n return [prefix + lowerCaseChar, prefix + upperCaseChar];\n }\n })));\n }\n return permutations;\n}\n\nconst checkForCaseInsensitiveDuplicates = (fieldName, displayName, fieldValue, ownUserId) => {\n // Some tests need the ability to add users with the same case insensitive\n // value, hence the _skipCaseInsensitiveChecksForTest check\n const skipCheck = Object.prototype.hasOwnProperty.call(Accounts._skipCaseInsensitiveChecksForTest, fieldValue);\n\n if (fieldValue && !skipCheck) {\n const matchedUsers = Meteor.users.find(\n selectorForFastCaseInsensitiveLookup(fieldName, fieldValue)).fetch();\n\n if (matchedUsers.length > 0 &&\n // If we don't have a userId yet, any match we find is a duplicate\n (!ownUserId ||\n // Otherwise, check to see if there are multiple matches or a match\n // that is not us\n (matchedUsers.length > 1 || matchedUsers[0]._id !== ownUserId))) {\n handleError(`${displayName} already exists.`);\n }\n }\n};\n\n// XXX maybe this belongs in the check package\nconst NonEmptyString = Match.Where(x => {\n check(x, String);\n return x.length > 0;\n});\n\nconst userQueryValidator = Match.Where(user => {\n check(user, {\n id: Match.Optional(NonEmptyString),\n username: Match.Optional(NonEmptyString),\n email: Match.Optional(NonEmptyString)\n });\n if (Object.keys(user).length !== 1)\n throw new Match.Error(\"User property must have exactly one field\");\n return true;\n});\n\nconst passwordValidator = Match.OneOf(\n String,\n { digest: String, algorithm: String }\n);\n\n// Handler to login with a password.\n//\n// The Meteor client sets options.password to an object with keys\n// 'digest' (set to SHA256(password)) and 'algorithm' (\"sha-256\").\n//\n// For other DDP clients which don't have access to SHA, the handler\n// also accepts the plaintext password in options.password as a string.\n//\n// (It might be nice if servers could turn the plaintext password\n// option off. Or maybe it should be opt-in, not opt-out?\n// Accounts.config option?)\n//\n// Note that neither password option is secure without SSL.\n//\nAccounts.registerLoginHandler(\"password\", options => {\n if (! options.password || options.srp)\n return undefined; // don't handle\n\n check(options, {\n user: userQueryValidator,\n password: passwordValidator\n });\n\n\n const user = Accounts._findUserByQuery(options.user);\n if (!user) {\n handleError(\"User not found\");\n }\n\n if (!user.services || !user.services.password ||\n !(user.services.password.bcrypt || user.services.password.srp)) {\n handleError(\"User has no password set\");\n }\n\n if (!user.services.password.bcrypt) {\n if (typeof options.password === \"string\") {\n // The client has presented a plaintext password, and the user is\n // not upgraded to bcrypt yet. We don't attempt to tell the client\n // to upgrade to bcrypt, because it might be a standalone DDP\n // client doesn't know how to do such a thing.\n const verifier = user.services.password.srp;\n const newVerifier = SRP.generateVerifier(options.password, {\n identity: verifier.identity, salt: verifier.salt});\n\n if (verifier.verifier !== newVerifier.verifier) {\n return {\n userId: Accounts._options.ambiguousErrorMessages ? null : user._id,\n error: handleError(\"Incorrect password\", false)\n };\n }\n\n return {userId: user._id};\n } else {\n // Tell the client to use the SRP upgrade process.\n throw new Meteor.Error(400, \"old password format\", EJSON.stringify({\n format: 'srp',\n identity: user.services.password.srp.identity\n }));\n }\n }\n\n return checkPassword(\n user,\n options.password\n );\n});\n\n// Handler to login using the SRP upgrade path. To use this login\n// handler, the client must provide:\n// - srp: H(identity + \":\" + password)\n// - password: a string or an object with properties 'digest' and 'algorithm'\n//\n// We use `options.srp` to verify that the client knows the correct\n// password without doing a full SRP flow. Once we've checked that, we\n// upgrade the user to bcrypt and remove the SRP information from the\n// user document.\n//\n// The client ends up using this login handler after trying the normal\n// login handler (above), which throws an error telling the client to\n// try the SRP upgrade path.\n//\n// XXX COMPAT WITH 0.8.1.3\nAccounts.registerLoginHandler(\"password\", options => {\n if (!options.srp || !options.password) {\n return undefined; // don't handle\n }\n\n check(options, {\n user: userQueryValidator,\n srp: String,\n password: passwordValidator\n });\n\n const user = Accounts._findUserByQuery(options.user);\n if (!user) {\n handleError(\"User not found\");\n }\n\n // Check to see if another simultaneous login has already upgraded\n // the user record to bcrypt.\n if (user.services && user.services.password && user.services.password.bcrypt) {\n return checkPassword(user, options.password);\n }\n\n if (!(user.services && user.services.password && user.services.password.srp)) {\n handleError(\"User has no password set\");\n }\n\n const v1 = user.services.password.srp.verifier;\n const v2 = SRP.generateVerifier(\n null,\n {\n hashedIdentityAndPassword: options.srp,\n salt: user.services.password.srp.salt\n }\n ).verifier;\n if (v1 !== v2) {\n return {\n userId: Accounts._options.ambiguousErrorMessages ? null : user._id,\n error: handleError(\"Incorrect password\", false)\n };\n }\n\n // Upgrade to bcrypt on successful login.\n const salted = hashPassword(options.password);\n Meteor.users.update(\n user._id,\n {\n $unset: { 'services.password.srp': 1 },\n $set: { 'services.password.bcrypt': salted }\n }\n );\n\n return {userId: user._id};\n});\n\n\n///\n/// CHANGING\n///\n\n/**\n * @summary Change a user's username. Use this instead of updating the\n * database directly. The operation will fail if there is an existing user\n * with a username only differing in case.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} newUsername A new username for the user.\n * @importFromPackage accounts-base\n */\nAccounts.setUsername = (userId, newUsername) => {\n check(userId, NonEmptyString);\n check(newUsername, NonEmptyString);\n\n const user = getUserById(userId);\n if (!user) {\n handleError(\"User not found\");\n }\n\n const oldUsername = user.username;\n\n // Perform a case insensitive check for duplicates before update\n checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);\n\n Meteor.users.update({_id: user._id}, {$set: {username: newUsername}});\n\n // Perform another check after update, in case a matching user has been\n // inserted in the meantime\n try {\n checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);\n } catch (ex) {\n // Undo update if the check fails\n Meteor.users.update({_id: user._id}, {$set: {username: oldUsername}});\n throw ex;\n }\n};\n\n// Let the user change their own password if they know the old\n// password. `oldPassword` and `newPassword` should be objects with keys\n// `digest` and `algorithm` (representing the SHA256 of the password).\n//\n// XXX COMPAT WITH 0.8.1.3\n// Like the login method, if the user hasn't been upgraded from SRP to\n// bcrypt yet, then this method will throw an 'old password format'\n// error. The client should call the SRP upgrade login handler and then\n// retry this method again.\n//\n// UNLIKE the login method, there is no way to avoid getting SRP upgrade\n// errors thrown. The reasoning for this is that clients using this\n// method directly will need to be updated anyway because we no longer\n// support the SRP flow that they would have been doing to use this\n// method previously.\nMeteor.methods({changePassword: function (oldPassword, newPassword) {\n check(oldPassword, passwordValidator);\n check(newPassword, passwordValidator);\n\n if (!this.userId) {\n throw new Meteor.Error(401, \"Must be logged in\");\n }\n\n const user = getUserById(this.userId);\n if (!user) {\n handleError(\"User not found\");\n }\n\n if (!user.services || !user.services.password ||\n (!user.services.password.bcrypt && !user.services.password.srp)) {\n handleError(\"User has no password set\");\n }\n\n if (! user.services.password.bcrypt) {\n throw new Meteor.Error(400, \"old password format\", EJSON.stringify({\n format: 'srp',\n identity: user.services.password.srp.identity\n }));\n }\n\n const result = checkPassword(user, oldPassword);\n if (result.error) {\n throw result.error;\n }\n\n const hashed = hashPassword(newPassword);\n\n // It would be better if this removed ALL existing tokens and replaced\n // the token for the current connection with a new one, but that would\n // be tricky, so we'll settle for just replacing all tokens other than\n // the one for the current connection.\n const currentToken = Accounts._getLoginToken(this.connection.id);\n Meteor.users.update(\n { _id: this.userId },\n {\n $set: { 'services.password.bcrypt': hashed },\n $pull: {\n 'services.resume.loginTokens': { hashedToken: { $ne: currentToken } }\n },\n $unset: { 'services.password.reset': 1 }\n }\n );\n\n return {passwordChanged: true};\n}});\n\n\n// Force change the users password.\n\n/**\n * @summary Forcibly change the password for a user.\n * @locus Server\n * @param {String} userId The id of the user to update.\n * @param {String} newPassword A new password for the user.\n * @param {Object} [options]\n * @param {Object} options.logout Logout all current connections with this userId (default: true)\n * @importFromPackage accounts-base\n */\nAccounts.setPassword = (userId, newPlaintextPassword, options) => {\n options = { logout: true , ...options };\n\n const user = getUserById(userId);\n if (!user) {\n throw new Meteor.Error(403, \"User not found\");\n }\n\n const update = {\n $unset: {\n 'services.password.srp': 1, // XXX COMPAT WITH 0.8.1.3\n 'services.password.reset': 1\n },\n $set: {'services.password.bcrypt': hashPassword(newPlaintextPassword)}\n };\n\n if (options.logout) {\n update.$unset['services.resume.loginTokens'] = 1;\n }\n\n Meteor.users.update({_id: user._id}, update);\n};\n\n\n///\n/// RESETTING VIA EMAIL\n///\n\n// Utility for plucking addresses from emails\nconst pluckAddresses = (emails = []) => emails.map(email => email.address);\n\n// Method called by a user to request a password reset email. This is\n// the start of the reset process.\nMeteor.methods({forgotPassword: options => {\n check(options, {email: String});\n\n const user = Accounts.findUserByEmail(options.email);\n if (!user) {\n handleError(\"User not found\");\n }\n\n const emails = pluckAddresses(user.emails);\n const caseSensitiveEmail = emails.find(\n email => email.toLowerCase() === options.email.toLowerCase()\n );\n\n Accounts.sendResetPasswordEmail(user._id, caseSensitiveEmail);\n}});\n\n/**\n * @summary Generates a reset token and saves it into the database.\n * @locus Server\n * @param {String} userId The id of the user to generate the reset token for.\n * @param {String} email Which address of the user to generate the reset token for. This address must be in the user's `emails` list. If `null`, defaults to the first email in the list.\n * @param {String} reason `resetPassword` or `enrollAccount`.\n * @param {Object} [extraTokenData] Optional additional data to be added into the token record.\n * @returns {Object} Object with {email, user, token} values.\n * @importFromPackage accounts-base\n */\nAccounts.generateResetToken = (userId, email, reason, extraTokenData) => {\n // Make sure the user exists, and email is one of their addresses.\n const user = getUserById(userId);\n if (!user) {\n handleError(\"Can't find user\");\n }\n\n // pick the first email if we weren't passed an email.\n if (!email && user.emails && user.emails[0]) {\n email = user.emails[0].address;\n }\n\n // make sure we have a valid email\n if (!email || \n !(pluckAddresses(user.emails).includes(email))) {\n handleError(\"No such email for user.\");\n }\n\n const token = Random.secret();\n const tokenRecord = {\n token,\n email,\n when: new Date()\n };\n\n if (reason === 'resetPassword') {\n tokenRecord.reason = 'reset';\n } else if (reason === 'enrollAccount') {\n tokenRecord.reason = 'enroll';\n } else if (reason) {\n // fallback so that this function can be used for unknown reasons as well\n tokenRecord.reason = reason;\n }\n\n if (extraTokenData) {\n Object.assign(tokenRecord, extraTokenData);\n }\n\n Meteor.users.update({_id: user._id}, {$set: {\n 'services.password.reset': tokenRecord\n }});\n\n // before passing to template, update user object with new token\n Meteor._ensure(user, 'services', 'password').reset = tokenRecord;\n\n return {email, user, token};\n};\n\n/**\n * @summary Generates an e-mail verification token and saves it into the database.\n * @locus Server\n * @param {String} userId The id of the user to generate the e-mail verification token for.\n * @param {String} email Which address of the user to generate the e-mail verification token for. This address must be in the user's `emails` list. If `null`, defaults to the first unverified email in the list.\n * @param {Object} [extraTokenData] Optional additional data to be added into the token record.\n * @returns {Object} Object with {email, user, token} values.\n * @importFromPackage accounts-base\n */\nAccounts.generateVerificationToken = (userId, email, extraTokenData) => {\n // Make sure the user exists, and email is one of their addresses.\n const user = getUserById(userId);\n if (!user) {\n handleError(\"Can't find user\");\n }\n\n // pick the first unverified email if we weren't passed an email.\n if (!email) {\n const emailRecord = (user.emails || []).find(e => !e.verified);\n email = (emailRecord || {}).address;\n\n if (!email) {\n handleError(\"That user has no unverified email addresses.\");\n }\n }\n\n // make sure we have a valid email\n if (!email || \n !(pluckAddresses(user.emails).includes(email))) {\n handleError(\"No such email for user.\");\n }\n\n const token = Random.secret();\n const tokenRecord = {\n token,\n // TODO: This should probably be renamed to \"email\" to match reset token record.\n address: email,\n when: new Date()\n };\n\n if (extraTokenData) {\n Object.assign(tokenRecord, extraTokenData);\n }\n\n Meteor.users.update({_id: user._id}, {$push: {\n 'services.email.verificationTokens': tokenRecord\n }});\n\n // before passing to template, update user object with new token\n Meteor._ensure(user, 'services', 'email');\n if (!user.services.email.verificationTokens) {\n user.services.email.verificationTokens = [];\n }\n user.services.email.verificationTokens.push(tokenRecord);\n\n return {email, user, token};\n};\n\n/**\n * @summary Creates options for email sending for reset password and enroll account emails.\n * You can use this function when customizing a reset password or enroll account email sending.\n * @locus Server\n * @param {Object} email Which address of the user's to send the email to.\n * @param {Object} user The user object to generate options for.\n * @param {String} url URL to which user is directed to confirm the email.\n * @param {String} reason `resetPassword` or `enrollAccount`.\n * @returns {Object} Options which can be passed to `Email.send`.\n * @importFromPackage accounts-base\n */\nAccounts.generateOptionsForEmail = (email, user, url, reason) => {\n const options = {\n to: email,\n from: Accounts.emailTemplates[reason].from\n ? Accounts.emailTemplates[reason].from(user)\n : Accounts.emailTemplates.from,\n subject: Accounts.emailTemplates[reason].subject(user)\n };\n\n if (typeof Accounts.emailTemplates[reason].text === 'function') {\n options.text = Accounts.emailTemplates[reason].text(user, url);\n }\n\n if (typeof Accounts.emailTemplates[reason].html === 'function') {\n options.html = Accounts.emailTemplates[reason].html(user, url);\n }\n\n if (typeof Accounts.emailTemplates.headers === 'object') {\n options.headers = Accounts.emailTemplates.headers;\n }\n\n return options;\n};\n\n// send the user an email with a link that when opened allows the user\n// to set a new password, without the old password.\n\n/**\n * @summary Send an email with a link the user can use to reset their password.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list.\n * @param {Object} [extraTokenData] Optional additional data to be added into the token record.\n * @returns {Object} Object with {email, user, token, url, options} values.\n * @importFromPackage accounts-base\n */\nAccounts.sendResetPasswordEmail = (userId, email, extraTokenData) => {\n const {email: realEmail, user, token} =\n Accounts.generateResetToken(userId, email, 'resetPassword', extraTokenData);\n const url = Accounts.urls.resetPassword(token);\n const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'resetPassword');\n Email.send(options);\n return {email: realEmail, user, token, url, options};\n};\n\n// send the user an email informing them that their account was created, with\n// a link that when opened both marks their email as verified and forces them\n// to choose their password. The email must be one of the addresses in the\n// user's emails field, or undefined to pick the first email automatically.\n//\n// This is not called automatically. It must be called manually if you\n// want to use enrollment emails.\n\n/**\n * @summary Send an email with a link the user can use to set their initial password.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list.\n * @param {Object} [extraTokenData] Optional additional data to be added into the token record.\n * @returns {Object} Object with {email, user, token, url, options} values.\n * @importFromPackage accounts-base\n */\nAccounts.sendEnrollmentEmail = (userId, email, extraTokenData) => {\n const {email: realEmail, user, token} =\n Accounts.generateResetToken(userId, email, 'enrollAccount', extraTokenData);\n const url = Accounts.urls.enrollAccount(token);\n const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'enrollAccount');\n Email.send(options);\n return {email: realEmail, user, token, url, options};\n};\n\n\n// Take token from sendResetPasswordEmail or sendEnrollmentEmail, change\n// the users password, and log them in.\nMeteor.methods({resetPassword: function (...args) {\n const token = args[0];\n const newPassword = args[1];\n return Accounts._loginMethod(\n this,\n \"resetPassword\",\n args,\n \"password\",\n () => {\n check(token, String);\n check(newPassword, passwordValidator);\n\n const user = Meteor.users.findOne({\n \"services.password.reset.token\": token});\n if (!user) {\n throw new Meteor.Error(403, \"Token expired\");\n }\n const { when, reason, email } = user.services.password.reset;\n let tokenLifetimeMs = Accounts._getPasswordResetTokenLifetimeMs();\n if (reason === \"enroll\") {\n tokenLifetimeMs = Accounts._getPasswordEnrollTokenLifetimeMs();\n }\n const currentTimeMs = Date.now();\n if ((currentTimeMs - when) > tokenLifetimeMs)\n throw new Meteor.Error(403, \"Token expired\");\n if (!(pluckAddresses(user.emails).includes(email)))\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Token has invalid email address\")\n };\n\n const hashed = hashPassword(newPassword);\n\n // NOTE: We're about to invalidate tokens on the user, who we might be\n // logged in as. Make sure to avoid logging ourselves out if this\n // happens. But also make sure not to leave the connection in a state\n // of having a bad token set if things fail.\n const oldToken = Accounts._getLoginToken(this.connection.id);\n Accounts._setLoginToken(user._id, this.connection, null);\n const resetToOldToken = () =>\n Accounts._setLoginToken(user._id, this.connection, oldToken);\n\n try {\n // Update the user record by:\n // - Changing the password to the new one\n // - Forgetting about the reset token that was just used\n // - Verifying their email, since they got the password reset via email.\n const affectedRecords = Meteor.users.update(\n {\n _id: user._id,\n 'emails.address': email,\n 'services.password.reset.token': token\n },\n {$set: {'services.password.bcrypt': hashed,\n 'emails.$.verified': true},\n $unset: {'services.password.reset': 1,\n 'services.password.srp': 1}});\n if (affectedRecords !== 1)\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Invalid email\")\n };\n } catch (err) {\n resetToOldToken();\n throw err;\n }\n\n // Replace all valid login tokens with new ones (changing\n // password should invalidate existing sessions).\n Accounts._clearAllLoginTokens(user._id);\n\n return {userId: user._id};\n }\n );\n}});\n\n///\n/// EMAIL VERIFICATION\n///\n\n\n// send the user an email with a link that when opened marks that\n// address as verified\n\n/**\n * @summary Send an email with a link the user can use verify their email address.\n * @locus Server\n * @param {String} userId The id of the user to send email to.\n * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first unverified email in the list.\n * @param {Object} [extraTokenData] Optional additional data to be added into the token record.\n * @returns {Object} Object with {email, user, token, url, options} values.\n * @importFromPackage accounts-base\n */\nAccounts.sendVerificationEmail = (userId, email, extraTokenData) => {\n // XXX Also generate a link using which someone can delete this\n // account if they own said address but weren't those who created\n // this account.\n\n const {email: realEmail, user, token} =\n Accounts.generateVerificationToken(userId, email, extraTokenData);\n const url = Accounts.urls.verifyEmail(token);\n const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'verifyEmail');\n Email.send(options);\n return {email: realEmail, user, token, url, options};\n};\n\n// Take token from sendVerificationEmail, mark the email as verified,\n// and log them in.\nMeteor.methods({verifyEmail: function (...args) {\n const token = args[0];\n return Accounts._loginMethod(\n this,\n \"verifyEmail\",\n args,\n \"password\",\n () => {\n check(token, String);\n\n const user = Meteor.users.findOne(\n {'services.email.verificationTokens.token': token});\n if (!user)\n throw new Meteor.Error(403, \"Verify email link expired\");\n\n const tokenRecord = user.services.email.verificationTokens.find(\n t => t.token == token\n );\n if (!tokenRecord)\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Verify email link expired\")\n };\n\n const emailsRecord = user.emails.find(\n e => e.address == tokenRecord.address\n );\n if (!emailsRecord)\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Verify email link is for unknown address\")\n };\n\n // By including the address in the query, we can use 'emails.$' in the\n // modifier to get a reference to the specific object in the emails\n // array. See\n // http://www.mongodb.org/display/DOCS/Updating/#Updating-The%24positionaloperator)\n // http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull\n Meteor.users.update(\n {_id: user._id,\n 'emails.address': tokenRecord.address},\n {$set: {'emails.$.verified': true},\n $pull: {'services.email.verificationTokens': {address: tokenRecord.address}}});\n\n return {userId: user._id};\n }\n );\n}});\n\n/**\n * @summary Add an email address for a user. Use this instead of directly\n * updating the database. The operation will fail if there is a different user\n * with an email only differing in case. If the specified user has an existing\n * email only differing in case however, we replace it.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} newEmail A new email address for the user.\n * @param {Boolean} [verified] Optional - whether the new email address should\n * be marked as verified. Defaults to false.\n * @importFromPackage accounts-base\n */\nAccounts.addEmail = (userId, newEmail, verified) => {\n check(userId, NonEmptyString);\n check(newEmail, NonEmptyString);\n check(verified, Match.Optional(Boolean));\n\n if (verified === void 0) {\n verified = false;\n }\n\n const user = getUserById(userId);\n if (!user)\n throw new Meteor.Error(403, \"User not found\");\n\n // Allow users to change their own email to a version with a different case\n\n // We don't have to call checkForCaseInsensitiveDuplicates to do a case\n // insensitive check across all emails in the database here because: (1) if\n // there is no case-insensitive duplicate between this user and other users,\n // then we are OK and (2) if this would create a conflict with other users\n // then there would already be a case-insensitive duplicate and we can't fix\n // that in this code anyway.\n const caseInsensitiveRegExp =\n new RegExp(`^${Meteor._escapeRegExp(newEmail)}$`, 'i');\n\n const didUpdateOwnEmail = user.emails.reduce(\n (prev, email) => {\n if (caseInsensitiveRegExp.test(email.address)) {\n Meteor.users.update({\n _id: user._id,\n 'emails.address': email.address\n }, {$set: {\n 'emails.$.address': newEmail,\n 'emails.$.verified': verified\n }});\n return true;\n } else {\n return prev;\n }\n }, \n false\n );\n\n // In the other updates below, we have to do another call to\n // checkForCaseInsensitiveDuplicates to make sure that no conflicting values\n // were added to the database in the meantime. We don't have to do this for\n // the case where the user is updating their email address to one that is the\n // same as before, but only different because of capitalization. Read the\n // big comment above to understand why.\n\n if (didUpdateOwnEmail) {\n return;\n }\n\n // Perform a case insensitive check for duplicates before update\n checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);\n\n Meteor.users.update({\n _id: user._id\n }, {\n $addToSet: {\n emails: {\n address: newEmail,\n verified: verified\n }\n }\n });\n\n // Perform another check after update, in case a matching user has been\n // inserted in the meantime\n try {\n checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);\n } catch (ex) {\n // Undo update if the check fails\n Meteor.users.update({_id: user._id},\n {$pull: {emails: {address: newEmail}}});\n throw ex;\n }\n}\n\n/**\n * @summary Remove an email address for a user. Use this instead of updating\n * the database directly.\n * @locus Server\n * @param {String} userId The ID of the user to update.\n * @param {String} email The email address to remove.\n * @importFromPackage accounts-base\n */\nAccounts.removeEmail = (userId, email) => {\n check(userId, NonEmptyString);\n check(email, NonEmptyString);\n\n const user = getUserById(userId);\n if (!user)\n throw new Meteor.Error(403, \"User not found\");\n\n Meteor.users.update({_id: user._id},\n {$pull: {emails: {address: email}}});\n}\n\n///\n/// CREATING USERS\n///\n\n// Shared createUser function called from the createUser method, both\n// if originates in client or server code. Calls user provided hooks,\n// does the actual user insertion.\n//\n// returns the user id\nconst createUser = options => {\n // Unknown keys allowed, because a onCreateUserHook can take arbitrary\n // options.\n check(options, Match.ObjectIncluding({\n username: Match.Optional(String),\n email: Match.Optional(String),\n password: Match.Optional(passwordValidator)\n }));\n\n const { username, email, password } = options;\n if (!username && !email)\n throw new Meteor.Error(400, \"Need to set a username or email\");\n\n const user = {services: {}};\n if (password) {\n const hashed = hashPassword(password);\n user.services.password = { bcrypt: hashed };\n }\n\n if (username)\n user.username = username;\n if (email)\n user.emails = [{address: email, verified: false}];\n\n // Perform a case insensitive check before insert\n checkForCaseInsensitiveDuplicates('username', 'Username', username);\n checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);\n\n const userId = Accounts.insertUserDoc(options, user);\n // Perform another check after insert, in case a matching user has been\n // inserted in the meantime\n try {\n checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);\n checkForCaseInsensitiveDuplicates('emails.address', 'Email', email, userId);\n } catch (ex) {\n // Remove inserted user if the check fails\n Meteor.users.remove(userId);\n throw ex;\n }\n return userId;\n};\n\n// method for create user. Requests come from the client.\nMeteor.methods({createUser: function (...args) {\n const options = args[0];\n return Accounts._loginMethod(\n this,\n \"createUser\",\n args,\n \"password\",\n () => {\n // createUser() above does more checking.\n check(options, Object);\n if (Accounts._options.forbidClientAccountCreation)\n return {\n error: new Meteor.Error(403, \"Signups forbidden\")\n };\n\n // Create user. result contains id and token.\n const userId = createUser(options);\n // safety belt. createUser is supposed to throw on error. send 500 error\n // instead of sending a verification email with empty userid.\n if (! userId)\n throw new Error(\"createUser failed to insert new user\");\n\n // If `Accounts._options.sendVerificationEmail` is set, register\n // a token to verify the user's primary email, and send it to\n // that address.\n if (options.email && Accounts._options.sendVerificationEmail)\n Accounts.sendVerificationEmail(userId, options.email);\n\n // client gets logged in as the new user afterwards.\n return {userId: userId};\n }\n );\n}});\n\n// Create user directly on the server.\n//\n// Unlike the client version, this does not log you in as this user\n// after creation.\n//\n// returns userId or throws an error if it can't create\n//\n// XXX add another argument (\"server options\") that gets sent to onCreateUser,\n// which is always empty when called from the createUser method? eg, \"admin:\n// true\", which we want to prevent the client from setting, but which a custom\n// method calling Accounts.createUser could set?\n//\nAccounts.createUser = (options, callback) => {\n options = { ...options };\n\n // XXX allow an optional callback?\n if (callback) {\n throw new Error(\"Accounts.createUser with callback not supported on the server yet.\");\n }\n\n return createUser(options);\n};\n\n///\n/// PASSWORD-SPECIFIC INDEXES ON USERS\n///\nMeteor.users._ensureIndex('services.email.verificationTokens.token',\n {unique: 1, sparse: 1});\nMeteor.users._ensureIndex('services.password.reset.token',\n {unique: 1, sparse: 1});\n"]}