fix: address changes

This commit is contained in:
Scott Wilson
2024-09-30 16:53:42 -07:00
parent f63c6b725b
commit ad88aaf17f
9 changed files with 1760 additions and 1602 deletions

View File

@@ -1,4 +1,4 @@
import { useQuery } from "@tanstack/react-query";
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
@@ -13,7 +13,8 @@ import {
IdentityMembershipOrg,
IdentityOidcAuth,
IdentityTokenAuth,
IdentityUniversalAuth} from "./types";
IdentityUniversalAuth
} from "./types";
export const identitiesKeys = {
getIdentityById: (identityId: string) => [{ identityId }, "identity"] as const,
@@ -64,9 +65,16 @@ export const useGetIdentityProjectMemberships = (identityId: string) => {
});
};
export const useGetIdentityUniversalAuth = (identityId: string) => {
export const useGetIdentityUniversalAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityUniversalAuth,
unknown,
IdentityUniversalAuth,
ReturnType<typeof identitiesKeys.getIdentityUniversalAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityUniversalAuth(identityId),
queryFn: async () => {
const {
@@ -76,8 +84,10 @@ export const useGetIdentityUniversalAuth = (identityId: string) => {
);
return identityUniversalAuth;
},
cacheTime: 0,
staleTime: 0,
cacheTime: 0
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
@@ -96,9 +106,16 @@ export const useGetIdentityUniversalAuthClientSecrets = (identityId: string) =>
});
};
export const useGetIdentityGcpAuth = (identityId: string) => {
export const useGetIdentityGcpAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityGcpAuth,
unknown,
IdentityGcpAuth,
ReturnType<typeof identitiesKeys.getIdentityGcpAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityGcpAuth(identityId),
queryFn: async () => {
const {
@@ -109,13 +126,22 @@ export const useGetIdentityGcpAuth = (identityId: string) => {
return identityGcpAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
export const useGetIdentityAwsAuth = (identityId: string) => {
export const useGetIdentityAwsAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityAwsAuth,
unknown,
IdentityAwsAuth,
ReturnType<typeof identitiesKeys.getIdentityAwsAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityAwsAuth(identityId),
queryFn: async () => {
const {
@@ -126,13 +152,22 @@ export const useGetIdentityAwsAuth = (identityId: string) => {
return identityAwsAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
export const useGetIdentityAzureAuth = (identityId: string) => {
export const useGetIdentityAzureAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityAzureAuth,
unknown,
IdentityAzureAuth,
ReturnType<typeof identitiesKeys.getIdentityAzureAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityAzureAuth(identityId),
queryFn: async () => {
const {
@@ -143,13 +178,22 @@ export const useGetIdentityAzureAuth = (identityId: string) => {
return identityAzureAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
export const useGetIdentityKubernetesAuth = (identityId: string) => {
export const useGetIdentityKubernetesAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityKubernetesAuth,
unknown,
IdentityKubernetesAuth,
ReturnType<typeof identitiesKeys.getIdentityKubernetesAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityKubernetesAuth(identityId),
queryFn: async () => {
const {
@@ -160,13 +204,22 @@ export const useGetIdentityKubernetesAuth = (identityId: string) => {
return identityKubernetesAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
export const useGetIdentityTokenAuth = (identityId: string) => {
export const useGetIdentityTokenAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityTokenAuth,
unknown,
IdentityTokenAuth,
ReturnType<typeof identitiesKeys.getIdentityTokenAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityTokenAuth(identityId),
queryFn: async () => {
const {
@@ -177,7 +230,9 @@ export const useGetIdentityTokenAuth = (identityId: string) => {
return identityTokenAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};
@@ -196,9 +251,16 @@ export const useGetIdentityTokensTokenAuth = (identityId: string) => {
});
};
export const useGetIdentityOidcAuth = (identityId: string) => {
export const useGetIdentityOidcAuth = (
identityId: string,
options?: UseQueryOptions<
IdentityOidcAuth,
unknown,
IdentityOidcAuth,
ReturnType<typeof identitiesKeys.getIdentityOidcAuth>
>
) => {
return useQuery({
enabled: Boolean(identityId),
queryKey: identitiesKeys.getIdentityOidcAuth(identityId),
queryFn: async () => {
const {
@@ -209,6 +271,8 @@ export const useGetIdentityOidcAuth = (identityId: string) => {
return identityOidcAuth;
},
staleTime: 0,
cacheTime: 0
cacheTime: 0,
...options,
enabled: Boolean(identityId) && (options?.enabled ?? true)
});
};

View File

@@ -21,7 +21,8 @@ import {
useDeleteIdentityKubernetesAuth,
useDeleteIdentityOidcAuth,
useDeleteIdentityTokenAuth,
useDeleteIdentityUniversalAuth} from "@app/hooks/api";
useDeleteIdentityUniversalAuth
} from "@app/hooks/api";
import { IdentityAuthMethod, identityAuthToNameMap } from "@app/hooks/api/identities";
import { UsePopUpState } from "@app/hooks/usePopUp";
@@ -54,7 +55,10 @@ const identityAuthMethods = [
const schema = yup
.object({
authMethod: yup.mixed<IdentityAuthMethod>().oneOf(Object.values(IdentityAuthMethod)).required("Auth method is required")
authMethod: yup
.mixed<IdentityAuthMethod>()
.oneOf(Object.values(IdentityAuthMethod))
.required("Auth method is required")
})
.required();
@@ -71,27 +75,33 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
const initialAuthMethod = popUp?.identityAuthMethod?.data?.authMethod;
const { control, watch, setValue } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
authMethod: initialAuthMethod
}
});
const identityAuthMethodData = {
identityId: popUp?.identityAuthMethod.data?.identityId,
name: popUp?.identityAuthMethod?.data?.name,
authMethod: watch("authMethod")
} as {
identityId: string;
name: string;
authMethod?: IdentityAuthMethod;
const { control, watch, setValue, reset } = useForm<FormData>({
resolver: yupResolver(schema),
defaultValues: {
authMethod: initialAuthMethod
}
});
useEffect(() => {
// reset form on open
if (popUp.identityAuthMethod.isOpen)
reset({ authMethod: popUp?.identityAuthMethod?.data?.authMethod });
}, [popUp.identityAuthMethod.isOpen]);
const identityAuthMethodData = {
identityId: popUp?.identityAuthMethod.data?.identityId,
name: popUp?.identityAuthMethod?.data?.name,
authMethod: watch("authMethod")
} as {
identityId: string;
name: string;
authMethod?: IdentityAuthMethod;
};
useEffect(() => {
useEffect(() => {
if (identityAuthMethodData?.authMethod) {
setValue("authMethod", identityAuthMethodData.authMethod);
return;
@@ -103,7 +113,6 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
const onRevokeAuthMethodSubmit = async (authMethod: IdentityAuthMethod) => {
if (!orgId || !authMethod) return;
try {
console.log("onRevokeAuthMethodSubmit identityId: ", identityAuthMethodData);
switch (authMethod) {
case IdentityAuthMethod.UNIVERSAL_AUTH: {
await revokeUniversalAuth({
@@ -159,9 +168,7 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
}
createNotification({
text: `Successfully removed ${
identityAuthToNameMap[authMethod]
} on ${identityAuthMethodData.name}`,
text: `Successfully removed ${identityAuthToNameMap[authMethod]} on ${identityAuthMethodData.name}`,
type: "success"
});
@@ -170,9 +177,7 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
} catch (err) {
console.error(err);
createNotification({
text: `Failed to remove ${identityAuthToNameMap[authMethod]} on ${
identityAuthMethodData.name
}`,
text: `Failed to remove ${identityAuthToNameMap[authMethod]} on ${identityAuthMethodData.name}`,
type: "error"
});
}
@@ -272,7 +277,9 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
<ModalContent
title={`${
identityAuthMethodData.authMethod === initialAuthMethod ? "Update" : "Configure"
} Identity Auth Method for ${identityAuthToNameMap[identityAuthMethodData.authMethod!] ?? ""}`}
} Identity Auth Method for ${
identityAuthToNameMap[identityAuthMethodData.authMethod!] ?? ""
}`}
>
<Controller
control={control}
@@ -283,7 +290,9 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
<Select
defaultValue={field.value}
{...field}
onValueChange={(e) => {onChange(e)}}
onValueChange={(e) => {
onChange(e);
}}
className="w-full"
>
{identityAuthMethods.map(({ label, value }) => (
@@ -310,6 +319,7 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Remove"
onDeleteApproved={() => onRevokeAuthMethodSubmit(identityAuthMethodData.authMethod!)}
/>
</ModalContent>

View File

@@ -82,11 +82,12 @@ export const IdentityAwsAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityAwsAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAwsAuth();
const { data } = useGetIdentityAwsAuth(identityAuthMethodData?.identityId ?? "");
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityAwsAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
@@ -183,8 +184,7 @@ export const IdentityAwsAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
@@ -198,207 +198,216 @@ export const IdentityAwsAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="allowedPrincipalArns"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Principal ARNs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="arn:aws:iam::123456789012:role/MyRoleName, arn:aws:iam::123456789012:user/MyUserName..."
type="text"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="allowedAccountIds"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Account IDs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="123456789012, ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="https://sts.amazonaws.com/"
name="stsEndpoint"
render={({ field, fieldState: { error } }) => (
<FormControl label="STS Endpoint" isError={Boolean(error)} errorText={error?.message}>
<Input {...field} placeholder="https://sts.amazonaws.com/" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="allowedPrincipalArns"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Principal ARNs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="arn:aws:iam::123456789012:role/MyRoleName, arn:aws:iam::123456789012:user/MyUserName..."
type="text"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="allowedAccountIds"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Account IDs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="123456789012, ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="https://sts.amazonaws.com/"
name="stsEndpoint"
render={({ field, fieldState: { error } }) => (
<FormControl label="STS Endpoint" isError={Boolean(error)} errorText={error?.message}>
<Input {...field} placeholder="https://sts.amazonaws.com/" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Overwrite
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => { await revokeAuth(initialAuthMethod); handleSubmit(onFormSubmit)(); }}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}}
/>
</>
);
};

View File

@@ -70,11 +70,12 @@ export const IdentityAzureAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityAzureAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAzureAuth();
const { data } = useGetIdentityAzureAuth(identityAuthMethodData?.identityId ?? "");
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityAzureAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
@@ -172,8 +173,7 @@ export const IdentityAzureAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
@@ -187,219 +187,225 @@ export const IdentityAzureAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="tenantId"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Tenant ID"
isError={Boolean(error)}
errorText={error?.message}
isRequired
>
<Input {...field} placeholder="00000000-0000-0000-0000-000000000000" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="resource"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Resource / Audience"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="https://management.azure.com/" />
</FormControl>
)}
/>
<Controller
control={control}
name="allowedServicePrincipalIds"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Principal IDs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="00000000-0000-0000-0000-000000000000, ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="tenantId"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Tenant ID"
isError={Boolean(error)}
errorText={error?.message}
isRequired
>
<Input {...field} placeholder="00000000-0000-0000-0000-000000000000" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="resource"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Resource / Audience"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="https://management.azure.com/" />
</FormControl>
)}
/>
<Controller
control={control}
name="allowedServicePrincipalIds"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Principal IDs"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="00000000-0000-0000-0000-000000000000, ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}>
Overwrite
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => {
const result = await trigger();
if(result){
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}else{
createNotification({
text: "Please fill in all required fields",
type: "error"
});
popup.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
const result = await trigger();
if (result) {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
} else {
createNotification({
text: "Please fill in all required fields",
type: "error"
});
internalPopUpState.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</>
);
};

View File

@@ -6,7 +6,15 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, DeleteActionModal, FormControl, IconButton, Input, Select, SelectItem } from "@app/components/v2";
import {
Button,
DeleteActionModal,
FormControl,
IconButton,
Input,
Select,
SelectItem
} from "@app/components/v2";
import { useOrganization, useSubscription } from "@app/context";
import {
useAddIdentityGcpAuth,
@@ -71,17 +79,18 @@ export const IdentityGcpAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityGcpAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityGcpAuth();
const { data } = useGetIdentityGcpAuth(identityAuthMethodData?.identityId ?? "");
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityGcpAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
handleSubmit,
reset,
formState: { isSubmitting },
watch,
watch
} = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: {
@@ -180,12 +189,10 @@ export const IdentityGcpAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
reset();
} catch (err) {
createNotification({
@@ -196,231 +203,244 @@ export const IdentityGcpAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
name="type"
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl label="Type" isError={Boolean(error)} errorText={error?.message}>
<Select
defaultValue={field.value}
{...field}
onValueChange={(e) => onChange(e)}
className="w-full"
>
<SelectItem value="gce" key="gce">
GCP ID Token Auth (Recommended)
</SelectItem>
<SelectItem value="iam" key="iam">
GCP IAM Auth
</SelectItem>
</Select>
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="allowedServiceAccounts"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Account Emails"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="test@project.iam.gserviceaccount.com, 12345-compute@developer.gserviceaccount.com"
type="text"
/>
</FormControl>
)}
/>
{watchedType === "gce" && (
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
name="allowedProjects"
name="type"
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl label="Type" isError={Boolean(error)} errorText={error?.message}>
<Select
defaultValue={field.value}
{...field}
onValueChange={(e) => onChange(e)}
className="w-full"
>
<SelectItem value="gce" key="gce">
GCP ID Token Auth (Recommended)
</SelectItem>
<SelectItem value="iam" key="iam">
GCP IAM Auth
</SelectItem>
</Select>
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="allowedServiceAccounts"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Projects"
label="Allowed Service Account Emails"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="my-gcp-project, ..." />
<Input
{...field}
placeholder="test@project.iam.gserviceaccount.com, 12345-compute@developer.gserviceaccount.com"
type="text"
/>
</FormControl>
)}
/>
)}
{watchedType === "gce" && (
<Controller
control={control}
name="allowedZones"
render={({ field, fieldState: { error } }) => (
<FormControl label="Allowed Zones" isError={Boolean(error)} errorText={error?.message}>
<Input {...field} placeholder="us-west2-a, us-central1-a, ..." />
</FormControl>
)}
/>
)}
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
{watchedType === "gce" && (
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
name="allowedProjects"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Projects"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="my-gcp-project, ..." />
</FormControl>
)}
/>
<IconButton
)}
{watchedType === "gce" && (
<Controller
control={control}
name="allowedZones"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Zones"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="us-west2-a, us-central1-a, ..." />
</FormControl>
)}
/>
)}
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Overwrite
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => { await revokeAuth(initialAuthMethod); handleSubmit(onFormSubmit)(); }}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
buttonText="Overwrite"
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}}
/>
</>
);
};

View File

@@ -6,7 +6,14 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, DeleteActionModal, FormControl, IconButton, Input, TextArea } from "@app/components/v2";
import {
Button,
DeleteActionModal,
FormControl,
IconButton,
Input,
TextArea
} from "@app/components/v2";
import { useOrganization, useSubscription } from "@app/context";
import {
useAddIdentityKubernetesAuth,
@@ -73,17 +80,18 @@ export const IdentityKubernetesAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityKubernetesAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityKubernetesAuth();
const { data } = useGetIdentityKubernetesAuth(identityAuthMethodData?.identityId ?? "");
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityKubernetesAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
handleSubmit,
reset,
trigger,
formState: { isSubmitting },
formState: { isSubmitting }
} = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: {
@@ -192,8 +200,7 @@ export const IdentityKubernetesAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
@@ -207,269 +214,277 @@ export const IdentityKubernetesAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="kubernetesHost"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Kubernetes Host / Base Kubernetes API URL "
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The host string, host:port pair, or URL to the base of the Kubernetes API server. This can usually be obtained by running 'kubectl cluster-info'"
isRequired
>
<Input {...field} placeholder="https://my-example-k8s-api-host.com" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="tokenReviewerJwt"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Token Reviewer JWT"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="A long-lived service account JWT token for Infisical to access the TokenReview API to validate other service account JWT tokens submitted by applications/pods."
isRequired
>
<Input {...field} placeholder="" type="password" />
</FormControl>
)}
/>
<Controller
control={control}
name="allowedNames"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Account Names"
isError={Boolean(error)}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any service account."
errorText={error?.message}
>
<Input {...field} placeholder="service-account-1-name, service-account-1-name" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedNamespaces"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Namespaces"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any namespaces."
>
<Input {...field} placeholder="namespaceA, namespaceB" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedAudience"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Audience"
isError={Boolean(error)} errorText={error?.message}
tooltipText="An optional audience claim that the service account JWT token must have to authenticate with Infisical. Leave empty to allow any audience claim."
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="kubernetesHost"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Kubernetes Host / Base Kubernetes API URL "
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The host string, host:port pair, or URL to the base of the Kubernetes API server. This can usually be obtained by running 'kubectl cluster-info'"
isRequired
>
<Input {...field} placeholder="" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="caCert"
render={({ field, fieldState: { error } }) => (
<FormControl
label="CA Certificate"
errorText={error?.message} isError={Boolean(error)}
tooltipText="An optional PEM-encoded CA cert for the Kubernetes API server. This is used by the TLS client for secure communication with the Kubernetes API server."
>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
tooltipText="The lifetime for an acccess token in seconds. This value will be referenced at renewal time."
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum lifetime for an access token in seconds. This value will be referenced at renewal time."
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses."
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0, allowing usage from any network address."
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
<Input {...field} placeholder="https://my-example-k8s-api-host.com" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="tokenReviewerJwt"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Token Reviewer JWT"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="A long-lived service account JWT token for Infisical to access the TokenReview API to validate other service account JWT tokens submitted by applications/pods."
isRequired
>
<Input {...field} placeholder="" type="password" />
</FormControl>
)}
/>
<Controller
control={control}
name="allowedNames"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Account Names"
isError={Boolean(error)}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any service account."
errorText={error?.message}
>
<Input {...field} placeholder="service-account-1-name, service-account-1-name" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedNamespaces"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Namespaces"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any namespaces."
>
<Input {...field} placeholder="namespaceA, namespaceB" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedAudience"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Audience"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="An optional audience claim that the service account JWT token must have to authenticate with Infisical. Leave empty to allow any audience claim."
>
<Input {...field} placeholder="" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="caCert"
render={({ field, fieldState: { error } }) => (
<FormControl
label="CA Certificate"
errorText={error?.message}
isError={Boolean(error)}
tooltipText="An optional PEM-encoded CA cert for the Kubernetes API server. This is used by the TLS client for secure communication with the Kubernetes API server."
>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
tooltipText="The lifetime for an acccess token in seconds. This value will be referenced at renewal time."
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum lifetime for an access token in seconds. This value will be referenced at renewal time."
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses."
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
tooltipText="The IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0, allowing usage from any network address."
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Overwrite
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => {
const result = await trigger();
if(result){
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}else{
createNotification({
text: "Please fill in all required fields",
type: "error"
});
popup.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
const result = await trigger();
if (result) {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
} else {
createNotification({
text: "Please fill in all required fields",
type: "error"
});
internalPopUpState.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</>
);
};

View File

@@ -7,7 +7,15 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import { Button, DeleteActionModal,FormControl, IconButton, Input, TextArea, Tooltip } from "@app/components/v2";
import {
Button,
DeleteActionModal,
FormControl,
IconButton,
Input,
TextArea,
Tooltip
} from "@app/components/v2";
import { useOrganization, useSubscription } from "@app/context";
import { useAddIdentityOidcAuth, useUpdateIdentityOidcAuth } from "@app/hooks/api";
import { IdentityAuthMethod } from "@app/hooks/api/identities";
@@ -74,10 +82,11 @@ export const IdentityOidcAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityOidcAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityOidcAuth();
const { data } = useGetIdentityOidcAuth(identityAuthMethodData?.identityId ?? "");
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityOidcAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
@@ -201,8 +210,7 @@ export const IdentityOidcAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
@@ -216,344 +224,350 @@ export const IdentityOidcAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
name="oidcDiscoveryUrl"
render={({ field, fieldState: { error } }) => (
<FormControl
isRequired
label="OIDC Discovery URL"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="https://token.actions.githubusercontent.com"
type="text"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="boundIssuer"
render={({ field, fieldState: { error } }) => (
<FormControl
isRequired
label="Issuer"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
type="text"
placeholder="https://token.actions.githubusercontent.com"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="caCert"
render={({ field, fieldState: { error } }) => (
<FormControl label="CA Certificate" errorText={error?.message} isError={Boolean(error)}>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
<Controller
control={control}
name="boundSubject"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Subject"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="boundAudiences"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Audiences"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" placeholder="service1, service2" />
</FormControl>
)}
/>
{boundClaimsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`boundClaims.${index}.key`}
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Claims" : undefined}
icon={
index === 0 ? (
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
) : undefined
}
isError={Boolean(error)}
errorText={error?.message}
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
name="oidcDiscoveryUrl"
render={({ field, fieldState: { error } }) => (
<FormControl
isRequired
label="OIDC Discovery URL"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
placeholder="https://token.actions.githubusercontent.com"
type="text"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="boundIssuer"
render={({ field, fieldState: { error } }) => (
<FormControl
isRequired
label="Issuer"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
type="text"
placeholder="https://token.actions.githubusercontent.com"
/>
</FormControl>
)}
/>
<Controller
control={control}
name="caCert"
render={({ field, fieldState: { error } }) => (
<FormControl label="CA Certificate" errorText={error?.message} isError={Boolean(error)}>
<TextArea {...field} placeholder="-----BEGIN CERTIFICATE----- ..." />
</FormControl>
)}
/>
<Controller
control={control}
name="boundSubject"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Subject"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<Input
value={field.value}
onChange={(e) => field.onChange(e)}
placeholder="property"
/>
</FormControl>
);
}}
/>
<Controller
control={control}
name={`boundClaims.${index}.value`}
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
isError={Boolean(error)}
errorText={error?.message}
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="boundAudiences"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Audiences"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<Input
value={field.value}
onChange={(e) => field.onChange(e)}
placeholder="value1, value2"
/>
</FormControl>
);
}}
/>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" placeholder="service1, service2" />
</FormControl>
)}
/>
{boundClaimsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`boundClaims.${index}.key`}
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Claims" : undefined}
icon={
index === 0 ? (
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
) : undefined
}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => field.onChange(e)}
placeholder="property"
/>
</FormControl>
);
}}
/>
<Controller
control={control}
name={`boundClaims.${index}.value`}
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => field.onChange(e)}
placeholder="value1, value2"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => removeBoundClaimField(index)}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
<IconButton
onClick={() => removeBoundClaimField(index)}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() =>
appendBoundClaimField({
key: "",
value: ""
})
}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add Claims
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() =>
appendBoundClaimField({
key: "",
value: ""
})
}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add Claims
</Button>
</div>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Overwrite
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => {
const result = await trigger();
if(result){
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}else{
createNotification({
text: "Please fill in all required fields",
type: "error"
});
popup.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
const result = await trigger();
if (result) {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
} else {
createNotification({
text: "Please fill in all required fields",
type: "error"
});
internalPopUpState.handlePopUpToggle("overwriteAuthMethod", false);
}
}}
/>
</>
);
};

View File

@@ -65,10 +65,11 @@ export const IdentityTokenAuthForm = ({
const { mutateAsync: addMutateAsync } = useAddIdentityTokenAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityTokenAuth();
const { data } = useGetIdentityTokenAuth(identityAuthMethodData?.identityId ?? "");
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityTokenAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
@@ -123,180 +124,189 @@ export const IdentityTokenAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
reset();
} catch (err) {
createNotification({
text: `Failed to ${identityAuthMethodData?.authMethod === initialAuthMethod ? "update" : "configure"} identity`,
text: `Failed to ${isCurrentAuthMethod ? "update" : "configure"} identity`,
type: "error"
});
}
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
Add IP Address
</Button>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}>
Overwrite
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
: <Button
className="mr-4"
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
type="submit"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => { await revokeAuth(initialAuthMethod); handleSubmit(onFormSubmit)(); }}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}}
/>
</>
);
};

View File

@@ -86,10 +86,12 @@ export const IdentityUniversalAuthForm = ({
const { subscription } = useSubscription();
const { mutateAsync: addMutateAsync } = useAddIdentityUniversalAuth();
const { mutateAsync: updateMutateAsync } = useUpdateIdentityUniversalAuth();
const { data } = useGetIdentityUniversalAuth(identityAuthMethodData?.identityId ?? "");
const popup = usePopUp([
"overwriteAuthMethod",
] as const);
const isCurrentAuthMethod = identityAuthMethodData?.authMethod === initialAuthMethod;
const { data } = useGetIdentityUniversalAuth(identityAuthMethodData?.identityId ?? "", {
enabled: isCurrentAuthMethod
});
const internalPopUpState = usePopUp(["overwriteAuthMethod"] as const);
const {
control,
@@ -188,8 +190,7 @@ export const IdentityUniversalAuthForm = ({
handlePopUpToggle("identityAuthMethod", false);
createNotification({
text: `Successfully ${identityAuthMethodData?.authMethod === initialAuthMethod ? "updated" : "configured"
} auth method`,
text: `Successfully ${isCurrentAuthMethod ? "updated" : "configured"} auth method`,
type: "success"
});
@@ -209,234 +210,243 @@ export const IdentityUniversalAuthForm = ({
};
return (
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{clientSecretTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`clientSecretTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Client Secret Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeClientSecretTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendClientSecretTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Add IP Address
</Button>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{(initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod) ?
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => popup.handlePopUpToggle("overwriteAuthMethod", true)}
<>
<form onSubmit={handleSubmit(onFormSubmit)}>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
Overwrite
</Button>
: <Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>Submit</Button>
}
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
{clientSecretTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`clientSecretTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Client Secret Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeClientSecretTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendClientSecretTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Cancel
Add IP Address
</Button>
</div>
{identityAuthMethodData?.authMethod === initialAuthMethod && (
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller
control={control}
name={`accessTokenTrustedIps.${index}.ipAddress`}
defaultValue="0.0.0.0/0"
render={({ field, fieldState: { error } }) => {
return (
<FormControl
className="mb-0 flex-grow"
label={index === 0 ? "Access Token Trusted IPs" : undefined}
isError={Boolean(error)}
errorText={error?.message}
>
<Input
value={field.value}
onChange={(e) => {
if (subscription?.ipAllowlisting) {
field.onChange(e);
return;
}
handlePopUpOpen("upgradePlan");
}}
placeholder="123.456.789.0"
/>
</FormControl>
);
}}
/>
<IconButton
onClick={() => {
if (subscription?.ipAllowlisting) {
removeAccessTokenTrustedIp(index);
return;
}
handlePopUpOpen("upgradePlan");
}}
size="lg"
colorSchema="danger"
variant="plain"
ariaLabel="update"
className="p-3"
>
<FontAwesomeIcon icon={faXmark} />
</IconButton>
</div>
))}
<div className="my-4 ml-1">
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
variant="outline_bg"
onClick={() => {
if (subscription?.ipAllowlisting) {
appendAccessTokenTrustedIp({
ipAddress: "0.0.0.0/0"
});
return;
}
handlePopUpOpen("upgradePlan");
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
size="xs"
>
Remove Auth Method
Add IP Address
</Button>
)}
</div>
</div>
<div className="flex justify-between">
<div className="flex items-center">
{initialAuthMethod && identityAuthMethodData?.authMethod !== initialAuthMethod ? (
<Button
className="mr-4"
size="sm"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", true)}
>
Overwrite
</Button>
) : (
<Button
className="mr-4"
size="sm"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting}
>
Submit
</Button>
)}
<Button
colorSchema="secondary"
variant="plain"
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
>
Cancel
</Button>
</div>
{isCurrentAuthMethod && (
<Button
size="sm"
colorSchema="danger"
isLoading={isSubmitting}
isDisabled={isSubmitting}
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
>
Remove Auth Method
</Button>
)}
</div>
</form>
<DeleteActionModal
isOpen={popup.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${
initialAuthMethod || "the auth method"
} on ${identityAuthMethodData?.name ?? ""}?`}
onChange={(isOpen) => popup.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
onDeleteApproved={async () => { await revokeAuth(initialAuthMethod); handleSubmit(onFormSubmit)(); }}
/>
</form>
isOpen={internalPopUpState.popUp.overwriteAuthMethod?.isOpen}
title={`Are you sure want to overwrite ${initialAuthMethod || "the auth method"} on ${
identityAuthMethodData?.name ?? ""
}?`}
onChange={(isOpen) => internalPopUpState.handlePopUpToggle("overwriteAuthMethod", isOpen)}
deleteKey="confirm"
buttonText="Overwrite"
onDeleteApproved={async () => {
await revokeAuth(initialAuthMethod);
handleSubmit(onFormSubmit)();
}}
/>
</>
);
};