I am trying to use the Firestore security rules to edit some data, as follows, with a transaction in Flutter:
Future sendRequest(uidSend, uidRec, pid, title) async {
final crSend = ChatRequest(uid: uidRec, pid: pid, title: title);
var _lsSend = List();
_lsSend.add(crSend.toJson());
final crRec = ChatRequest(uid: uidSend, pid: pid, title: title);
var _lsRec = List();
_lsRec.add(crRec.toJson());
final uMSendDocref = userMetadataCollection.document(uidSend);
final uMRecDocref = userMetadataCollection.document(uidRec);
Firestore.instance.runTransaction((transaction) async {
await transaction.update(uMSendDocref, <String, dynamic>{
"sentRequests": FieldValue.arrayUnion(
_lsSend,
),
});
await transaction.update(uMRecDocref, <String, dynamic>{
"receivedRequests": FieldValue.arrayUnion(
_lsRec,
),
});
});
}
Notice that user1 is trying to update both his/her own data, as well as user2's. However, I only want user1 to be able to update this single field of user2's. I make my Firestore rules as such:
match /userMetadata/{uid} {
allow read: if uid == request.auth.uid || uid == 'PREVIEW';
allow write: if uid == request.auth.uid && uid != 'PREVIEW';
match /receivedRequests {
allow read: if uid == request.auth.uid;
allow write: if request.auth != null && request.auth.uid != 'PREVIEW';
}
match /sentRequests {
allow read: if uid == request.auth.uid;
allow write: if request.auth != null && request.auth.uid != 'PREVIEW';
}
}
receivedRequests (and sentRequests) only require that a user has a non-null auth to edit, ie, any user should be able to edit. However, I get a permissions error when running my transaction. Why is that? Perhaps I am misunderstanding Firestore rules? Perhaps the transaction is trying to do a read? Any thoughts?
UPDATE:
I tried using a batch:
Future sendRequest(uidSend, uidRec, pid, title) async {
//update own uM with post
//update other uM with user
final crSend = ChatRequest(uid: uidRec, pid: pid, title: title);
var _lsSend = List();
_lsSend.add(crSend.toJson());
final crRec = ChatRequest(uid: uidSend, pid: pid, title: title);
var _lsRec = List();
_lsRec.add(crRec.toJson());
final uMSendDocref = userMetadataCollection.document(uidSend);
final uMRecDocref = userMetadataCollection.document(uidRec);
var batch = Firestore.instance.batch();
batch.updateData(uMSendDocref, <String, dynamic>{
"sentRequests": FieldValue.arrayUnion(
_lsSend,
),
});
batch.updateData(uMRecDocref, <String, dynamic>{
"receivedRequests": FieldValue.arrayUnion(
_lsRec,
),
});
return await batch.commit();
}
Still does not work. Something is either incredibly unintuitive with Firestore, or there is a serious bug.
Another thing to note: some of the userMetadata might not currently have the fields that are being updated.