Reputation: 33
The goal is to save user information to MongoDB and display a success message in the UI. The app will ultimately be a Twilio template I can use on my apps. I expected to send the user data and auth token to a "MongoUtils" class component. Then send the auth token to the middleware. Save the info to the database. And get a successful response. Instead, the auth token passed and the data was saved, but, no success message in the UI. The error message is that of the " Converting circular structure to JSON error".
The relevant code is as follows:
const { password, displayName } = model;
const initials = displayName[0] + displayName[1];
const avColor = `#${Math.floor(Math.random() * 16777215).toString(16)}`;
const email = `${window.localStorage.getItem('emailForResgistrant')}`;
return firebaseService.auth
.signInWithEmailLink(email, window.location.href)
.then((result) => {
console.log('registerSliceYes check 1 --->', result.user);
dispatch(
createUserSettingsFirebase({
...result.user,
displayName,
email,
initials,
avColor,
})
);
// send success message
dispatch(
showMessage({
message: `Verification email sent to ${email}. Click the link to complete account`,
})
);
This is the relevant snippet from the UI client registration slice. I am using redux toolkit. createUserSettingsFirebase ended up being used for sending the data to MongoDB also. Currently sends to both firebase and mongo. This takes us to the userSlice:
export const createUserSettingsFirebase = (authUser) => async (dispatch, getState) => {
console.log('userslice check 2 --->', authUser);
// const guestUser = getState().auth.user;
// current user is destructured from the firebase.auth object(not a local variable)
const { currentUser } = firebase.auth();
console.log('register check 1 --->', currentUser);
// console.log('register check 1.5 --->', idTokenResult);
/**
* Merge with current Settings
*/
// <--- updates user profile in firebase(only basic info)
const user = _.merge(
{},
{
uid: authUser.uid,
from: 'firebase',
role: ['admin'],
data: {
displayName: authUser.displayName,
email: authUser.email,
initials: authUser.initials,
avColor: authUser.avColor,
redirectUrl: '/apps/chat',
},
}
);
currentUser.updateProfile(user.data);
// updates user profile in firebase(only basic info) --->
// this updates the firebase db by ultimately making a call to firebase
const idTokenResult = await currentUser.getIdTokenResult();
dispatch(updateUserData(user));
dispatch(updateUserDataMongoDB(authUser, idTokenResult.token));
return dispatch(setUserData(user));
};
Some of the notes are for my memory. The key action here is the updateUserDataMongoDB action. It is also located in the userSlice:
export const updateUserDataMongoDB = (authUser, authtoken) => async (dispatch, getState) => {
console.log('updateUserDataMongoDB', authtoken);
await MongoUtils.updateUserDataTwo(authUser, authtoken)
.then((response) => {
console.log('mongo success message');
dispatch(showMessage({ message: 'User data saved to MongoDB' }));
})
.catch((error) => {
console.log('mongo error message', error);
dispatch(showMessage({ message: error.message }));
});
};
And finally, the MongoUtils class component:
static updateUserDataTwo(authUser, authtoken) {
if (!authUser) {
return false;
}
return new Promise((resolve, reject) => {
axios
.post(
`${process.env.REACT_APP_API}/complete-user`,
{ authUser },
{
headers: {
authtoken,
},
}
)
.then((response) => {
resolve(response.data);
})
.catch((error) => {
// handle error
console.trace('MongoDB Utility Error(updateUserDataTwo)', error);
reject(error);
});
});
}
Also, the mongoose middleware:
exports.authCheck = async (req, res, next) => {
console.log('authcheck ---->', req.headers); //token
try {
const firebaseUser = await admin
.auth()
.verifyIdToken(req.headers.authtoken);
console.log('FIREBASE USER PASSED AUTHCHECK', firebaseUser)
req.user = firebaseUser;
next();
} catch (err) {
console.log(err)
res.status(401).json({
err: "Invalid or expired token",
});
}
};
I tried different code structures in my mongo class. I managed to save to the db but no Promise resolution. The error is as follows:
react_devtools_backend.js:2540 MongoDB Utility Error(updateUserDataTwo) TypeError: Converting circular structure to JSON
--> starting at object with constructor 'D'
| property 'c' -> object with constructor 'D'
| property 'b' -> object with constructor 'Dc'
--- property 'a' closes the circle
at JSON.stringify (<anonymous>)
at transformRequest (defaults.js:52)
at transform (transformData.js:16)
at Object.forEach (utils.js:247)
at transformData (transformData.js:15)
at dispatchRequest (dispatchRequest.js:30)
overrideMethod @ react_devtools_backend.js:2540
(anonymous) @ MongoUtils.js:46
Promise.catch (async)
(anonymous) @ MongoUtils.js:43
updateUserDataTwo @ MongoUtils.js:30
(anonymous) @ userSlice.js:189
(anonymous) @ index.js:8
dispatch @ redux.js:659
(anonymous) @ userSlice.js:61
await in (anonymous) (async)
(anonymous) @ index.js:8
dispatch @ redux.js:659
(anonymous) @ registerSlice.js:121
The app works but obviously something doesn't and I can't display the message in the UI. Thanks for your input!
Edit: This is the user logged to console... not sure if this may shed some light or not:
Im {N: Array(0), l: 'AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0', m: '[DEFAULT]', s: 'twilio-3915f.firebaseapp.com', a: Ii, …}
$: Fn {l: false, settings: em, app: FirebaseAppImpl, a: Ii, P: Array(0), …}
Aa: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjgwNTg1Zjk5MjExMmZmODgxMTEzOTlhMzY5NzU2MTc1YWExYjRjZjkiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibG9wZXpqZXNzZTEyNzdAZ21haWwuY29tIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL3R3aWxpby0zOTE1ZiIsImF1ZCI6InR3aWxpby0zOTE1ZiIsImF1dGhfdGltZSI6MTYzODA1MzM1MywidXNlcl9pZCI6ImtKYkxVTU9mNzJXT1hLR2lOdXkzYTNaRUVIUjIiLCJzdWIiOiJrSmJMVU1PZjcyV09YS0dpTnV5M2EzWkVFSFIyIiwiaWF0IjoxNjM4MDY0NTQxLCJleHAiOjE2MzgwNjgxNDEsImVtYWlsIjoiY2hhbXBpb25zbGFuZHNjYXBlMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJjaGFtcGlvbnNsYW5kc2NhcGUxQGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIn19.cWLpobXqqjp5zq_RHRCLr78CPxyVLmlL6t-Eo7_U0R6Kgsgma8bQJp_WYZEXgKfF4wgEK4XhjSfuCy2rdreaJ70NgFdeCSQdibJiPSyY_ORMkBbR8s3ux32sWKMw9HPj1YMyu-oo2INGLbi7ttwmI9fmlNMJy3SXe-VS1j7-Eo1C4FCQ6m1m2S0O59oh2QVOjuEcqwHe9c0GwRn7Edw-0ozpeCvW0pS6Df_N79c24aFhg6XgtqVLzfgfAhRheDEO1sSCl1XvLOyeMYxcSr49YvQ0dv5a8H412q7Wohc3XV4XnPd-M-C1EQNNmHnnwJBx_dT2TEO4rmIn_pJEICp6Zw"
Ba: ƒ (f)
D: xm {c: 30000, f: 960000, h: ƒ, i: ƒ, g: ƒ, …}
N: []
Oa: ƒ (f)
P: true
Pa: ƒ (f)
S: tm {a: Im, b: Array(0), enrolledFactors: Array(0), c: ƒ}
W: [ƒ]
a: Ii {c: 'AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0', l: 'https://securetoken.googleapis.com/v1/token', m: Ze, g: {…}, h: 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/', …}
aa: []
b: Gl {i: {…}, u: 0, D: 'twilio-3915f.firebaseapp.com', v: 'AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0', m: '[DEFAULT]', …}
ba: ƒ ()
bc: Im {N: Array(0), l: 'AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0', m: '[DEFAULT]', s: 'twilio-3915f.firebaseapp.com', a: Ii, …}
displayName: "[email protected]"
email: "[email protected]"
emailVerified: true
h: Am {f: Ii, a: 'AFxQ4_ov0xeye6FQ23KAFH4b4Lb-7npe34-sGKQwWZYVeX2r8p…xI5aTc1c2NUTKILj-tbExZ38iwtqLppZUgQXTqHi_zMJ8C25I', b: hg, c: 1638068141823}
ha: tn {a: 'AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0:[DEFAULT]', b: Tk}
hb: null
i: null
isAnonymous: false
ja: Fn {l: false, settings: em, app: FirebaseAppImpl, a: Ii, P: Array(0), …}
l: "AIzaSyCHVffqdXsT1_NypdTU2F29NhOUbSG-lw0"
m: "[DEFAULT]"
metadata: Fm {a: '1638053351217', b: '1638053351217', lastSignInTime: 'Sat, 27 Nov 2021 22:49:11 GMT', creationTime: 'Sat, 27 Nov 2021 22:49:11 GMT'}
multiFactor: tm {a: Im, b: Array(0), enrolledFactors: Array(0), c: ƒ}
pa: undefined
phoneNumber: null
photoURL: null
providerData: [{…}]
qa: Fn {l: false, settings: em, app: FirebaseAppImpl, a: Ii, P: Array(0), …}
refreshToken: "AFxQ4_ov0xeye6FQ23KAFH4b4Lb-7npe34-sGKQwWZYVeX2r8p2OXV_dvhY6G1vQIZ80Y-kKUr2YmQqPDwE2kbVl-_04iweIczJotfXPXjeGGcKrpc86virbSR4Tpp4r0jxBDXjDXjhm8BLKgjMLQ805REE2-4CxfWYlQzEi9VsFziNcEczNRzL-uiiH97vR3mQgwsBMcSwLogufOyfjzhXYumwxI5aTc1c2NUTKILj-tbExZ38iwtqLppZUgQXTqHi_zMJ8C25I"
s: "twilio-3915f.firebaseapp.com"
tenantId: null
u: null
uid: "kJbLUMOf72WOXKGiNuy3a3ZEEHR2"
v: hd {src: Im, a: {…}, b: 4}
ya: false
za: null
_lat: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjgwNTg1Zjk5MjExMmZmODgxMTEzOTlhMzY5NzU2MTc1YWExYjRjZjkiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibG9wZXpqZXNzZTEyNzdAZ21haWwuY29tIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL3R3aWxpby0zOTE1ZiIsImF1ZCI6InR3aWxpby0zOTE1ZiIsImF1dGhfdGltZSI6MTYzODA1MzM1MywidXNlcl9pZCI6ImtKYkxVTU9mNzJXT1hLR2lOdXkzYTNaRUVIUjIiLCJzdWIiOiJrSmJMVU1PZjcyV09YS0dpTnV5M2EzWkVFSFIyIiwiaWF0IjoxNjM4MDY0NTQxLCJleHAiOjE2MzgwNjgxNDEsImVtYWlsIjoiY2hhbXBpb25zbGFuZHNjYXBlMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJjaGFtcGlvbnNsYW5kc2NhcGUxQGdtYWlsLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIn19.cWLpobXqqjp5zq_RHRCLr78CPxyVLmlL6t-Eo7_U0R6Kgsgma8bQJp_WYZEXgKfF4wgEK4XhjSfuCy2rdreaJ70NgFdeCSQdibJiPSyY_ORMkBbR8s3ux32sWKMw9HPj1YMyu-oo2INGLbi7ttwmI9fmlNMJy3SXe-VS1j7-Eo1C4FCQ6m1m2S0O59oh2QVOjuEcqwHe9c0GwRn7Edw-0ozpeCvW0pS6Df_N79c24aFhg6XgtqVLzfgfAhRheDEO1sSCl1XvLOyeMYxcSr49YvQ0dv5a8H412q7Wohc3XV4XnPd-M-C1EQNNmHnnwJBx_dT2TEO4rmIn_pJEICp6Zw"
[[Prototype]]: H
Upvotes: 1
Views: 324
Reputation: 33
And answered, as jfriend00 explained(not sure how to mark his comment as an answer):
export const createUserSettingsFirebase = (authUser) => async (dispatch, getState) => {
console.log('userslice check 2 --->', authUser);
// const guestUser = getState().auth.user;
// current user is destructured from the firebase.auth object(not a local variable)
const { currentUser } = firebase.auth();
console.log('register check 1 --->', currentUser);
// console.log('register check 1.5 --->', idTokenResult);
/**
* Merge with current Settings
*/
// <--- updates user profile in firebase(only basic info)
const user = _.merge(
{},
{
uid: authUser.uid,
from: 'firebase',
role: ['admin'],
data: {
displayName: authUser.displayName,
email: authUser.email,
initials: authUser.initials,
avColor: authUser.avColor,
redirectUrl: '/apps/chat',
},
}
);
currentUser.updateProfile(user.data);
// updates user profile in firebase(only basic info) --->
// this updates the firebase db by ultimately making a call to firebase
const idTokenResult = await currentUser.getIdTokenResult();
dispatch(updateUserData(user));
dispatch(updateUserDataMongoDB(authUser, idTokenResult.token));
return dispatch(setUserData(user));
};
I mistakenly sent the firebase response.user(as authuser) to the database. I instead sent the user as defined in createUserSettingsFirebase. And, magically, haha, successful promise resolution and the message in the UI.
redux-logger.es.js:659 action message/showMessage @ 19:51:52.405
redux-logger.es.js:679 prev state
{auth: {…}, rise: {…}, i18n: {…}, chatApp: {…}}
redux-logger.es.js:687 action
{type: 'message/showMessage', payload: {…}}
payload: {message: 'User data saved to MongoDB'}
type: "message/showMessage"
[[Prototype]]: Object
Upvotes: 1