{"version":3,"sources":["meteor://💻app/packages/accounts-base/server_main.js","meteor://💻app/packages/accounts-base/accounts_common.js","meteor://💻app/packages/accounts-base/accounts_server.js"],"names":["module1","export","AccountsServer","link","v","Accounts","Meteor","server","users","_objectSpread","module","default","AccountsCommon","EXPIRE_TOKENS_INTERVAL_MS","CONNECTION_CLOSE_DELAY_MS","VALID_CONFIG_KEYS","constructor","options","_options","connection","undefined","_initConnection","Mongo","Collection","_preventAutopublish","_onLoginHook","Hook","bindEnvironment","debugPrintExceptions","_onLoginFailureHook","_onLogoutHook","DEFAULT_LOGIN_EXPIRATION_DAYS","LOGIN_UNEXPIRING_TOKEN_DAYS","lceName","LoginCancelledError","makeErrorType","description","message","prototype","name","numericError","startup","ServiceConfiguration","Package","loginServiceConfiguration","configurations","ConfigError","settings","packages","oauthSecretKey","Error","OAuthEncryption","loadKey","Object","keys","forEach","key","includes","userId","_addDefaultFieldSelector","defaultFieldSelector","fields","length","keys2","user","findOne","config","isServer","__meteor_runtime_config__","accountsConfigCalled","_debug","hasOwnProperty","call","isClient","onLogin","func","ret","register","_startupCallback","callback","onLoginFailure","onLogout","ddpUrl","DDP","connect","ACCOUNTS_CONNECTION_URL","_getTokenLifetimeMs","loginExpirationInDays","loginExpiration","_getPasswordResetTokenLifetimeMs","passwordResetTokenExpiration","passwordResetTokenExpirationInDays","DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS","_getPasswordEnrollTokenLifetimeMs","passwordEnrollTokenExpiration","passwordEnrollTokenExpirationInDays","DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS","_tokenExpiration","when","Date","getTime","_tokenExpiresSoon","minLifetimeMs","minLifetimeCapMs","MIN_TOKEN_LIFETIME_CAP_SECS","_objectWithoutProperties","crypto","URL","hasOwn","NonEmptyString","Match","Where","x","check","String","onCreateLoginToken","_onCreateLoginTokenHook","_selectorForFastCaseInsensitiveLookup","fieldName","string","prefix","substring","Math","min","orClause","generateCasePermutationsForString","map","prefixPermutation","selector","RegExp","_escapeRegExp","caseInsensitiveClause","$and","$or","_findUserByQuery","query","id","fieldValue","username","email","candidateUsers","find","fetch","_handleError","msg","throwError","errorCode","error","ambiguousErrorMessages","_userQueryValidator","Optional","_server","_initServerMethods","_initAccountDataHooks","_autopublishFields","loggedInUser","otherUsers","_defaultPublishFields","projection","profile","emails","_initServerPublications","_accountData","_userObservesForConnections","_nextUserObserveNumber","_loginHandlers","setupUsersCollection","setupDefaultLoginHandlers","setExpireTokensInterval","_validateLoginHook","_validateNewUserHooks","defaultValidateNewUserHook","bind","_deleteSavedTokensForAllUsersOnStartup","_skipCaseInsensitiveChecksForTest","urls","resetPassword","token","extraParams","buildEmailUrl","verifyEmail","loginToken","enrollAccount","addDefaultRateLimit","path","url","absoluteUrl","params","entries","value","searchParams","append","toString","currentInvocation","_CurrentMethodInvocation","get","_CurrentPublicationInvocation","validateLoginAttempt","validateNewUser","push","beforeExternalLogin","_beforeExternalLoginHook","onCreateUser","_onCreateUserHook","onExternalLogin","_onExternalLoginHook","setAdditionalFindUserOnExternalLogin","_additionalFindUserOnExternalLogin","_validateLogin","attempt","each","cloneAttemptWithConnection","e","allowed","_successfulLogin","_failedLogin","_successfulLogout","_loginUser","methodInvocation","stampedLoginToken","_generateStampedLoginToken","_insertLoginToken","_noYieldsAllowed","_setLoginToken","_hashLoginToken","setUserId","tokenExpires","_attemptLogin","methodName","methodArgs","result","type","methodArguments","Array","from","_loginMethod","fn","tryLoginMethod","_reportLoginFailure","registerLoginHandler","handler","_runLoginHandlers","destroyToken","update","$pull","hashedToken","accounts","methods","login","arguments","logout","_getLoginToken","getNewToken","currentHashedToken","currentStampedToken","services","resume","loginTokens","stampedToken","newStampedToken","removeOtherTokens","currentToken","$ne","configureLoginService","ObjectIncluding","service","oauth","serviceNames","usingOAuthEncryption","secret","seal","insert","onConnection","onClose","_removeTokenFromConnection","publish","is_auto","customFields","_id","autopublish","toFieldSelector","reduce","prev","field","addAutopublishFields","opts","apply","forLoggedInUser","forOtherUsers","setDefaultPublishFields","_getAccountData","connectionId","data","_setAccountData","hash","createHash","digest","_hashStampedToken","hashedStampedToken","_insertHashedLoginToken","$addToSet","_clearAllLoginTokens","$set","_getUserObserve","observe","stop","newToken","myObserveNumber","defer","foundMatchingUser","observeChanges","added","removed","close","nonMutatingCallbacks","Random","_expirePasswordResetTokens","oldestValidDate","tokenLifetimeMs","tokenFilter","$exists","expirePasswordToken","_expirePasswordEnrollTokens","_expireTokens","userFilter","$lt","multi","superResult","expireTokenInterval","clearInterval","insertUserDoc","createdAt","pinEncryptedFieldsToUser","fullUser","defaultCreateUserHook","hook","errmsg","_testEmailDomain","domain","restrictCreationByEmailDomain","test","_deleteSavedTokensForUser","tokensToDelete","$unset","$pullAll","loginTokensToDelete","updateOrCreateUserFromExternalService","serviceName","serviceData","serviceIdKey","isNaN","parseInt","setAttrs","removeDefaultRateLimit","resp","DDPRateLimiter","removeRule","defaultRateLimiterRuleId","addRule","clientAddress","generateOptionsForEmail","reason","extra","to","emailTemplates","subject","text","html","headers","_checkForCaseInsensitiveDuplicates","displayName","ownUserId","skipCheck","matchedUsers","limit","_createUserCheckingDuplicates","newUser","address","verified","ex","remove","clonedAttempt","EJSON","clone","defaultResumeLoginHandler","oldUnhashedStyleToken","isEnroll","resetRangeOr","expireFilter","setInterval","keyIsLoaded","isSealed","open","emailIsGood","values","allow","modifier","createIndex","unique","sparse","permutations","i","ch","charAt","concat","lowerCaseChar","toLowerCase","upperCaseChar","toUpperCase"],"mappings":"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","file":"/packages/accounts-base.js","sourcesContent":["import { AccountsServer } from \"./accounts_server.js\";\n\n/**\n * @namespace Accounts\n * @summary The namespace for all server-side accounts-related methods.\n */\nAccounts = new AccountsServer(Meteor.server);\n\n// Users table. Don't use the normal autopublish, since we want to hide\n// some fields. Code to autopublish this is in accounts_server.js.\n// XXX Allow users to configure this collection name.\n\n/**\n * @summary A [Mongo.Collection](#collections) containing user documents.\n * @locus Anywhere\n * @type {Mongo.Collection}\n * @importFromPackage meteor\n*/\nMeteor.users = Accounts.users;\n\nexport {\n // Since this file is the main module for the server version of the\n // accounts-base package, properties of non-entry-point modules need to\n // be re-exported in order to be accessible to modules that import the\n // accounts-base package.\n AccountsServer\n};\n","import { Meteor } from 'meteor/meteor';\n\n// config option keys\nconst VALID_CONFIG_KEYS = [\n 'sendVerificationEmail',\n 'forbidClientAccountCreation',\n 'passwordEnrollTokenExpiration',\n 'passwordEnrollTokenExpirationInDays',\n 'restrictCreationByEmailDomain',\n 'loginExpirationInDays',\n 'loginExpiration',\n 'passwordResetTokenExpirationInDays',\n 'passwordResetTokenExpiration',\n 'ambiguousErrorMessages',\n 'bcryptRounds',\n 'defaultFieldSelector',\n];\n\n/**\n * @summary Super-constructor for AccountsClient and AccountsServer.\n * @locus Anywhere\n * @class AccountsCommon\n * @instancename accountsClientOrServer\n * @param options {Object} an object with fields:\n * - connection {Object} Optional DDP connection to reuse.\n * - ddpUrl {String} Optional URL for creating a new DDP connection.\n */\nexport class AccountsCommon {\n constructor(options) {\n // Currently this is read directly by packages like accounts-password\n // and accounts-ui-unstyled.\n this._options = {};\n\n // Note that setting this.connection = null causes this.users to be a\n // LocalCollection, which is not what we want.\n this.connection = undefined;\n this._initConnection(options || {});\n\n // There is an allow call in accounts_server.js that restricts writes to\n // this collection.\n this.users = new Mongo.Collection('users', {\n _preventAutopublish: true,\n connection: this.connection,\n });\n\n // Callback exceptions are printed with Meteor._debug and ignored.\n this._onLoginHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: 'onLogin callback',\n });\n\n this._onLoginFailureHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: 'onLoginFailure callback',\n });\n\n this._onLogoutHook = new Hook({\n bindEnvironment: false,\n debugPrintExceptions: 'onLogout callback',\n });\n\n // Expose for testing.\n this.DEFAULT_LOGIN_EXPIRATION_DAYS = DEFAULT_LOGIN_EXPIRATION_DAYS;\n this.LOGIN_UNEXPIRING_TOKEN_DAYS = LOGIN_UNEXPIRING_TOKEN_DAYS;\n\n // Thrown when the user cancels the login process (eg, closes an oauth\n // popup, declines retina scan, etc)\n const lceName = 'Accounts.LoginCancelledError';\n this.LoginCancelledError = Meteor.makeErrorType(lceName, function(\n description\n ) {\n this.message = description;\n });\n this.LoginCancelledError.prototype.name = lceName;\n\n // This is used to transmit specific subclass errors over the wire. We\n // should come up with a more generic way to do this (eg, with some sort of\n // symbolic error code rather than a number).\n this.LoginCancelledError.numericError = 0x8acdc2f;\n\n // loginServiceConfiguration and ConfigError are maintained for backwards compatibility\n Meteor.startup(() => {\n const { ServiceConfiguration } = Package['service-configuration'];\n this.loginServiceConfiguration = ServiceConfiguration.configurations;\n this.ConfigError = ServiceConfiguration.ConfigError;\n\n const settings = Meteor.settings?.packages?.['accounts-base'];\n if (settings) {\n if (settings.oauthSecretKey) {\n if (!Package['oauth-encryption']) {\n throw new Error(\n 'The oauth-encryption package must be loaded to set oauthSecretKey'\n );\n }\n Package['oauth-encryption'].OAuthEncryption.loadKey(\n settings.oauthSecretKey\n );\n delete settings.oauthSecretKey;\n }\n // Validate config options keys\n Object.keys(settings).forEach(key => {\n if (!VALID_CONFIG_KEYS.includes(key)) {\n // TODO Consider just logging a debug message instead to allow for additional keys in the settings here?\n throw new Meteor.Error(\n `Accounts configuration: Invalid key: ${key}`\n );\n } else {\n // set values in Accounts._options\n this._options[key] = settings[key];\n }\n });\n }\n });\n }\n\n /**\n * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere\n */\n userId() {\n throw new Error('userId method not implemented');\n }\n\n // merge the defaultFieldSelector with an existing options object\n _addDefaultFieldSelector(options = {}) {\n // this will be the most common case for most people, so make it quick\n if (!this._options.defaultFieldSelector) return options;\n\n // if no field selector then just use defaultFieldSelector\n if (!options.fields)\n return {\n ...options,\n fields: this._options.defaultFieldSelector,\n };\n\n // if empty field selector then the full user object is explicitly requested, so obey\n const keys = Object.keys(options.fields);\n if (!keys.length) return options;\n\n // if the requested fields are +ve then ignore defaultFieldSelector\n // assume they are all either +ve or -ve because Mongo doesn't like mixed\n if (!!options.fields[keys[0]]) return options;\n\n // The requested fields are -ve.\n // If the defaultFieldSelector is +ve then use requested fields, otherwise merge them\n const keys2 = Object.keys(this._options.defaultFieldSelector);\n return this._options.defaultFieldSelector[keys2[0]]\n ? options\n : {\n ...options,\n fields: {\n ...options.fields,\n ...this._options.defaultFieldSelector,\n },\n };\n }\n\n /**\n * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere\n * @param {Object} [options]\n * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n */\n user(options) {\n const userId = this.userId();\n return userId\n ? this.users.findOne(userId, this._addDefaultFieldSelector(options))\n : null;\n }\n\n // Set up config for the accounts system. Call this on both the client\n // and the server.\n //\n // Note that this method gets overridden on AccountsServer.prototype, but\n // the overriding method calls the overridden method.\n //\n // XXX we should add some enforcement that this is called on both the\n // client and the server. Otherwise, a user can\n // 'forbidClientAccountCreation' only on the client and while it looks\n // like their app is secure, the server will still accept createUser\n // calls. https://github.com/meteor/meteor/issues/828\n //\n // @param options {Object} an object with fields:\n // - sendVerificationEmail {Boolean}\n // Send email address verification emails to new users created from\n // client signups.\n // - forbidClientAccountCreation {Boolean}\n // Do not allow clients to create accounts directly.\n // - restrictCreationByEmailDomain {Function or String}\n // Require created users to have an email matching the function or\n // having the string as domain.\n // - loginExpirationInDays {Number}\n // Number of days since login until a user is logged out (login token\n // expires).\n // - passwordResetTokenExpirationInDays {Number}\n // Number of days since password reset token creation until the\n // token cannt be used any longer (password reset token expires).\n // - ambiguousErrorMessages {Boolean}\n // Return ambiguous error messages from login failures to prevent\n // user enumeration.\n // - bcryptRounds {Number}\n // Allows override of number of bcrypt rounds (aka work factor) used\n // to store passwords.\n\n /**\n * @summary Set global accounts options. You can also set these in `Meteor.settings.packages.accounts` without the need to call this function.\n * @locus Anywhere\n * @param {Object} options\n * @param {Boolean} options.sendVerificationEmail New users with an email address will receive an address verification email.\n * @param {Boolean} options.forbidClientAccountCreation Calls to [`createUser`](#accounts_createuser) from the client will be rejected. In addition, if you are using [accounts-ui](#accountsui), the \"Create account\" link will not be available.\n * @param {String | Function} options.restrictCreationByEmailDomain If set to a string, only allows new users if the domain part of their email address matches the string. If set to a function, only allows new users if the function returns true. The function is passed the full email address of the proposed new user. Works with password-based sign-in and external services that expose email addresses (Google, Facebook, GitHub). All existing users still can log in after enabling this option. Example: `Accounts.config({ restrictCreationByEmailDomain: 'school.edu' })`.\n * @param {Number} options.loginExpirationInDays The number of days from when a user logs in until their token expires and they are logged out. Defaults to 90. Set to `null` to disable login expiration.\n * @param {Number} options.loginExpiration The number of milliseconds from when a user logs in until their token expires and they are logged out, for a more granular control. If `loginExpirationInDays` is set, it takes precedent.\n * @param {String} options.oauthSecretKey When using the `oauth-encryption` package, the 16 byte key using to encrypt sensitive account credentials in the database, encoded in base64. This option may only be specified on the server. See packages/oauth-encryption/README.md for details.\n * @param {Number} options.passwordResetTokenExpirationInDays The number of days from when a link to reset password is sent until token expires and user can't reset password with the link anymore. Defaults to 3.\n * @param {Number} options.passwordResetTokenExpiration The number of milliseconds from when a link to reset password is sent until token expires and user can't reset password with the link anymore. If `passwordResetTokenExpirationInDays` is set, it takes precedent.\n * @param {Number} options.passwordEnrollTokenExpirationInDays The number of days from when a link to set initial password is sent until token expires and user can't set password with the link anymore. Defaults to 30.\n * @param {Number} options.passwordEnrollTokenExpiration The number of milliseconds from when a link to set initial password is sent until token expires and user can't set password with the link anymore. If `passwordEnrollTokenExpirationInDays` is set, it takes precedent.\n * @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to false.\n * @param {MongoFieldSpecifier} options.defaultFieldSelector To exclude by default large custom fields from `Meteor.user()` and `Meteor.findUserBy...()` functions when called without a field selector, and all `onLogin`, `onLoginFailure` and `onLogout` callbacks. Example: `Accounts.config({ defaultFieldSelector: { myBigArray: 0 }})`. Beware when using this. If, for instance, you do not include `email` when excluding the fields, you can have problems with functions like `forgotPassword` that will break because they won't have the required data available. It's recommend that you always keep the fields `_id`, `username`, and `email`.\n */\n config(options) {\n // We don't want users to accidentally only call Accounts.config on the\n // client, where some of the options will have partial effects (eg removing\n // the \"create account\" button from accounts-ui if forbidClientAccountCreation\n // is set, or redirecting Google login to a specific-domain page) without\n // having their full effects.\n if (Meteor.isServer) {\n __meteor_runtime_config__.accountsConfigCalled = true;\n } else if (!__meteor_runtime_config__.accountsConfigCalled) {\n // XXX would be nice to \"crash\" the client and replace the UI with an error\n // message, but there's no trivial way to do this.\n Meteor._debug(\n 'Accounts.config was called on the client but not on the ' +\n 'server; some configuration options may not take effect.'\n );\n }\n\n // We need to validate the oauthSecretKey option at the time\n // Accounts.config is called. We also deliberately don't store the\n // oauthSecretKey in Accounts._options.\n if (Object.prototype.hasOwnProperty.call(options, 'oauthSecretKey')) {\n if (Meteor.isClient) {\n throw new Error(\n 'The oauthSecretKey option may only be specified on the server'\n );\n }\n if (!Package['oauth-encryption']) {\n throw new Error(\n 'The oauth-encryption package must be loaded to set oauthSecretKey'\n );\n }\n Package['oauth-encryption'].OAuthEncryption.loadKey(\n options.oauthSecretKey\n );\n options = { ...options };\n delete options.oauthSecretKey;\n }\n\n // Validate config options keys\n Object.keys(options).forEach(key => {\n if (!VALID_CONFIG_KEYS.includes(key)) {\n throw new Meteor.Error(`Accounts.config: Invalid key: ${key}`);\n }\n });\n\n // set values in Accounts._options\n VALID_CONFIG_KEYS.forEach(key => {\n if (key in options) {\n if (key in this._options) {\n throw new Meteor.Error(`Can't set \\`${key}\\` more than once`);\n }\n this._options[key] = options[key];\n }\n });\n }\n\n /**\n * @summary Register a callback to be called after a login attempt succeeds.\n * @locus Anywhere\n * @param {Function} func The callback to be called when login is successful.\n * The callback receives a single object that\n * holds login details. This object contains the login\n * result type (password, resume, etc.) on both the\n * client and server. `onLogin` callbacks registered\n * on the server also receive extra data, such\n * as user details, connection information, etc.\n */\n onLogin(func) {\n let ret = this._onLoginHook.register(func);\n // call the just registered callback if already logged in\n this._startupCallback(ret.callback);\n return ret;\n }\n\n /**\n * @summary Register a callback to be called after a login attempt fails.\n * @locus Anywhere\n * @param {Function} func The callback to be called after the login has failed.\n */\n onLoginFailure(func) {\n return this._onLoginFailureHook.register(func);\n }\n\n /**\n * @summary Register a callback to be called after a logout attempt succeeds.\n * @locus Anywhere\n * @param {Function} func The callback to be called when logout is successful.\n */\n onLogout(func) {\n return this._onLogoutHook.register(func);\n }\n\n _initConnection(options) {\n if (!Meteor.isClient) {\n return;\n }\n\n // The connection used by the Accounts system. This is the connection\n // that will get logged in by Meteor.login(), and this is the\n // connection whose login state will be reflected by Meteor.userId().\n //\n // It would be much preferable for this to be in accounts_client.js,\n // but it has to be here because it's needed to create the\n // Meteor.users collection.\n if (options.connection) {\n this.connection = options.connection;\n } else if (options.ddpUrl) {\n this.connection = DDP.connect(options.ddpUrl);\n } else if (\n typeof __meteor_runtime_config__ !== 'undefined' &&\n __meteor_runtime_config__.ACCOUNTS_CONNECTION_URL\n ) {\n // Temporary, internal hook to allow the server to point the client\n // to a different authentication server. This is for a very\n // particular use case that comes up when implementing a oauth\n // server. Unsupported and may go away at any point in time.\n //\n // We will eventually provide a general way to use account-base\n // against any DDP connection, not just one special one.\n this.connection = DDP.connect(\n __meteor_runtime_config__.ACCOUNTS_CONNECTION_URL\n );\n } else {\n this.connection = Meteor.connection;\n }\n }\n\n _getTokenLifetimeMs() {\n // When loginExpirationInDays is set to null, we'll use a really high\n // number of days (LOGIN_UNEXPIRABLE_TOKEN_DAYS) to simulate an\n // unexpiring token.\n const loginExpirationInDays =\n this._options.loginExpirationInDays === null\n ? LOGIN_UNEXPIRING_TOKEN_DAYS\n : this._options.loginExpirationInDays;\n return (\n this._options.loginExpiration ||\n (loginExpirationInDays || DEFAULT_LOGIN_EXPIRATION_DAYS) * 86400000\n );\n }\n\n _getPasswordResetTokenLifetimeMs() {\n return (\n this._options.passwordResetTokenExpiration ||\n (this._options.passwordResetTokenExpirationInDays ||\n DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS) * 86400000\n );\n }\n\n _getPasswordEnrollTokenLifetimeMs() {\n return (\n this._options.passwordEnrollTokenExpiration ||\n (this._options.passwordEnrollTokenExpirationInDays ||\n DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS) * 86400000\n );\n }\n\n _tokenExpiration(when) {\n // We pass when through the Date constructor for backwards compatibility;\n // `when` used to be a number.\n return new Date(new Date(when).getTime() + this._getTokenLifetimeMs());\n }\n\n _tokenExpiresSoon(when) {\n let minLifetimeMs = 0.1 * this._getTokenLifetimeMs();\n const minLifetimeCapMs = MIN_TOKEN_LIFETIME_CAP_SECS * 1000;\n if (minLifetimeMs > minLifetimeCapMs) {\n minLifetimeMs = minLifetimeCapMs;\n }\n return new Date() > new Date(when) - minLifetimeMs;\n }\n\n // No-op on the server, overridden on the client.\n _startupCallback(callback) {}\n}\n\n// Note that Accounts is defined separately in accounts_client.js and\n// accounts_server.js.\n\n/**\n * @summary Get the current user id, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n */\nMeteor.userId = () => Accounts.userId();\n\n/**\n * @summary Get the current user record, or `null` if no user is logged in. A reactive data source.\n * @locus Anywhere but publish functions\n * @importFromPackage meteor\n * @param {Object} [options]\n * @param {MongoFieldSpecifier} options.fields Dictionary of fields to return or exclude.\n */\nMeteor.user = options => Accounts.user(options);\n\n// how long (in days) until a login token expires\nconst DEFAULT_LOGIN_EXPIRATION_DAYS = 90;\n// how long (in days) until reset password token expires\nconst DEFAULT_PASSWORD_RESET_TOKEN_EXPIRATION_DAYS = 3;\n// how long (in days) until enrol password token expires\nconst DEFAULT_PASSWORD_ENROLL_TOKEN_EXPIRATION_DAYS = 30;\n// Clients don't try to auto-login with a token that is going to expire within\n// .1 * DEFAULT_LOGIN_EXPIRATION_DAYS, capped at MIN_TOKEN_LIFETIME_CAP_SECS.\n// Tries to avoid abrupt disconnects from expiring tokens.\nconst MIN_TOKEN_LIFETIME_CAP_SECS = 3600; // one hour\n// how often (in milliseconds) we check for expired tokens\nexport const EXPIRE_TOKENS_INTERVAL_MS = 600 * 1000; // 10 minutes\n// how long we wait before logging out clients when Meteor.logoutOtherClients is\n// called\nexport const CONNECTION_CLOSE_DELAY_MS = 10 * 1000;\n// A large number of expiration days (approximately 100 years worth) that is\n// used when creating unexpiring tokens.\nconst LOGIN_UNEXPIRING_TOKEN_DAYS = 365 * 100;\n","import crypto from 'crypto';\nimport {\n AccountsCommon,\n EXPIRE_TOKENS_INTERVAL_MS,\n} from './accounts_common.js';\nimport { URL } from 'meteor/url';\n\nconst hasOwn = Object.prototype.hasOwnProperty;\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\n/**\n * @summary Constructor for the `Accounts` namespace on the server.\n * @locus Server\n * @class AccountsServer\n * @extends AccountsCommon\n * @instancename accountsServer\n * @param {Object} server A server object such as `Meteor.server`.\n */\nexport class AccountsServer extends AccountsCommon {\n // Note that this constructor is less likely to be instantiated multiple\n // times than the `AccountsClient` constructor, because a single server\n // can provide only one set of methods.\n constructor(server) {\n super();\n\n this._server = server || Meteor.server;\n // Set up the server's methods, as if by calling Meteor.methods.\n this._initServerMethods();\n\n this._initAccountDataHooks();\n\n // If autopublish is on, publish these user fields. Login service\n // packages (eg accounts-google) add to these by calling\n // addAutopublishFields. Notably, this isn't implemented with multiple\n // publishes since DDP only merges only across top-level fields, not\n // subfields (such as 'services.facebook.accessToken')\n this._autopublishFields = {\n loggedInUser: ['profile', 'username', 'emails'],\n otherUsers: ['profile', 'username']\n };\n\n // use object to keep the reference when used in functions\n // where _defaultPublishFields is destructured into lexical scope\n // for publish callbacks that need `this`\n this._defaultPublishFields = {\n projection: {\n profile: 1,\n username: 1,\n emails: 1,\n }\n };\n\n this._initServerPublications();\n\n // connectionId -> {connection, loginToken}\n this._accountData = {};\n\n // connection id -> observe handle for the login token that this connection is\n // currently associated with, or a number. The number indicates that we are in\n // the process of setting up the observe (using a number instead of a single\n // sentinel allows multiple attempts to set up the observe to identify which\n // one was theirs).\n this._userObservesForConnections = {};\n this._nextUserObserveNumber = 1; // for the number described above.\n\n // list of all registered handlers.\n this._loginHandlers = [];\n\n setupUsersCollection(this.users);\n setupDefaultLoginHandlers(this);\n setExpireTokensInterval(this);\n\n this._validateLoginHook = new Hook({ bindEnvironment: false });\n this._validateNewUserHooks = [\n defaultValidateNewUserHook.bind(this)\n ];\n\n this._deleteSavedTokensForAllUsersOnStartup();\n\n this._skipCaseInsensitiveChecksForTest = {};\n\n this.urls = {\n resetPassword: (token, extraParams) => this.buildEmailUrl(`#/reset-password/${token}`, extraParams),\n verifyEmail: (token, extraParams) => this.buildEmailUrl(`#/verify-email/${token}`, extraParams),\n loginToken: (selector, token, extraParams) =>\n this.buildEmailUrl(`/?loginToken=${token}&selector=${selector}`, extraParams),\n enrollAccount: (token, extraParams) => this.buildEmailUrl(`#/enroll-account/${token}`, extraParams),\n };\n\n this.addDefaultRateLimit();\n\n this.buildEmailUrl = (path, extraParams = {}) => {\n const url = new URL(Meteor.absoluteUrl(path));\n const params = Object.entries(extraParams);\n if (params.length > 0) {\n // Add additional parameters to the url\n for (const [key, value] of params) {\n url.searchParams.append(key, value);\n }\n }\n return url.toString();\n };\n }\n\n ///\n /// CURRENT USER\n ///\n\n // @override of \"abstract\" non-implementation in accounts_common.js\n userId() {\n // This function only works if called inside a method or a pubication.\n // Using any of the information from Meteor.user() in a method or\n // publish function will always use the value from when the function first\n // runs. This is likely not what the user expects. The way to make this work\n // in a method or publish function is to do Meteor.find(this.userId).observe\n // and recompute when the user record changes.\n const currentInvocation = DDP._CurrentMethodInvocation.get() || DDP._CurrentPublicationInvocation.get();\n if (!currentInvocation)\n throw new Error(\"Meteor.userId can only be invoked in method calls or publications.\");\n return currentInvocation.userId;\n }\n\n ///\n /// LOGIN HOOKS\n ///\n\n /**\n * @summary Validate login attempts.\n * @locus Server\n * @param {Function} func Called whenever a login is attempted (either successful or unsuccessful). A login can be aborted by returning a falsy value or throwing an exception.\n */\n validateLoginAttempt(func) {\n // Exceptions inside the hook callback are passed up to us.\n return this._validateLoginHook.register(func);\n }\n\n /**\n * @summary Set restrictions on new user creation.\n * @locus Server\n * @param {Function} func Called whenever a new user is created. Takes the new user object, and returns true to allow the creation or false to abort.\n */\n validateNewUser(func) {\n this._validateNewUserHooks.push(func);\n }\n\n /**\n * @summary Validate login from external service\n * @locus Server\n * @param {Function} func Called whenever login/user creation from external service is attempted. Login or user creation based on this login can be aborted by passing a falsy value or throwing an exception.\n */\n beforeExternalLogin(func) {\n if (this._beforeExternalLoginHook) {\n throw new Error(\"Can only call beforeExternalLogin once\");\n }\n\n this._beforeExternalLoginHook = func;\n }\n\n ///\n /// CREATE USER HOOKS\n ///\n\n /**\n * @summary Customize login token creation.\n * @locus Server\n * @param {Function} func Called whenever a new token is created.\n * Return the sequence and the user object. Return true to keep sending the default email, or false to override the behavior.\n */\n onCreateLoginToken = function(func) {\n if (this._onCreateLoginTokenHook) {\n throw new Error('Can only call onCreateLoginToken once');\n }\n\n this._onCreateLoginTokenHook = func;\n };\n\n /**\n * @summary Customize new user creation.\n * @locus Server\n * @param {Function} func Called whenever a new user is created. Return the new user object, or throw an `Error` to abort the creation.\n */\n onCreateUser(func) {\n if (this._onCreateUserHook) {\n throw new Error(\"Can only call onCreateUser once\");\n }\n\n this._onCreateUserHook = func;\n }\n\n /**\n * @summary Customize oauth user profile updates\n * @locus Server\n * @param {Function} func Called whenever a user is logged in via oauth. Return the profile object to be merged, or throw an `Error` to abort the creation.\n */\n onExternalLogin(func) {\n if (this._onExternalLoginHook) {\n throw new Error(\"Can only call onExternalLogin once\");\n }\n\n this._onExternalLoginHook = func;\n }\n\n /**\n * @summary Customize user selection on external logins\n * @locus Server\n * @param {Function} func Called whenever a user is logged in via oauth and a\n * user is not found with the service id. Return the user or undefined.\n */\n setAdditionalFindUserOnExternalLogin(func) {\n if (this._additionalFindUserOnExternalLogin) {\n throw new Error(\"Can only call setAdditionalFindUserOnExternalLogin once\");\n }\n this._additionalFindUserOnExternalLogin = func;\n }\n\n _validateLogin(connection, attempt) {\n this._validateLoginHook.each(callback => {\n let ret;\n try {\n ret = callback(cloneAttemptWithConnection(connection, attempt));\n }\n catch (e) {\n attempt.allowed = false;\n // XXX this means the last thrown error overrides previous error\n // messages. Maybe this is surprising to users and we should make\n // overriding errors more explicit. (see\n // https://github.com/meteor/meteor/issues/1960)\n attempt.error = e;\n return true;\n }\n if (! ret) {\n attempt.allowed = false;\n // don't override a specific error provided by a previous\n // validator or the initial attempt (eg \"incorrect password\").\n if (!attempt.error)\n attempt.error = new Meteor.Error(403, \"Login forbidden\");\n }\n return true;\n });\n };\n\n _successfulLogin(connection, attempt) {\n this._onLoginHook.each(callback => {\n callback(cloneAttemptWithConnection(connection, attempt));\n return true;\n });\n };\n\n _failedLogin(connection, attempt) {\n this._onLoginFailureHook.each(callback => {\n callback(cloneAttemptWithConnection(connection, attempt));\n return true;\n });\n };\n\n _successfulLogout(connection, userId) {\n // don't fetch the user object unless there are some callbacks registered\n let user;\n this._onLogoutHook.each(callback => {\n if (!user && userId) user = this.users.findOne(userId, {fields: this._options.defaultFieldSelector});\n callback({ user, connection });\n return true;\n });\n };\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).\n _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 _findUserByQuery = (query, options) => {\n let user = null;\n\n if (query.id) {\n // default field selector is added within getUserById()\n user = Meteor.users.findOne(query.id, this._addDefaultFieldSelector(options));\n } else {\n options = this._addDefaultFieldSelector(options);\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, options);\n // If user is not found, try a case insensitive lookup\n if (!user) {\n selector = this._selectorForFastCaseInsensitiveLookup(fieldName, fieldValue);\n const candidateUsers = Meteor.users.find(selector, options).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 /// LOGIN METHODS\n ///\n\n // Login methods return to the client an object containing these\n // fields when the user was logged in successfully:\n //\n // id: userId\n // token: *\n // tokenExpires: *\n //\n // tokenExpires is optional and intends to provide a hint to the\n // client as to when the token will expire. If not provided, the\n // client will call Accounts._tokenExpiration, passing it the date\n // that it received the token.\n //\n // The login method will throw an error back to the client if the user\n // failed to log in.\n //\n //\n // Login handlers and service specific login methods such as\n // `createUser` internally return a `result` object containing these\n // fields:\n //\n // type:\n // optional string; the service name, overrides the handler\n // default if present.\n //\n // error:\n // exception; if the user is not allowed to login, the reason why.\n //\n // userId:\n // string; the user id of the user attempting to login (if\n // known), required for an allowed login.\n //\n // options:\n // optional object merged into the result returned by the login\n // method; used by HAMK from SRP.\n //\n // stampedLoginToken:\n // optional object with `token` and `when` indicating the login\n // token is already present in the database, returned by the\n // \"resume\" login handler.\n //\n // For convenience, login methods can also throw an exception, which\n // is converted into an {error} result. However, if the id of the\n // user attempting the login is known, a {userId, error} result should\n // be returned instead since the user id is not captured when an\n // exception is thrown.\n //\n // This internal `result` object is automatically converted into the\n // public {id, token, tokenExpires} object returned to the client.\n\n // Try a login method, converting thrown exceptions into an {error}\n // result. The `type` argument is a default, inserted into the result\n // object if not explicitly returned.\n //\n // Log in a user on a connection.\n //\n // We use the method invocation to set the user id on the connection,\n // not the connection object directly. setUserId is tied to methods to\n // enforce clear ordering of method application (using wait methods on\n // the client, and a no setUserId after unblock restriction on the\n // server)\n //\n // The `stampedLoginToken` parameter is optional. When present, it\n // indicates that the login token has already been inserted into the\n // database and doesn't need to be inserted again. (It's used by the\n // \"resume\" login handler).\n _loginUser(methodInvocation, userId, stampedLoginToken) {\n if (! stampedLoginToken) {\n stampedLoginToken = this._generateStampedLoginToken();\n this._insertLoginToken(userId, stampedLoginToken);\n }\n\n // This order (and the avoidance of yields) is important to make\n // sure that when publish functions are rerun, they see a\n // consistent view of the world: the userId is set and matches\n // the login token on the connection (not that there is\n // currently a public API for reading the login token on a\n // connection).\n Meteor._noYieldsAllowed(() =>\n this._setLoginToken(\n userId,\n methodInvocation.connection,\n this._hashLoginToken(stampedLoginToken.token)\n )\n );\n\n methodInvocation.setUserId(userId);\n\n return {\n id: userId,\n token: stampedLoginToken.token,\n tokenExpires: this._tokenExpiration(stampedLoginToken.when)\n };\n };\n\n // After a login method has completed, call the login hooks. Note\n // that `attemptLogin` is called for *all* login attempts, even ones\n // which aren't successful (such as an invalid password, etc).\n //\n // If the login is allowed and isn't aborted by a validate login hook\n // callback, log in the user.\n //\n _attemptLogin(\n methodInvocation,\n methodName,\n methodArgs,\n result\n ) {\n if (!result)\n throw new Error(\"result is required\");\n\n // XXX A programming error in a login handler can lead to this occurring, and\n // then we don't call onLogin or onLoginFailure callbacks. Should\n // tryLoginMethod catch this case and turn it into an error?\n if (!result.userId && !result.error)\n throw new Error(\"A login method must specify a userId or an error\");\n\n let user;\n if (result.userId)\n user = this.users.findOne(result.userId, {fields: this._options.defaultFieldSelector});\n\n const attempt = {\n type: result.type || \"unknown\",\n allowed: !! (result.userId && !result.error),\n methodName: methodName,\n methodArguments: Array.from(methodArgs)\n };\n if (result.error) {\n attempt.error = result.error;\n }\n if (user) {\n attempt.user = user;\n }\n\n // _validateLogin may mutate `attempt` by adding an error and changing allowed\n // to false, but that's the only change it can make (and the user's callbacks\n // only get a clone of `attempt`).\n this._validateLogin(methodInvocation.connection, attempt);\n\n if (attempt.allowed) {\n const ret = {\n ...this._loginUser(\n methodInvocation,\n result.userId,\n result.stampedLoginToken\n ),\n ...result.options\n };\n ret.type = attempt.type;\n this._successfulLogin(methodInvocation.connection, attempt);\n return ret;\n }\n else {\n this._failedLogin(methodInvocation.connection, attempt);\n throw attempt.error;\n }\n };\n\n // All service specific login methods should go through this function.\n // Ensure that thrown exceptions are caught and that login hook\n // callbacks are still called.\n //\n _loginMethod(\n methodInvocation,\n methodName,\n methodArgs,\n type,\n fn\n ) {\n return this._attemptLogin(\n methodInvocation,\n methodName,\n methodArgs,\n tryLoginMethod(type, fn)\n );\n };\n\n\n // Report a login attempt failed outside the context of a normal login\n // method. This is for use in the case where there is a multi-step login\n // procedure (eg SRP based password login). If a method early in the\n // chain fails, it should call this function to report a failure. There\n // is no corresponding method for a successful login; methods that can\n // succeed at logging a user in should always be actual login methods\n // (using either Accounts._loginMethod or Accounts.registerLoginHandler).\n _reportLoginFailure(\n methodInvocation,\n methodName,\n methodArgs,\n result\n ) {\n const attempt = {\n type: result.type || \"unknown\",\n allowed: false,\n error: result.error,\n methodName: methodName,\n methodArguments: Array.from(methodArgs)\n };\n\n if (result.userId) {\n attempt.user = this.users.findOne(result.userId, {fields: this._options.defaultFieldSelector});\n }\n\n this._validateLogin(methodInvocation.connection, attempt);\n this._failedLogin(methodInvocation.connection, attempt);\n\n // _validateLogin may mutate attempt to set a new error message. Return\n // the modified version.\n return attempt;\n };\n\n ///\n /// LOGIN HANDLERS\n ///\n\n // The main entry point for auth packages to hook in to login.\n //\n // A login handler is a login method which can return `undefined` to\n // indicate that the login request is not handled by this handler.\n //\n // @param name {String} Optional. The service name, used by default\n // if a specific service name isn't returned in the result.\n //\n // @param handler {Function} A function that receives an options object\n // (as passed as an argument to the `login` method) and returns one of:\n // - `undefined`, meaning don't handle;\n // - a login method result object\n\n registerLoginHandler(name, handler) {\n if (! handler) {\n handler = name;\n name = null;\n }\n\n this._loginHandlers.push({\n name: name,\n handler: handler\n });\n };\n\n\n // Checks a user's credentials against all the registered login\n // handlers, and returns a login token if the credentials are valid. It\n // is like the login method, except that it doesn't set the logged-in\n // user on the connection. Throws a Meteor.Error if logging in fails,\n // including the case where none of the login handlers handled the login\n // request. Otherwise, returns {id: userId, token: *, tokenExpires: *}.\n //\n // For example, if you want to login with a plaintext password, `options` could be\n // { user: { username: }, password: }, or\n // { user: { email: }, password: }.\n\n // Try all of the registered login handlers until one of them doesn't\n // return `undefined`, meaning it handled this call to `login`. Return\n // that return value.\n _runLoginHandlers(methodInvocation, options) {\n for (let handler of this._loginHandlers) {\n const result = tryLoginMethod(\n handler.name,\n () => handler.handler.call(methodInvocation, options)\n );\n\n if (result) {\n return result;\n }\n\n if (result !== undefined) {\n throw new Meteor.Error(400, \"A login handler should return a result or undefined\");\n }\n }\n\n return {\n type: null,\n error: new Meteor.Error(400, \"Unrecognized options for login request\")\n };\n };\n\n // Deletes the given loginToken from the database.\n //\n // For new-style hashed token, this will cause all connections\n // associated with the token to be closed.\n //\n // Any connections associated with old-style unhashed tokens will be\n // in the process of becoming associated with hashed tokens and then\n // they'll get closed.\n destroyToken(userId, loginToken) {\n this.users.update(userId, {\n $pull: {\n \"services.resume.loginTokens\": {\n $or: [\n { hashedToken: loginToken },\n { token: loginToken }\n ]\n }\n }\n });\n };\n\n _initServerMethods() {\n // The methods created in this function need to be created here so that\n // this variable is available in their scope.\n const accounts = this;\n\n\n // This object will be populated with methods and then passed to\n // accounts._server.methods further below.\n const methods = {};\n\n // @returns {Object|null}\n // If successful, returns {token: reconnectToken, id: userId}\n // If unsuccessful (for example, if the user closed the oauth login popup),\n // throws an error describing the reason\n methods.login = function (options) {\n // Login handlers should really also check whatever field they look at in\n // options, but we don't enforce it.\n check(options, Object);\n\n const result = accounts._runLoginHandlers(this, options);\n\n return accounts._attemptLogin(this, \"login\", arguments, result);\n };\n\n methods.logout = function () {\n const token = accounts._getLoginToken(this.connection.id);\n accounts._setLoginToken(this.userId, this.connection, null);\n if (token && this.userId) {\n accounts.destroyToken(this.userId, token);\n }\n accounts._successfulLogout(this.connection, this.userId);\n this.setUserId(null);\n };\n\n // Generates a new login token with the same expiration as the\n // connection's current token and saves it to the database. Associates\n // the connection with this new token and returns it. Throws an error\n // if called on a connection that isn't logged in.\n //\n // @returns Object\n // If successful, returns { token: , id: ,\n // tokenExpires: }.\n methods.getNewToken = function () {\n const user = accounts.users.findOne(this.userId, {\n fields: { \"services.resume.loginTokens\": 1 }\n });\n if (! this.userId || ! user) {\n throw new Meteor.Error(\"You are not logged in.\");\n }\n // Be careful not to generate a new token that has a later\n // expiration than the curren token. Otherwise, a bad guy with a\n // stolen token could use this method to stop his stolen token from\n // ever expiring.\n const currentHashedToken = accounts._getLoginToken(this.connection.id);\n const currentStampedToken = user.services.resume.loginTokens.find(\n stampedToken => stampedToken.hashedToken === currentHashedToken\n );\n if (! currentStampedToken) { // safety belt: this should never happen\n throw new Meteor.Error(\"Invalid login token\");\n }\n const newStampedToken = accounts._generateStampedLoginToken();\n newStampedToken.when = currentStampedToken.when;\n accounts._insertLoginToken(this.userId, newStampedToken);\n return accounts._loginUser(this, this.userId, newStampedToken);\n };\n\n // Removes all tokens except the token associated with the current\n // connection. Throws an error if the connection is not logged\n // in. Returns nothing on success.\n methods.removeOtherTokens = function () {\n if (! this.userId) {\n throw new Meteor.Error(\"You are not logged in.\");\n }\n const currentToken = accounts._getLoginToken(this.connection.id);\n accounts.users.update(this.userId, {\n $pull: {\n \"services.resume.loginTokens\": { hashedToken: { $ne: currentToken } }\n }\n });\n };\n\n // Allow a one-time configuration for a login service. Modifications\n // to this collection are also allowed in insecure mode.\n methods.configureLoginService = (options) => {\n check(options, Match.ObjectIncluding({service: String}));\n // Don't let random users configure a service we haven't added yet (so\n // that when we do later add it, it's set up with their configuration\n // instead of ours).\n // XXX if service configuration is oauth-specific then this code should\n // be in accounts-oauth; if it's not then the registry should be\n // in this package\n if (!(accounts.oauth\n && accounts.oauth.serviceNames().includes(options.service))) {\n throw new Meteor.Error(403, \"Service unknown\");\n }\n\n const { ServiceConfiguration } = Package['service-configuration'];\n if (ServiceConfiguration.configurations.findOne({service: options.service}))\n throw new Meteor.Error(403, `Service ${options.service} already configured`);\n\n if (hasOwn.call(options, 'secret') && usingOAuthEncryption())\n options.secret = OAuthEncryption.seal(options.secret);\n\n ServiceConfiguration.configurations.insert(options);\n };\n\n accounts._server.methods(methods);\n };\n\n _initAccountDataHooks() {\n this._server.onConnection(connection => {\n this._accountData[connection.id] = {\n connection: connection\n };\n\n connection.onClose(() => {\n this._removeTokenFromConnection(connection.id);\n delete this._accountData[connection.id];\n });\n });\n };\n\n _initServerPublications() {\n // Bring into lexical scope for publish callbacks that need `this`\n const { users, _autopublishFields, _defaultPublishFields } = this;\n\n // Publish all login service configuration fields other than secret.\n this._server.publish(\"meteor.loginServiceConfiguration\", () => {\n const { ServiceConfiguration } = Package['service-configuration'];\n return ServiceConfiguration.configurations.find({}, {fields: {secret: 0}});\n }, {is_auto: true}); // not technically autopublish, but stops the warning.\n\n // Use Meteor.startup to give other packages a chance to call\n // setDefaultPublishFields.\n Meteor.startup(() => {\n // Merge custom fields selector and default publish fields so that the client\n // gets all the necessary fields to run properly\n const customFields = this._addDefaultFieldSelector().fields || {};\n const keys = Object.keys(customFields);\n // If the custom fields are negative, then ignore them and only send the necessary fields\n const fields = keys.length > 0 && customFields[keys[0]] ? {\n ...this._addDefaultFieldSelector().fields,\n ..._defaultPublishFields.projection\n } : _defaultPublishFields.projection\n // Publish the current user's record to the client.\n this._server.publish(null, function () {\n if (this.userId) {\n return users.find({\n _id: this.userId\n }, {\n fields,\n });\n } else {\n return null;\n }\n }, /*suppress autopublish warning*/{is_auto: true});\n });\n\n // Use Meteor.startup to give other packages a chance to call\n // addAutopublishFields.\n Package.autopublish && Meteor.startup(() => {\n // ['profile', 'username'] -> {profile: 1, username: 1}\n const toFieldSelector = fields => fields.reduce((prev, field) => (\n { ...prev, [field]: 1 }),\n {}\n );\n this._server.publish(null, function () {\n if (this.userId) {\n return users.find({ _id: this.userId }, {\n fields: toFieldSelector(_autopublishFields.loggedInUser),\n })\n } else {\n return null;\n }\n }, /*suppress autopublish warning*/{is_auto: true});\n\n // XXX this publish is neither dedup-able nor is it optimized by our special\n // treatment of queries on a specific _id. Therefore this will have O(n^2)\n // run-time performance every time a user document is changed (eg someone\n // logging in). If this is a problem, we can instead write a manual publish\n // function which filters out fields based on 'this.userId'.\n this._server.publish(null, function () {\n const selector = this.userId ? { _id: { $ne: this.userId } } : {};\n return users.find(selector, {\n fields: toFieldSelector(_autopublishFields.otherUsers),\n })\n }, /*suppress autopublish warning*/{is_auto: true});\n });\n };\n\n // Add to the list of fields or subfields to be automatically\n // published if autopublish is on. Must be called from top-level\n // code (ie, before Meteor.startup hooks run).\n //\n // @param opts {Object} with:\n // - forLoggedInUser {Array} Array of fields published to the logged-in user\n // - forOtherUsers {Array} Array of fields published to users that aren't logged in\n addAutopublishFields(opts) {\n this._autopublishFields.loggedInUser.push.apply(\n this._autopublishFields.loggedInUser, opts.forLoggedInUser);\n this._autopublishFields.otherUsers.push.apply(\n this._autopublishFields.otherUsers, opts.forOtherUsers);\n };\n\n // Replaces the fields to be automatically\n // published when the user logs in\n //\n // @param {MongoFieldSpecifier} fields Dictionary of fields to return or exclude.\n setDefaultPublishFields(fields) {\n this._defaultPublishFields.projection = fields;\n };\n\n ///\n /// ACCOUNT DATA\n ///\n\n // HACK: This is used by 'meteor-accounts' to get the loginToken for a\n // connection. Maybe there should be a public way to do that.\n _getAccountData(connectionId, field) {\n const data = this._accountData[connectionId];\n return data && data[field];\n };\n\n _setAccountData(connectionId, field, value) {\n const data = this._accountData[connectionId];\n\n // safety belt. shouldn't happen. accountData is set in onConnection,\n // we don't have a connectionId until it is set.\n if (!data)\n return;\n\n if (value === undefined)\n delete data[field];\n else\n data[field] = value;\n };\n\n ///\n /// RECONNECT TOKENS\n ///\n /// support reconnecting using a meteor login token\n\n _hashLoginToken(loginToken) {\n const hash = crypto.createHash('sha256');\n hash.update(loginToken);\n return hash.digest('base64');\n };\n\n // {token, when} => {hashedToken, when}\n _hashStampedToken(stampedToken) {\n const { token, ...hashedStampedToken } = stampedToken;\n return {\n ...hashedStampedToken,\n hashedToken: this._hashLoginToken(token)\n };\n };\n\n // Using $addToSet avoids getting an index error if another client\n // logging in simultaneously has already inserted the new hashed\n // token.\n _insertHashedLoginToken(userId, hashedToken, query) {\n query = query ? { ...query } : {};\n query._id = userId;\n this.users.update(query, {\n $addToSet: {\n \"services.resume.loginTokens\": hashedToken\n }\n });\n };\n\n // Exported for tests.\n _insertLoginToken(userId, stampedToken, query) {\n this._insertHashedLoginToken(\n userId,\n this._hashStampedToken(stampedToken),\n query\n );\n };\n\n _clearAllLoginTokens(userId) {\n this.users.update(userId, {\n $set: {\n 'services.resume.loginTokens': []\n }\n });\n };\n\n // test hook\n _getUserObserve(connectionId) {\n return this._userObservesForConnections[connectionId];\n };\n\n // Clean up this connection's association with the token: that is, stop\n // the observe that we started when we associated the connection with\n // this token.\n _removeTokenFromConnection(connectionId) {\n if (hasOwn.call(this._userObservesForConnections, connectionId)) {\n const observe = this._userObservesForConnections[connectionId];\n if (typeof observe === 'number') {\n // We're in the process of setting up an observe for this connection. We\n // can't clean up that observe yet, but if we delete the placeholder for\n // this connection, then the observe will get cleaned up as soon as it has\n // been set up.\n delete this._userObservesForConnections[connectionId];\n } else {\n delete this._userObservesForConnections[connectionId];\n observe.stop();\n }\n }\n };\n\n _getLoginToken(connectionId) {\n return this._getAccountData(connectionId, 'loginToken');\n };\n\n // newToken is a hashed token.\n _setLoginToken(userId, connection, newToken) {\n this._removeTokenFromConnection(connection.id);\n this._setAccountData(connection.id, 'loginToken', newToken);\n\n if (newToken) {\n // Set up an observe for this token. If the token goes away, we need\n // to close the connection. We defer the observe because there's\n // no need for it to be on the critical path for login; we just need\n // to ensure that the connection will get closed at some point if\n // the token gets deleted.\n //\n // Initially, we set the observe for this connection to a number; this\n // signifies to other code (which might run while we yield) that we are in\n // the process of setting up an observe for this connection. Once the\n // observe is ready to go, we replace the number with the real observe\n // handle (unless the placeholder has been deleted or replaced by a\n // different placehold number, signifying that the connection was closed\n // already -- in this case we just clean up the observe that we started).\n const myObserveNumber = ++this._nextUserObserveNumber;\n this._userObservesForConnections[connection.id] = myObserveNumber;\n Meteor.defer(() => {\n // If something else happened on this connection in the meantime (it got\n // closed, or another call to _setLoginToken happened), just do\n // nothing. We don't need to start an observe for an old connection or old\n // token.\n if (this._userObservesForConnections[connection.id] !== myObserveNumber) {\n return;\n }\n\n let foundMatchingUser;\n // Because we upgrade unhashed login tokens to hashed tokens at\n // login time, sessions will only be logged in with a hashed\n // token. Thus we only need to observe hashed tokens here.\n const observe = this.users.find({\n _id: userId,\n 'services.resume.loginTokens.hashedToken': newToken\n }, { fields: { _id: 1 } }).observeChanges({\n added: () => {\n foundMatchingUser = true;\n },\n removed: connection.close,\n // The onClose callback for the connection takes care of\n // cleaning up the observe handle and any other state we have\n // lying around.\n }, { nonMutatingCallbacks: true });\n\n // If the user ran another login or logout command we were waiting for the\n // defer or added to fire (ie, another call to _setLoginToken occurred),\n // then we let the later one win (start an observe, etc) and just stop our\n // observe now.\n //\n // Similarly, if the connection was already closed, then the onClose\n // callback would have called _removeTokenFromConnection and there won't\n // be an entry in _userObservesForConnections. We can stop the observe.\n if (this._userObservesForConnections[connection.id] !== myObserveNumber) {\n observe.stop();\n return;\n }\n\n this._userObservesForConnections[connection.id] = observe;\n\n if (! foundMatchingUser) {\n // We've set up an observe on the user associated with `newToken`,\n // so if the new token is removed from the database, we'll close\n // the connection. But the token might have already been deleted\n // before we set up the observe, which wouldn't have closed the\n // connection because the observe wasn't running yet.\n connection.close();\n }\n });\n }\n };\n\n // (Also used by Meteor Accounts server and tests).\n //\n _generateStampedLoginToken() {\n return {\n token: Random.secret(),\n when: new Date\n };\n };\n\n ///\n /// TOKEN EXPIRATION\n ///\n\n // Deletes expired password reset tokens from the database.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expirePasswordResetTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getPasswordResetTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n\n const tokenFilter = {\n $or: [\n { \"services.password.reset.reason\": \"reset\"},\n { \"services.password.reset.reason\": {$exists: false}}\n ]\n };\n\n expirePasswordToken(this, oldestValidDate, tokenFilter, userId);\n }\n\n // Deletes expired password enroll tokens from the database.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expirePasswordEnrollTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getPasswordEnrollTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n\n const tokenFilter = {\n \"services.password.enroll.reason\": \"enroll\"\n };\n\n expirePasswordToken(this, oldestValidDate, tokenFilter, userId);\n }\n\n // Deletes expired tokens from the database and closes all open connections\n // associated with these tokens.\n //\n // Exported for tests. Also, the arguments are only used by\n // tests. oldestValidDate is simulate expiring tokens without waiting\n // for them to actually expire. userId is used by tests to only expire\n // tokens for the test user.\n _expireTokens(oldestValidDate, userId) {\n const tokenLifetimeMs = this._getTokenLifetimeMs();\n\n // when calling from a test with extra arguments, you must specify both!\n if ((oldestValidDate && !userId) || (!oldestValidDate && userId)) {\n throw new Error(\"Bad test. Must specify both oldestValidDate and userId.\");\n }\n\n oldestValidDate = oldestValidDate ||\n (new Date(new Date() - tokenLifetimeMs));\n const userFilter = userId ? {_id: userId} : {};\n\n\n // Backwards compatible with older versions of meteor that stored login token\n // timestamps as numbers.\n this.users.update({ ...userFilter,\n $or: [\n { \"services.resume.loginTokens.when\": { $lt: oldestValidDate } },\n { \"services.resume.loginTokens.when\": { $lt: +oldestValidDate } }\n ]\n }, {\n $pull: {\n \"services.resume.loginTokens\": {\n $or: [\n { when: { $lt: oldestValidDate } },\n { when: { $lt: +oldestValidDate } }\n ]\n }\n }\n }, { multi: true });\n // The observe on Meteor.users will take care of closing connections for\n // expired tokens.\n };\n\n // @override from accounts_common.js\n config(options) {\n // Call the overridden implementation of the method.\n const superResult = AccountsCommon.prototype.config.apply(this, arguments);\n\n // If the user set loginExpirationInDays to null, then we need to clear the\n // timer that periodically expires tokens.\n if (hasOwn.call(this._options, 'loginExpirationInDays') &&\n this._options.loginExpirationInDays === null &&\n this.expireTokenInterval) {\n Meteor.clearInterval(this.expireTokenInterval);\n this.expireTokenInterval = null;\n }\n\n return superResult;\n };\n\n // Called by accounts-password\n insertUserDoc(options, user) {\n // - clone user document, to protect from modification\n // - add createdAt timestamp\n // - prepare an _id, so that you can modify other collections (eg\n // create a first task for every new user)\n //\n // XXX If the onCreateUser or validateNewUser hooks fail, we might\n // end up having modified some other collection\n // inappropriately. The solution is probably to have onCreateUser\n // accept two callbacks - one that gets called before inserting\n // the user document (in which you can modify its contents), and\n // one that gets called after (in which you should change other\n // collections)\n user = {\n createdAt: new Date(),\n _id: Random.id(),\n ...user,\n };\n\n if (user.services) {\n Object.keys(user.services).forEach(service =>\n pinEncryptedFieldsToUser(user.services[service], user._id)\n );\n }\n\n let fullUser;\n if (this._onCreateUserHook) {\n fullUser = this._onCreateUserHook(options, user);\n\n // This is *not* part of the API. We need this because we can't isolate\n // the global server environment between tests, meaning we can't test\n // both having a create user hook set and not having one set.\n if (fullUser === 'TEST DEFAULT HOOK')\n fullUser = defaultCreateUserHook(options, user);\n } else {\n fullUser = defaultCreateUserHook(options, user);\n }\n\n this._validateNewUserHooks.forEach(hook => {\n if (! hook(fullUser))\n throw new Meteor.Error(403, \"User validation failed\");\n });\n\n let userId;\n try {\n userId = this.users.insert(fullUser);\n } catch (e) {\n // XXX string parsing sucks, maybe\n // https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day\n // https://jira.mongodb.org/browse/SERVER-4637\n if (!e.errmsg) throw e;\n if (e.errmsg.includes('emails.address'))\n throw new Meteor.Error(403, \"Email already exists.\");\n if (e.errmsg.includes('username'))\n throw new Meteor.Error(403, \"Username already exists.\");\n throw e;\n }\n return userId;\n };\n\n // Helper function: returns false if email does not match company domain from\n // the configuration.\n _testEmailDomain(email) {\n const domain = this._options.restrictCreationByEmailDomain;\n\n return !domain ||\n (typeof domain === 'function' && domain(email)) ||\n (typeof domain === 'string' &&\n (new RegExp(`@${Meteor._escapeRegExp(domain)}$`, 'i')).test(email));\n };\n\n ///\n /// CLEAN UP FOR `logoutOtherClients`\n ///\n\n _deleteSavedTokensForUser(userId, tokensToDelete) {\n if (tokensToDelete) {\n this.users.update(userId, {\n $unset: {\n \"services.resume.haveLoginTokensToDelete\": 1,\n \"services.resume.loginTokensToDelete\": 1\n },\n $pullAll: {\n \"services.resume.loginTokens\": tokensToDelete\n }\n });\n }\n };\n\n _deleteSavedTokensForAllUsersOnStartup() {\n // If we find users who have saved tokens to delete on startup, delete\n // them now. It's possible that the server could have crashed and come\n // back up before new tokens are found in localStorage, but this\n // shouldn't happen very often. We shouldn't put a delay here because\n // that would give a lot of power to an attacker with a stolen login\n // token and the ability to crash the server.\n Meteor.startup(() => {\n this.users.find({\n \"services.resume.haveLoginTokensToDelete\": true\n }, {fields: {\n \"services.resume.loginTokensToDelete\": 1\n }}).forEach(user => {\n this._deleteSavedTokensForUser(\n user._id,\n user.services.resume.loginTokensToDelete\n );\n });\n });\n };\n\n ///\n /// MANAGING USER OBJECTS\n ///\n\n // Updates or creates a user after we authenticate with a 3rd party.\n //\n // @param serviceName {String} Service name (eg, twitter).\n // @param serviceData {Object} Data to store in the user's record\n // under services[serviceName]. Must include an \"id\" field\n // which is a unique identifier for the user in the service.\n // @param options {Object, optional} Other options to pass to insertUserDoc\n // (eg, profile)\n // @returns {Object} Object with token and id keys, like the result\n // of the \"login\" method.\n //\n updateOrCreateUserFromExternalService(\n serviceName,\n serviceData,\n options\n ) {\n options = { ...options };\n\n if (serviceName === \"password\" || serviceName === \"resume\") {\n throw new Error(\n \"Can't use updateOrCreateUserFromExternalService with internal service \"\n + serviceName);\n }\n if (!hasOwn.call(serviceData, 'id')) {\n throw new Error(\n `Service data for service ${serviceName} must include id`);\n }\n\n // Look for a user with the appropriate service user id.\n const selector = {};\n const serviceIdKey = `services.${serviceName}.id`;\n\n // XXX Temporary special case for Twitter. (Issue #629)\n // The serviceData.id will be a string representation of an integer.\n // We want it to match either a stored string or int representation.\n // This is to cater to earlier versions of Meteor storing twitter\n // user IDs in number form, and recent versions storing them as strings.\n // This can be removed once migration technology is in place, and twitter\n // users stored with integer IDs have been migrated to string IDs.\n if (serviceName === \"twitter\" && !isNaN(serviceData.id)) {\n selector[\"$or\"] = [{},{}];\n selector[\"$or\"][0][serviceIdKey] = serviceData.id;\n selector[\"$or\"][1][serviceIdKey] = parseInt(serviceData.id, 10);\n } else {\n selector[serviceIdKey] = serviceData.id;\n }\n\n let user = this.users.findOne(selector, {fields: this._options.defaultFieldSelector});\n\n // Check to see if the developer has a custom way to find the user outside\n // of the general selectors above.\n if (!user && this._additionalFindUserOnExternalLogin) {\n user = this._additionalFindUserOnExternalLogin({serviceName, serviceData, options})\n }\n\n // Before continuing, run user hook to see if we should continue\n if (this._beforeExternalLoginHook && !this._beforeExternalLoginHook(serviceName, serviceData, user)) {\n throw new Meteor.Error(403, \"Login forbidden\");\n }\n\n // When creating a new user we pass through all options. When updating an\n // existing user, by default we only process/pass through the serviceData\n // (eg, so that we keep an unexpired access token and don't cache old email\n // addresses in serviceData.email). The onExternalLogin hook can be used when\n // creating or updating a user, to modify or pass through more options as\n // needed.\n let opts = user ? {} : options;\n if (this._onExternalLoginHook) {\n opts = this._onExternalLoginHook(options, user);\n }\n\n if (user) {\n pinEncryptedFieldsToUser(serviceData, user._id);\n\n let setAttrs = {};\n Object.keys(serviceData).forEach(key =>\n setAttrs[`services.${serviceName}.${key}`] = serviceData[key]\n );\n\n // XXX Maybe we should re-use the selector above and notice if the update\n // touches nothing?\n setAttrs = { ...setAttrs, ...opts };\n this.users.update(user._id, {\n $set: setAttrs\n });\n\n return {\n type: serviceName,\n userId: user._id\n };\n } else {\n // Create a new user with the service data.\n user = {services: {}};\n user.services[serviceName] = serviceData;\n return {\n type: serviceName,\n userId: this.insertUserDoc(opts, user)\n };\n }\n };\n\n // Removes default rate limiting rule\n removeDefaultRateLimit() {\n const resp = DDPRateLimiter.removeRule(this.defaultRateLimiterRuleId);\n this.defaultRateLimiterRuleId = null;\n return resp;\n };\n\n // Add a default rule of limiting logins, creating new users and password reset\n // to 5 times every 10 seconds per connection.\n addDefaultRateLimit() {\n if (!this.defaultRateLimiterRuleId) {\n this.defaultRateLimiterRuleId = DDPRateLimiter.addRule({\n userId: null,\n clientAddress: null,\n type: 'method',\n name: name => ['login', 'createUser', 'resetPassword', 'forgotPassword']\n .includes(name),\n connectionId: (connectionId) => true,\n }, 5, 10000);\n }\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 */\n generateOptionsForEmail(email, user, url, reason, extra = {}){\n const options = {\n to: email,\n from: this.emailTemplates[reason].from\n ? this.emailTemplates[reason].from(user)\n : this.emailTemplates.from,\n subject: this.emailTemplates[reason].subject(user, url, extra),\n };\n\n if (typeof this.emailTemplates[reason].text === 'function') {\n options.text = this.emailTemplates[reason].text(user, url, extra);\n }\n\n if (typeof this.emailTemplates[reason].html === 'function') {\n options.html = this.emailTemplates[reason].html(user, url, extra);\n }\n\n if (typeof this.emailTemplates.headers === 'object') {\n options.headers = this.emailTemplates.headers;\n }\n\n return options;\n };\n\n _checkForCaseInsensitiveDuplicates(\n fieldName,\n displayName,\n fieldValue,\n ownUserId\n ) {\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(\n this._skipCaseInsensitiveChecksForTest,\n fieldValue\n );\n\n if (fieldValue && !skipCheck) {\n const matchedUsers = Meteor.users\n .find(\n this._selectorForFastCaseInsensitiveLookup(fieldName, fieldValue),\n {\n fields: { _id: 1 },\n // we only need a maximum of 2 users for the logic below to work\n limit: 2,\n }\n )\n .fetch();\n\n if (\n 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 ) {\n this._handleError(`${displayName} already exists.`);\n }\n }\n };\n\n _createUserCheckingDuplicates({ user, email, username, options }) {\n const newUser = {\n ...user,\n ...(username ? { username } : {}),\n ...(email ? { emails: [{ address: email, verified: false }] } : {}),\n };\n\n // Perform a case insensitive check before insert\n this._checkForCaseInsensitiveDuplicates('username', 'Username', username);\n this._checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);\n\n const userId = this.insertUserDoc(options, newUser);\n // Perform another check after insert, in case a matching user has been\n // inserted in the meantime\n try {\n this._checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);\n this._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 _handleError = (msg, throwError = true, errorCode = 403) => {\n const error = new Meteor.Error(\n errorCode,\n this._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 _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\n}\n\n// Give each login hook callback a fresh cloned copy of the attempt\n// object, but don't clone the connection.\n//\nconst cloneAttemptWithConnection = (connection, attempt) => {\n const clonedAttempt = EJSON.clone(attempt);\n clonedAttempt.connection = connection;\n return clonedAttempt;\n};\n\nconst tryLoginMethod = (type, fn) => {\n let result;\n try {\n result = fn();\n }\n catch (e) {\n result = {error: e};\n }\n\n if (result && !result.type && type)\n result.type = type;\n\n return result;\n};\n\nconst setupDefaultLoginHandlers = accounts => {\n accounts.registerLoginHandler(\"resume\", function (options) {\n return defaultResumeLoginHandler.call(this, accounts, options);\n });\n};\n\n// Login handler for resume tokens.\nconst defaultResumeLoginHandler = (accounts, options) => {\n if (!options.resume)\n return undefined;\n\n check(options.resume, String);\n\n const hashedToken = accounts._hashLoginToken(options.resume);\n\n // First look for just the new-style hashed login token, to avoid\n // sending the unhashed token to the database in a query if we don't\n // need to.\n let user = accounts.users.findOne(\n {\"services.resume.loginTokens.hashedToken\": hashedToken},\n {fields: {\"services.resume.loginTokens.$\": 1}});\n\n if (! user) {\n // If we didn't find the hashed login token, try also looking for\n // the old-style unhashed token. But we need to look for either\n // the old-style token OR the new-style token, because another\n // client connection logging in simultaneously might have already\n // converted the token.\n user = accounts.users.findOne({\n $or: [\n {\"services.resume.loginTokens.hashedToken\": hashedToken},\n {\"services.resume.loginTokens.token\": options.resume}\n ]\n },\n // Note: Cannot use ...loginTokens.$ positional operator with $or query.\n {fields: {\"services.resume.loginTokens\": 1}});\n }\n\n if (! user)\n return {\n error: new Meteor.Error(403, \"You've been logged out by the server. Please log in again.\")\n };\n\n // Find the token, which will either be an object with fields\n // {hashedToken, when} for a hashed token or {token, when} for an\n // unhashed token.\n let oldUnhashedStyleToken;\n let token = user.services.resume.loginTokens.find(token =>\n token.hashedToken === hashedToken\n );\n if (token) {\n oldUnhashedStyleToken = false;\n } else {\n token = user.services.resume.loginTokens.find(token =>\n token.token === options.resume\n );\n oldUnhashedStyleToken = true;\n }\n\n const tokenExpires = accounts._tokenExpiration(token.when);\n if (new Date() >= tokenExpires)\n return {\n userId: user._id,\n error: new Meteor.Error(403, \"Your session has expired. Please log in again.\")\n };\n\n // Update to a hashed token when an unhashed token is encountered.\n if (oldUnhashedStyleToken) {\n // Only add the new hashed token if the old unhashed token still\n // exists (this avoids resurrecting the token if it was deleted\n // after we read it). Using $addToSet avoids getting an index\n // error if another client logging in simultaneously has already\n // inserted the new hashed token.\n accounts.users.update(\n {\n _id: user._id,\n \"services.resume.loginTokens.token\": options.resume\n },\n {$addToSet: {\n \"services.resume.loginTokens\": {\n \"hashedToken\": hashedToken,\n \"when\": token.when\n }\n }}\n );\n\n // Remove the old token *after* adding the new, since otherwise\n // another client trying to login between our removing the old and\n // adding the new wouldn't find a token to login with.\n accounts.users.update(user._id, {\n $pull: {\n \"services.resume.loginTokens\": { \"token\": options.resume }\n }\n });\n }\n\n return {\n userId: user._id,\n stampedLoginToken: {\n token: options.resume,\n when: token.when\n }\n };\n};\n\nconst expirePasswordToken = (\n accounts,\n oldestValidDate,\n tokenFilter,\n userId\n) => {\n // boolean value used to determine if this method was called from enroll account workflow\n let isEnroll = false;\n const userFilter = userId ? {_id: userId} : {};\n // check if this method was called from enroll account workflow\n if(tokenFilter['services.password.enroll.reason']) {\n isEnroll = true;\n }\n let resetRangeOr = {\n $or: [\n { \"services.password.reset.when\": { $lt: oldestValidDate } },\n { \"services.password.reset.when\": { $lt: +oldestValidDate } }\n ]\n };\n if(isEnroll) {\n resetRangeOr = {\n $or: [\n { \"services.password.enroll.when\": { $lt: oldestValidDate } },\n { \"services.password.enroll.when\": { $lt: +oldestValidDate } }\n ]\n };\n }\n const expireFilter = { $and: [tokenFilter, resetRangeOr] };\n if(isEnroll) {\n accounts.users.update({...userFilter, ...expireFilter}, {\n $unset: {\n \"services.password.enroll\": \"\"\n }\n }, { multi: true });\n } else {\n accounts.users.update({...userFilter, ...expireFilter}, {\n $unset: {\n \"services.password.reset\": \"\"\n }\n }, { multi: true });\n }\n\n};\n\nconst setExpireTokensInterval = accounts => {\n accounts.expireTokenInterval = Meteor.setInterval(() => {\n accounts._expireTokens();\n accounts._expirePasswordResetTokens();\n accounts._expirePasswordEnrollTokens();\n }, EXPIRE_TOKENS_INTERVAL_MS);\n};\n\n///\n/// OAuth Encryption Support\n///\n\nconst OAuthEncryption =\n Package[\"oauth-encryption\"] &&\n Package[\"oauth-encryption\"].OAuthEncryption;\n\nconst usingOAuthEncryption = () => {\n return OAuthEncryption && OAuthEncryption.keyIsLoaded();\n};\n\n// OAuth service data is temporarily stored in the pending credentials\n// collection during the oauth authentication process. Sensitive data\n// such as access tokens are encrypted without the user id because\n// we don't know the user id yet. We re-encrypt these fields with the\n// user id included when storing the service data permanently in\n// the users collection.\n//\nconst pinEncryptedFieldsToUser = (serviceData, userId) => {\n Object.keys(serviceData).forEach(key => {\n let value = serviceData[key];\n if (OAuthEncryption && OAuthEncryption.isSealed(value))\n value = OAuthEncryption.seal(OAuthEncryption.open(value), userId);\n serviceData[key] = value;\n });\n};\n\n\n// Encrypt unencrypted login service secrets when oauth-encryption is\n// added.\n//\n// XXX For the oauthSecretKey to be available here at startup, the\n// developer must call Accounts.config({oauthSecretKey: ...}) at load\n// time, instead of in a Meteor.startup block, because the startup\n// block in the app code will run after this accounts-base startup\n// block. Perhaps we need a post-startup callback?\n\nMeteor.startup(() => {\n if (! usingOAuthEncryption()) {\n return;\n }\n\n const { ServiceConfiguration } = Package['service-configuration'];\n\n ServiceConfiguration.configurations.find({\n $and: [{\n secret: { $exists: true }\n }, {\n \"secret.algorithm\": { $exists: false }\n }]\n }).forEach(config => {\n ServiceConfiguration.configurations.update(config._id, {\n $set: {\n secret: OAuthEncryption.seal(config.secret)\n }\n });\n });\n});\n\n// XXX see comment on Accounts.createUser in passwords_server about adding a\n// second \"server options\" argument.\nconst defaultCreateUserHook = (options, user) => {\n if (options.profile)\n user.profile = options.profile;\n return user;\n};\n\n// Validate new user's email or Google/Facebook/GitHub account's email\nfunction defaultValidateNewUserHook(user) {\n const domain = this._options.restrictCreationByEmailDomain;\n if (!domain) {\n return true;\n }\n\n let emailIsGood = false;\n if (user.emails && user.emails.length > 0) {\n emailIsGood = user.emails.reduce(\n (prev, email) => prev || this._testEmailDomain(email.address), false\n );\n } else if (user.services && Object.values(user.services).length > 0) {\n // Find any email of any service and check it\n emailIsGood = Object.values(user.services).reduce(\n (prev, service) => service.email && this._testEmailDomain(service.email),\n false,\n );\n }\n\n if (emailIsGood) {\n return true;\n }\n\n if (typeof domain === 'string') {\n throw new Meteor.Error(403, `@${domain} email required`);\n } else {\n throw new Meteor.Error(403, \"Email doesn't match the criteria.\");\n }\n}\n\nconst setupUsersCollection = users => {\n ///\n /// RESTRICTING WRITES TO USER OBJECTS\n ///\n users.allow({\n // clients can modify the profile field of their own document, and\n // nothing else.\n update: (userId, user, fields, modifier) => {\n // make sure it is our record\n if (user._id !== userId) {\n return false;\n }\n\n // user can only modify the 'profile' field. sets to multiple\n // sub-keys (eg profile.foo and profile.bar) are merged into entry\n // in the fields list.\n if (fields.length !== 1 || fields[0] !== 'profile') {\n return false;\n }\n\n return true;\n },\n fetch: ['_id'] // we only look at _id.\n });\n\n /// DEFAULT INDEXES ON USERS\n users.createIndex('username', { unique: true, sparse: true });\n users.createIndex('emails.address', { unique: true, sparse: true });\n users.createIndex('services.resume.loginTokens.hashedToken',\n { unique: true, sparse: true });\n users.createIndex('services.resume.loginTokens.token',\n { unique: true, sparse: true });\n // For taking care of logoutOtherClients calls that crashed before the\n // tokens were deleted.\n users.createIndex('services.resume.haveLoginTokensToDelete',\n { sparse: true });\n // For expiring login tokens\n users.createIndex(\"services.resume.loginTokens.when\", { sparse: true });\n // For expiring password tokens\n users.createIndex('services.password.reset.when', { sparse: true });\n users.createIndex('services.password.enroll.when', { sparse: true });\n};\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 unnecessary 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\n"]}