import { PAGES } from "@/accounts/constants/pages"; import { generateKeyAndSRPAttributes } from "@/accounts/services/srp"; import { sendOTT } from "@/accounts/services/user"; import { isWeakPassword } from "@/accounts/utils/password"; import { LinkButton } from "@/base/components/LinkButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { isMuseumHTTPError } from "@/base/http"; import log from "@/base/log"; import { LS_KEYS, setLSUser } from "@ente/shared//storage/localStorage"; import { VerticallyCentered } from "@ente/shared/components/Container"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; import { generateAndSaveIntermediateKeyAttributes, saveKeyInSessionStore, } from "@ente/shared/crypto/helpers"; import { setData } from "@ente/shared/storage/localStorage"; import { setJustSignedUp, setLocalReferralSource, } from "@ente/shared/storage/localStorage/helpers"; import { SESSION_KEYS } from "@ente/shared/storage/sessionStorage"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import { Box, Checkbox, FormControlLabel, FormGroup, IconButton, InputAdornment, Link, Stack, TextField, Tooltip, Typography, } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; import type { NextRouter } from "next/router"; import React, { useState } from "react"; import { Trans } from "react-i18next"; import * as Yup from "yup"; import { PasswordStrengthHint } from "./PasswordStrength"; import { AccountsPageFooter, AccountsPageTitle, } from "./layouts/centered-paper"; interface FormValues { email: string; passphrase: string; confirm: string; referral: string; } interface SignUpContentsProps { router: NextRouter; /** Called when the user clicks the login option instead. */ onLogin: () => void; /** Reactive value of {@link customAPIHost}. */ host: string | undefined; } export const SignUpContents: React.FC = ({ router, onLogin, host, }) => { const [acceptTerms, setAcceptTerms] = useState(false); const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const handleClickShowPassword = () => { setShowPassword(!showPassword); }; const handleMouseDownPassword = ( event: React.MouseEvent, ) => { event.preventDefault(); }; const registerUser = async ( { email, passphrase, confirm, referral }: FormValues, { setFieldError }: FormikHelpers, ) => { try { if (passphrase !== confirm) { setFieldError("confirm", t("password_mismatch_error")); return; } setLoading(true); try { setLocalReferralSource(referral); await sendOTT(email, "signup"); await setLSUser({ email }); } catch (e) { log.error("Signup failed", e); if ( await isMuseumHTTPError(e, 409, "USER_ALREADY_REGISTERED") ) { setFieldError("email", t("email_already_registered")); } else { setFieldError("email", t("generic_error")); } throw e; } try { const { keyAttributes, masterKey, srpSetupAttributes } = await generateKeyAndSRPAttributes(passphrase); setData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES, keyAttributes); setData(LS_KEYS.SRP_SETUP_ATTRIBUTES, srpSetupAttributes); await generateAndSaveIntermediateKeyAttributes( passphrase, keyAttributes, masterKey, ); await saveKeyInSessionStore( SESSION_KEYS.ENCRYPTION_KEY, masterKey, ); setJustSignedUp(true); void router.push(PAGES.VERIFY); } catch (e) { setFieldError("confirm", t("password_generation_failed")); throw e; } } catch (e) { log.error("signup failed", e); } setLoading(false); }; const form = ( initialValues={{ email: "", passphrase: "", confirm: "", referral: "", }} validationSchema={Yup.object().shape({ email: Yup.string() .email(t("invalid_email_error")) .required(t("required")), passphrase: Yup.string().required(t("required")), confirm: Yup.string().required(t("required")), })} validateOnChange={false} validateOnBlur={false} onSubmit={registerUser} > {({ values, errors, handleChange, handleSubmit, }): React.JSX.Element => (
), }, }} /> {t("referral_source_hint")} ), }, }} /> setAcceptTerms(e.target.checked) } color="accent" /> } label={ ), b: ( ), }} /> } /> {t("create_account")} {loading && ( {t("key_generation_in_progress")} )}
)} ); return ( <> {t("sign_up")} {form} {t("existing_account")} {host ?? "" /* prevent layout shift with a minHeight */} ); };