misc: added timer

This commit is contained in:
Sheen Capadngan
2024-11-21 04:09:19 +08:00
parent bce3f3d676
commit 00dcadbc08
2 changed files with 71 additions and 8 deletions

View File

@ -65,7 +65,10 @@ export const TotpProvider = (): TDynamicProviderFns => {
authenticatorInstance.options = { step: period };
}
return { entityId, data: { TOTP: authenticatorInstance.generate(secret) } };
return {
entityId,
data: { TOTP: authenticatorInstance.generate(secret), TIME_REMAINING: authenticatorInstance.timeRemaining() }
};
};
const revoke = async (_inputs: unknown, entityId: string) => {

View File

@ -1,4 +1,4 @@
import { ReactNode, useEffect } from "react";
import { ReactNode, useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -62,7 +62,60 @@ const OutputDisplay = ({
);
};
const renderOutputForm = (provider: DynamicSecretProviders, data: unknown) => {
const TotpOutputDisplay = ({
totp,
remainingSeconds,
triggerLeaseCreation
}: {
totp: string;
remainingSeconds: number;
triggerLeaseCreation: (details: { ttl?: string }) => Promise<void>;
}) => {
const [remainingTime, setRemainingTime] = useState(remainingSeconds);
const [shouldShowRegenerate, setShouldShowRegenerate] = useToggle(false);
useEffect(() => {
setRemainingTime(remainingSeconds);
setShouldShowRegenerate.off();
// Set up countdown interval
const intervalId = setInterval(() => {
setRemainingTime((prevTime) => {
if (prevTime <= 1) {
clearInterval(intervalId);
setShouldShowRegenerate.on();
return 0;
}
return prevTime - 1;
});
}, 1000);
// Cleanup interval on unmount or when totp changes
return () => clearInterval(intervalId);
}, [totp, remainingSeconds]);
return (
<div>
<OutputDisplay label="Time-based one-time password" value={totp} />
{remainingTime > 0 && (
<div>
Valid for {remainingTime} {remainingTime > 1 ? "seconds" : "second"}
</div>
)}
{shouldShowRegenerate && (
<Button colorSchema="secondary" className="mt-2" onClick={() => triggerLeaseCreation({})}>
Regenerate
</Button>
)}
</div>
);
};
const renderOutputForm = (
provider: DynamicSecretProviders,
data: unknown,
triggerLeaseCreation: (details: { ttl?: string }) => Promise<void>
) => {
if (
provider === DynamicSecretProviders.SqlDatabase ||
provider === DynamicSecretProviders.Cassandra ||
@ -251,14 +304,17 @@ const renderOutputForm = (provider: DynamicSecretProviders, data: unknown) => {
}
if (provider === DynamicSecretProviders.Totp) {
const { TOTP } = data as {
const { TOTP, TIME_REMAINING } = data as {
TOTP: string;
TIME_REMAINING: number;
};
return (
<div>
<OutputDisplay label="Time-based one-time password" value={TOTP} />
</div>
<TotpOutputDisplay
totp={TOTP}
remainingSeconds={TIME_REMAINING}
triggerLeaseCreation={triggerLeaseCreation}
/>
);
}
@ -391,7 +447,11 @@ export const CreateDynamicSecretLease = ({
animate={{ opacity: 1, translateX: 0 }}
exit={{ opacity: 0, translateX: 30 }}
>
{renderOutputForm(provider, createDynamicSecretLease.data?.data)}
{renderOutputForm(
provider,
createDynamicSecretLease.data?.data,
handleDynamicSecretLeaseCreate
)}
</motion.div>
)}
</AnimatePresence>