import { Button, Checkbox, Divider, Input } from "@mui/joy"; import { ClientError } from "nice-grpc-web"; import { useEffect, useState } from "react"; import { toast } from "react-hot-toast"; import { Link } from "react-router-dom"; import AppearanceSelect from "@/components/AppearanceSelect"; import LocaleSelect from "@/components/LocaleSelect"; import { authServiceClient, identityProviderServiceClient } from "@/grpcweb"; import { absolutifyLink } from "@/helpers/utils"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { useCommonContext } from "@/layouts/CommonContextProvider"; import { extractIdentityProviderIdFromName, useUserStore, useWorkspaceSettingStore } from "@/store/v1"; import { IdentityProvider, IdentityProvider_Type } from "@/types/proto/api/v1/idp_service"; import { WorkspaceGeneralSetting } from "@/types/proto/api/v1/workspace_setting_service"; import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting"; import { useTranslate } from "@/utils/i18n"; const SignIn = () => { const t = useTranslate(); const navigateTo = useNavigateTo(); const commonContext = useCommonContext(); const workspaceSettingStore = useWorkspaceSettingStore(); const userStore = useUserStore(); const actionBtnLoadingState = useLoading(false); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [remember, setRemember] = useState(true); const [identityProviderList, setIdentityProviderList] = useState([]); const workspaceGeneralSetting = workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.GENERAL).generalSetting || WorkspaceGeneralSetting.fromPartial({}); useEffect(() => { const fetchIdentityProviderList = async () => { const { identityProviders } = await identityProviderServiceClient.listIdentityProviders({}); setIdentityProviderList(identityProviders); }; fetchIdentityProviderList(); }, []); useEffect(() => { if (commonContext.profile.mode === "demo") { setUsername("yourselfhosted"); setPassword("yourselfhosted"); } }, [commonContext.profile.mode]); const handleUsernameInputChanged = (e: React.ChangeEvent) => { const text = e.target.value as string; setUsername(text); }; const handlePasswordInputChanged = (e: React.ChangeEvent) => { const text = e.target.value as string; setPassword(text); }; const handleLocaleSelectChange = (locale: Locale) => { commonContext.setLocale(locale); }; const handleAppearanceSelectChange = (appearance: Appearance) => { commonContext.setAppearance(appearance); }; const handleFormSubmit = (e: React.FormEvent) => { e.preventDefault(); handleSignInButtonClick(); }; const handleSignInButtonClick = async () => { if (username === "" || password === "") { return; } if (actionBtnLoadingState.isLoading) { return; } try { actionBtnLoadingState.setLoading(); await authServiceClient.signIn({ username, password, neverExpire: remember }); await userStore.fetchCurrentUser(); navigateTo("/"); } catch (error: any) { console.error(error); toast.error((error as ClientError).details || "Failed to sign in."); } actionBtnLoadingState.setFinish(); }; const handleSignInWithIdentityProvider = async (identityProvider: IdentityProvider) => { const stateQueryParameter = `auth.signin.${identityProvider.title}-${extractIdentityProviderIdFromName(identityProvider.name)}`; if (identityProvider.type === IdentityProvider_Type.OAUTH2) { const redirectUri = absolutifyLink("/auth/callback"); const oauth2Config = identityProvider.config?.oauth2Config; if (!oauth2Config) { toast.error("Identity provider configuration is invalid."); return; } const authUrl = `${oauth2Config.authUrl}?client_id=${ oauth2Config.clientId }&redirect_uri=${redirectUri}&state=${stateQueryParameter}&response_type=code&scope=${encodeURIComponent( oauth2Config.scopes.join(" "), )}`; window.location.href = authUrl; } }; return (

{workspaceGeneralSetting.customProfile?.title || "Memos"}

{commonContext.profile.passwordAuth ? (
{t("common.username")}
{t("common.password")}
setRemember(e.target.checked)} />
) : (

Password auth is not allowed.

)} {commonContext.profile.public && commonContext.profile.passwordAuth && (

{t("auth.sign-up-tip")} {t("common.sign-up")}

)} {identityProviderList.length > 0 && ( <> {t("common.or")}
{identityProviderList.map((identityProvider) => ( ))}
)}
); }; export default SignIn;