mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 18:29:07 +00:00
124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import { useEffect } from "react";
|
|
import { useForm } from "react-hook-form";
|
|
import { faGithub, faGitlab, faGoogle, IconDefinition } from "@fortawesome/free-brands-svg-icons";
|
|
import { faEnvelope } from "@fortawesome/free-regular-svg-icons";
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
import * as yup from "yup";
|
|
|
|
import { createNotification } from "@app/components/notifications";
|
|
import { Switch } from "@app/components/v2";
|
|
import { useUser } from "@app/context";
|
|
import { useUpdateUserAuthMethods } from "@app/hooks/api";
|
|
import { AuthMethod } from "@app/hooks/api/users/types";
|
|
|
|
interface AuthMethodOption {
|
|
label: string;
|
|
value: AuthMethod;
|
|
icon: IconDefinition;
|
|
}
|
|
|
|
const authMethodOpts: AuthMethodOption[] = [
|
|
{ label: "Email", value: AuthMethod.EMAIL, icon: faEnvelope },
|
|
{ label: "Google", value: AuthMethod.GOOGLE, icon: faGoogle },
|
|
{ label: "GitHub", value: AuthMethod.GITHUB, icon: faGithub },
|
|
{ label: "GitLab", value: AuthMethod.GITLAB, icon: faGitlab }
|
|
];
|
|
|
|
const schema = yup.object({
|
|
authMethods: yup.array().required("Auth method is required")
|
|
});
|
|
|
|
export type FormData = yup.InferType<typeof schema>;
|
|
|
|
export const AuthMethodSection = () => {
|
|
|
|
const { user } = useUser();
|
|
const { mutateAsync } = useUpdateUserAuthMethods();
|
|
|
|
const { reset, setValue, watch } = useForm<FormData>({
|
|
defaultValues: {
|
|
authMethods: user.authMethods
|
|
},
|
|
resolver: yupResolver(schema)
|
|
});
|
|
|
|
const authMethods = watch("authMethods");
|
|
|
|
useEffect(() => {
|
|
if (user) {
|
|
reset({
|
|
authMethods: user.authMethods
|
|
});
|
|
}
|
|
}, [user]);
|
|
|
|
const onAuthMethodToggle = async (value: boolean, authMethodOpt: AuthMethodOption) => {
|
|
const newAuthMethods = value
|
|
? [...authMethods, authMethodOpt.value]
|
|
: authMethods.filter((auth) => auth !== authMethodOpt.value);
|
|
|
|
if (value) {
|
|
const newUser = await mutateAsync({
|
|
authMethods: newAuthMethods
|
|
});
|
|
|
|
setValue("authMethods", newUser.authMethods);
|
|
createNotification({
|
|
text: "Successfully enabled authentication method",
|
|
type: "success"
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (newAuthMethods.length === 0) {
|
|
createNotification({
|
|
text: "You must keep at least 1 authentication method enabled",
|
|
type: "error"
|
|
});
|
|
return;
|
|
}
|
|
|
|
const newUser = await mutateAsync({
|
|
authMethods: newAuthMethods
|
|
});
|
|
|
|
setValue("authMethods", newUser.authMethods);
|
|
createNotification({
|
|
text: "Successfully disabled authentication method",
|
|
type: "success"
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
|
<h2 className="mb-8 flex-1 text-xl font-semibold text-mineshaft-100">
|
|
Authentication methods
|
|
</h2>
|
|
<p className="mb-4 text-gray-400">
|
|
By enabling a SSO provider, you are allowing an account with that provider which uses the
|
|
same email address as your existing Infisical account to be able to log in to Infisical.
|
|
</p>
|
|
<div className="mb-4">
|
|
{user &&
|
|
authMethodOpts.map((authMethodOpt) => {
|
|
return (
|
|
<div className="flex items-center p-4" key={`auth-method-${authMethodOpt.value}`}>
|
|
<div className="flex items-center">
|
|
<FontAwesomeIcon icon={authMethodOpt.icon} className="mr-4" />
|
|
</div>
|
|
<Switch
|
|
id={`enable-${authMethodOpt.value}-auth`}
|
|
onCheckedChange={(value) => onAuthMethodToggle(value, authMethodOpt)}
|
|
isChecked={authMethods?.includes(authMethodOpt.value) ?? false}
|
|
>
|
|
<p className="mr-4 w-12">{authMethodOpt.label}</p>
|
|
</Switch>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|