<commit_before>var express = require('express');
var log4js = require('log4js');
var httpLogger = log4js.getLogger('http');
var settings = require('../../utils/Settings');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
var ueberStore = require('../../db/SessionStore');
var stats = require('ep_etherpad-lite/node/stats');
var sessionModule = require('express-session');
var cookieParser = require('cookie-parser');

// checks for basic http auth
exports.basicAuth = (req, res, next) => {
  var hookResultMangle = (cb) => {
    return (err, data) => {
      return cb(!err && data.length && data[0]);
    };
  };

  var authorize = (cb) => {
    // Do not require auth for static paths and the API...this could be a bit brittle
    if (req.path.match(/^\/(static|javascripts|pluginfw|api)/)) return cb(true);

    if (req.path.toLowerCase().indexOf('/admin') != 0) {
      if (!settings.requireAuthentication) return cb(true);
      if (!settings.requireAuthorization && req.session && req.session.user) return cb(true);
    }

    if (req.session && req.session.user && req.session.user.is_admin) return cb(true);

    hooks.aCallFirst('authorize', {req: req, res: res, next: next, resource: req.path}, hookResultMangle(cb));
  };

  var authenticate = (cb) => {
    // If auth headers are present use them to authenticate...
    if (req.headers.authorization && req.headers.authorization.search('Basic ') === 0) {
      var userpass = Buffer.from(req.headers.authorization.split(' ')[1], 'base64').toString().split(':');
      var username = userpass.shift();
      var password = <PASSWORD>pass.join(':');
      var fallback = (success) => {
        if (success) return cb(true);
        if (!(username in settings.users)) {
          httpLogger.info(`Failed authentication from IP ${req.ip} - no such user`);
          return cb(false);
        }
        if (settings.users[username].password !== password) {
          httpLogger.info(`Failed authentication from IP ${req.ip} for user ${username} - incorrect password`);
          return cb(false);
        }
        httpLogger.info(`Successful authentication from IP ${req.ip} for user ${username}`);
        settings.users[username].username = username;
        req.session.user = settings.users[username];
        return cb(true);
      };
      return hooks.aCallFirst('authenticate', {req: req, res: res, next: next, username: username, password: password}, hookResultMangle(fallback));
    }
    hooks.aCallFirst('authenticate', {req: req, res: res, next: next}, hookResultMangle(cb));
  };


  /* Authentication OR authorization failed. */
  var failure = () => {
    return hooks.aCallFirst('authFailure', {req: req, res: res, next: next}, hookResultMangle((ok) => {
      if (ok) return;
      /* No plugin handler for invalid auth. Return Auth required
       * Headers, delayed for 1 second, if authentication failed
       * before. */
      res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
      if (req.headers.authorization) {
        setTimeout(() => {
          res.status(401).send('Authentication required');
        }, 1000);
      } else {
        res.status(401).send('Authentication required');
      }
    }));
  };


  /* This is the actual authentication/authorization hoop. It is done in four steps:

     1) Try to just access the thing
     2) If not allowed using whatever creds are in the current session already, try to authenticate
     3) If authentication using already supplied credentials succeeds, try to access the thing again
     4) If all els fails, give the user a 401 to request new credentials

     Note that the process could stop already in step 3 with a redirect to login page.

  */

  authorize((ok) => {
    if (ok) return next();
    authenticate((ok) => {
      if (!ok) return failure();
      authorize((ok) => {
        if (ok) return next();
        failure();
      });
    });
  });
};

exports.secret = null;

