2023-01-06 12:15:37 +05:00
|
|
|
/*
|
|
|
|
|
This file is part of the Notesnook project (https://notesnook.com/)
|
|
|
|
|
|
2023-01-16 13:44:52 +05:00
|
|
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
2023-01-06 12:15:37 +05:00
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { useRef, useState } from "react";
|
|
|
|
|
import { db } from "../../common/database";
|
2023-08-29 20:42:45 +05:00
|
|
|
import { eSendEvent, ToastManager } from "../../services/event-manager";
|
2023-01-06 12:15:37 +05:00
|
|
|
import { clearMessage } from "../../services/message";
|
|
|
|
|
import PremiumService from "../../services/premium";
|
|
|
|
|
import SettingsService from "../../services/settings";
|
|
|
|
|
import { useUserStore } from "../../stores/use-user-store";
|
|
|
|
|
import { eCloseSheet } from "../../utils/events";
|
|
|
|
|
import TwoFactorVerification from "./two-factor";
|
2024-07-27 10:19:43 +05:00
|
|
|
import { strings } from "@notesnook/intl";
|
2023-01-06 12:15:37 +05:00
|
|
|
|
|
|
|
|
export const LoginSteps = {
|
|
|
|
|
emailAuth: 1,
|
|
|
|
|
mfaAuth: 2,
|
|
|
|
|
passwordAuth: 3
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-30 11:56:52 +05:00
|
|
|
export const useLogin = (onFinishLogin, sessionExpired = false) => {
|
2023-01-06 12:15:37 +05:00
|
|
|
const [error, setError] = useState(false);
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const setUser = useUserStore((state) => state.setUser);
|
|
|
|
|
const [step, setStep] = useState(LoginSteps.emailAuth);
|
2023-01-06 12:36:28 +05:00
|
|
|
const email = useRef();
|
2023-01-06 12:15:37 +05:00
|
|
|
const password = useRef();
|
|
|
|
|
const emailInputRef = useRef();
|
|
|
|
|
const passwordInputRef = useRef();
|
|
|
|
|
|
|
|
|
|
const validateInfo = () => {
|
|
|
|
|
if (
|
|
|
|
|
(!password.current && step === LoginSteps.passwordAuth) ||
|
|
|
|
|
(!email.current && step === LoginSteps.emailAuth)
|
|
|
|
|
) {
|
2023-08-29 20:42:45 +05:00
|
|
|
ToastManager.show({
|
2024-07-27 10:19:43 +05:00
|
|
|
heading: strings.allFieldsRequired(),
|
|
|
|
|
message: strings.allFieldsRequiredDesc(),
|
2023-01-06 12:15:37 +05:00
|
|
|
type: "error",
|
|
|
|
|
context: "local"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const login = async () => {
|
|
|
|
|
if (!validateInfo() || error) return;
|
|
|
|
|
try {
|
2023-09-04 14:27:15 +05:00
|
|
|
if (loading) return;
|
2023-01-06 12:15:37 +05:00
|
|
|
setLoading(true);
|
|
|
|
|
switch (step) {
|
|
|
|
|
case LoginSteps.emailAuth: {
|
|
|
|
|
const mfaInfo = await db.user.authenticateEmail(email.current);
|
2025-01-20 17:17:01 +05:00
|
|
|
|
2023-01-06 12:15:37 +05:00
|
|
|
if (mfaInfo) {
|
2024-11-06 10:57:04 +05:00
|
|
|
TwoFactorVerification.present(
|
|
|
|
|
async (mfa, callback) => {
|
|
|
|
|
try {
|
|
|
|
|
const success = await db.user.authenticateMultiFactorCode(
|
|
|
|
|
mfa.code,
|
|
|
|
|
mfa.method
|
|
|
|
|
);
|
2023-02-23 15:49:35 +05:00
|
|
|
|
2024-11-06 10:57:04 +05:00
|
|
|
if (success) {
|
|
|
|
|
setStep(LoginSteps.passwordAuth);
|
|
|
|
|
setLoading(false);
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
passwordInputRef.current?.focus();
|
|
|
|
|
}, 500);
|
|
|
|
|
callback && callback(true);
|
|
|
|
|
}
|
|
|
|
|
callback && callback(false);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
callback && callback(false);
|
|
|
|
|
if (e.message === "invalid_grant") {
|
|
|
|
|
eSendEvent(eCloseSheet, "two_factor_verify");
|
|
|
|
|
setLoading(false);
|
|
|
|
|
setStep(LoginSteps.emailAuth);
|
|
|
|
|
}
|
2023-01-06 12:15:37 +05:00
|
|
|
}
|
2024-11-06 10:57:04 +05:00
|
|
|
},
|
|
|
|
|
mfaInfo,
|
|
|
|
|
() => {
|
|
|
|
|
eSendEvent(eCloseSheet, "two_factor_verify");
|
|
|
|
|
setLoading(false);
|
|
|
|
|
setStep(LoginSteps.emailAuth);
|
2023-01-06 12:15:37 +05:00
|
|
|
}
|
2024-11-06 10:57:04 +05:00
|
|
|
);
|
2023-02-23 15:49:35 +05:00
|
|
|
} else {
|
2024-08-15 15:39:53 +05:00
|
|
|
finishWithError(new Error(strings.unableToSend2faCode()));
|
2023-01-06 12:15:37 +05:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case LoginSteps.passwordAuth: {
|
2023-10-30 11:56:52 +05:00
|
|
|
await db.user.authenticatePassword(
|
|
|
|
|
email.current,
|
|
|
|
|
password.current,
|
|
|
|
|
null,
|
|
|
|
|
sessionExpired
|
|
|
|
|
);
|
2023-01-06 12:15:37 +05:00
|
|
|
finishLogin();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setLoading(false);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
finishWithError(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const finishWithError = async (e) => {
|
2023-01-06 12:36:28 +05:00
|
|
|
if (e.message === "invalid_grant") setStep(LoginSteps.emailAuth);
|
2023-01-06 12:15:37 +05:00
|
|
|
setLoading(false);
|
2023-08-29 20:42:45 +05:00
|
|
|
ToastManager.show({
|
2024-07-27 10:19:43 +05:00
|
|
|
heading: strings.loginFailed(),
|
2023-01-06 12:15:37 +05:00
|
|
|
message: e.message,
|
|
|
|
|
type: "error",
|
|
|
|
|
context: "local"
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const finishLogin = async () => {
|
|
|
|
|
const user = await db.user.getUser();
|
2024-08-15 15:39:53 +05:00
|
|
|
if (!user) throw new Error(strings.emailOrPasswordIncorrect());
|
2023-01-06 12:15:37 +05:00
|
|
|
PremiumService.setPremiumStatus();
|
|
|
|
|
setUser(user);
|
|
|
|
|
clearMessage();
|
2023-08-29 20:42:45 +05:00
|
|
|
ToastManager.show({
|
2024-07-27 10:19:43 +05:00
|
|
|
heading: strings.loginSuccess(),
|
|
|
|
|
message: strings.loginSuccessDesc(),
|
2023-01-06 12:15:37 +05:00
|
|
|
type: "success",
|
|
|
|
|
context: "global"
|
|
|
|
|
});
|
|
|
|
|
SettingsService.set({
|
|
|
|
|
sessionExpired: false,
|
|
|
|
|
userEmailConfirmed: user?.isEmailConfirmed
|
|
|
|
|
});
|
|
|
|
|
onFinishLogin?.();
|
|
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
login,
|
|
|
|
|
step,
|
|
|
|
|
setStep,
|
|
|
|
|
email,
|
|
|
|
|
password,
|
|
|
|
|
passwordInputRef,
|
|
|
|
|
emailInputRef,
|
|
|
|
|
loading,
|
|
|
|
|
setLoading,
|
|
|
|
|
error,
|
|
|
|
|
setError
|
|
|
|
|
};
|
|
|
|
|
};
|