<commit_before>var express = require('express');
var hyperquest = require('hyperquest');

module.exports = function (options) {

  options = options || {};

  var self = this;

  var ONE_YEAR = 31536000000;

  // missing session secret
  if (!options.secretKey) {
    throw new Error('(webmaker-auth): secretKey was not passed into webmaker-auth');
  }

  // missing login URL
  if (!options.loginURL) {
    throw new Error('(webmaker-auth): loginURL was not passed into webmaker-auth');
  }

  // missing Login Host URL
  if (!options.loginHost) {
    throw new Error('(webmaker-auth): loginHost was not passed into webmaker-auth');
  }

  self.loginURL = options.loginURL;
  self.authLoginURL = options.authLoginURL;
  self.loginHost = options.loginHost;

  self.refreshTime = options.refreshTime || 1000 * 60 * 15; // 15 minutes

  self.forceSSL = options.forceSSL || false;
  self.secretKey = options.secretKey;
  self.domain = options.domain;
  self.cookieName = 'webmakerlogin';

  self.cookieParser = function () {
    return express.cookieParser();
  };

  self.cookieSession = function () {
    var options = {
      key: self.cookieName,
      secret: self.secretKey,
      cookie: {
        expires: false,
        secure: self.forceSSL
      },
      proxy: true
    };

    if (self.domain) {
      options.cookie.domain = self.domain;
    }

    var cookieSessionMiddleware = express.cookieSession(options);

    // This is a work-around for cross-origin OPTIONS requests
    // See https://github.com/senchalabs/connect/issues/323
    return function (req, res, next) {
      if (req.method.toLowerCase() === 'options') {
        return next();
      } else {
        cookieSessionMiddleware(req, res, next);
      }
    };

  };

  function authenticateCallback(err, req, res, json) {
    if (err) {
      return res.json(500, {
        error: err
      });
    }
    if (!json) {
      return res.json(500, {
        error: 'The Login server sent an invalid response'
      });
    }
    if (json.error) {
      return res.json({
        error: json.error
      });
    }
    if (json.user) {
      if (req.body.validFor === 'one-year') {
        req.session.cookie.maxAge = ONE_YEAR;
      }

      req.session.user = json.user;
      req.session.email = json.email;
      req.session.refreshAfter = Date.now() + self.refreshTime;
      res.json({
        user: json.user,
        email: json.email
      });
    } else {
      res.json({
        error: 'No user for email address',
        email: json.email
      });
    }
  }

  function refreshSession(req, res, next) {
    var hReq = hyperquest.get({
      uri: self.authLoginURL + '/user/id/' + req.session.user.id
    });
    hReq.on('error', next);
    hReq.on('response', function (resp) {
      if (resp.statusCode !== 200) {
        return res.json(resp.statusCode || 500, {
          error: 'There was an error on the login server'
        });
      }
      var bodyParts = [];
      var bytes = 0;
      resp.on('data', function (c) {
        bodyParts.push(c);
        bytes += c.length;
      });
      resp.on('end', function () {
        var body = Buffer.concat(bodyParts, bytes).toString('utf8');
        var json;

        try {
          json = JSON.parse(body);
        } catch (ex) {
          return authenticateCallback(ex, req, res);
        }
        json.email = json.user.email;
        authenticateCallback(null, req, res, json);
      });
    });
  }

  function getIPAddress(req) {
    // account for load balancer!
    if (options.forceSSL) {
      return req.headers['x-forwarded-for'];
    }

    return req.connection.remoteAddress;
  }

  self.handlers = {
    request: function (req, res, next) {
      if (!req.body.uid) {
        return res.json(400, {
          error: 'missing email or username'
        });
      }
      var hReq = hyperquest.post({
        headers: {
          'Content-Type': 'application/json',
          'x-forwarded-for': getIPAddress(req)
        },
        uri: self.authLoginURL + '/api/v2/user/request'
      });
      hReq.on('error', next);
      hReq.on('response', function (resp) {

        if (resp.statusCode === 429) {
          res.set({
            'x-ratelimit-limit': resp.headers['x-ratelimit-limit'],
            'x-ratelimit-remaining': resp.headers['x-ratelimit-remaining'],
            'retry-after': resp.headers['retry-after']
          });
          return res.json(resp.statusCode, {
            error: 'Request Limit Exceeded'
          });
        }

        var bodyParts = [];
        var bytes = 0;
        resp.on('data', function (c) {
          bodyParts.push(c);
          bytes += c.length;
        });
        resp.on('end', function () {
          var body = Buffer.concat(bodyParts, bytes).toString('utf8');
          var json;

          try {
            json = JSON.parse(body);
          } catch (ex) {
            return authenticateCallback(ex, req, res);
          }

          res.json(json);
        });
      });
      hReq.end(JSON.stringify({
        uid: req.body.uid,
        appURL: self.loginHost
      }), 'utf8');
    },
    authenticateToken: function (req, res, next) {
      if (!req.body.uid || !req.body.token) {
        return res.json(400, {
          error: 'uid and token are required'
        });
      }
      var hReq = hyperquest.post({
        headers: {
          'Content-Type': 'application/json',
          'x-forwarded-for': getIPAddress(req)
        },<commit_msg>include optional pathname in login link param<commit_after>var express = require('express');
var hyperquest = require('hyperquest');

module.exports = function (options) {

  options = options || {};

  var self = this;

  var ONE_YEAR = 31536000000;

  // missing session secret
  if (!options.secretKey) {
    throw new Error('(webmaker-auth): secretKey was not passed into webmaker-auth');
  }

  // missing login URL
  if (!options.loginURL) {
    throw new Error('(webmaker-auth): loginURL was not passed into webmaker-auth');
  }

  // missing Login Host URL
  if (!options.loginHost) {
    throw new Error('(webmaker-auth): loginHost was not passed into webmaker-auth');
  }

  self.loginURL = options.loginURL;
  self.authLoginURL = options.authLoginURL;
  self.loginHost = options.loginHost;

  self.refreshTime = options.refreshTime || 1000 * 60 * 15; // 15 minutes

  self.forceSSL = options.forceSSL || false;
  self.secretKey = options.secretKey;
  self.domain = options.domain;
  self.cookieName = 'webmakerlogin';

  self.cookieParser = function () {
    return express.cookieParser();
  };

  self.cookieSession = function () {
    var options = {
      key: self.cookieName,
      secret: self.secretKey,
      cookie: {
        expires: false,
        secure: self.forceSSL
      },
      proxy: true
    };

    if (self.domain) {
      options.cookie.domain = self.domain;
    }

    var cookieSessionMiddleware = express.cookieSession(options);

    // This is a work-around for cross-origin OPTIONS requests
    // See https://github.com/senchalabs/connect/issues/323
    return function (req, res, next) {
      if (req.method.toLowerCase() === 'options') {
        return next();
      } else {
        cookieSessionMiddleware(req, res, next);
      }
    };

  };

  function authenticateCallback(err, req, res, json) {
    if (err) {
      return res.json(500, {
        error: err
      });
    }
    if (!json) {
      return res.json(500, {
        error: 'The Login server sent an invalid response'
      });
    }
    if (json.error) {
      return res.json({
        error: json.error
      });
    }
    if (json.user) {
      if (req.body.validFor === 'one-year') {
        req.session.cookie.maxAge = ONE_YEAR;
      }

      req.session.user = json.user;
      req.session.email = json.email;
      req.session.refreshAfter = Date.now() + self.refreshTime;
      res.json({
        user: json.user,
        email: json.email
      });
    } else {
      res.json({
        error: 'No user for email address',
        email: json.email
      });
    }
  }

  function refreshSession(req, res, next) {
    var hReq = hyperquest.get({
      uri: self.authLoginURL + '/user/id/' + req.session.user.id
    });
    hReq.on('error', next);
    hReq.on('response', function (resp) {
      if (resp.statusCode !== 200) {
        return res.json(resp.statusCode || 500, {
          error: 'There was an error on the login server'
        });
      }
      var bodyParts = [];
      var bytes = 0;
      resp.on('data', function (c) {
        bodyParts.push(c);
        bytes += c.length;
      });
      resp.on('end', function () {
        var body = Buffer.concat(bodyParts, bytes).toString('utf8');
        var json;

        try {
          json = JSON.parse(body);
        } catch (ex) {
          return authenticateCallback(ex, req, res);
        }
        json.email = json.user.email;
        authenticateCallback(null, req, res, json);
      });
    });
  }

  function getIPAddress(req) {
    // account for load balancer!
    if (options.forceSSL) {
      return req.headers['x-forwarded-for'];
    }

    return req.connection.remoteAddress;
  }

  self.handlers = {
    request: function (req, res, next) {
      if (!req.body.uid) {
        return res.json(400, {
          error: 'missing email or username'
        });
      }

      if ( !req.body.path ) {
        req.body.path = '';
      }

      var hReq = hyperquest.post({
        headers: {
          'Content-Type': 'application/json',
          'x-forwarded-for': getIPAddress(req)
        },
        uri: self.authLoginURL + '/api/v2/user/request'
      });
      hReq.on('error', next);
      hReq.on('response', function (resp) {

        if (resp.statusCode === 429) {
          res.set({
            'x-ratelimit-limit': resp.headers['x-ratelimit-limit'],
            'x-ratelimit-remaining': resp.headers['x-ratelimit-remaining'],
            'retry-after': resp.headers['retry-after']
          });
          return res.json(resp.statusCode, {
            error: 'Request Limit Exceeded'
          });
        }

        var bodyParts = [];
        var bytes = 0;
        resp.on('data', function (c) {
          bodyParts.push(c);
          bytes += c.length;
        });
        resp.on('end', function () {
          var body = Buffer.concat(bodyParts, bytes).toString('utf8');
          var json;

          try {
            json = JSON.parse(body);
          } catch (ex) {
            return authenticateCallback(ex, req, res);
          }

          res.json(json);
        });
      });
      hReq.end(JSON.stringify({
        uid: req.body.uid,
        appURL: self.loginHost + req.body.path
      }), 'utf8');
    },
    authenticateToken: function (req, res, next) {
      if (!req.body.uid || !req.body.token) {
        return res.json(400, {
          error: 'uid and token are required'
        });
      }
      var hReq = hyperquest.post({
        headers: {
          'Content-Type': 'application/json',
          'x-forwarded-for': getIPAddress(req)
        },
{'fraction_non_alphanumeric': 0.14156572048454166, 'fraction_numerical': 0.009220755740372446, 'mean_word_length': 1.9867710583153348, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, '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': '4831405', 'n_tokens_mistral': 3502, 'n_tokens_neox': 3365, 'n_words': 756}