On logging on via my signin page and navigating to my dashboard, I am trying to query a collection calls 'hotels' based upon the uid of the logged in user.
The issue I have is the uid I am using to query the collection, appears blank or as per the previous user logged in.
I am calling the data service after signin at my dashboard:
Dashboard.ts
this.getAllStudents();
}
// register() {
// this.auth.logout();
// }
getAllStudents() {
this.data.getAllStudents().subscribe(res => {
this.studentsList = res.map((e: any) => {
const data = e.payload.doc.data();
data.id = e.payload.doc.id;
return data;
})
}, err => {
alert('Error while fetching student data');
})
The dataserivce (data.ts) has the below code, which works, but the uid is either blank on first login or the previous user:
getAllStudents() {
return this.afs.collection('/hotels',ref=>ref.where('userid','==',this.auth.userState.uid)).snapshotChanges();
//return this.afs.collection('/hotels',ref=>ref.where('userid','==',)).snapshotChanges().subscribe(res =>
}
Help! I assume login is not set at the point of querying the database. Cheers
Related
I am working for a task related to react native app based user management. After they successful sign up themselves as a user, I include a data which is store Boolean value and I have named it as emailVerifiedAccount (this is the stored data if they registered themselves successful and indicate if they are a verified user if they click on email verification link send to them). In login screen I would like to check the Boolean value that I get from firestore in onAuthStateChanged and only direct them to index screen when the emailVerifiedAccount that I get is return true. Code below is authstatechanged for login screen .
const onAuthStateChanged = (user) => {
if (user) {
checkEmailVerifiedAccount=firestoreService.isEmailVerifiedAccount(user);
try {
if(checkEmailVerifiedAccount===true){
navigation.navigate('Index');
}else{
Alert.alert(
"Verify as a Playbookx user",
"Please click on email verification link send to your email. If you do not receive any email ,please contact user support",
"You may come back to login again after you verified your email",
[
{ text: "OK"}
]
)
}
} catch (error) {
console.log(error);
}
}
};
and in firestore.js is where all the code and function that is related with Firestore database. isEmailVerifiedAccount is one of the class object which checking verified user using email.
isEmailVerifiedAccount = async (user) => {
return await firestore()
.collection('users')
.doc(user)
.get()
.then(snapshot => {
if (snapshot.exists){
const user=snapshot.data();
const emailVerifiedAccount={
emailVerifiedAccount:user.emailVerifiedAccount
};
return emailVerifiedAccount
}
})
.catch(error => {
console.log(error);
});
};
And the problem that I facing right now is that, it lead me to index screen when the emailVerifiedAccount in Firestore is false. Picture below is the structure for Firestore.
Your isEmailVerifiedAccount function is asynchronous, so when calling it you have to await the result:
checkEmailVerifiedAccount = await firestoreService.isEmailVerifiedAccount(user);
const checkEmailVerifiedAccount = firestoreService.isEmailVerifiedAccount(user);
checkEmailVerifiedAcccount seems to be an object but you are checking if it's equal to true. Either return user.emailVerifiedAccount directly from isEmailVerifiedAccount function or read that property like this:
const checkEmailVerifiedAccount = firestoreService.isEmailVerifiedAccount(user);
if(checkEmailVerifiedAccount.emailVerifiedAccount) {
navigation.navigate('Index');
}
hi i want to get all data from menus collection by user.uid.
with my code i can retrieve the last data but not all with this code and i want to know why it just retrieves the last one record and not all of the user's connected thank you in advance for your help
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
console.log("userId", user.uid)
firebase.firestore().collection('menus').doc(user.uid)
.get()
.then(response => {
console.log("menus",response.data())
})
.catch(error => {
// setError(error);
});
} else {
// No user is signed in.
}
Hi I am using express for backend authentication and these are my sign in functions/controllers on the front end.
export const signInUser = async credentials => {
console.log('this is for the signInUser', credentials)
try {
const resp = await api.post('/sign-in', credentials)
localStorage.setItem('token', resp.data.token)
return resp.data
} catch (error) {
throw error
}
}
onSignIn = event => {
event.preventDefault()
const { history, setUser } = this.props
signInUser(this.state)
.then(res => setUser(res.user))
.then(() => history.push('/Home'))
.catch(error => {
console.error(error)
this.setState({
loginUsername: '',
loginPassword: '',
})
})
}
setUser = user => this.setState({ user })
and this is my sign in controller on the backend
const signIn = async (req, res) => {
try {
console.log('hello' ,req.body);
const { loginUsername, username, loginPassword } = req.body;
const user = await User.findOne({
where: {
username: loginUsername
}
});
console.log('this is the user', user)
if (await bcrypt.compare(loginPassword, user.dataValues.password_digest)) {
const payload = {
id: user.id,
username: user.username,
password: user.password
};
const token = jwt.sign(payload, TOKEN_KEY);
return res.status(201).json({ user, token });
} else {
res.status(401).send("Username or Password is invalid- try again.");
}
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
The issue is the state of the user doesn't persist on refresh but I still have the json webtoken in my local storage and this is an issue when I make post requests and even signing up since I am redirecting to the home page and losing the user state. Any help would be appreciated!
From your tags, I noticed that you are using React, so the solution is simple!
you can have an GlobalAuthManager context for your application that would wrap all the components at the most higher level! after <React.strictMode> like below:
<React.StrictMode>
<GlobalAuthManager.Provider value={{authData}}>
<App />
</GlobalAuthManager.Provider>
</React.StrictMode>
As you might guess, this would be a context! that would provide you your user data to all your components!
The Pattern:
1. Store token:
when your user logins to your app, you would receive a token ( in your response or in response header ), you need to store the token value in localstorage, or more better in cookie storage (there are a lot of articles about it why), one is here.
2. have a /getUserData endpoint in backend:
you need to have a /getUserData endpoint in backend to retrive your user data based on token
3. call /getUserData in app mount:
before every thing in your app, you need to call this endpoint if you find token in localstorage or cookie storage. so if you run this in your componnetDidMount or useEffect(() => { ... }, []), that would work!
4. store your user data and state in context:
after you've called the /getUserData and if you had a valid token(i mean not expired token or not interrupted and edited token) , you will get you user data and what you need to do is that you need to store this in your GlobalAuthManager and provide that in to your Global App component!
after that you have your user data available to you that you can decide to show login or sign up button in your Navbar or disable/enable comment section for example based on your user data!
Wrap up:
So the key is that you have to have a GlobalAuthManager for only one purpose, that before every thing it runs in the top level in your app and gets you your user data based on provided token from localstorage or cookie storage!
after that you can manage your app state based on that your user is logged in or not!
I am using Angular and cloud firestore for backend. I have a user profile, a logged in user and other users with follow or unfollow action button, based on the logged in user's current following list. I want the button text and the list of followers and following to get updated in the front end as soon as the click event is successfully completed. But, I am able to see the updated values only after there is a change in route, or I click the button twice.
Is there any way that, as soon as follow or unfollow is successful, data of loggedUser and selectedUser gets updated and the same updated data is reflected in my component.
userDetails.component.ts
ngOnInit(): void {
this.loggedUser = this.userService.getLoggedUserData();
//--------Get displayed user data
this.userService.SelectedUserChanged.pipe(take(1))
.subscribe(
(user:User)=>{
this.user=user;
if(this.user){
this.btnToDisplay(); //.....To show follow or unfollow depending on logged user's data
}}
);
}
I have a UserService, where I have subscribed to logged user's valueChanges()
fetchLoggedUser(uid: string) { //Subscribed in the appcomponent using authenticated user's id.
return this.db.collection('Users').doc(uid)
.valueChanges()
.pipe(
tap((user: User) => {
this.loggeduser = user;
this.loggeduser.id = user.userid;
this.fetchAllUsers();
})
);
}
fetchAllUsers() {
this.userSubs.push(
this.db
.collection('Users')
.valueChanges({ idField: 'id' })
.subscribe((users: User[]) => {
this.allUsers = users;
this.usersChanged.next([...this.allUsers]);
})
);
}
selectUser(uid: string) {
this.selectedUser = this.allUsers.find((user) => user.id === uid);
this.SelectedUserChanged.next({ ...this.selectedUser });
}
getLoggedUserData() {
return ({...this.loggeduser});
}
followUser(uid: string, email: string) {
this.db.collection('Users').doc(this.loggeduser.userid)
.update({
following: firebase.firestore.FieldValue.arrayUnion({
uid: uid,
email: email,
}),
});
this.db.collection('Users').doc(uid)
.update({
followers: firebase.firestore.FieldValue.arrayUnion({
uid: this.loggeduser.userid,
email: this.loggeduser.email,
}),
});
}
According to this post, valueChanges() and onSnapshot() automatically return the changes taking place to the document or collection that they are listening to. get() is used to get the data only once.
To achieve what you would like to, you'll need to follow the instructions on
Get real time updates with Cloud Firestore.
Based on this documentation, I have tested this code sample and when I am updating a value in the database the new document with the updated data are returned.
async function monitorUser(uid){
const doc = db.collection('users').doc(uid);
const observer = doc.onSnapshot(docSnapshot => {
console.log(`Received doc snapshot:`, docSnapshot.data());
}, err => {
console.log(`Encountered error: ${err}`);
});
}
Then you can update the public variable that corresponds to your user's data with the new values and the view should be updated.
Currently, when the user goes through the Social auth (via redirects), it successfully creates a user under Firebase Authentication, but fails to retrieve the Google/Facebook API's data. Perplexed as to how it's failing to retrieve the data when the Auth is successful.
I used to only have the SignInWithPopup (which works perfectly fine), but am trying to get getRedirectResults to work too (for mobile).
Given the behavior I've been seeing, the problem is most likely with the getRedirectResults. Most likely not the social API setup, because otherwise the user would never get created in Authentication.
The following code resides in componentDidMount (this is a React.js app):
if (this.state.device === 'mobile') {
firebase.auth().getRedirectResult().then(function(result) {
console.log('login successful! Data is:');
console.log(result);
if (result.credential) {
var provider = result.credential.providerId;
self.handleSocialAuth(provider, result);
}
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
});
}
results is supposed to contain the user's data, keeps returning:
login successful! Data is:
{user: null}
I have not deviated from official docs examples, which is why I'm confused.
firebase.auth().getRedirectResult() - is called after the page loads.
Official doc link: https://firebase.google.com/docs/auth/web/google-signin
Use the below method to retrieve the user that is logged in.
firebase.auth().onAuthStateChanged(function(user) {
console.log(user);
});
If no user is logged in the user will be null.
Live example:
checkAuthStatus(){
firebase.auth().onAuthStateChanged(user => {
this.setState({ btnWithImg: user });
if(user !== null){
this.setState({ userIsLoggedIn: true });
this.props.toggleLogIn();
}
});
}
You should call firebase.auth().getRedirectResult() only when user has been authenticated. Example
firebase.auth().onAuthStateChanged(user => {
if (user) {
const result = await firebase.auth().getRedirectResult();
assert(result.user, 'user is empty')
}
});