mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
requested changes
This commit is contained in:
@@ -367,7 +367,8 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const tokens = await identityAccessTokenDAL.find(
|
||||
{
|
||||
identityId
|
||||
identityId,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
{ offset, limit, sort: [["updatedAt", "desc"]] }
|
||||
);
|
||||
@@ -383,8 +384,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
}: TUpdateTokenAuthTokenDTO) => {
|
||||
const foundToken = await identityAccessTokenDAL.findById(tokenId);
|
||||
const foundToken = await identityAccessTokenDAL.findOne({
|
||||
id: tokenId,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
});
|
||||
if (!foundToken) throw new NotFoundError({ message: `Token with ID ${tokenId} not found` });
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new NotFoundError({ message: `Failed to find identity with ID ${foundToken.identityId}` });
|
||||
@@ -418,6 +423,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const [token] = await identityAccessTokenDAL.update(
|
||||
{
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH,
|
||||
identityId: foundToken.identityId,
|
||||
id: tokenId
|
||||
},
|
||||
@@ -438,7 +444,8 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TRevokeTokenAuthTokenDTO) => {
|
||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: tokenId,
|
||||
isAccessTokenRevoked: false
|
||||
isAccessTokenRevoked: false,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
});
|
||||
if (!identityAccessToken)
|
||||
throw new NotFoundError({
|
||||
@@ -462,9 +469,15 @@ export const identityTokenAuthServiceFactory = ({
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
|
||||
|
||||
const revokedToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, {
|
||||
isAccessTokenRevoked: true
|
||||
});
|
||||
const [revokedToken] = await identityAccessTokenDAL.update(
|
||||
{
|
||||
id: identityAccessToken.id,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
{
|
||||
isAccessTokenRevoked: true
|
||||
}
|
||||
);
|
||||
|
||||
return { revokedToken };
|
||||
};
|
||||
|
||||
@@ -18,12 +18,12 @@ export const buildAuthMethods = ({
|
||||
tokenId?: string;
|
||||
}) => {
|
||||
return [
|
||||
...(uaId ? [IdentityAuthMethod.UNIVERSAL_AUTH] : []),
|
||||
...(gcpId ? [IdentityAuthMethod.GCP_AUTH] : []),
|
||||
...(awsId ? [IdentityAuthMethod.AWS_AUTH] : []),
|
||||
...(kubernetesId ? [IdentityAuthMethod.KUBERNETES_AUTH] : []),
|
||||
...(oidcId ? [IdentityAuthMethod.OIDC_AUTH] : []),
|
||||
...(azureId ? [IdentityAuthMethod.AZURE_AUTH] : []),
|
||||
...(tokenId ? [IdentityAuthMethod.TOKEN_AUTH] : [])
|
||||
].filter((authMethod) => authMethod);
|
||||
...[uaId ? IdentityAuthMethod.UNIVERSAL_AUTH : null],
|
||||
...[gcpId ? IdentityAuthMethod.GCP_AUTH : null],
|
||||
...[awsId ? IdentityAuthMethod.AWS_AUTH : null],
|
||||
...[kubernetesId ? IdentityAuthMethod.KUBERNETES_AUTH : null],
|
||||
...[oidcId ? IdentityAuthMethod.OIDC_AUTH : null],
|
||||
...[azureId ? IdentityAuthMethod.AZURE_AUTH : null],
|
||||
...[tokenId ? IdentityAuthMethod.TOKEN_AUTH : null]
|
||||
].filter((authMethod) => authMethod) as IdentityAuthMethod[];
|
||||
};
|
||||
|
||||
@@ -1,40 +1,10 @@
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
import { useState } from "react";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
Badge,
|
||||
DeleteActionModal,
|
||||
FormControl,
|
||||
Modal,
|
||||
ModalContent,
|
||||
Select,
|
||||
SelectItem,
|
||||
Tooltip,
|
||||
UpgradePlanModal
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import {
|
||||
useDeleteIdentityAwsAuth,
|
||||
useDeleteIdentityAzureAuth,
|
||||
useDeleteIdentityGcpAuth,
|
||||
useDeleteIdentityKubernetesAuth,
|
||||
useDeleteIdentityOidcAuth,
|
||||
useDeleteIdentityTokenAuth,
|
||||
useDeleteIdentityUniversalAuth
|
||||
} from "@app/hooks/api";
|
||||
import { Modal, ModalContent } from "@app/components/v2";
|
||||
import { IdentityAuthMethod, identityAuthToNameMap } from "@app/hooks/api/identities";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
import { IdentityAwsAuthForm } from "./IdentityAwsAuthForm";
|
||||
import { IdentityAzureAuthForm } from "./IdentityAzureAuthForm";
|
||||
import { IdentityGcpAuthForm } from "./IdentityGcpAuthForm";
|
||||
import { IdentityKubernetesAuthForm } from "./IdentityKubernetesAuthForm";
|
||||
import { IdentityOidcAuthForm } from "./IdentityOidcAuthForm";
|
||||
import { IdentityTokenAuthForm } from "./IdentityTokenAuthForm";
|
||||
import { IdentityUniversalAuthForm } from "./IdentityUniversalAuthForm";
|
||||
import { IdentityAuthMethodModalContent } from "./IdentityAuthMethodModalContent";
|
||||
|
||||
type Props = {
|
||||
popUp: UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>;
|
||||
@@ -45,175 +15,13 @@ type Props = {
|
||||
) => void;
|
||||
};
|
||||
|
||||
type TRevokeOptions = {
|
||||
identityId: string;
|
||||
organizationId: string;
|
||||
};
|
||||
|
||||
type TRevokeMethods = {
|
||||
revokeMethod: (revokeOptions: TRevokeOptions) => Promise<any>;
|
||||
render: () => JSX.Element;
|
||||
};
|
||||
|
||||
const identityAuthMethods = [
|
||||
{ label: "Token Auth", value: IdentityAuthMethod.TOKEN_AUTH },
|
||||
{ label: "Universal Auth", value: IdentityAuthMethod.UNIVERSAL_AUTH },
|
||||
{ label: "Kubernetes Auth", value: IdentityAuthMethod.KUBERNETES_AUTH },
|
||||
{ label: "GCP Auth", value: IdentityAuthMethod.GCP_AUTH },
|
||||
{ label: "AWS Auth", value: IdentityAuthMethod.AWS_AUTH },
|
||||
{ label: "Azure Auth", value: IdentityAuthMethod.AZURE_AUTH },
|
||||
{ label: "OIDC Auth", value: IdentityAuthMethod.OIDC_AUTH }
|
||||
];
|
||||
|
||||
const schema = yup
|
||||
.object({
|
||||
authMethod: yup
|
||||
.mixed<IdentityAuthMethod>()
|
||||
.oneOf(Object.values(IdentityAuthMethod))
|
||||
.required("Auth method is required")
|
||||
})
|
||||
.required();
|
||||
|
||||
export type FormData = yup.InferType<typeof schema>;
|
||||
|
||||
export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?.id || "";
|
||||
|
||||
const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth();
|
||||
const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth();
|
||||
const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth();
|
||||
const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth();
|
||||
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
|
||||
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
|
||||
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
|
||||
const [selectedAuthMethod, setSelectedAuthMethod] = useState<IdentityAuthMethod | null>(null);
|
||||
|
||||
const initialAuthMethod = popUp?.identityAuthMethod?.data?.authMethod;
|
||||
|
||||
const { control, watch, setValue, reset } = useForm<FormData>({
|
||||
resolver: yupResolver(schema),
|
||||
defaultValues: {
|
||||
authMethod: initialAuthMethod
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (popUp.identityAuthMethod.isOpen) {
|
||||
reset({ authMethod: popUp?.identityAuthMethod?.data?.authMethod });
|
||||
}
|
||||
}, [popUp.identityAuthMethod.isOpen]);
|
||||
|
||||
const watchedAuthMethod = watch("authMethod");
|
||||
|
||||
const identityAuthMethodData = {
|
||||
identityId: popUp?.identityAuthMethod.data?.identityId,
|
||||
name: popUp?.identityAuthMethod?.data?.name,
|
||||
authMethod: watch("authMethod"),
|
||||
configuredAuthMethods: popUp?.identityAuthMethod?.data?.allAuthMethods
|
||||
} as {
|
||||
identityId: string;
|
||||
name: string;
|
||||
authMethod?: IdentityAuthMethod;
|
||||
configuredAuthMethods?: IdentityAuthMethod[];
|
||||
};
|
||||
|
||||
const isSelectedAuthAlreadyConfigured =
|
||||
identityAuthMethodData?.configuredAuthMethods?.includes(watchedAuthMethod);
|
||||
|
||||
useEffect(() => {
|
||||
if (popUp?.identityAuthMethod?.data?.authMethod) {
|
||||
setValue("authMethod", popUp?.identityAuthMethod?.data?.authMethod);
|
||||
} else {
|
||||
const firstAuthMethodNotConfiguredAuthMethod = identityAuthMethods.find(
|
||||
({ value }) => !identityAuthMethodData?.configuredAuthMethods?.includes(value)
|
||||
);
|
||||
|
||||
if (firstAuthMethodNotConfiguredAuthMethod) {
|
||||
setValue("authMethod", firstAuthMethodNotConfiguredAuthMethod.value);
|
||||
}
|
||||
}
|
||||
}, [popUp.identityAuthMethod.isOpen]);
|
||||
|
||||
const methodMap: Record<IdentityAuthMethod, TRevokeMethods | undefined> = {
|
||||
[IdentityAuthMethod.UNIVERSAL_AUTH]: {
|
||||
revokeMethod: revokeUniversalAuth,
|
||||
render: () => (
|
||||
<IdentityUniversalAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.OIDC_AUTH]: {
|
||||
revokeMethod: revokeOidcAuth,
|
||||
render: () => (
|
||||
<IdentityOidcAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.TOKEN_AUTH]: {
|
||||
revokeMethod: revokeTokenAuth,
|
||||
render: () => (
|
||||
<IdentityTokenAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.AZURE_AUTH]: {
|
||||
revokeMethod: revokeAzureAuth,
|
||||
render: () => (
|
||||
<IdentityAzureAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.GCP_AUTH]: {
|
||||
revokeMethod: revokeGcpAuth,
|
||||
render: () => (
|
||||
<IdentityGcpAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.KUBERNETES_AUTH]: {
|
||||
revokeMethod: revokeKubernetesAuth,
|
||||
render: () => (
|
||||
<IdentityKubernetesAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.AWS_AUTH]: {
|
||||
revokeMethod: revokeAwsAuth,
|
||||
render: () => (
|
||||
<IdentityAwsAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
const selectedMethodItem = methodMap[identityAuthMethodData.authMethod!];
|
||||
popUp?.identityAuthMethod?.data?.allAuthMethods?.includes(selectedAuthMethod);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -225,97 +33,21 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
|
||||
<ModalContent
|
||||
title={
|
||||
isSelectedAuthAlreadyConfigured
|
||||
? `Edit ${identityAuthToNameMap[identityAuthMethodData.authMethod!] ?? ""}`
|
||||
: `Create new ${identityAuthToNameMap[identityAuthMethodData.authMethod!] ?? ""}`
|
||||
? `Edit ${identityAuthToNameMap[selectedAuthMethod!] ?? ""}`
|
||||
: `Create new ${identityAuthToNameMap[selectedAuthMethod!] ?? ""}`
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="authMethod"
|
||||
defaultValue={IdentityAuthMethod.UNIVERSAL_AUTH}
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl label="Auth Method" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Select
|
||||
isDisabled={isSelectedAuthAlreadyConfigured}
|
||||
defaultValue={field.value}
|
||||
{...field}
|
||||
onValueChange={(e) => {
|
||||
const alreadyConfigured =
|
||||
popUp?.identityAuthMethod?.data?.allAuthMethods?.includes(e);
|
||||
|
||||
if (!alreadyConfigured) {
|
||||
onChange(e);
|
||||
}
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
{identityAuthMethods.map(({ label, value }) => {
|
||||
const alreadyConfigured =
|
||||
popUp?.identityAuthMethod?.data?.allAuthMethods?.includes(value);
|
||||
return (
|
||||
<Tooltip
|
||||
key={`auth-method-${value}`}
|
||||
content="Authentication method already configured"
|
||||
isDisabled={!alreadyConfigured}
|
||||
>
|
||||
<SelectItem
|
||||
isDisabled={alreadyConfigured}
|
||||
value={String(value || "")}
|
||||
key={label}
|
||||
>
|
||||
{label}{" "}
|
||||
{alreadyConfigured && !isSelectedAuthAlreadyConfigured && (
|
||||
<Badge>Configured</Badge>
|
||||
)}
|
||||
</SelectItem>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{selectedMethodItem?.render ? selectedMethodItem.render() : <div />}
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp?.upgradePlan?.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||
text="You can use IP allowlisting if you switch to Infisical's Pro plan."
|
||||
/>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
||||
title={`Are you sure want to remove ${
|
||||
identityAuthMethodData?.authMethod
|
||||
? identityAuthToNameMap[identityAuthMethodData.authMethod]
|
||||
: "the auth method"
|
||||
} on ${identityAuthMethodData?.name ?? ""}?`}
|
||||
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
||||
deleteKey="confirm"
|
||||
buttonText="Remove"
|
||||
onDeleteApproved={async () => {
|
||||
if (!identityAuthMethodData.authMethod || !orgId || !selectedMethodItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await selectedMethodItem.revokeMethod({
|
||||
identityId: identityAuthMethodData.identityId,
|
||||
organizationId: orgId
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully removed auth method",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
handlePopUpToggle("revokeAuthMethod", false);
|
||||
handlePopUpToggle("identityAuthMethod", false);
|
||||
} catch (err) {
|
||||
createNotification({
|
||||
text: "Failed to remove auth method",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
<IdentityAuthMethodModalContent
|
||||
popUp={popUp}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
identity={{
|
||||
name: popUp?.identityAuthMethod?.data?.name,
|
||||
authMethods: popUp?.identityAuthMethod?.data?.allAuthMethods,
|
||||
id: popUp?.identityAuthMethod.data?.identityId
|
||||
}}
|
||||
initialAuthMethod={initialAuthMethod}
|
||||
setSelectedAuthMethod={setSelectedAuthMethod}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
import { useCallback } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
Badge,
|
||||
DeleteActionModal,
|
||||
FormControl,
|
||||
Select,
|
||||
SelectItem,
|
||||
Tooltip,
|
||||
UpgradePlanModal
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import {
|
||||
useDeleteIdentityAwsAuth,
|
||||
useDeleteIdentityAzureAuth,
|
||||
useDeleteIdentityGcpAuth,
|
||||
useDeleteIdentityKubernetesAuth,
|
||||
useDeleteIdentityOidcAuth,
|
||||
useDeleteIdentityTokenAuth,
|
||||
useDeleteIdentityUniversalAuth
|
||||
} from "@app/hooks/api";
|
||||
import { IdentityAuthMethod, identityAuthToNameMap } from "@app/hooks/api/identities";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
import { IdentityAwsAuthForm } from "./IdentityAwsAuthForm";
|
||||
import { IdentityAzureAuthForm } from "./IdentityAzureAuthForm";
|
||||
import { IdentityGcpAuthForm } from "./IdentityGcpAuthForm";
|
||||
import { IdentityKubernetesAuthForm } from "./IdentityKubernetesAuthForm";
|
||||
import { IdentityOidcAuthForm } from "./IdentityOidcAuthForm";
|
||||
import { IdentityTokenAuthForm } from "./IdentityTokenAuthForm";
|
||||
import { IdentityUniversalAuthForm } from "./IdentityUniversalAuthForm";
|
||||
|
||||
type Props = {
|
||||
popUp: UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>;
|
||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||
handlePopUpToggle: (
|
||||
popUpName: keyof UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>,
|
||||
state?: boolean
|
||||
) => void;
|
||||
|
||||
identity: {
|
||||
name: string;
|
||||
id: string;
|
||||
authMethods: IdentityAuthMethod[];
|
||||
};
|
||||
initialAuthMethod: IdentityAuthMethod;
|
||||
setSelectedAuthMethod: (authMethod: IdentityAuthMethod) => void;
|
||||
};
|
||||
|
||||
type TRevokeOptions = {
|
||||
identityId: string;
|
||||
organizationId: string;
|
||||
};
|
||||
|
||||
type TRevokeMethods = {
|
||||
revokeMethod: (revokeOptions: TRevokeOptions) => Promise<any>;
|
||||
render: () => JSX.Element;
|
||||
};
|
||||
|
||||
const identityAuthMethods = [
|
||||
{ label: "Token Auth", value: IdentityAuthMethod.TOKEN_AUTH },
|
||||
{ label: "Universal Auth", value: IdentityAuthMethod.UNIVERSAL_AUTH },
|
||||
{ label: "Kubernetes Auth", value: IdentityAuthMethod.KUBERNETES_AUTH },
|
||||
{ label: "GCP Auth", value: IdentityAuthMethod.GCP_AUTH },
|
||||
{ label: "AWS Auth", value: IdentityAuthMethod.AWS_AUTH },
|
||||
{ label: "Azure Auth", value: IdentityAuthMethod.AZURE_AUTH },
|
||||
{ label: "OIDC Auth", value: IdentityAuthMethod.OIDC_AUTH }
|
||||
];
|
||||
|
||||
const schema = yup
|
||||
.object({
|
||||
authMethod: yup
|
||||
.mixed<IdentityAuthMethod>()
|
||||
.oneOf(Object.values(IdentityAuthMethod))
|
||||
.required("Auth method is required")
|
||||
})
|
||||
.required();
|
||||
|
||||
export type FormData = yup.InferType<typeof schema>;
|
||||
|
||||
export const IdentityAuthMethodModalContent = ({
|
||||
popUp,
|
||||
handlePopUpOpen,
|
||||
handlePopUpToggle,
|
||||
identity,
|
||||
initialAuthMethod,
|
||||
setSelectedAuthMethod
|
||||
}: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?.id || "";
|
||||
|
||||
const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth();
|
||||
const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth();
|
||||
const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth();
|
||||
const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth();
|
||||
const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth();
|
||||
const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth();
|
||||
const { mutateAsync: revokeOidcAuth } = useDeleteIdentityOidcAuth();
|
||||
|
||||
const { control, watch } = useForm<FormData>({
|
||||
resolver: yupResolver(schema),
|
||||
defaultValues: async () => {
|
||||
let authMethod = initialAuthMethod;
|
||||
|
||||
if (!authMethod) {
|
||||
const firstAuthMethodNotConfiguredAuthMethod = identityAuthMethods.find(
|
||||
({ value }) => !identity?.authMethods?.includes(value)
|
||||
);
|
||||
|
||||
if (firstAuthMethodNotConfiguredAuthMethod) {
|
||||
authMethod = firstAuthMethodNotConfiguredAuthMethod.value;
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedAuthMethod(authMethod);
|
||||
return {
|
||||
authMethod
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const watchedAuthMethod = watch("authMethod");
|
||||
|
||||
const identityAuthMethodData = {
|
||||
identityId: identity.id,
|
||||
name: identity.name,
|
||||
authMethod: watch("authMethod"),
|
||||
configuredAuthMethods: identity.authMethods
|
||||
} as {
|
||||
identityId: string;
|
||||
name: string;
|
||||
authMethod?: IdentityAuthMethod;
|
||||
configuredAuthMethods?: IdentityAuthMethod[];
|
||||
};
|
||||
|
||||
const isSelectedAuthAlreadyConfigured =
|
||||
identityAuthMethodData?.configuredAuthMethods?.includes(watchedAuthMethod);
|
||||
|
||||
const methodMap: Record<IdentityAuthMethod, TRevokeMethods | undefined> = {
|
||||
[IdentityAuthMethod.UNIVERSAL_AUTH]: {
|
||||
revokeMethod: revokeUniversalAuth,
|
||||
render: () => (
|
||||
<IdentityUniversalAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.OIDC_AUTH]: {
|
||||
revokeMethod: revokeOidcAuth,
|
||||
render: () => (
|
||||
<IdentityOidcAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.TOKEN_AUTH]: {
|
||||
revokeMethod: revokeTokenAuth,
|
||||
render: () => (
|
||||
<IdentityTokenAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.AZURE_AUTH]: {
|
||||
revokeMethod: revokeAzureAuth,
|
||||
render: () => (
|
||||
<IdentityAzureAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.GCP_AUTH]: {
|
||||
revokeMethod: revokeGcpAuth,
|
||||
render: () => (
|
||||
<IdentityGcpAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.KUBERNETES_AUTH]: {
|
||||
revokeMethod: revokeKubernetesAuth,
|
||||
render: () => (
|
||||
<IdentityKubernetesAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
[IdentityAuthMethod.AWS_AUTH]: {
|
||||
revokeMethod: revokeAwsAuth,
|
||||
render: () => (
|
||||
<IdentityAwsAuthForm
|
||||
identityAuthMethodData={identityAuthMethodData}
|
||||
handlePopUpOpen={handlePopUpOpen}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
const isAlreadyConfigured = useCallback((method: IdentityAuthMethod) => {
|
||||
return identityAuthMethodData?.configuredAuthMethods?.includes(method);
|
||||
}, []);
|
||||
|
||||
const selectedMethodItem = methodMap[identityAuthMethodData.authMethod!];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="authMethod"
|
||||
defaultValue={IdentityAuthMethod.UNIVERSAL_AUTH}
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl label="Auth Method" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Select
|
||||
isDisabled={isSelectedAuthAlreadyConfigured}
|
||||
defaultValue={field.value}
|
||||
{...field}
|
||||
onValueChange={(e) => {
|
||||
if (!isAlreadyConfigured(e as IdentityAuthMethod)) {
|
||||
setSelectedAuthMethod(e as IdentityAuthMethod);
|
||||
onChange(e);
|
||||
}
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
{identityAuthMethods.map(({ label, value }) => {
|
||||
const alreadyConfigured = isAlreadyConfigured(value);
|
||||
return (
|
||||
<Tooltip
|
||||
key={`auth-method-${value}`}
|
||||
content="Authentication method already configured"
|
||||
isDisabled={!alreadyConfigured}
|
||||
>
|
||||
<SelectItem
|
||||
isDisabled={alreadyConfigured}
|
||||
value={String(value || "")}
|
||||
key={label}
|
||||
>
|
||||
{label}{" "}
|
||||
{alreadyConfigured && !isSelectedAuthAlreadyConfigured && (
|
||||
<Badge>Configured</Badge>
|
||||
)}
|
||||
</SelectItem>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{selectedMethodItem?.render ? selectedMethodItem.render() : <div />}
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp?.upgradePlan?.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||
text="You can use IP allowlisting if you switch to Infisical's Pro plan."
|
||||
/>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
||||
title={`Are you sure want to remove ${
|
||||
identityAuthMethodData?.authMethod
|
||||
? identityAuthToNameMap[identityAuthMethodData.authMethod]
|
||||
: "the auth method"
|
||||
} on ${identityAuthMethodData?.name ?? ""}?`}
|
||||
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
||||
deleteKey="confirm"
|
||||
buttonText="Remove"
|
||||
onDeleteApproved={async () => {
|
||||
if (!identityAuthMethodData.authMethod || !orgId || !selectedMethodItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await selectedMethodItem.revokeMethod({
|
||||
identityId: identityAuthMethodData.identityId,
|
||||
organizationId: orgId
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully removed auth method",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
handlePopUpToggle("revokeAuthMethod", false);
|
||||
handlePopUpToggle("identityAuthMethod", false);
|
||||
} catch (err) {
|
||||
createNotification({
|
||||
text: "Failed to remove auth method",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user