add 2fa type tracking to credentials (#3647)
This commit is contained in:
@@ -423,6 +423,7 @@ export type Createv2TaskRequest = {
|
||||
|
||||
export type PasswordCredentialApiResponse = {
|
||||
username: string;
|
||||
totp_type: "authenticator" | "email" | "text" | "none";
|
||||
};
|
||||
|
||||
export type CreditCardCredentialApiResponse = {
|
||||
@@ -459,6 +460,7 @@ export type PasswordCredential = {
|
||||
username: string;
|
||||
password: string;
|
||||
totp: string | null;
|
||||
totp_type: "authenticator" | "email" | "text" | "none";
|
||||
};
|
||||
|
||||
export type CreditCardCredential = {
|
||||
|
||||
@@ -7,6 +7,20 @@ type Props = {
|
||||
};
|
||||
|
||||
function CredentialItem({ credential }: Props) {
|
||||
const getTotpTypeDisplay = (totpType: string) => {
|
||||
switch (totpType) {
|
||||
case "authenticator":
|
||||
return "Authenticator App";
|
||||
case "email":
|
||||
return "Email";
|
||||
case "text":
|
||||
return "Text Message";
|
||||
case "none":
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex gap-5 rounded-lg bg-slate-elevation2 p-4">
|
||||
<div className="w-48 space-y-2">
|
||||
@@ -21,10 +35,18 @@ function CredentialItem({ credential }: Props) {
|
||||
<div className="shrink-0 space-y-2">
|
||||
<p className="text-sm text-slate-400">Username/Email</p>
|
||||
<p className="text-sm text-slate-400">Password</p>
|
||||
{credential.credential.totp_type !== "none" && (
|
||||
<p className="text-sm text-slate-400">2FA Type</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm">{credential.credential.username}</p>
|
||||
<p className="text-sm">{"********"}</p>
|
||||
{credential.credential.totp_type !== "none" && (
|
||||
<p className="text-sm text-blue-400">
|
||||
{getTotpTypeDisplay(credential.credential.totp_type)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -27,6 +27,7 @@ const PASSWORD_CREDENTIAL_INITIAL_VALUES = {
|
||||
username: "",
|
||||
password: "",
|
||||
totp: "",
|
||||
totp_type: "none" as "none" | "authenticator" | "email" | "text",
|
||||
};
|
||||
|
||||
const CREDIT_CARD_CREDENTIAL_INITIAL_VALUES = {
|
||||
@@ -156,6 +157,7 @@ function CredentialsModal({ onCredentialCreated }: Props) {
|
||||
username,
|
||||
password,
|
||||
totp: totp === "" ? null : totp,
|
||||
totp_type: passwordCredentialValues.totp_type,
|
||||
},
|
||||
});
|
||||
} else if (type === CredentialModalTypes.CREDIT_CARD) {
|
||||
|
||||
@@ -24,24 +24,40 @@ type Props = {
|
||||
username: string;
|
||||
password: string;
|
||||
totp: string;
|
||||
totp_type: "authenticator" | "email" | "text" | "none";
|
||||
};
|
||||
onChange: (values: {
|
||||
name: string;
|
||||
username: string;
|
||||
password: string;
|
||||
totp: string;
|
||||
totp_type: "authenticator" | "email" | "text" | "none";
|
||||
}) => void;
|
||||
};
|
||||
|
||||
function PasswordCredentialContent({
|
||||
values: { name, username, password, totp },
|
||||
values: { name, username, password, totp, totp_type },
|
||||
onChange,
|
||||
}: Props) {
|
||||
const [totpMethod, setTotpMethod] = useState<
|
||||
"text" | "email" | "authenticator"
|
||||
"authenticator" | "email" | "text"
|
||||
>("authenticator");
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
// Update totp_type when totpMethod changes
|
||||
const handleTotpMethodChange = (
|
||||
method: "authenticator" | "email" | "text",
|
||||
) => {
|
||||
setTotpMethod(method);
|
||||
onChange({
|
||||
name,
|
||||
username,
|
||||
password,
|
||||
totp: method === "authenticator" ? totp : "",
|
||||
totp_type: method,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div className="flex">
|
||||
@@ -59,6 +75,7 @@ function PasswordCredentialContent({
|
||||
username,
|
||||
password,
|
||||
totp,
|
||||
totp_type,
|
||||
})
|
||||
}
|
||||
/>
|
||||
@@ -76,6 +93,7 @@ function PasswordCredentialContent({
|
||||
username: e.target.value,
|
||||
password,
|
||||
totp,
|
||||
totp_type,
|
||||
})
|
||||
}
|
||||
/>
|
||||
@@ -95,6 +113,7 @@ function PasswordCredentialContent({
|
||||
username,
|
||||
totp,
|
||||
password: e.target.value,
|
||||
totp_type,
|
||||
})
|
||||
}
|
||||
/>
|
||||
@@ -133,7 +152,7 @@ function PasswordCredentialContent({
|
||||
"bg-slate-elevation3": totpMethod === "authenticator",
|
||||
},
|
||||
)}
|
||||
onClick={() => setTotpMethod("authenticator")}
|
||||
onClick={() => handleTotpMethodChange("authenticator")}
|
||||
>
|
||||
<QRCodeIcon className="h-6 w-6" />
|
||||
<Label>Authenticator App</Label>
|
||||
@@ -145,7 +164,7 @@ function PasswordCredentialContent({
|
||||
"bg-slate-elevation3": totpMethod === "email",
|
||||
},
|
||||
)}
|
||||
onClick={() => setTotpMethod("email")}
|
||||
onClick={() => handleTotpMethodChange("email")}
|
||||
>
|
||||
<EnvelopeClosedIcon className="h-6 w-6" />
|
||||
<Label>Email</Label>
|
||||
@@ -157,7 +176,7 @@ function PasswordCredentialContent({
|
||||
"bg-slate-elevation3": totpMethod === "text",
|
||||
},
|
||||
)}
|
||||
onClick={() => setTotpMethod("text")}
|
||||
onClick={() => handleTotpMethodChange("text")}
|
||||
>
|
||||
<MobileIcon className="h-6 w-6" />
|
||||
<Label>Text Message</Label>
|
||||
@@ -202,6 +221,7 @@ function PasswordCredentialContent({
|
||||
username,
|
||||
password,
|
||||
totp: e.target.value,
|
||||
totp_type,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user