mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 12:04:03 +00:00
Finish preliminary email validation, merge user flow w saml/ldap
This commit is contained in:
+2
-6
@@ -6,11 +6,11 @@ import ReactCodeInput from "react-code-input";
|
||||
import Error from "@app/components/basic/Error";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button } from "@app/components/v2";
|
||||
import { useUser } from "@app/context";
|
||||
import {
|
||||
fetchUsersWithMyEmail,
|
||||
useSendEmailVerificationCode,
|
||||
useVerifyEmailVerificationCode} from "@app/hooks/api";
|
||||
useVerifyEmailVerificationCode
|
||||
} from "@app/hooks/api";
|
||||
|
||||
type Props = {
|
||||
email: string;
|
||||
@@ -56,7 +56,6 @@ const propsPhone = {
|
||||
} as const;
|
||||
|
||||
export const EmailConfirmationStep = ({ email, setStep }: Props) => {
|
||||
const { user } = useUser();
|
||||
const [code, setCode] = useState("");
|
||||
const [codeError, setCodeError] = useState(false);
|
||||
const [isResendingVerificationEmail] = useState(false);
|
||||
@@ -106,9 +105,6 @@ export const EmailConfirmationStep = ({ email, setStep }: Props) => {
|
||||
<p className="text-md flex justify-center text-bunker-200">
|
||||
We've sent a verification code to {email}
|
||||
</p>
|
||||
<p className="text-md my-1 flex justify-center font-semibold text-bunker-200">
|
||||
{user?.email}
|
||||
</p>
|
||||
<div className="mx-auto hidden w-max min-w-[20rem] md:block">
|
||||
<ReactCodeInput
|
||||
name=""
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { faUsers } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
@@ -5,6 +6,8 @@ import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
Button,
|
||||
EmptyState,
|
||||
Modal,
|
||||
ModalContent,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
@@ -15,28 +18,49 @@ import {
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { useListUsersWithMyEmail, useMergeUsers } from "@app/hooks/api";
|
||||
import { UserAliasType } from "@app/hooks/api/users/types";
|
||||
|
||||
type Props = {
|
||||
username: string;
|
||||
authType?: UserAliasType;
|
||||
organizationSlug: string;
|
||||
};
|
||||
|
||||
export const MergeUsersStep = ({ username }: Props) => {
|
||||
export const MergeUsersStep = ({ username, authType, organizationSlug }: Props) => {
|
||||
const router = useRouter();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [targetUsername, setTargetUsername] = useState("");
|
||||
const { data: users, isLoading: isLoadingUsers } = useListUsersWithMyEmail();
|
||||
const { mutateAsync: mergeUser, isLoading: isLoadingMerge } = useMergeUsers();
|
||||
const handleMergeUser = async (targetUsername: string) => {
|
||||
const handleMergeUser = async (mergeWithUsername: string) => {
|
||||
try {
|
||||
console.log("merge A");
|
||||
await mergeUser({ username: targetUsername });
|
||||
// TODO: logout, make user re-login
|
||||
console.log("merge B");
|
||||
if (!mergeWithUsername) return;
|
||||
await mergeUser({ username: mergeWithUsername });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully merged user",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
router.push("/login");
|
||||
setIsOpen(false);
|
||||
|
||||
switch (authType) {
|
||||
case UserAliasType.SAML: {
|
||||
window.open(`/api/v1/sso/redirect/saml2/organizations/${organizationSlug}`);
|
||||
window.close();
|
||||
break;
|
||||
}
|
||||
case UserAliasType.LDAP: {
|
||||
router.push(`/login/ldap?organizationSlug=${organizationSlug}`);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
router.push("/login");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setTargetUsername("");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
createNotification({
|
||||
@@ -72,14 +96,16 @@ export const MergeUsersStep = ({ username }: Props) => {
|
||||
return (
|
||||
<Tr className="h-10 items-center" key={`same-email-user-${user.id}`}>
|
||||
<Td>{`${user.firstName ?? ""} ${user.lastName ?? ""}`}</Td>
|
||||
<Td>{username}</Td>
|
||||
<Td>{user.username}</Td>
|
||||
<Td>
|
||||
<Button
|
||||
isLoading={isLoadingMerge}
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handleMergeUser(user.username)}
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
setTargetUsername(user.username);
|
||||
}}
|
||||
>
|
||||
Merge
|
||||
</Button>
|
||||
@@ -97,6 +123,35 @@ export const MergeUsersStep = ({ username }: Props) => {
|
||||
</TBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Modal isOpen={isOpen} onOpenChange={setIsOpen}>
|
||||
<ModalContent title="Merge User Confirmation">
|
||||
<p className="mb-4 text-bunker-300">
|
||||
The merge operation will transfer / consolidate your existing organization membership to
|
||||
the target user you're merging with.
|
||||
</p>
|
||||
<p className="mb-4 text-bunker-300">
|
||||
If the target user is not yet part of the same organization, then they will be added to
|
||||
it under your current organization membership. Conversely, if the target user is already
|
||||
part of the organization, then their existing organization membership will remain.
|
||||
</p>
|
||||
<p className="text-bunker-300">
|
||||
Once the merge operation is complete, you'll be prompted to re-login.
|
||||
</p>
|
||||
<div className="mt-8 flex items-center">
|
||||
<Button
|
||||
isLoading={isLoadingMerge}
|
||||
colorSchema="primary"
|
||||
onClick={async () => handleMergeUser(targetUsername)}
|
||||
className="mr-4"
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
<Button colorSchema="secondary" variant="plain" onClick={() => setIsOpen(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
import { Button, Input } from "@app/components/v2";
|
||||
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||
import { sendEmailVerificationCode } from "@app/hooks/api/users/mutation";
|
||||
import ProjectService from "@app/services/ProjectService";
|
||||
|
||||
// eslint-disable-next-line new-cap
|
||||
@@ -205,10 +206,11 @@ export const UserInfoSSOStep = ({
|
||||
|
||||
if (email) {
|
||||
// move to verify email
|
||||
await sendEmailVerificationCode();
|
||||
setStep(1);
|
||||
} else {
|
||||
// move to backup PDF step
|
||||
setStep(2);
|
||||
setStep(3);
|
||||
}
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
|
||||
Reference in New Issue
Block a user