import { message } from "antd"; import dayjs from '../../util/day.js'; //import LogRocket from "logrocket"; import * as Sentry from "@sentry/electron"; import { all, call, delay, put, takeLatest } from "redux-saga/effects"; import { auth, getCurrentUser, updateCurrentUser, } from "../../firebase/firebase.utils"; import client from "../../graphql/GraphQLClient"; import { QUERY_BODYSHOP, QUERY_NOTIFICATIONS, } from "../../graphql/bodyshop.queries"; import { UPSERT_USER } from "../../graphql/user.queries"; import ipcTypes from "../../ipc.types"; import { checkForNotification, sendPasswordResetFailure, sendPasswordResetSuccess, setBodyshop, setNotification, setTargets, signInFailure, signInSuccess, signOutFailure, signOutSuccess, unauthorizedUser, updateUserDetailsSuccess, } from "./user.actions"; import UserActionTypes from "./user.types"; const { ipcRenderer } = window; export function* onEmailSignInStart() { yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail); } export function* signInWithEmail({ payload: { email, password } }) { try { ipcRenderer.send(ipcTypes.app.toMain.track, { event: "SIGN_IN_ATTEMPT", email: email, }); const { user } = yield auth.signInWithEmailAndPassword(email, password); const result = yield client.mutate({ mutation: UPSERT_USER, variables: { authEmail: user.email, authToken: user.uid }, }); if (!result.errors) { yield put( signInSuccess({ uid: user.uid, email: user.email, displayName: user.displayName, photoURL: user.photoURL, authorized: true, }) ); } else { yield put(signInFailure(JSON.stringify(result.errors))); } } catch (error) { yield put( signInFailure({ ...error, messagePretty: ErrorFormatter(error.code) }) ); } } export function* onCheckUserSession() { yield takeLatest(UserActionTypes.CHECK_USER_SESSION, isUserAuthenticated); } export function* isUserAuthenticated() { try { const user = yield getCurrentUser(); if (!user) { yield put(unauthorizedUser()); return; } 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 { ipcRenderer.send(ipcTypes.app.toMain.track, { event: "SIGN_OUT", }); ipcRenderer.send(ipcTypes.fileWatcher.toMain.stop); 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)); } catch (error) { //yield put(signOutFailure(error.message)); //TODO error handling console.log(error); } } export function* onSignInSuccess() { yield takeLatest(UserActionTypes.SIGN_IN_SUCCESS, signInSuccessSaga); } export function* signInSuccessSaga({ payload }) { //Query for the Correct Bodyshop ipcRenderer.send(ipcTypes.app.toMain.setUserName, payload.email); // LogRocket.identify(payload.email, { // email: payload.email, // }); ipcRenderer.send(ipcTypes.app.toMain.checkForUpdates); ipcRenderer.send(ipcTypes.app.toMain.track, { event: "SIGN_IN_SUCCESS", email: payload.email, }); const shop = yield client.query({ query: QUERY_BODYSHOP }); if (shop.data.bodyshops.length > 0) { yield put(setBodyshop(shop.data.bodyshops[0])); ipcRenderer.send( ipcTypes.app.toMain.setAcceptableInsCoNm, shop.data.bodyshops[0].accepted_ins_co ); ipcRenderer.send(ipcTypes.fileWatcher.toMain.start, { startup: true, }); yield put(checkForNotification()); //Check for notifications, and continue to check. window.$crisp.push([ "set", "user:company", [shop.data.bodyshops[0].shopname], ]); window.$crisp.push([ "set", "user:nickname", [payload.displayName || payload.email], ]); window.$crisp.push(["set", "user:email", [payload.email]]); window.$crisp.push(["set", "session:segments", [["rps-user"]]]); ipcRenderer.send(ipcTypes.app.toMain.getAppVersion); Sentry.setUser({ email: payload.email, username: payload.displayName || payload.email, }); } else { console.log("No bodyshop has been associated."); yield put(setBodyshop(false)); } if (shop.data.targets.length > 0) { yield put(setTargets(shop.data.targets)); } else { console.log("No bodyshop has been associated."); yield put(setTargets(null)); } // LogRocket.identify(payload.email); // if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid)); // yield logImEXEvent("redux_sign_in_success"); } export function* onCheckForNotification() { yield takeLatest( UserActionTypes.CHECK_FOR_NOTIFICATION, checkForNotificationSaga ); } export function* checkForNotificationSaga() { const { data: { notifications }, } = yield client.query({ query: QUERY_NOTIFICATIONS, variables: { now: dayjs() }, }); if (notifications) { yield put(setNotification(notifications)); } yield delay(4 * 60 * 60 * 1000); yield put(checkForNotification()); } export function* onSendPasswordResetStart() { yield takeLatest( UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START, sendPasswordResetEmail ); } export function* sendPasswordResetEmail({ payload }) { try { ipcRenderer.send(ipcTypes.app.toMain.track, { event: "RESET_PASSWORD", email: payload, }); yield auth.sendPasswordResetEmail(payload); yield put(sendPasswordResetSuccess()); message.success("Password reset sent succesfully."); } catch (error) { yield put(sendPasswordResetFailure(error.message)); } } export function* userSagas() { yield all([ call(onEmailSignInStart), call(onCheckUserSession), call(onSignOutStart), call(onUpdateUserDetails), call(onSignInSuccess), call(onSendPasswordResetStart), call(onCheckForNotification), ]); } const ErrorFormatter = (code) => { switch (code) { case "auth/invalid-email": return "Please enter a valid email."; case "auth/user-not-found": return "A user does not exist with that email."; case "auth/wrong-password": return "The email or password is incorrect."; default: return code; } };