英文:
Firebase Firestore Rules: Allow read/write only if auth.id == request.data.id
问题
这是您提供的一段代码和问题描述。以下是翻译的部分:
我正在使用以下规则:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Documents can only be read or written by authenticated users
match /{document=**} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
}
}
}
根据我的理解,这应该意味着:“只有在用户经过身份验证且其 uid
与他们正在读取或写入的文档的 uid
匹配时,才允许读取或写入操作”。
然而,我不断收到“permission-denied”错误。
这是我正在使用的代码(Dart/Flutter):
static FirebaseFirestore instance = FirebaseFirestore.instance;
static CollectionReference colRef = instance.collection('someCollection');
使用此包装方法(已更新):
Future<void> updateData() async {
final uid_ = FirebaseAuth.instance.currentUser!.uid;
final data = {'uid': uid_};
await colRef.doc(uid_).set(data);
}
基本上,我将用户的 uid
传递给 updateData
函数,并确保文档具有相同的 uid
,以符合规则。
我做错了什么?
编辑:
我尝试过的事情:
-
确保用户已经通过身份验证,以及将正确的
uid
传递给包装函数。 -
使用
set
方法而不是update
方法,以避免如果文档尚不存在会出现任何问题。 -
在了解有关
resource
对象的更多信息后,将uid
附加到data
映射中。 -
在
rules
之间切换,从request.auth.uid == resource.data.uid
到request.auth.uid == resource.id
。 -
将规则更改为仅为
request.auth != null
,这最终按预期工作,但对于我的舒适区来说有点太宽泛。然而,这证明了用户已通过身份验证。我只需要一种方法来将auth.uid
与数据映射对象内的document.id
或uid
进行比较。 -
更改包装方法以明确使用
FirebaseAuth.instance
。
具体错误:
flutter: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
英文:
I am using these rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Documents can only be read or written by authenticated users
match /{document=**} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
}
}
}
From my understanding, this should mean: "Allow read or write operations ONLY IF the user is authenticated and their uid
matches the uid
of the document they are reading or writing".
Yet, I continually get permission-denied
errors.
This is the code I am using (Dart/Flutter):
static FirebaseFirestore instance = FirebaseFirestore.instance;
static CollectionReference colRef = instance.collection('someCollection');
With this wrapper method (updated):
Future<void> updateData() async {
final uid_ = FirebaseAuth.instance.currentUser!.uid;
final data = {'uid': uid_};
await colRef.doc(uid_).set(data);
}
Basically, I am passing the user uid
to the updateData
function, and ensuring the document has the same uid
so it conforms with the rules.
What am I doing wrong?
EDIT:
Things that I have tried:
-
Ensured that the user was authenticated and that the correct
uid
was being passed to the wrapper function. -
Used the
set
method instead of theupdate
method to avoid any issues if the document does not yet exist. -
Appended the
uid
to thedata
map after learning more about theresource
object. -
Toggled the rules between
request.auth.uid == resource.data.uid
andrequest.auth.uid == resource.id
. -
Changed the rule to only be
request.auth != null
, which ended up working as expected, but is a bit too broad for my comfort zone. Yet, this is proof that the user is authenticated. I just need a way to compare theauth.uid
with either thedocument.id
oruid
within the data map object. -
Changed the wrapper method to explicitly use
FirebaseAuth.instance
.
The specific error:
flutter: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
答案1
得分: 1
The key was that you're trying to write the uid
field for the first time.
Your rules now do this:
resource.data.uid
The resource
here refers to the document as it exists before the current operation, which doesn't seem to have the uid
value yet.
If you want to refer to the document as it'll exist after the write operation (if that write operation is allowed), use:
request.resource.data.uid
Also see the documentation on the resource
and request.resource
variables.
英文:
The key was that you're trying to write the uid
field for the first time.
Your rules now do this:
resource.data.uid
The resource
here refers to the document as it exists before the current operation, which doesn't seem to have the uid
value yet.
If you want to refer to the document as it'll exist after the write operation (if that write operation is allowed), use:
request.resource.data.uid
Also see the documentation on the resource
and request.resource
variables.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论