<commit_before>var crypto = Npm.require('crypto');

///
/// CURRENT USER
///

Meteor.userId = function () {
  // This function only works if called inside a method. In theory, it
  // could also be called from publish statements, since they also
  // have a userId associated with them. However, given that publish
  // functions aren't reactive, using any of the infomation from
  // Meteor.user() in a publish function will always use the value
  // from when the function first runs. This is likely not what the
  // user expects. The way to make this work in a publish is to do
  // Meteor.find(this.userId()).observe and recompute when the user
  // record changes.
  var currentInvocation = DDP._CurrentInvocation.get();
  if (!currentInvocation)
    throw new Error("Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.");
  return currentInvocation.userId;
};

Meteor.user = function () {
  var userId = Meteor.userId();
  if (!userId)
    return null;
  return Meteor.users.findOne(userId);
};

///
/// LOGIN HANDLERS
///

// The main entry point for auth packages to hook in to login.
//
// @param handler {Function} A function that receives an options object
// (as passed as an argument to the `login` method) and returns one of:
// - `undefined`, meaning don't handle;
// - {id: userId, token: *, tokenExpires: *}, if the user logged in
//   successfully. tokenExpires is optional and intends to provide a hint to the
//   client as to when the token will expire. If not provided, the client will
//   call Accounts._tokenExpiration, passing it the date that it received the
//   token.
// - throw an error, if the user failed to log in.
//
Accounts.registerLoginHandler = function(handler) {
  loginHandlers.push(handler);
};

// list of all registered handlers.
loginHandlers = [];


// Checks a user's credentials against all the registered login handlers, and
// returns a newly created login token if the credentials are valid. It is like
// the login method, except that it doesn't set the logged-in user on the
// connection. Throws a Meteor.Error if logging in fails, including the case
// where none of the login handlers handled the login request. Otherwise, returns
// {id: userId, token: *, tokenExpires: *}.
//
// For example, if you want to login with a plaintext password, `options` could be
//   { user: { username: <username> }, password: <password> }, or
//   { user: { email: <email> }, password: <password> }.
Accounts.createToken = function (options) {
  // Try all of the registered login handlers until one of them doesn' return
  // `undefined`, meaning it handled this call to `login`. Return that return
  // value, which ought to be a {id/token} pair.
  for (var i = 0; i < loginHandlers.length; ++i) {
    var handler = loginHandlers[i];
    var result = handler(options);
    if (result !== undefined)
      return result;
  }
  throw new Meteor.Error(400, "Unrecognized options for login request");
};

// Deletes the given loginToken from the database. This will cause all
// connections associated with the token to be closed.
Accounts.destroyToken = function (userId, loginToken) {
  Meteor.users.update(userId, {
    $pull: {
      "services.resume.loginTokens": { "token": loginToken }
    }
  });
};

