Reputation: 388
What I'm trying to achieve is to only show the documents that match request.auth.uid
. I've seen these examples on a lot of website but none of them seems to work for me. No matter what article I read I see these examples there but none of them seems to work for me. I have a (posts) collection with bunch of documents with auto-generated (ids).
// I cannot attach more than 2 images it gives me formatting error that's why.
https://i.sstatic.net/M84P5.png
https://i.sstatic.net/hbBii.png
https://i.sstatic.net/lm4HH.png
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if request.auth.uid == resource.data.userId; // This doesn't work
}
}
}
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if request.auth.uid == postId; // This also doesn't work
}
}
}
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if request.auth.uid != null; // even though this works fine but it is general.
}
}
}
Below I've shared my code.
class App extends React.Component {
constructor() {
super();
this.state = { social: [], loggedIn: "false" };
}
componentDidMount = () => {
firestore.collection("posts").onSnapshot((snapshot) => {
const social = snapshot.docs.map((doc) => {
return { id: doc.id, ...doc.data() };
});
this.setState({
social
});
});
};
// clickHandle(id, likes) {
// firestore
// .collection("posts")
// .doc(id)
// .update({ likes: likes + 1 });
// }
handleCreate() {
var obj = { title: "Never Ever GIve Up" };
firestore.collection("posts").add(obj);
}
handleDelete(id) {
firestore.collection("posts").doc(id).delete();
}
handleLogin() {
var provider = new firebase.auth.GoogleAuthProvider();
auth.signInWithPopup(provider).then((result) => {
console.log(result);
});
}
handleLogout() {
firebase.auth().onAuthStateChanged((user) => {
auth.signOut();
});
}
render() {
return (
<div>
<button onClick={this.handleLogin.bind(this)}>Login to Google</button>
<button onClick={this.handleLogout.bind(this)}> Logout from Google</button>
{this.state.social.map((obj) => {
return (
<h1>{obj.title} </h1>
);
})}
<br />
<button id="create" onClick={this.handleCreate.bind(this)}>
Create
</button>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"));
Upvotes: 0
Views: 1330
Reputation: 317392
The problem is that Firestore security rules are not filters. Please read that documentation carefully, and also this blog.
Your query is asking for all documents in the posts collection. However, your rules do not allow that. The rules will not filter the documents that match the rules. Instead, your client app needs to filter for the documents that the user should be able to read, and your rules need to validate that filter.
If you want to require the userId field to be the same as the authenticated user ID for the purpose of reading the document, your query needs to add a filter to ensure they aren't asking for anything more than they have permission to read:
firestore.collection("posts").where("userId", "==", uid)
Where uid
is the user ID that you got from the Firebase Auth SDK.
Then your rules can check to see that the filter is correct:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{postId} {
allow read: if request.auth.uid == resource.data.userId;
}
}
}
Upvotes: 1
Reputation: 1965
I bet you're doing something funky with your requests.
resource.data
will return the attributes of the document accessed. In your first example, this will work if the document at path posts/{post_id}
has the attribute userId
, and the userId
attribute matches the uid
of the incoming request context. I would verify the structure of each document in the posts collection to check that it matches.
The first example should work, I would double-check the user id matches of the sender. Check the "Authentication" tab of your Firebase console. (In the document shown, looks like the userId
is the id of another post, which might indicate some misbehavior?)
The second example won't work because the document doesn't have a postId
attribute.
Upvotes: 0