import { Badge, Button, Center, Container, Group, Paper, PasswordInput, Stack, Tabs, Text, TextInput, Title, } from "@mantine/core"; import { useForm, yupResolver } from "@mantine/form"; import { useModals } from "@mantine/modals"; import { useEffect, useState } from "react"; import { TbAuth2Fa } from "react-icons/tb"; import { FormattedMessage } from "react-intl"; import * as yup from "yup"; import Meta from "../../components/Meta"; import LanguagePicker from "../../components/account/LanguagePicker"; import ThemeSwitcher from "../../components/account/ThemeSwitcher"; import showEnableTotpModal from "../../components/account/showEnableTotpModal"; import useConfig from "../../hooks/config.hook"; import useTranslate from "../../hooks/useTranslate.hook"; import useUser from "../../hooks/user.hook"; import authService from "../../services/auth.service"; import userService from "../../services/user.service"; import { getOAuthIcon, getOAuthUrl, unlinkOAuth } from "../../utils/oauth.util"; import toast from "../../utils/toast.util"; const Account = () => { const [oauth, setOAuth] = useState([]); const [oauthStatus, setOAuthStatus] = useState | null>(null); const { user, refreshUser } = useUser(); const modals = useModals(); const t = useTranslate(); const config = useConfig(); const accountForm = useForm({ initialValues: { username: user?.username, email: user?.email, }, validate: yupResolver( yup.object().shape({ email: yup.string().email(t("common.error.invalid-email")), username: yup .string() .min(3, t("common.error.too-short", { length: 3 })), }), ), }); const passwordForm = useForm({ initialValues: { oldPassword: "", password: "", }, validate: yupResolver( yup.object().shape({ oldPassword: yup.string().when([], { is: () => !!user?.hasPassword, then: (schema) => schema .min(8, t("common.error.too-short", { length: 8 })) .required(t("common.error.field-required")), otherwise: (schema) => schema.notRequired(), }), password: yup .string() .min(8, t("common.error.too-short", { length: 8 })) .required(t("common.error.field-required")), }), ), }); const enableTotpForm = useForm({ initialValues: { password: "", }, validate: yupResolver( yup.object().shape({ password: yup .string() .min(8, t("common.error.too-short", { length: 8 })) .required(t("common.error.field-required")), }), ), }); const disableTotpForm = useForm({ initialValues: { password: "", code: "", }, validate: yupResolver( yup.object().shape({ password: yup.string().min(8), code: yup .string() .min(6, t("common.error.exact-length", { length: 6 })) .max(6, t("common.error.exact-length", { length: 6 })) .matches(/^[0-9]+$/, { message: t("common.error.invalid-number") }), }), ), }); const refreshOAuthStatus = () => { authService .getOAuthStatus() .then((data) => { setOAuthStatus(data.data); }) .catch(toast.axiosError); }; useEffect(() => { authService .getAvailableOAuth() .then((data) => { setOAuth(data.data); }) .catch(toast.axiosError); refreshOAuthStatus(); }, []); return ( <> <FormattedMessage id="account.title" /> <FormattedMessage id="account.card.info.title" /> {user?.isLdap ? ( <Badge style={{ marginLeft: "1em" }}>LDAP</Badge> ) : null}
userService .updateCurrentUser({ username: values.username, email: values.email, }) .then(() => toast.success(t("account.notify.info.success"))) .catch(toast.axiosError), )} > {!user?.isLdap && ( )}
{user?.isLdap ? null : ( <FormattedMessage id="account.card.password.title" />
authService .updatePassword(values.oldPassword, values.password) .then(async () => { refreshUser(); toast.success(t("account.notify.password.success")); passwordForm.reset(); }) .catch(toast.axiosError), )} > {user?.hasPassword ? ( ) : ( )}
)} {oauth.length > 0 && ( <FormattedMessage id="account.card.oauth.title" /> {oauth.map((provider) => ( {t(`account.card.oauth.${provider}`)} ))} {oauth.map((provider) => ( {oauthStatus?.[provider] ? oauthStatus[provider].providerUsername : t("account.card.oauth.unlinked")} {oauthStatus?.[provider] ? ( ) : ( )} ))} )} <FormattedMessage id="account.card.security.title" /> }> TOTP {user?.totpVerified ? ( <>
{ authService .disableTOTP(values.code, values.password) .then(() => { toast.success(t("account.notify.totp.disable")); values.password = ""; values.code = ""; refreshUser(); }) .catch(toast.axiosError); })} >
) : ( <>
{ authService .enableTOTP(values.password) .then((result) => { showEnableTotpModal(modals, refreshUser, { qrCode: result.qrCode, secret: result.totpSecret, password: values.password, }); values.password = ""; }) .catch(toast.axiosError); })} >
)}
<FormattedMessage id="account.card.language.title" /> <FormattedMessage id="account.card.color.title" />
); }; export default Account;