// Actual methods for login and logout. This is the entry point for
// clients to actually log in.
Meteor.methods({
  // @returns {Object|null}
  //   If successful, returns {token: reconnectToken, id: userId}
  //   If unsuccessful (for example, if the user closed the oauth login popup),
  //     returns null
  login: function(options) {
    var self = this;

    // Login handlers should really also check whatever field they look at in
    // options, but we don't enforce it.
    check(options, Object);
    var result = Accounts.createToken(options);
    if (result !== null) {
      // This order (and the avoidance of yields) is important to make
      // sure that when publish functions are rerun, they see a
      // consistent view of the world: this.userId is set and matches
      // the login token on the connection (not that there is
      // currently a public API for reading the login token on a
      // connection).
      Meteor._noYieldsAllowed(function () {
        Accounts._setLoginToken(
          result.id,
          this.connection,
          Accounts._hashLoginToken(result.token)
        );
      });
      self.setUserId(result.id);
    }
    return result;
  },

  logout: function() {
    var token = Accounts._getLoginToken(this.connection.id);
    Accounts._setLoginToken(this.userId, this.connection, null);
    if (token && this.userId)
      Accounts.destroyToken(this.userId, token);
    this.setUserId(null);
  },

  // Delete all the current user's tokens and close all open connections logged
  // in as this user. Returns a fresh new login token that this client can
  // use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens
  // immediately instead of using a delay.
  //
  // @returns {Object} Object with token and tokenExpires keys.
  logoutOtherClients: function () {
    var self = this;
    var user = Meteor.users.findOne(self.userId, {
      fields: {
        "services.resume.loginTokens": true
      }
    });<commit_msg>Fix hashed login token test failures caused by merge mishap.<commit_after>var crypto = Npm.require('crypto');

///
/// CURRENT USER
///

Meteor.userId = function () {
  // This function only works if called inside a method. In theory, it
  // could also be called from publish statements, since they also
  // have a userId associated with them. However, given that publish
  // functions aren't reactive, using any of the infomation from
  // Meteor.user() in a publish function will always use the value
  // from when the function first runs. This is likely not what the
  // user expects. The way to make this work in a publish is to do
  // Meteor.find(this.userId()).observe and recompute when the user
  // record changes.
  var currentInvocation = DDP._CurrentInvocation.get();
  if (!currentInvocation)
    throw new Error("Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.");
  return currentInvocation.userId;
};

Meteor.user = function () {
  var userId = Meteor.userId();
  if (!userId)
    return null;
  return Meteor.users.findOne(userId);
};

///
/// LOGIN HANDLERS
///

// The main entry point for auth packages to hook in to login.
//
// @param handler {Function} A function that receives an options object
// (as passed as an argument to the `login` method) and returns one of:
// - `undefined`, meaning don't handle;
// - {id: userId, token: *, tokenExpires: *}, if the user logged in
//   successfully. tokenExpires is optional and intends to provide a hint to the
//   client as to when the token will expire. If not provided, the client will
//   call Accounts._tokenExpiration, passing it the date that it received the
//   token.
// - throw an error, if the user failed to log in.
//
Accounts.registerLoginHandler = function(handler) {
  loginHandlers.push(handler);
};

// list of all registered handlers.
loginHandlers = [];


// Checks a user's credentials against all the registered login handlers, and
// returns a newly created login token if the credentials are valid. It is like
// the login method, except that it doesn't set the logged-in user on the
// connection. Throws a Meteor.Error if logging in fails, including the case
// where none of the login handlers handled the login request. Otherwise, returns
// {id: userId, token: *, tokenExpires: *}.
//
// For example, if you want to login with a plaintext password, `options` could be
//   { user: { username: <username> }, password: <password> }, or
//   { user: { email: <email> }, password: <password> }.
Accounts.createToken = function (options) {
  // Try all of the registered login handlers until one of them doesn' return
  // `undefined`, meaning it handled this call to `login`. Return that return
  // value, which ought to be a {id/token} pair.
  for (var i = 0; i < loginHandlers.length; ++i) {
    var handler = loginHandlers[i];
    var result = handler(options);
    if (result !== undefined)
      return result;
  }
  throw new Meteor.Error(400, "Unrecognized options for login request");
};

// Deletes the given loginToken from the database.
//
// For new-style hashed token, this will cause all connections
// associated with the token to be closed.
//
// Any connections associated with old-style unhashed tokens will be
// in the process of becoming associated with hashed tokens and then
// they'll get closed.
Accounts.destroyToken = function (userId, loginToken) {
  Meteor.users.update(userId, {
    $pull: {
      "services.resume.loginTokens": {
        $or: [
          { hashedToken: loginToken },
          { token: loginToken }
        ]
      }
    }
  });
};

// Actual methods for login and logout. This is the entry point for
// clients to actually log in.
Meteor.methods({
  // @returns {Object|null}
  //   If successful, returns {token: reconnectToken, id: userId}
  //   If unsuccessful (for example, if the user closed the oauth login popup),
  //     returns null
  login: function(options) {
    var self = this;

    // Login handlers should really also check whatever field they look at in
    // options, but we don't enforce it.
    check(options, Object);
    var result = Accounts.createToken(options);
    if (result !== null) {
      // This order (and the avoidance of yields) is important to make
      // sure that when publish functions are rerun, they see a
      // consistent view of the world: this.userId is set and matches
      // the login token on the connection (not that there is
      // currently a public API for reading the login token on a
      // connection).
      Meteor._noYieldsAllowed(function () {
        Accounts._setLoginToken(
          result.id,
          self.connection,
          Accounts._hashLoginToken(result.token)
        );
      });
      self.setUserId(result.id);
    }
    return result;
  },

  logout: function() {
    var token = Accounts._getLoginToken(this.connection.id);
    Accounts._setLoginToken(this.userId, this.connection, null);
    if (token && this.userId)
      Accounts.destroyToken(this.userId, token);
    this.setUserId(null);
  },

  // Delete all the current user's tokens and close all open connections logged
  // in as this user. Returns a fresh new login token that this client can
  // use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens
  // immediately instead of using a delay.
  //
  // @returns {Object} Object with token and tokenExpires keys.
  logoutOtherClients: function () {
    var self = this;
    var user = Meteor.users.findOne(self.userId, {
      fields: {
        "services.resume.loginTokens": true
      }
    });
{'fraction_non_alphanumeric': 0.10226751124575416, 'fraction_numerical': 0.0007344165978151107, 'mean_word_length': 2.996331621423331, 'pattern_counts': {'":': 5, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6707515', 'n_tokens_mistral': 3040, 'n_tokens_neox': 3008, 'n_words': 1269}