Reputation: 2953
I'm setting up a new project in Vue JS. I'm building a blog, with a Firebase integration. The idea is that any logged in user is able to create blog posts which gets saved to the Firebase real-time database under: https://xxx.firebaseio.com/blogs.json
, each blog has a unique firebase ID.
The issue I'm having, is that if there are multiple users creating blog posts, the traditional Firebase rules dictate that for the logged in user, the blog posts will be created under that user, and if another user is logged in, their blogs posts will appear under their user.
This is fine, however it means when I'm trying to do a v-for
over my blog posts, I have two objects, each for the user, with potentially multiple blog objects in each one with no way of taking these out.
Below is my current rules:
{
"rules": {
"blogs": {
".read": true,
".write": false,
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
I'd like to be able to create all the blog posts for a logged in user, and have the posts created under blogs
rather than the user ID: $uid
, how can I achieve this?
Currently, this is the output I get with my current rules listed about:
{
"PvWsi3t9mFZza5gXP8qNQaCktDN2": {
"-LrZ87XS02DanBTybhij": {
"body": "<p><strong>test</strong></p>",
"creation": "",
"slug": "test",
"title": "My very first blog post"
},
"-LrZ8KjsJyGT1YFsIJ3G": {
"body": "<p><strong>jjj</strong></p>",
"creation": "2019-10-19",
"slug": "test-2",
"title": "Second post"
}
},
"yLLOq9jC5odefHBENkO3r2ztNzZ2": {
"-LrZ8ZRhLVEylBFaGcnq": {
"body": "<p>content here</p>",
"creation": "2019-10-04",
"slug": "test-two",
"title": "My very first blog post - ryan"
}
}
}
UPDATE
Here's my Firebase ref which adds a blog post:
firebase.database().ref('blogs/' + this.$store.state.user.uid).push(this.post).then(() => {
console.log('success')
}).catch((err) => {
console.log('error', err)
})
Upvotes: 1
Views: 834
Reputation: 3067
With rules such as (untested)
"rules": {
"blogs": {
".read": true,
"$blogId": {
".write": "(!data.exists() || data.child('author').val() == auth.uid)
&& (newData.child('author').val() == auth.uid || !newData.exists())"
}
}
}
you can use a flat structure for your blogs, by adding an author
field in them and forcing it to be the UID of the creator.
First ".write" line means "it's a new blog or it's YOUR blog".
Second line means "it is now YOUR blog or it is deleted".
Your code should be something like
const postWithAuthor = this.post;
postWithAuthor.author = this.$store.state.user.uid;
firebase.database().ref('blogs').push(postWithAuthor).then(() => {
console.log('success');
}).catch((err) => {
console.log('error', err);
});
You are concerned that, by making the UIDs publicly known, anyone can use a fake UID and write to your database. It's like saying people shouldn't know you're "RyanHolton", because they could make posts and label them as yours.
In your rules, newData.child('author').val() == auth.uid
ensures that if someone says they're X, they're also authenticated as X. People would indeed be able to write to your database, but they'd have to put their real UID for "author".
If you want to allow only SOME people to write, you should add their UIDs in your database, possibly in the "admins" path, and add
&& root.child('admins/'+auth.uid).exists()
to your ".write" rules.
Upvotes: 1