Files
bodyshop/client/src/redux/user/user.sagas.js

270 lines
7.2 KiB
JavaScript

import Fingerprint2 from "@fingerprintjs/fingerprintjs";
import { notification } from "antd";
import i18next from "i18next";
import LogRocket from "logrocket";
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
import {
analytics,
auth,
firestore,
getCurrentUser,
logImEXEvent,
updateCurrentUser,
} from "../../firebase/firebase.utils";
import {
checkInstanceId,
sendPasswordResetFailure,
sendPasswordResetSuccess,
setAuthlevel,
setInstanceConflict,
setLocalFingerprint,
signInFailure,
signInSuccess,
signOutFailure,
signOutSuccess,
unauthorizedUser,
updateUserDetailsSuccess,
validatePasswordResetFailure,
validatePasswordResetSuccess,
} from "./user.actions";
import UserActionTypes from "./user.types";
export function* onEmailSignInStart() {
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
}
export function* signInWithEmail({ payload: { email, password } }) {
try {
logImEXEvent("redux_sign_in_attempt", { user: email });
const { user } = yield auth.signInWithEmailAndPassword(email, password);
yield put(
signInSuccess({
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL,
authorized: true,
})
);
} catch (error) {
yield put(signInFailure(error));
logImEXEvent("redux_sign_in_failure", { user: email, error });
}
}
export function* onCheckUserSession() {
yield takeLatest(UserActionTypes.CHECK_USER_SESSION, isUserAuthenticated);
}
export function* isUserAuthenticated() {
try {
logImEXEvent("redux_auth_check");
const user = yield getCurrentUser();
if (!user) {
yield put(unauthorizedUser());
return;
}
LogRocket.identify(user.email);
yield put(
signInSuccess({
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL,
authorized: true,
})
);
} catch (error) {
yield put(signInFailure(error));
}
}
export function* onSignOutStart() {
yield takeLatest(UserActionTypes.SIGN_OUT_START, signOutStart);
}
export function* signOutStart() {
try {
logImEXEvent("redux_sign_out");
yield auth.signOut();
yield put(signOutSuccess());
localStorage.removeItem("token");
} catch (error) {
yield put(signOutFailure(error.message));
}
}
export function* onUpdateUserDetails() {
yield takeLatest(UserActionTypes.UPDATE_USER_DETAILS, updateUserDetails);
}
export function* updateUserDetails(userDetails) {
try {
yield updateCurrentUser(userDetails.payload);
yield put(updateUserDetailsSuccess(userDetails.payload));
notification.open({
type: "success",
message: i18next.t("profile.successes.updated"),
});
} catch (error) {
//yield put(signOutFailure(error.message));
}
}
export function* onSetInstanceId() {
yield takeLatest(UserActionTypes.SET_INSTANCE_ID, setInstanceIdSaga);
}
export function* setInstanceIdSaga({ payload: uid }) {
try {
const userInstanceRef = firestore.doc(`userInstance/${uid}`);
const fingerprint = Fingerprint2.x64hash128(
(yield Fingerprint2.getPromise({})).map((c) => c.value).join(""),
31
);
yield userInstanceRef.set({
timestamp: new Date(),
fingerprint,
});
yield put(setLocalFingerprint(fingerprint));
yield delay(5 * 60 * 1000);
if (process.env.NODE_ENV === "production") yield put(checkInstanceId(uid));
} catch (error) {
console.log("error", error);
}
}
export function* onCheckInstanceId() {
yield takeLatest(UserActionTypes.CHECK_INSTANCE_ID, checkInstanceIdSaga);
}
export function* checkInstanceIdSaga({ payload: uid }) {
try {
const userInstanceRef = firestore.doc(`userInstance/${uid}`);
const snapshot = yield userInstanceRef.get();
let fingerprint = yield select((state) => state.user.fingerprint);
if (snapshot.data().fingerprint === fingerprint) {
yield delay(5 * 60 * 1000);
yield put(checkInstanceId(uid));
} else {
console.log("ERROR: Fingerprints do not match. Conflict detected.");
logImEXEvent("instance_confict");
yield put(setInstanceConflict());
}
} catch (error) {
console.log("error", error);
}
}
export function* onSignInSuccess() {
yield takeLatest(UserActionTypes.SIGN_IN_SUCCESS, signInSuccessSaga);
}
export function* signInSuccessSaga({ payload }) {
LogRocket.identify(payload.email);
try {
// window.$crisp.push(["set", "user:email", [payload.email]]);
window.$crisp.push([
"set",
"user:nickname",
[payload.displayName || payload.email],
]);
} catch (error) {
console.log("Error updating Crisp settings.", error);
}
// if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid));
analytics.setUserId(payload.email);
analytics.setUserProperties(payload);
yield logImEXEvent("redux_sign_in_success");
}
export function* onSendPasswordResetStart() {
yield takeLatest(
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
sendPasswordResetEmail
);
yield takeLatest(
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START_AGAIN,
sendPasswordResetEmail
);
}
export function* sendPasswordResetEmail({ payload }) {
try {
yield auth.sendPasswordResetEmail(payload, {
url: "https://imex.online/passwordreset",
});
yield put(sendPasswordResetSuccess());
} catch (error) {
yield put(sendPasswordResetFailure(error.message));
}
}
export function* onValidatePasswordResetStart() {
yield takeLatest(
UserActionTypes.VALIDATE_PASSWORD_RESET_START,
validatePasswordResetStart
);
}
export function* validatePasswordResetStart({ payload: { password, code } }) {
try {
auth.checkActionCode(code);
yield auth.confirmPasswordReset(code, password);
yield put(validatePasswordResetSuccess());
} catch (error) {
console.log("function*validatePasswordResetStart -> error", error);
yield put(validatePasswordResetFailure(error.message));
}
}
export function* onSetShopDetails() {
yield takeLatest(
UserActionTypes.SET_SHOP_DETAILS,
SetAuthLevelFromShopDetails
);
}
export function* SetAuthLevelFromShopDetails({ payload }) {
try {
const userEmail = yield select((state) => state.user.currentUser.email);
window.$crisp.push(["set", "user:company", [payload.shopname]]);
const authRecord = payload.associations.filter(
(a) => a.useremail === userEmail
);
if (authRecord[0] && authRecord[0].user.validemail) {
window.$crisp.push(["set", "user:email", [authRecord[0].user.email]]);
}
yield put(setAuthlevel(authRecord[0] ? authRecord[0].authlevel : 0));
yield put(
updateUserDetailsSuccess(
authRecord[0]
? { validemail: authRecord[0].user.validemail }
: { validemail: false }
)
);
} catch (error) {
yield put(signInFailure(error.message));
}
}
export function* userSagas() {
yield all([
call(onEmailSignInStart),
call(onCheckUserSession),
call(onSignOutStart),
call(onUpdateUserDetails),
call(onSetInstanceId),
call(onCheckInstanceId),
call(onSignInSuccess),
call(onSendPasswordResetStart),
call(onValidatePasswordResetStart),
call(onSetShopDetails),
]);
}