Home > database >  Firestore Rules using get returns insufficient permissions
Firestore Rules using get returns insufficient permissions

Time:04-26

I'm making a query to firestore using:

setDoc(doc(db, "vendors", this.vendorId), {
    title: "test listing",
    vendorId: this.vendorId
}, {merge: true}).then(i => {
    console.log("i", i)
}).catch(e => {
    console.log("error", e)
})

I have 2 collections the first one has a sub collection

Collection users/${userId}

{
    "userId": "123.uuu",
    "role": "vendor"
}

Sub collection users/${userId}/vendors/${vendorId}

{
    "user": "123.uuu",
    "vendor": "123..vvv"
}

The second collection is Collection vendors/${vendorId}

{
    "userId": "123.uuu",
    "role": "vendor"
}

I want to be able to update the second collection vendors/${vendorId} but only if the users sub collection users/${userId}/vendors/${vendorId} exists and therefore has access to it.

The below rule doesn't work - returns FirebaseError: Missing or insufficient permissions.

match /vendors/{vendorId}{
    allow update: if get(/databases/$(database)/documents/users/$(request.auth.uid)/vendors/$(vendorId)).data.user == request.auth.uid
}

CodePudding user response:

The allow update will allow update operations only i.e. the document must already exist. Since you are using using setDoc(), that means a new document is being created if it doesn't exist already. Try allowing create as well:

allow create, update: if ....;

Checkout the documentation on Security Rules and also this Firecast

CodePudding user response:

According to @Doug Stevenson: "Security rules don't mean anything unless paired with code that makes the query.", you can try to follow the example code below that works upon replicating on my end:

// Where the user.uid is the users document id;
// and the vendorId is the value of the "user" under vendors' sub-collection
const userRef = doc(db, "users", {user.uid}, "vendors", {vendorId});
const userSnap = await getDoc(userRef);

if (userSnap.exists()){
  // Where the vendorId is the value of the user under vendors' collection
  await setDoc(doc(db, "vendors", {vendorId}), {
    title: "test listing",
    vendorId: this.vendorId
  }, 
    {merge: true}).catch(e => {
      console.log("error", e);
  })
}
else{
    // doc.data() will be undefined in this case
    console.log("No such document!");
}

Additionally, following the answer of @Dharmaraj, you can try this rule:

match /vendors/{vendorId} {
    // 'user' field in collection 'vendors', and users' sub-collection 'vendors', should have the same value for this rule to work
    // this will check 'vendors' and users' sub-collection 'vendors' user field if its the same or not
    allow read, create, update: if resource.data.user == request.auth.uid && request.auth.uid != null
}

For more information, you can check the guide below:

How to fix Firestore Error: PERMISSION_DENIED: Missing or insufficient permissions

  • Related