diff --git a/monkey/monkey_island/cc/ui/package-lock.json b/monkey/monkey_island/cc/ui/package-lock.json index b10402d7bda..7202e7846fd 100644 --- a/monkey/monkey_island/cc/ui/package-lock.json +++ b/monkey/monkey_island/cc/ui/package-lock.json @@ -46,6 +46,7 @@ "react-router-dom": "6.8.2", "react-spinners": "0.13.8", "react-table": "^6.11.5", + "react-timer-hook": "^3.0.5", "react-tsparticles": "^1.43.1", "remark-breaks": "3.0.2", "request": "^2.88.2", @@ -13656,6 +13657,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-timer-hook": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-timer-hook/-/react-timer-hook-3.0.5.tgz", + "integrity": "sha512-n+98SdmYvui2ne3KyWb3Ldu4k0NYQa3g/VzW6VEIfZJ8GAk/jJsIY700M8Nd2vNSTj05c7wKyQfJBqZ0x7zfiA==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-to-print": { "version": "2.14.12", "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.12.tgz", diff --git a/monkey/monkey_island/cc/ui/package.json b/monkey/monkey_island/cc/ui/package.json index c836564c60c..55f33cc769d 100644 --- a/monkey/monkey_island/cc/ui/package.json +++ b/monkey/monkey_island/cc/ui/package.json @@ -100,6 +100,7 @@ "react-router-dom": "6.8.2", "react-spinners": "0.13.8", "react-table": "^6.11.5", + "react-timer-hook": "^3.0.5", "react-tsparticles": "^1.43.1", "remark-breaks": "3.0.2", "request": "^2.88.2", diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunManually/LocalManualRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunManually/LocalManualRunOptions.js index 1083f1deaba..1e556cc4aa3 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunManually/LocalManualRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunManually/LocalManualRunOptions.js @@ -8,6 +8,8 @@ import GenerateLocalLinuxCurl from '../commands/local_linux_curl'; import CommandDisplay from '../utils/CommandDisplay'; import {Button, Form, Col} from 'react-bootstrap'; import IslandHttpClient, { APIEndpoint } from '../../../IslandHttpClient'; +import { useTimer } from 'react-timer-hook'; +import { CommandExpirationTimer } from '../utils/CommandExpirationTimer'; const LocalManualRunOptions = (props) => { @@ -24,6 +26,12 @@ const getContents = (props) => { [OS_TYPES.LINUX_64]: 'Linux 64bit' } + const { + seconds, + minutes, + restart + } = useTimer({ expiryTimestamp: new Date(), onExpire: () => getOtp() }); + const [otp, setOtp] = useState(''); const [osType, setOsType] = useState(OS_TYPES.WINDOWS_64); const [selectedIp, setSelectedIp] = useState(props.ips[0]); @@ -52,8 +60,9 @@ const getContents = (props) => { } function getOtp() { - IslandHttpClient.get(APIEndpoint.agent_otp).then(res =>{ + IslandHttpClient.get(APIEndpoint.agent_otp).then(res => { setOtp(res.body.otp); + restart(newExpirationTime()); }); } @@ -66,6 +75,13 @@ const getContents = (props) => { } } + function newExpirationTime() { + const time = new Date(); + time.setSeconds(time.getSeconds() + 120); + console.log('timeout is now: ' + time); + return time; + } + return ( <> @@ -84,9 +100,14 @@ const getContents = (props) => { - - - +
+ +
+
+ + + +
) } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/utils/CommandExpirationTimer.tsx b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/utils/CommandExpirationTimer.tsx new file mode 100644 index 00000000000..a43e959f015 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/utils/CommandExpirationTimer.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +export function CommandExpirationTimer({ minutes, seconds }) { + + function formatDigits(number) { + return number.toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false}) + } + + function generateText() { + if (minutes === 0 && seconds === 0) { + return 'Command expired'; + } else { + return 'Command expires in: ' + formatDigits(minutes) + ':' + formatDigits(seconds); + } + } + + return ( +
+ {generateText()} +
+ ); +}