mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: public page shows left views or time on shared secret
This commit is contained in:
@@ -8,9 +8,7 @@ export const useGetSharedSecrets = () => {
|
||||
return useQuery({
|
||||
queryKey: ["sharedSecrets"],
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TSharedSecret[]>(
|
||||
"/api/v1/secret-sharing/"
|
||||
);
|
||||
const { data } = await apiRequest.get<TSharedSecret[]>("/api/v1/secret-sharing/");
|
||||
return data;
|
||||
}
|
||||
});
|
||||
@@ -23,11 +21,11 @@ export const useGetActiveSharedSecretByIdAndHashedHex = (id: string, hashedHex:
|
||||
`/api/v1/secret-sharing/public/${id}?hashedHex=${hashedHex}`
|
||||
);
|
||||
return {
|
||||
name: data.name,
|
||||
encryptedValue: data.encryptedValue,
|
||||
iv: data.iv,
|
||||
tag: data.tag,
|
||||
expiresAt: data.expiresAt
|
||||
expiresAt: data.expiresAt,
|
||||
expiresAfterViews: data.expiresAfterViews
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,14 +21,18 @@ export const ShareSecretPublicPage = () => {
|
||||
}
|
||||
}, [id, publicKey]);
|
||||
|
||||
const { isLoading, data } = useGetActiveSharedSecretByIdAndHashedHex(id as string, hashedHex as string );
|
||||
const { isLoading, data } = useGetActiveSharedSecretByIdAndHashedHex(
|
||||
id as string,
|
||||
hashedHex as string
|
||||
);
|
||||
|
||||
const decryptedSecret = useMemo(() => {
|
||||
if (data && data.encryptedValue && publicKey) {
|
||||
const res = decryptSymmetric({
|
||||
ciphertext: data.encryptedValue,
|
||||
iv: data.iv,
|
||||
tag: data.tag,
|
||||
key,
|
||||
key
|
||||
});
|
||||
return res;
|
||||
}
|
||||
@@ -37,7 +41,7 @@ export const ShareSecretPublicPage = () => {
|
||||
|
||||
const [timeLeft, setTimeLeft] = useState("");
|
||||
const [isUrlCopied, , setIsUrlCopied] = useTimedReset<boolean>({
|
||||
initialState: false,
|
||||
initialState: false
|
||||
});
|
||||
|
||||
const millisecondsPerDay = 1000 * 60 * 60 * 24;
|
||||
@@ -46,18 +50,26 @@ export const ShareSecretPublicPage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const updateTimer = () => {
|
||||
if (data && data.expiresAt) {
|
||||
const expirationTime = new Date(data.expiresAt).getTime();
|
||||
const currentTime = new Date().getTime();
|
||||
const timeDifference = expirationTime - currentTime;
|
||||
if (data) {
|
||||
if (data.expiresAt) {
|
||||
const expirationTime = new Date(data.expiresAt).getTime();
|
||||
const currentTime = new Date().getTime();
|
||||
const timeDifference = expirationTime - currentTime;
|
||||
|
||||
if (timeDifference < 0) {
|
||||
setTimeLeft("Expired");
|
||||
} else {
|
||||
const hoursRemaining = Math.floor((timeDifference % millisecondsPerDay) / millisecondsPerHour);
|
||||
const minutesRemaining = Math.floor((timeDifference % millisecondsPerHour) / millisecondsPerMinute);
|
||||
const secondsRemaining = Math.floor((timeDifference % millisecondsPerMinute) / 1000);
|
||||
setTimeLeft(`${hoursRemaining}h ${minutesRemaining}m ${secondsRemaining}s`);
|
||||
if (timeDifference < 0) {
|
||||
setTimeLeft("Expired");
|
||||
} else {
|
||||
const hoursRemaining = Math.floor(
|
||||
(timeDifference % millisecondsPerDay) / millisecondsPerHour
|
||||
);
|
||||
const minutesRemaining = Math.floor(
|
||||
(timeDifference % millisecondsPerHour) / millisecondsPerMinute
|
||||
);
|
||||
const secondsRemaining = Math.floor((timeDifference % millisecondsPerMinute) / 1000);
|
||||
setTimeLeft(`${hoursRemaining}h ${minutesRemaining}m ${secondsRemaining}s`);
|
||||
}
|
||||
} else if (data.expiresAfterViews) {
|
||||
setTimeLeft(`${data.expiresAfterViews - 1} more views`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -72,7 +84,6 @@ export const ShareSecretPublicPage = () => {
|
||||
}
|
||||
}, [isUrlCopied]);
|
||||
|
||||
|
||||
const copyUrlToClipboard = () => {
|
||||
navigator.clipboard.writeText(decryptedSecret);
|
||||
setIsUrlCopied(true);
|
||||
|
||||
@@ -37,23 +37,17 @@ export const SecretTable = ({
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th>Name</Th>
|
||||
<Th>Value</Th>
|
||||
<Th>Secret</Th>
|
||||
<Th>Valid Until</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{!isLoading && sharedSecret && decryptedSecret && (
|
||||
<Tr key={sharedSecret.name}>
|
||||
<Td>{sharedSecret.name}</Td>
|
||||
<Tr key={sharedSecret.encryptedValue}>
|
||||
<Td>
|
||||
<div className="flex items-center md:space-x-2">
|
||||
<div className="max-w-[20rem] flex-1 break-words">
|
||||
<SecretInput
|
||||
isVisible
|
||||
value={decryptedSecret}
|
||||
readOnly
|
||||
/>
|
||||
<SecretInput isVisible value={decryptedSecret} readOnly />
|
||||
</div>
|
||||
<IconButton
|
||||
ariaLabel="copy to clipboard"
|
||||
|
||||
Reference in New Issue
Block a user