exports.expressConfigure = (hook_name, args, cb) => {
  // Measure response time
  args.app.use((req, res, next) => {
    var stopWatch = stats.timer('httpRequests').start();
    var sendFn = res.send;
    res.send = function() { // function, not arrow, due to use of 'arguments'
      stopWatch.end();
      sendFn.apply(res, arguments);
    };
    next();
  });

  // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158.
  // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway.
  if (!(settings.loglevel === 'WARN' || settings.loglevel == 'ERROR'))
    args.app.use(log4js.connectLogger(httpLogger, {level: log4js.levels.DEBUG, format: ':status, :method :url'}));

  /* Do not let express create the session, so that we can retain a
   * reference to it for socket.io to use. Also, set the key (cookie
   * name) to a javascript identifier compatible string. Makes code
   * handling it cleaner :) */

  if (!exports.sessionStore) {
    exports.sessionStore = new ueberStore();
    exports.secret = settings.sessionKey;
  }

  if (settings.ssl) {
    var sameSite = 'Strict';
  } else {
    var sameSite = 'Lax';
  }

  args.app.sessionStore = exports.sessionStore;<commit_msg>webaccess: Use `const` or `let` instead of `var`<commit_after>const express = require('express');
const log4js = require('log4js');
const httpLogger = log4js.getLogger('http');
const settings = require('../../utils/Settings');
const hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
const ueberStore = require('../../db/SessionStore');
const stats = require('ep_etherpad-lite/node/stats');
const sessionModule = require('express-session');
const cookieParser = require('cookie-parser');

// checks for basic http auth
exports.basicAuth = (req, res, next) => {
  const hookResultMangle = (cb) => {
    return (err, data) => {
      return cb(!err && data.length && data[0]);
    };
  };

  const authorize = (cb) => {
    // Do not require auth for static paths and the API...this could be a bit brittle
    if (req.path.match(/^\/(static|javascripts|pluginfw|api)/)) return cb(true);

    if (req.path.toLowerCase().indexOf('/admin') != 0) {
      if (!settings.requireAuthentication) return cb(true);
      if (!settings.requireAuthorization && req.session && req.session.user) return cb(true);
    }

    if (req.session && req.session.user && req.session.user.is_admin) return cb(true);

    hooks.aCallFirst('authorize', {req: req, res: res, next: next, resource: req.path}, hookResultMangle(cb));
  };

  const authenticate = (cb) => {
    // If auth headers are present use them to authenticate...
    if (req.headers.authorization && req.headers.authorization.search('Basic ') === 0) {
      const userpass = Buffer.from(req.headers.authorization.split(' ')[1], 'base64').toString().split(':');
      const username = userpass.shift();
      const password = <PASSWORD>(':');
      const fallback = (success) => {
        if (success) return cb(true);
        if (!(username in settings.users)) {
          httpLogger.info(`Failed authentication from IP ${req.ip} - no such user`);
          return cb(false);
        }
        if (settings.users[username].password !== password) {
          httpLogger.info(`Failed authentication from IP ${req.ip} for user ${username} - incorrect password`);
          return cb(false);
        }
        httpLogger.info(`Successful authentication from IP ${req.ip} for user ${username}`);
        settings.users[username].username = username;
        req.session.user = settings.users[username];
        return cb(true);
      };
      return hooks.aCallFirst('authenticate', {req: req, res: res, next: next, username: username, password: password}, hookResultMangle(fallback));
    }
    hooks.aCallFirst('authenticate', {req: req, res: res, next: next}, hookResultMangle(cb));
  };


  /* Authentication OR authorization failed. */
  const failure = () => {
    return hooks.aCallFirst('authFailure', {req: req, res: res, next: next}, hookResultMangle((ok) => {
      if (ok) return;
      /* No plugin handler for invalid auth. Return Auth required
       * Headers, delayed for 1 second, if authentication failed
       * before. */
      res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
      if (req.headers.authorization) {
        setTimeout(() => {
          res.status(401).send('Authentication required');
        }, 1000);
      } else {
        res.status(401).send('Authentication required');
      }
    }));
  };


  /* This is the actual authentication/authorization hoop. It is done in four steps:

     1) Try to just access the thing
     2) If not allowed using whatever creds are in the current session already, try to authenticate
     3) If authentication using already supplied credentials succeeds, try to access the thing again
     4) If all els fails, give the user a 401 to request new credentials

     Note that the process could stop already in step 3 with a redirect to login page.

  */

  authorize((ok) => {
    if (ok) return next();
    authenticate((ok) => {
      if (!ok) return failure();
      authorize((ok) => {
        if (ok) return next();
        failure();
      });
    });
  });
};

exports.secret = null;

exports.expressConfigure = (hook_name, args, cb) => {
  // Measure response time
  args.app.use((req, res, next) => {
    const stopWatch = stats.timer('httpRequests').start();
    const sendFn = res.send;
    res.send = function() { // function, not arrow, due to use of 'arguments'
      stopWatch.end();
      sendFn.apply(res, arguments);
    };
    next();
  });

  // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158.
  // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway.
  if (!(settings.loglevel === 'WARN' || settings.loglevel == 'ERROR'))
    args.app.use(log4js.connectLogger(httpLogger, {level: log4js.levels.DEBUG, format: ':status, :method :url'}));

  /* Do not let express create the session, so that we can retain a
   * reference to it for socket.io to use. Also, set the key (cookie
   * name) to a javascript identifier compatible string. Makes code
   * handling it cleaner :) */

  if (!exports.sessionStore) {
    exports.sessionStore = new ueberStore();
    exports.secret = settings.sessionKey;
  }

  const sameSite = settings.ssl ? 'Strict' : 'Lax';

  args.app.sessionStore = exports.sessionStore;
{'fraction_non_alphanumeric': 0.140739350722462, 'fraction_numerical': 0.006380183899418277, 'mean_word_length': 3.1767241379310347, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, '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': '1991537', 'n_tokens_mistral': 3097, 'n_tokens_neox': 3013, 'n_words': 980}