Firebase rules to only allow author to update, delete

2,953 views
Skip to first unread message

michael powers

unread,
Dec 9, 2019, 1:38:55 PM12/9/19
to Firebase Google Group
I posted on Stackoverflow but they closed my question rather than answer it. Annoying.

I want to move from testing to production so want to tighten up my rules. I want only authors of documents to be able to update or delete.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if request.auth != null;
      allow update, delete: if request.auth != null && request.auth.uid == resource.data.author_uid;
      allow create: if request.auth != null;
    }
  }
}


Secondarily when I go to execute a delete I get a permissions error and the delete does not execute.

const decrement = firebase.firestore.FieldValue.increment(-1);
firestore.collection('story').doc(storyid).delete().then(function() {
    firestore.collection('users').doc(getUserID()).update({
        saves: decrement 
    });
})


Sam Stern

unread,
Dec 9, 2019, 1:51:04 PM12/9/19
to Firebase Google Group
Hey Michael,

Are you sure that the permissions error is coming from your delete() call and not your update() call?  The rules you wrote apply to all documents in the database so if the 'users' doc doesn't also have the right author_uid properties you would get a permission denied error from the update() call.  If you are sure of that, let's break this down into a smaller and more informative reproduction.  Could you run this code (or something like it) and share the results:

console.log("getUserID", getUserID());
console.log("currentUser", JSON.stringify(firebase.auth().currentUser));

firestore.collection("story").doc(storyid).get().then(function (snap) {
  console.log("Story doc:", JSON.stringify(snap.data());
});

firestore.collection('story').doc(storyid).delete().then(function() {
   console.log("Delete success")
}).catch(function (e) {
   console.log("Delete failed", e);
});

I think the various logs from that snippet will make the issue apparent.  Apologize if I made any small mistakes, coding in Gmail :-)

- Sam

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/156a624b-64a4-4902-85a4-1c7d0cb2f394%40googlegroups.com.

michael powers

unread,
Dec 9, 2019, 10:57:59 PM12/9/19
to Firebase Google Group
Thanks for the help ...

Added (you were only missing one paren!):

