<commit_before>import React from 'react';
import { Route, IndexRoute } from 'react-router';

import AppComponent from './components/app';
import Patients from './pages/patients';
import Login from './pages/login';
import Signup from './pages/signup';
import Profile from './pages/profile';
import Patient from './pages/patient';
import PatientNew from './pages/patientnew';
import PatientData from './pages/patientdata';
import RequestPasswordReset from './pages/passwordreset/request';
import ConfirmPasswordReset from './pages/passwordreset/confirm';
import EmailVerification from './pages/emailverification';

/**
 * Creates the route map with authentication associated with each route built in.
 * 
 * @param  {Object} appContext
 * @return {Route} the react-router routes
 */
export default (appContext) => {
  /**
   * This function redirects any requests that land on pages that should only be
   * visible when logged in if the user is logged out
   * 
   * @param  {Object} nextState
   * @param  {Function} replaceState
   *
   * @return {boolean|null} returns true if hash mapping happened
   */
  const requireAuth = (nextState, replaceState) => {
    if(!appContext.api.user.isAuthenticated()) {
      replaceState(null, '/login');
    }
  };

  /**
   * This function redirects any requests that land on pages that should only be
   * visible when logged out if the user is logged in
   * 
   * @param  {Object} nextState
   * @param  {Function} replaceState
   *
   * @return {boolean|null} returns true if hash mapping happened
   */
  const requireNoAuth = (nextState, replaceState) => {
    if(appContext.api.user.isAuthenticated()) {
      replaceState(null, '/patients');
    }
  };

  /**
   * This function exists for backward compatibility and maps hash
   * urls to standard urls
   * 
   * @param  {Object} nextState
   * @param  {Function} replaceState
   *
   * @return {boolean|null} returns true if hash mapping happened
   */
  const hashToUrl = (nextState, replaceState) => {
    let path = nextState.location.pathname;
    let hash = nextState.location.hash;

    if((!path || path === '/') && hash) {
      replaceState(null, hash.substring(2));
      return true;
    }
  }

  /**
   * onEnter handler for IndexRoute.
   *
   * This function calls hashToUrl and requireNoAuth
   * 
   * @param  {Object} nextState
   * @param  {Function} replaceState
   */
  const onIndexRouteEnter = (nextState, replaceState) => {
    if (!hashToUrl(nextState, replaceState)) {
      requireNoAuth(nextState, replaceState);
    }
  }

  return (
    <Route path='/' component={AppComponent} {...appContext.props}>
      <IndexRoute components={{login:Login}} onEnter={onIndexRouteEnter} />
      <Route path='login' components={{login:Login}} onEnter={requireNoAuth} />
      <Route path='signup' components={{signup: Signup}} onEnter={requireNoAuth} />
      <Route path='email-verification' components={{emailVerification: EmailVerification}} onEnter={requireNoAuth} />
      <Route path='profile' components={{profile: Profile}} onEnter={requireAuth} />
      <Route path='patients' components={{patients: Patients}} onEnter={requireAuth} />
      <Route path='patients/new' components={{patientNew: PatientNew}} onEnter={requireAuth} />
      <Route path='patients/:id/profile' components={{patient: Patient}} onEnter={requireAuth} />
      <Route path='patients/:id/share' components={{patientShare: Patient}} onEnter={requireAuth} />
      <Route path='patients/:id/data' components={{patientData: PatientData}} onEnter={requireAuth} />
      <Route path='request-password-reset' components={{requestPasswordReset: RequestPasswordReset}} onEnter={requireNoAuth} />
      <Route path='confirm-password-reset' components={{ confirmPasswordReset: ConfirmPasswordReset}} onEnter={requireNoAuth} />
      <Route path='request-password-from-uploader' components={{ requestPasswordReset: RequestPasswordReset}} onEnter={requireNoAuth} />
    </Route>
  );
}<commit_msg>Extract onEnter functions from inside getRoutes for testability<commit_after>import React from 'react';
import { Route, IndexRoute } from 'react-router';

