From 201e85d7dbfb342f3d79ce8e13b3faed88693d11 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 21 May 2020 13:17:59 -0700 Subject: [PATCH] Added fingerprinting fixed + update firebase fingerprint on log in BOD-132 --- _reference/firebase.md | 3 +- bodyshop_translations.babel | 63 ++++ .../conflict/conflict.component.jsx | 27 ++ .../pages/manage/manage.page.component.jsx | 284 ++++++++++-------- client/src/redux/user/user.reducer.js | 2 + client/src/redux/user/user.sagas.js | 38 +-- client/src/translations/en_us/common.json | 3 + client/src/translations/es/common.json | 3 + client/src/translations/fr/common.json | 3 + 9 files changed, 279 insertions(+), 147 deletions(-) create mode 100644 client/src/components/conflict/conflict.component.jsx diff --git a/_reference/firebase.md b/_reference/firebase.md index ba407f4cf..ceb800e04 100644 --- a/_reference/firebase.md +++ b/_reference/firebase.md @@ -12,4 +12,5 @@ 6. Deploy the function 1. $ firebase deploy --only functions 7. Add the allowed domains. -8. Update server variables including FIREBASE_ADMINSDK_JSON, FIREBASE_DATABASE_URL \ No newline at end of file +8. Update server variables including FIREBASE_ADMINSDK_JSON, FIREBASE_DATABASE_URL +9. Create the firestore and copy the rules from dev for userinstances. \ No newline at end of file diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 19bcce99c..8d596ee75 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -4573,6 +4573,27 @@ + + refresh + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + reset false @@ -4746,6 +4767,48 @@ + + instanceconflictext + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + instanceconflictitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + loading false diff --git a/client/src/components/conflict/conflict.component.jsx b/client/src/components/conflict/conflict.component.jsx new file mode 100644 index 000000000..efac77288 --- /dev/null +++ b/client/src/components/conflict/conflict.component.jsx @@ -0,0 +1,27 @@ +import React from "react"; +import { Result, Button } from "antd"; +import { useTranslation } from "react-i18next"; + +export default function ConflictComponent() { + const { t } = useTranslation(); + return ( +
+ +
{t("general.labels.instanceconflictext")}
+ +
+ } + /> + + ); +} diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index e304a3ba6..deec86f50 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -7,10 +7,15 @@ import ChatAffixContainer from "../../components/chat-affix/chat-affix.container import ErrorBoundary from "../../components/error-boundary/error-boundary.component"; import FcmNotification from "../../components/fcm-notification/fcm-notification.component"; import FooterComponent from "../../components/footer/footer.component"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectInstanceConflict } from "../../redux/user/user.selectors"; //Component Imports import HeaderContainer from "../../components/header/header.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container"; +import ConflictComponent from '../../components/conflict/conflict.component' + import "./manage.page.styles.scss"; const ManageRootPage = lazy(() => import("../manage-root/manage-root.page.container") @@ -91,7 +96,15 @@ const JobsClose = lazy(() => import("../jobs-close/jobs-close.container")); const { Header, Content, Footer } = Layout; -export default function Manage({ match }) { +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + conflict: selectInstanceConflict, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); + +export function Manage({ match, conflict }) { const { t } = useTranslation(); useEffect(() => { @@ -105,145 +118,159 @@ export default function Manage({ match }) { + className="content-container" + style={{ padding: "0em 4em 4em" }} + > - - }> - - - - - - - + {conflict ? ( + + ) : ( + + } + > + + + + + + + - + + + + + + + - - - - - - - - + + - + - - + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + )} @@ -255,3 +282,4 @@ export default function Manage({ match }) { ); } +export default connect(mapStateToProps, mapDispatchToProps)(Manage); diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js index d263b5fc8..329df35ae 100644 --- a/client/src/redux/user/user.reducer.js +++ b/client/src/redux/user/user.reducer.js @@ -12,6 +12,8 @@ const INITIAL_STATE = { const userReducer = (state = INITIAL_STATE, action) => { switch (action.type) { + case UserActionTypes.SET_INSTANCE_ID: + return { ...state, conflict: false }; case UserActionTypes.SET_INSTANCE_CONFLICT: return { ...state, conflict: true }; case UserActionTypes.SIGN_IN_SUCCESS: diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 4f615d5b9..7d52ddfa3 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -26,7 +26,6 @@ export function* signInWithEmail({ payload: { email, password } }) { const { user } = yield auth.signInWithEmailAndPassword(email, password); LogRocket.identify(user.email); - yield put(setInstanceId("123")); yield put( signInSuccess({ uid: user.uid, @@ -51,7 +50,7 @@ export function* isUserAuthenticated() { yield put(unauthorizedUser()); return; } - yield put(setInstanceId(user.uid)); + LogRocket.identify(user.email); yield put( signInSuccess({ @@ -101,16 +100,15 @@ export function* setInstanceIdSaga({ payload: uid }) { const userInstanceRef = firestore.doc(`userInstance/${uid}`); const fingerprint = Fingerprint2.x64hash128( - (yield Fingerprint2.getPromise({ - excludes: { fonts: true, audio: true, webgl: true }, - })).join(""), + (yield Fingerprint2.getPromise({})).map((c) => c.value).join(""), 31 ); - - yield userInstanceRef.set({ - timestamp: new Date(), - fingerprint, - }); + var result = window.confirm("Press a button!"); + if (result) + yield userInstanceRef.set({ + timestamp: new Date(), + fingerprint, + }); yield delay(5000); yield put(checkInstanceId(uid)); @@ -129,22 +127,17 @@ export function* checkInstanceIdSaga({ payload: uid }) { const userInstanceRef = firestore.doc(`userInstance/${uid}`); const fingerprint = Fingerprint2.x64hash128( - (yield Fingerprint2.getPromise({ - excludes: { fonts: true, audio: true, webgl: true }, - })).join(""), + (yield Fingerprint2.getPromise({})).map((c) => c.value).join(""), 31 ); const snapshot = yield userInstanceRef.get(); - console.log("function*checkInstanceIdSaga -> snapshot", snapshot.data()); - console.log("fingerprint", fingerprint); if (snapshot.data().fingerprint === fingerprint) { - console.log("Waiting and checking."); - yield delay(5000); + yield delay(30000); yield put(checkInstanceId(uid)); } else { - console.log("Didnt match"); + console.log("ERROR: Fingerprints do not match. Conflict detected."); yield put(setInstanceConflict()); } // yield userInstanceRef.set({ @@ -158,6 +151,14 @@ export function* checkInstanceIdSaga({ payload: uid }) { } } +export function* onSignInSuccess() { + yield takeLatest(UserActionTypes.SIGN_IN_SUCCESS, signInSuccessSaga); +} + +export function* signInSuccessSaga({ payload }) { + yield put(setInstanceId(payload.uid)); +} + export function* userSagas() { yield all([ call(onEmailSignInStart), @@ -166,5 +167,6 @@ export function* userSagas() { call(onUpdateUserDetails), call(onSetInstanceId), call(onCheckInstanceId), + call(onSignInSuccess), ]); } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index e5c95a94e..74fad518a 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -312,6 +312,7 @@ "create": "Create", "delete": "Delete", "edit": "Edit", + "refresh": "Refresh", "reset": "Reset to original.", "save": "Save", "saveandnew": "Save and New", @@ -322,6 +323,8 @@ "areyousure": "Are you sure?", "barcode": "Barcode", "in": "In", + "instanceconflictext": "Your $t(titles.app) account can only be used on one device at any given time. Refresh your session to take control.", + "instanceconflictitle": "Your account is being used elsewhere.", "loading": "Loading...", "loadingapp": "Loading Bodyshop.app", "loadingshop": "Loading shop data...", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index e5f52e1c3..0982b7d80 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -312,6 +312,7 @@ "create": "", "delete": "Borrar", "edit": "Editar", + "refresh": "", "reset": "Restablecer a original.", "save": "Salvar", "saveandnew": "", @@ -322,6 +323,8 @@ "areyousure": "", "barcode": "código de barras", "in": "en", + "instanceconflictext": "", + "instanceconflictitle": "", "loading": "Cargando...", "loadingapp": "Cargando Bodyshop.app", "loadingshop": "Cargando datos de la tienda ...", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 67da69916..b07c1c8aa 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -312,6 +312,7 @@ "create": "", "delete": "Effacer", "edit": "modifier", + "refresh": "", "reset": "Rétablir l'original.", "save": "sauvegarder", "saveandnew": "", @@ -322,6 +323,8 @@ "areyousure": "", "barcode": "code à barre", "in": "dans", + "instanceconflictext": "", + "instanceconflictitle": "", "loading": "Chargement...", "loadingapp": "Chargement de Bodyshop.app", "loadingshop": "Chargement des données de la boutique ...",