diff --git a/frontend/src/helpers/datetime.ts b/frontend/src/helpers/datetime.ts
index 3dd57cf52..d8a5e90c6 100644
--- a/frontend/src/helpers/datetime.ts
+++ b/frontend/src/helpers/datetime.ts
@@ -23,29 +23,6 @@ export const formatDateTime = ({
return format(date, dateFormat);
};
-// Helper function to convert duration to seconds
-export const durationToSeconds = (
- value: number,
- unit: "s" | "m" | "h" | "d" | "w" | "y"
-): number => {
- switch (unit) {
- case "s":
- return value;
- case "m":
- return value * 60;
- case "h":
- return value * 60 * 60;
- case "d":
- return value * 60 * 60 * 24;
- case "w":
- return value * 60 * 60 * 24 * 7;
- case "y":
- return value * 60 * 60 * 24 * 365;
- default:
- return 0;
- }
-};
-
// Helper function to convert seconds to value and unit
export const getObjectFromSeconds = (
totalSeconds: number,
diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx
index 9681461e6..3fb7a3acc 100644
--- a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx
+++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx
@@ -3,6 +3,7 @@ import { Controller, useFieldArray, useForm } from "react-hook-form";
import { faPlus, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
+import ms from "ms";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
@@ -20,7 +21,7 @@ import {
Tabs
} from "@app/components/v2";
import { useOrganization, useSubscription } from "@app/context";
-import { durationToSeconds, getObjectFromSeconds } from "@app/helpers/datetime";
+import { getObjectFromSeconds } from "@app/helpers/datetime";
import {
useAddIdentityUniversalAuth,
useGetIdentityUniversalAuth,
@@ -117,11 +118,9 @@ const schema = z
if (isAnyParseError) return;
- const lockoutDurationInSeconds = durationToSeconds(parsedLockoutDuration, lockoutDurationUnit);
- const lockoutCounterResetInSeconds = durationToSeconds(
- parsedLockoutCounterReset,
- lockoutCounterResetUnit
- );
+ const lockoutDurationInSeconds = ms(`${parsedLockoutDuration}${lockoutDurationUnit}`) / 1000;
+ const lockoutCounterResetInSeconds =
+ ms(`${parsedLockoutCounterReset}${lockoutCounterResetUnit}`) / 1000;
if (lockoutDurationInSeconds > 86400 || lockoutDurationInSeconds < 30) {
ctx.addIssue({
@@ -279,14 +278,9 @@ export const IdentityUniversalAuthForm = ({
try {
if (!identityId) return;
- const lockoutDurationSeconds = durationToSeconds(
- Number(lockoutDurationValue),
- lockoutDurationUnit
- );
- const lockoutCounterResetSeconds = durationToSeconds(
- Number(lockoutCounterResetValue),
- lockoutCounterResetUnit
- );
+ const lockoutDurationSeconds = ms(`${lockoutDurationValue}${lockoutDurationUnit}`) / 1000;
+ const lockoutCounterResetSeconds =
+ ms(`${lockoutCounterResetValue}${lockoutCounterResetUnit}`) / 1000;
if (data) {
// update universal auth configuration
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx
index 1b7cb956b..446e54885 100644
--- a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx
+++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx
@@ -118,6 +118,7 @@ const Page = () => {
authMethod={popUp.viewAuthMethod.data?.authMethod}
lockedOut={popUp.viewAuthMethod.data?.lockedOut || false}
identityId={identityId}
+ onResetAllLockouts={popUp.viewAuthMethod.data?.refetchIdentity}
/>
);
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx
index 61268070b..a1051afb8 100644
--- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx
+++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx
@@ -2,7 +2,7 @@ import { faCog, faLock, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { OrgPermissionCan } from "@app/components/permissions";
-import { Button } from "@app/components/v2";
+import { Button, Tooltip } from "@app/components/v2";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/context";
import { IdentityAuthMethod, identityAuthToNameMap, useGetIdentityById } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
@@ -16,7 +16,7 @@ type Props = {
};
export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: Props) => {
- const { data } = useGetIdentityById(identityId);
+ const { data, refetch } = useGetIdentityById(identityId);
return data ? (
@@ -31,7 +31,8 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
onClick={() =>
handlePopUpOpen("viewAuthMethod", {
authMethod,
- lockedOut: data.identity.activeLockoutAuthMethods.includes(authMethod)
+ lockedOut: data.identity.activeLockoutAuthMethods.includes(authMethod),
+ refetchIdentity: refetch
})
}
type="button"
@@ -40,7 +41,9 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
{identityAuthToNameMap[authMethod]}
{data.identity.activeLockoutAuthMethods.includes(authMethod) && (
-
+
+
+
)}
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx
index 7236d4c27..f95a20789 100644
--- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx
+++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx
@@ -41,6 +41,7 @@ type Props = {
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
onDeleteAuthMethod: () => void;
+ onResetAllLockouts: () => void;
};
type TRevokeOptions = {
@@ -52,8 +53,12 @@ export const Content = ({
identityId,
authMethod,
lockedOut,
- onDeleteAuthMethod
-}: Pick
) => {
+ onDeleteAuthMethod,
+ onResetAllLockouts
+}: Pick<
+ Props,
+ "authMethod" | "lockedOut" | "identityId" | "onDeleteAuthMethod" | "onResetAllLockouts"
+>) => {
const { currentOrg } = useOrganization();
const orgId = currentOrg?.id || "";
@@ -161,6 +166,7 @@ export const Content = ({
) => {
if (!identityId || !authMethod) return null;
@@ -200,6 +207,7 @@ export const ViewIdentityAuthModal = ({
authMethod={authMethod}
lockedOut={lockedOut}
onDeleteAuthMethod={() => onOpenChange(false)}
+ onResetAllLockouts={() => onResetAllLockouts()}
/>
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityUniversalAuthContent.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityUniversalAuthContent.tsx
index 70f7e6948..a9cb5a1d1 100644
--- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityUniversalAuthContent.tsx
+++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityUniversalAuthContent.tsx
@@ -26,7 +26,8 @@ export const ViewIdentityUniversalAuthContent = ({
handlePopUpOpen,
onDelete,
popUp,
- lockedOut
+ lockedOut,
+ onResetAllLockouts
}: ViewAuthMethodProps) => {
const { data, isPending } = useGetIdentityUniversalAuth(identityId);
const { data: clientSecrets = [], isPending: clientSecretsPending } =
@@ -48,6 +49,7 @@ export const ViewIdentityUniversalAuthContent = ({
type: "success"
});
setLockedOutState(false);
+ onResetAllLockouts();
} catch (error) {
console.error(error);
createNotification({
@@ -124,7 +126,7 @@ export const ViewIdentityUniversalAuthContent = ({
isLoading={isClearLockoutsPending}
colorSchema="secondary"
>
- Clear All Lockouts
+ Reset All Lockouts
)}
diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/types/index.ts b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/types/index.ts
index c566040b4..da31a233c 100644
--- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/types/index.ts
+++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/types/index.ts
@@ -10,4 +10,5 @@ export type ViewAuthMethodProps = {
) => void;
popUp: UsePopUpState<["revokeAuthMethod", "upgradePlan", "identityAuthMethod"]>;
lockedOut: boolean;
+ onResetAllLockouts: () => void;
};
diff --git a/frontend/src/pages/organization/SecretSharingSettingsPage/components/OrgSecretShareLimitSection/OrgSecretShareLimitSection.tsx b/frontend/src/pages/organization/SecretSharingSettingsPage/components/OrgSecretShareLimitSection/OrgSecretShareLimitSection.tsx
index b3e4976f3..cc90cd43f 100644
--- a/frontend/src/pages/organization/SecretSharingSettingsPage/components/OrgSecretShareLimitSection/OrgSecretShareLimitSection.tsx
+++ b/frontend/src/pages/organization/SecretSharingSettingsPage/components/OrgSecretShareLimitSection/OrgSecretShareLimitSection.tsx
@@ -1,13 +1,14 @@
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
+import ms from "ms";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import { Button, FormControl, Input, Select, SelectItem } from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
-import { durationToSeconds, getObjectFromSeconds } from "@app/helpers/datetime";
+import { getObjectFromSeconds } from "@app/helpers/datetime";
import { useUpdateOrg } from "@app/hooks/api";
const MAX_SHARED_SECRET_LIFETIME_SECONDS = 30 * 24 * 60 * 60; // 30 days in seconds
@@ -25,7 +26,7 @@ const formSchema = z
.superRefine((data, ctx) => {
const { maxLifetimeValue, maxLifetimeUnit } = data;
- const durationInSeconds = durationToSeconds(maxLifetimeValue, maxLifetimeUnit);
+ const durationInSeconds = ms(`${maxLifetimeValue}${maxLifetimeUnit}`) / 1000;
if (durationInSeconds > MAX_SHARED_SECRET_LIFETIME_SECONDS) {
ctx.addIssue({
@@ -90,10 +91,8 @@ export const OrgSecretShareLimitSection = () => {
const handleFormSubmit = async (formData: TForm) => {
try {
- const maxSharedSecretLifetimeSeconds = durationToSeconds(
- formData.maxLifetimeValue,
- formData.maxLifetimeUnit
- );
+ const maxSharedSecretLifetimeSeconds =
+ ms(`${formData.maxLifetimeValue}${formData.maxLifetimeUnit}`) / 1000;
await mutateAsync({
orgId: currentOrg.id,