import AppComponent from './components/app';
import Patients from './pages/patients';
import Login from './pages/login';
import Signup from './pages/signup';
import Profile from './pages/profile';
import Patient from './pages/patient';
import PatientNew from './pages/patientnew';
import PatientData from './pages/patientdata';
import RequestPasswordReset from './pages/passwordreset/request';
import ConfirmPasswordReset from './pages/passwordreset/confirm';
import EmailVerification from './pages/emailverification';

/**
 * This function redirects any requests that land on pages that should only be
 * visible when logged in if the user is logged out
 * 
 * @param  {Object} nextState
 * @param  {Function} replaceState
 *
 * @return {boolean|null} returns true if hash mapping happened
 */
const requireAuth = (api) => (nextState, replaceState) => {
  if(!api.user.isAuthenticated()) {
    replaceState(null, '/login');
  }
};

/**
 * This function redirects any requests that land on pages that should only be
 * visible when logged out if the user is logged in
 * 
 * @param  {Object} nextState
 * @param  {Function} replaceState
 *
 * @return {boolean|null} returns true if hash mapping happened
 */
const requireNoAuth = (api) => (nextState, replaceState) => {
  if(api.user.isAuthenticated()) {
    replaceState(null, '/patients');
  }
};

/**
 * This function exists for backward compatibility and maps hash
 * urls to standard urls
 * 
 * @param  {Object} nextState
 * @param  {Function} replaceState
 *
 * @return {boolean|null} returns true if hash mapping happened
 */
const hashToUrl = (nextState, replaceState) => {
  let path = nextState.location.pathname;
  let hash = nextState.location.hash;

  if((!path || path === '/') && hash) {
    replaceState(null, hash.substring(2));
    return true;
  }
}

/**
 * onEnter handler for IndexRoute.
 *
 * This function calls hashToUrl and requireNoAuth
 * 
 * @param  {Object} nextState
 * @param  {Function} replaceState
 */
const onIndexRouteEnter = (api) => (nextState, replaceState) => {
  if (!hashToUrl(nextState, replaceState)) {
    requireNoAuth(api)(nextState, replaceState);
  }
}

/**
 * Creates the route map with authentication associated with each route built in.
 * 
 * @param  {Object} appContext
 * @return {Route} the react-router routes
 */
export default (appContext) => {
  let props = appContext.props;
  let api = props.api;

  return (
    <Route path='/' component={AppComponent} {...props}>
      <IndexRoute components={{login:Login}} onEnter={onIndexRouteEnter(api)} />
      <Route path='login' components={{login:Login}} onEnter={requireNoAuth(api)} />
      <Route path='signup' components={{signup: Signup}} onEnter={requireNoAuth(api)} />
      <Route path='email-verification' components={{emailVerification: EmailVerification}} onEnter={requireNoAuth(api)} />
      <Route path='profile' components={{profile: Profile}} onEnter={requireAuth(api)} />
      <Route path='patients' components={{patients: Patients}} onEnter={requireAuth(api)} />
      <Route path='patients/new' components={{patientNew: PatientNew}} onEnter={requireAuth(api)} />
      <Route path='patients/:id/profile' components={{patient: Patient}} onEnter={requireAuth(api)} />
      <Route path='patients/:id/share' components={{patientShare: Patient}} onEnter={requireAuth(api)} />
      <Route path='patients/:id/data' components={{patientData: PatientData}} onEnter={requireAuth(api)} />
      <Route path='request-password-reset' components={{requestPasswordReset: RequestPasswordReset}} onEnter={requireNoAuth(api)} />
      <Route path='confirm-password-reset' components={{ confirmPasswordReset: ConfirmPasswordReset}} onEnter={requireNoAuth(api)} />
      <Route path='request-password-from-uploader' components={{ requestPasswordReset: RequestPasswordReset}} onEnter={requireNoAuth(api)} />
    </Route>
  );
}
{'fraction_non_alphanumeric': 0.1376432486297957, 'fraction_numerical': 0.00024912805181863477, 'mean_word_length': 4.366978609625669, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 46, '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': '6907037', 'n_tokens_mistral': 2246, 'n_tokens_neox': 2226, 'n_words': 622}