function deleteStory(storyid, photoid) {
console.log("getUserID", getUserID());
console.log("currentUser", JSON.stringify(firebase.auth().currentUser));

firestore.collection("story").doc(storyid).get().then(function (snap) {
  console.log("Story doc:", JSON.stringify(snap.data()));
});

firestore.collection('story').doc(storyid).delete().then(function() {
   console.log("Delete success")
}).catch(function (e) {
   console.log("Delete failed", e);
});



It looks like it is failing on delete:

getUserID qFzhqv8wB8T7a4dazM8ihfzBlEq1
app.js:291 currentUser {"uid":"qFzhqv8wB8T7a4dazM8ihfzBlEq1","displayName":"michael powers","photoURL":"https://lh3.googleusercontent.com/a-/AAuE7mCBAcE8gPAtYp8dKtosIBpGgRwVzuiWjpY4YHIoYA","email":"email","emailVerified":true,"phoneNumber":null,"isAnonymous":false,"tenantId":null,"providerData":[{"uid":"106855305726401203115","displayName":"michael powers","photoURL":"https://lh3.googleusercontent.com/a-/AAuE7mCBAcE8gPAtYp8dKtosIBpGgRwVzuiWjpY4YHIoYA","email":"email","phoneNumber":null,"providerId":"google.com"}],"apiKey":"AIzaSyDbAww7OZSKLjS7AixIp3VcRNHbm7YqZxQ","appName":"[DEFAULT]","authDomain":"fling.photo","stsTokenManager":{"apiKey":"AIzaSyDbAww7OZSKLjS7AixIp3VcRNHbm7YqZxQ","refreshToken":"AEu4IL27xL8PaD-IbzGon5JbY-cy8VFohe6j-s1mQ6TOTjfNkTToELxpu1KxNHnFHKHh6awVsvftNqpsnaCki2TxEB8IQoMHESs1c-K9gImWuD990tqO9I9f1yn7QSfU3WyMXSRpX3hpA3eMJXkmYE59dkHswlKqLgus0xJBa83JFPtrGP5QVicjthA54QRiHdCuv5mokzUrK252Qlf_jH8myp5rbiD1RiG-JSf0KtupzX06Mo6seyI9di5i0gYF04thHnzKZDi428h3nhES47fim27hY7fiPS0YyqBy4DaSssbYV_3nATM4ZJnKKAUJ7koXiCZkFEKiCsuEjlbqDBPcsv1Kf5__LjG3EXDrq3m6W2e501J7wz-Ca-ES-ChvoTw-3XzXFOn0rWz9jRHTdNAFjFqfaZxkqw","accessToken":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjA0NjUxMTM5ZDg4NzUyYjY0OTM0MjUzNGE2YjRhMDUxMjVkNzhmYmIiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoibWljaGFlbCBwb3dlcnMiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EtL0FBdUU3bUNCQWNFOGdQQXRZcDhkS3Rvc0lCcEdnUndWenVpV2pwWTRZSElvWUEiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZmxpbmdwaG90by0xIiwiYXVkIjoiZmxpbmdwaG90by0xIiwiYXV0aF90aW1lIjoxNTc1NjY3MDQ0LCJ1c2VyX2lkIjoicUZ6aHF2OHdCOFQ3YTRkYXpNOGloZnpCbEVxMSIsInN1YiI6InFGemhxdjh3QjhUN2E0ZGF6TThpaGZ6QmxFcTEiLCJpYXQiOjE1NzU5MTg3NTAsImV4cCI6MTU3NTkyMjM1MCwiZW1haWwiOiJwb3dlcnBvcEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjEwNjg1NTMwNTcyNjQwMTIwMzExNSJdLCJlbWFpbCI6WyJwb3dlcnBvcEBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.WuWjnGPCZu_s0XU0kcdw4plrU9MFKP9OyZeNzCj85UZFjktPLymDMHqP4PFsm4xRClJasBcCrGeD_GkxTB8nyPh6ioR27NaHPjQaf7QDoz0KU2RpgpcSdS1qPhM1vDrGW_cmNpgy3_n_EL3BUJfbfd7_5UB7S5Qc996tc3SxCR4ReqPrysyroUnUUKmr1F_tmq6squ6hDj3m_V5ij3SwT3V1WPTeHnx_sHyO708ER_zgytpX1z0Fvn0sABZtBgBxzK6elkr7pSAQ93PdDafgE1UpfbcbML-Tyo4fzD3FUQ953AS-ICd3Fjocq3oIZqQkqvtujpssMjm3UVTUTgWqCA","expirationTime":1575922348619},"redirectEventId":null,"lastLoginAt":"1575667044929","createdAt":"1574905934451"}
app.js:300 Delete failed FirebaseError: Missing or insufficient permissions.
app.js:294 Story doc: {"created":{"seconds":1575919342,"nanoseconds":719000000},"name":"michael","owner":"qFzhqv8wB8T7a4dazM8ihfzBlEq1","pic":"https://lh3.googleusercontent.com/a-/AAuE7mCBAcE8gPAtYp8dKtosIBpGgRwVzuiWjpY4YHIoYA","publicid":"savesbeta/237_h0pums","status":"ACTIVE","story":"","tags":[],"timestamp":{"seconds":1575919342,"nanoseconds":719000000}}
To unsubscribe from this group and stop receiving emails from it, send an email to fireba...@googlegroups.com.

Sam Stern

unread,
Dec 10, 2019, 12:13:01 AM12/10/19
to Firebase Google Group
Thanks for the logs!

Looks like your rules check "resource.data.author_uid" but your story doc doesn't have that field.  It does have an "owner" field though, did you mean to check that field in your rules?

Sam

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/6a1c6bb0-0a2d-48d7-8a37-626db29706c9%40googlegroups.com.

michael powers

unread,
Dec 10, 2019, 9:51:46 AM12/10/19
to Firebase Google Group
Foolish me ... I thought that author_id was a hidden value of all documents rather than a creator id that I manually added to each document

When I create my user object I use the userid as the document id ... so I imagine there I will then have to add a creator field to the user documents. Is there a way to compare the id of the document with the request.auth.uid

Sam Stern

unread,
Dec 10, 2019, 11:31:03 AM12/10/19
to Firebase Google Group
Hey Michael,

You can definitely use the ID of the document in rules by matching the path.  Here's a simple example:

service cloud.firestore {
   match /databases/{database}/documents {
     match /users/{userId} {
       // In this scope the "userId" variable is equal to the documentId because of the wildcard declaration {userId}
       allow write: if request.auth.uid == userId;
     }
   }
}


Hope that helps!

- Sam

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/8db41879-1a98-46f7-bde0-704635745cfa%40googlegroups.com.

michael powers

unread,
Dec 12, 2019, 10:08:51 AM12/12/19
to Firebase Google Group
Fantastic, both the UserId pattern and the original one in my question (your answer) work! I was able to get the SO question revived and posted both answers - will add attribution.

Thank you - love Firebase

almino malaza

unread,
Jun 3, 2020, 10:31:44 PM6/3/20
to Firebase Google Group
Hi Sam,

I have actually tried this and several rules on this page


I have actually tried this

service cloud.firestore {
  match
/databases/{database}/documents {

   
// Allow only authenticated content owners access
    match
/my_collection/{userId}/{documents=**} {
      allow read
, write: if request.auth.uid == userId
   
}
 
}
}


and even tried your solution.

I do no know if I should create a new post for my issue, but I have almost the same issue as Michael's. I just needed the user to be able to read and write on his own document or create a new one if his ID is not yet in. I did use the users uid as the document's id.  But still get a missing or insufficient permissions.

So here is my query for the get data

db.collection('theCollection').get().then(function(querySnapshot) {
                querySnapshot
.forEach(function(doc) {
                   
// doc.data() is never undefined for query doc snapshots
                    let currUserId
= user.uid;
                    let userDoc
= doc.id;
                   
if(currUserId == userDoc){
                      console
.log(currUserId, " => ", doc.data());
                   
}
                   
                   
               
});
             
});

I have also tried adding

testAdd.addEventListener('click', function(){
                console
.log('button test');
                db
.collection('theCollection').add({
                  createDate
:firebase.firestore.Timestamp.now()
               
}).then(() => {
                  console
.log('created');
                 
               
});
             
});



I get the same error heading for the two which is

Uncaught (in promise) FirebaseError: Missing or insufficient permissions.

My DB is something like this

mycollection > docId (the same as the user id) > createDate

I hope this make sense.

Thanks,
Al
Reply all
Reply to author
Forward
0 new messages