+ {!authenticated - && } + && } {authenticated && renderAuthenticatedRoutes()} diff --git a/frontend/src/components/IdleModal.js b/frontend/src/components/IdleModal.js new file mode 100644 index 0000000000..5c25e0deb6 --- /dev/null +++ b/frontend/src/components/IdleModal.js @@ -0,0 +1,107 @@ +/* + Displays a modal after $modalTimeout milliseconds if the user is inactive. If + the user becomes active when the modal is shown it will disappear. After $logoutTimeout + milliseconds the logout prop is called. +*/ + +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { useIdleTimer } from 'react-idle-timer'; +import { + Button, Modal, connectModal, useModal, Alert, +} from '@trussworks/react-uswds'; + +// list of events to determine activity +// https://github.com/SupremeTechnopriest/react-idle-timer#default-events +const EVENTS = [ + 'keydown', + 'wheel', + 'DOMMouseSc', + 'mousewheel', + 'mousedown', + 'touchstart', + 'touchmove', + 'MSPointerDown', + 'MSPointerMove', + 'visibilitychange', +]; + +function IdleModal({ modalTimeout, logoutTimeout, logoutUser }) { + const [inactiveTimeout, updateInactiveTimeout] = useState(); + const { isOpen, openModal, closeModal } = useModal(); + const modalVisibleTime = logoutTimeout - modalTimeout; + const timeoutMinutes = Math.floor(modalVisibleTime / 1000 / 60); + + let timeToLogoutMsg = ''; + if (timeoutMinutes < 1) { + timeToLogoutMsg = 'less than a minute'; + } else if (timeoutMinutes === 1) { + timeToLogoutMsg = 'a minute'; + } else { + timeToLogoutMsg = `${timeoutMinutes} minutes`; + } + + const Connected = connectModal(() => ( + Are you still there?} + actions={( + + )} + > + + You will be automatically logged out due to inactivity in + {' '} + { timeToLogoutMsg } + {' '} + unless you become active again. + + Press any key to continue your session + + + + )); + + // Make sure we clean up any timeout functions when this component + // is unmounted + useEffect(() => function cleanup() { + if (inactiveTimeout) { + clearTimeout(inactiveTimeout); + } + }); + + const onIdle = () => { + const timer = setTimeout(() => { + closeModal(); + logoutUser(true); + }, modalVisibleTime); + openModal(); + updateInactiveTimeout(timer); + }; + + const onActive = () => { + closeModal(); + clearTimeout(inactiveTimeout); + }; + + useIdleTimer({ + timeout: modalTimeout, + onIdle, + onActive, + events: EVENTS, + debounce: 500, + }); + + return ( + + ); +} + +IdleModal.propTypes = { + modalTimeout: PropTypes.number.isRequired, + logoutTimeout: PropTypes.number.isRequired, + logoutUser: PropTypes.func.isRequired, +}; + +export default IdleModal; diff --git a/frontend/src/components/__tests__/IdleModal.js b/frontend/src/components/__tests__/IdleModal.js new file mode 100644 index 0000000000..0dcc82c066 --- /dev/null +++ b/frontend/src/components/__tests__/IdleModal.js @@ -0,0 +1,98 @@ +import '@testing-library/jest-dom'; +import { act } from 'react-dom/test-utils'; +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; + +import IdleModal from '../IdleModal'; + +describe('IdleModal', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + + const renderIdleModal = ( + logoutTimeout = 20, + modalTimeout = 10, + logoutUser = () => {}, + ) => { + render( + <> +
+ + , + ); + }; + + it('modal is shown after modalTimeout', () => { + renderIdleModal(); + act(() => { + jest.advanceTimersByTime(11); + }); + expect(screen.getByTestId('modal')).toBeVisible(); + }); + + it('logout is called after logoutTimeout milliseconds of inactivity', () => { + const logout = jest.fn(); + renderIdleModal(20, 10, logout); + act(() => { + jest.advanceTimersByTime(21); + }); + expect(logout).toHaveBeenCalled(); + }); + + it('modal is not shown after modalTimeout if there is activity', () => { + const logout = jest.fn(); + renderIdleModal(20, 10, logout); + act(() => { + jest.advanceTimersByTime(7); + const testDiv = screen.getByTestId('test'); + fireEvent.keyDown(testDiv, { key: 'Enter', code: 'Enter' }); + jest.advanceTimersByTime(7); + }); + expect(logout).not.toHaveBeenCalled(); + expect(screen.queryByTestId('modal')).toBeNull(); + }); + + it('a shown modal is removed after action is taken', () => { + const logout = jest.fn(); + renderIdleModal(20, 10, logout); + act(() => { + jest.advanceTimersByTime(12); + expect(screen.getByTestId('modal')).toBeVisible(); + const testDiv = screen.getByTestId('test'); + fireEvent.keyDown(testDiv, { key: 'Enter', code: 'Enter' }); + }); + expect(logout).not.toHaveBeenCalled(); + expect(screen.queryByTestId('modal')).toBeNull(); + }); + + describe('modal message', () => { + it('shows less than a minute if logoutTimeout - modalTimeout is less than a minute', () => { + renderIdleModal(20, 10); + act(() => { + jest.advanceTimersByTime(11); + expect(screen.getByRole('alert').textContent).toContain('in less than a minute'); + }); + }); + + it('shows a minute if logoutTimeout - modalTimeout is a minute', () => { + renderIdleModal(1000 * 60 + 10, 10); + act(() => { + jest.advanceTimersByTime(11); + expect(screen.getByRole('alert').textContent).toContain('in a minute'); + }); + }); + + it('shows logoutTimeout - modalTimeout minutes when greater than one minute', () => { + renderIdleModal((1000 * 60 * 5) + 10, 10); + act(() => { + jest.advanceTimersByTime(11); + expect(screen.getByRole('alert').textContent).toContain('in 5 minutes'); + }); + }); + }); +}); diff --git a/frontend/src/pages/ActivityReport/SectionOne.js b/frontend/src/pages/ActivityReport/SectionOne.js index af1f94fda2..1871f1f333 100644 --- a/frontend/src/pages/ActivityReport/SectionOne.js +++ b/frontend/src/pages/ActivityReport/SectionOne.js @@ -54,23 +54,25 @@ const PageOne = ({ <>
- Was this activity for a grantee or a non-grantee? - - +
+ Was this activity for a grantee or a non-grantee? + + +
@@ -104,23 +106,25 @@ const PageOne = ({
- Who requested this activity? - - +
+ Who requested this activity? + + +
diff --git a/frontend/src/pages/ActivityReport/SectionThree.js b/frontend/src/pages/ActivityReport/SectionThree.js index 68ae8f104b..aab248f967 100644 --- a/frontend/src/pages/ActivityReport/SectionThree.js +++ b/frontend/src/pages/ActivityReport/SectionThree.js @@ -50,27 +50,31 @@ const PageThree = ({ <>
- How was this activity conducted? (select at least one) - - - {renderCheckbox('activity-method', 'virtual', 'Virtual')} - {renderCheckbox('activity-method', 'in-person', 'In Person')} - {renderCheckbox('activity-method', 'telephone', 'Telephone')} - - - {renderCheckbox('activity-method', 'email', 'Email')} - {renderCheckbox('activity-method', 'multi-recurring', 'Multi-grantee: Recurring Event (Community Practice)')} - {renderCheckbox('activity-method', 'multi-single', 'Multi-grantee: Single Event (Cluster)')} +
+ How was this activity conducted? (select at least one) + + + {renderCheckbox('activity-method', 'virtual', 'Virtual')} + {renderCheckbox('activity-method', 'in-person', 'In Person')} + {renderCheckbox('activity-method', 'telephone', 'Telephone')} + + + {renderCheckbox('activity-method', 'email', 'Email')} + {renderCheckbox('activity-method', 'multi-recurring', 'Multi-grantee: Recurring Event (Community Practice)')} + {renderCheckbox('activity-method', 'multi-single', 'Multi-grantee: Single Event (Cluster)')} + - +
- - Was this activity Training or Technical Assistance? - Select both options if both Training and Technical Assistance took place. - - {renderCheckbox('activity-type', 'training', 'Training')} - {renderCheckbox('activity-type', 'technical-assistance', 'Technical Assistance')} +
+ + Was this activity Training or Technical Assistance? + Select both options if both Training and Technical Assistance took place. + + {renderCheckbox('activity-type', 'training', 'Training')} + {renderCheckbox('activity-type', 'technical-assistance', 'Technical Assistance')} +
diff --git a/frontend/src/pages/Home/index.js b/frontend/src/pages/Home/index.js index 2d9d9b275e..990b2ff10e 100644 --- a/frontend/src/pages/Home/index.js +++ b/frontend/src/pages/Home/index.js @@ -17,7 +17,7 @@ function Home() { {' '} {user.name} - diff --git a/frontend/src/pages/Unauthenticated/__tests__/index.js b/frontend/src/pages/Unauthenticated/__tests__/index.js index ba0c94c793..5742347b66 100644 --- a/frontend/src/pages/Unauthenticated/__tests__/index.js +++ b/frontend/src/pages/Unauthenticated/__tests__/index.js @@ -28,4 +28,14 @@ describe('Unauthenticated Page', () => { expect(screen.getByText('You have successfully logged out of the TTA Smart Hub')).toBeVisible(); }); }); + + describe('when logged out and timed out', () => { + beforeEach(() => { + render(); + }); + + it('displays the logout due to inactivity message', () => { + expect(screen.getByText('You have been logged out due to inactivity')).toBeVisible(); + }); + }); }); diff --git a/frontend/src/pages/Unauthenticated/index.js b/frontend/src/pages/Unauthenticated/index.js index 71872cecf3..2d67b3ac54 100644 --- a/frontend/src/pages/Unauthenticated/index.js +++ b/frontend/src/pages/Unauthenticated/index.js @@ -5,13 +5,23 @@ import { } from '@trussworks/react-uswds'; import Container from '../../components/Container'; -function Unauthenticated({ loggedOut }) { +function Unauthenticated({ loggedOut, timedOut }) { + let msg = 'You have successfully logged out of the TTA Smart Hub'; + let type = 'success'; + let heading = 'Logout Successful'; + + if (timedOut) { + msg = 'You have been logged out due to inactivity'; + type = 'info'; + heading = 'Logout due to inactivity'; + } + return ( {loggedOut && ( - - You have successfully logged out of the TTA Smart Hub + + {msg} )}

@@ -29,10 +39,12 @@ function Unauthenticated({ loggedOut }) { Unauthenticated.propTypes = { loggedOut: PropTypes.bool, + timedOut: PropTypes.bool, }; Unauthenticated.defaultProps = { loggedOut: false, + timedOut: false, }; export default Unauthenticated; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index b4b66fff23..b4009c33ba 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -166,13 +166,6 @@ dependencies: "@babel/types" "^7.11.0" -"@babel/helper-module-imports@^7.0.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" - integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== - dependencies: - "@babel/types" "^7.12.1" - "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" @@ -1100,13 +1093,6 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.4.4", "@babel/runtime@^7.8.7": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" - integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/template@^7.10.4", "@babel/template@^7.4.0", "@babel/template@^7.8.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -1140,15 +1126,6 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" - integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -1167,83 +1144,6 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== -"@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": - version "10.0.29" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" - integrity sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ== - dependencies: - "@emotion/sheet" "0.9.4" - "@emotion/stylis" "0.8.5" - "@emotion/utils" "0.11.3" - "@emotion/weak-memoize" "0.2.5" - -"@emotion/core@^10.0.9": - version "10.0.35" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.35.tgz#513fcf2e22cd4dfe9d3894ed138c9d7a859af9b3" - integrity sha512-sH++vJCdk025fBlRZSAhkRlSUoqSqgCzYf5fMOmqqi3bM6how+sQpg3hkgJonj8GxXM4WbD7dRO+4tegDB9fUw== - dependencies: - "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.27" - "@emotion/css" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - -"@emotion/css@^10.0.27", "@emotion/css@^10.0.9": - version "10.0.27" - resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" - integrity sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw== - dependencies: - "@emotion/serialize" "^0.11.15" - "@emotion/utils" "0.11.3" - babel-plugin-emotion "^10.0.27" - -"@emotion/hash@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== - -"@emotion/memoize@0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== - -"@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": - version "0.11.16" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" - integrity sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg== - dependencies: - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/unitless" "0.7.5" - "@emotion/utils" "0.11.3" - csstype "^2.5.7" - -"@emotion/sheet@0.9.4": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" - integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== - -"@emotion/stylis@0.8.5": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== - -"@emotion/unitless@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== - -"@emotion/utils@0.11.3": - version "0.11.3" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" - integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== - -"@emotion/weak-memoize@0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== - "@fortawesome/fontawesome-common-types@^0.2.32": version "0.2.32" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.32.tgz#3436795d5684f22742989bfa08f46f50f516f259" @@ -1788,11 +1688,6 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-calendar@^3.0.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@types/react-calendar/-/react-calendar-3.1.2.tgz#a8afe394aadd639cfee7f0441bc3ced4fa0092f3" - integrity sha512-QZ8EMG2P3230GQNEMXtSJq8v8zJkJqs8xpbohMbBefYG7i1MX2YzOsDoBWF2dpq36mrkXpoNgmmeVnXIT0DYtw== - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -2006,11 +1901,6 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" -"@wojtekmaj/date-utils@^1.0.2", "@wojtekmaj/date-utils@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@wojtekmaj/date-utils/-/date-utils-1.0.3.tgz#2dcfd92881425c5923e429c2aec86fb3609032a1" - integrity sha512-1VPkkTBk07gMR1fjpBtse4G+oJqpmE+0gUFB0dg3VIL7qJmUVaBoD/vlzMm/jNeOPfvlmerl1lpnsZyBUFIRuw== - "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2509,22 +2399,6 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-emotion@^10.0.27: - version "10.0.33" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz#ce1155dcd1783bbb9286051efee53f4e2be63e03" - integrity sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/serialize" "^0.11.16" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - escape-string-regexp "^1.0.5" - find-root "^1.1.0" - source-map "^0.5.7" - babel-plugin-istanbul@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" @@ -2542,7 +2416,7 @@ babel-plugin-jest-hoist@^24.9.0: dependencies: "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@2.8.0, babel-plugin-macros@^2.0.0: +babel-plugin-macros@2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -2556,11 +2430,6 @@ babel-plugin-named-asset-import@^0.3.6: resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz#c9750a1b38d85112c9e166bf3ef7c5dbc605f4be" integrity sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA== -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= - babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" @@ -3415,7 +3284,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@1.7.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.7.0: +convert-source-map@1.7.0, convert-source-map@^1.4.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -3838,16 +3707,6 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: dependencies: cssom "0.3.x" -csstype@^2.5.7: - version "2.6.13" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f" - integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== - -csstype@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" - integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== - cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -3882,7 +3741,7 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@^2.0.1, date-fns@^2.16.1: +date-fns@^2.0.1: version "2.16.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b" integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ== @@ -4022,11 +3881,6 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-element-overflow@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/detect-element-overflow/-/detect-element-overflow-1.2.0.tgz#86e504292ffedc3aef813395fbdf0261aaf6afa9" - integrity sha512-Jtr9ivYPhpd9OJux+hjL0QjUKiS1Ghgy8tvIufUjFslQgIWvgGr4mn57H190APbKkiOmXnmtMI6ytaKzMusecg== - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -4128,14 +3982,6 @@ dom-converter@^0.2: dependencies: utila "~0.4" -dom-helpers@^5.0.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" - integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== - dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" - dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -5105,11 +4951,6 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-root@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - find-up@4.1.0, find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -5341,13 +5182,6 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-user-locale@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/get-user-locale/-/get-user-locale-1.4.0.tgz#a2c4b5da46feec9f03c9b07d197b1620490a5370" - integrity sha512-gQo03lP1OArHLKlnoglqrGGl7b04u2EP9Xutmp72cMdtrrSD7ZgIsCsUKZynYWLDkVJW33Cj3pliP7uP0UonHQ== - dependencies: - lodash.once "^4.1.1" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -7220,11 +7054,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.once@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -7301,11 +7130,6 @@ make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-event-props@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/make-event-props/-/make-event-props-1.2.0.tgz#96b87d88919533b8f8934b58b4c3d5679459a0cf" - integrity sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg== - makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -7359,11 +7183,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memoize-one@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" - integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== - memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -7380,11 +7199,6 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" -merge-class-names@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge-class-names/-/merge-class-names-1.3.0.tgz#c4cdc1a981a81dd9afc27aa4287e912a337c5dee" - integrity sha512-k0Qaj36VBpKgdc8c188LEZvo6v/zzry/FUufwopWbMSp6/knfVFU/KIB55/hJjeIpg18IH2WskXJCRnM/1BrdQ== - merge-deep@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/merge-deep/-/merge-deep-3.0.2.tgz#f39fa100a4f1bd34ff29f7d2bf4508fbb8d83ad2" @@ -9148,7 +8962,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -9314,31 +9128,6 @@ react-app-polyfill@^1.0.6: regenerator-runtime "^0.13.3" whatwg-fetch "^3.0.0" -react-calendar@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/react-calendar/-/react-calendar-3.1.0.tgz#7a384a70f98e02177d176c45f6918fb6a15ce41f" - integrity sha512-xoKdRe6FrnZ30LD9pyr20fhet1uwSbc6srLGm1ib7G4b7tAXniZrwzrJ4YV/Hbmmwf/zAFGyXtBzLAIV1KNvuA== - dependencies: - "@wojtekmaj/date-utils" "^1.0.2" - get-user-locale "^1.2.0" - merge-class-names "^1.1.1" - prop-types "^15.6.0" - -react-date-picker@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/react-date-picker/-/react-date-picker-8.0.3.tgz#6814e3b5f8ce0ffa9e12bbc932ab852389c56b11" - integrity sha512-X6uy0VSgW9uqYk2IaB8Y+a7IRD8JBY0Pl9kwxWepp838+ykcy/roXKZUEuW7VYQ+QUy3Vo5zUEKmeUxo56sw/A== - dependencies: - "@types/react-calendar" "^3.0.0" - "@wojtekmaj/date-utils" "^1.0.3" - get-user-locale "^1.2.0" - make-event-props "^1.1.0" - merge-class-names "^1.1.1" - prop-types "^15.6.0" - react-calendar "^3.0.0" - react-fit "^1.0.3" - update-input-width "^1.1.1" - react-datepicker@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.3.0.tgz#38dec531fd7c8e0de6860a55dfbc3a8ff803d43c" @@ -9404,40 +9193,15 @@ react-error-overlay@^6.0.7: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== -react-fast-compare@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-fit@^1.0.3: - version "1.3.1" - resolved "https://registry.yarnpkg.com/react-fit/-/react-fit-1.3.1.tgz#850cb5d554fdfa4b27891f62a9d290d3e7eda57b" - integrity sha512-MmVk/SXyVbxiz9peAeD7fWxFdGLoy/sCxte01M3w74regPIVkLqc2yT0wUAGRd1MNP1fQ40MqYKNBLpbK/aI1w== - dependencies: - detect-element-overflow "^1.2.0" - prop-types "^15.6.0" - -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== - dependencies: - object-assign "^4.1.1" - prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" - react-hook-form@^6.9.0: version "6.9.5" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.9.5.tgz#a700ff55987c4409d938f3609f06bd516e8a86d7" integrity sha512-kkUm6b4u1Iy3wCdHA0fal23sjGQMg8BBRAT3KBG9PEdls5e+7OX2Df20oBPgpXxo/GaIwk2Lh5DeVv5OeVjKsg== -react-input-autosize@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" - integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== - dependencies: - prop-types "^15.5.8" +react-idle-timer@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-idle-timer/-/react-idle-timer-4.4.2.tgz#52bd8798d1bc8107548fedfab955be1e4a99d9c7" + integrity sha512-ORLyVFXj/4tTZL63ztbJDtPqQK2LzZw/QXSMakTR/VGdL0VQqJ6Zg43HJmY6HcwUj8i5bjvf8gJYl5s7N+9eiw== react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" @@ -9559,35 +9323,6 @@ react-scripts@^3.4.4: optionalDependencies: fsevents "2.1.2" -react-select@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27" - integrity sha512-wBFVblBH1iuCBprtpyGtd1dGMadsG36W5/t2Aj8OE6WbByDg5jIFyT7X5gT+l0qmT5TqWhxX+VsKJvCEl2uL9g== - dependencies: - "@babel/runtime" "^7.4.4" - "@emotion/cache" "^10.0.9" - "@emotion/core" "^10.0.9" - "@emotion/css" "^10.0.9" - memoize-one "^5.0.0" - prop-types "^15.6.0" - react-input-autosize "^2.2.2" - react-transition-group "^4.3.0" - -react-side-effect@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.0.tgz#1ce4a8b4445168c487ed24dab886421f74d380d3" - integrity sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg== - -react-transition-group@^4.3.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" - integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - react@^16.10.0, react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -10446,7 +10181,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -11193,11 +10928,6 @@ upath@^1.1.1: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-input-width@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/update-input-width/-/update-input-width-1.2.1.tgz#769d6182413590c3b50b52ffa9c65d79e2c17f95" - integrity sha512-zygDshqDb2C2/kgfoD423n5htv/3OBF7aTaz2u2zZy998EJki8njOHOeZjKEd8XSYeDziIX1JXfMsKaIRJeJ/Q== - uri-js@^4.2.2: version "4.4.0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" diff --git a/src/app.js b/src/app.js index bcf653c347..74d5a62666 100644 --- a/src/app.js +++ b/src/app.js @@ -28,7 +28,9 @@ app.use(session({ cookie: { httpOnly: true, sameSite: 'strict', + maxAge: Number(process.env.SESSION_TIMEOUT), }, + rolling: true, store: new MemoryStore({ // Potentially change this to a different store checkPeriod: 86400000, // prune expired entries every 24h }),