简介
我的数据库上有这个结构
C- usernames
D- paola
-> userId: 7384-aaL732-8923dsnio92202-peesK
D- alex
-> userId: ...
D- adam
-> userId: ...
C- users
D- userId of paola
-> username: "paola"
-> ...
D- userId of alex
-> username: "alex"
-> ...
D- userId of adam
-> username: "adam"
-> ...
我正在客户端注册用户,所以我必须编写一些安全规则。。。
在我的客户端代码中我做:
- 将用户名(文档id(和userId(文档数据(添加到用户名集合
- 在users集合中创建一个包含用户名和其他内容的用户文档
安全规则
所以,我的安全规则是这样的:
function isUsernameOwner(username) {
return get(/databases/$(database)/documents/usernames/$(username)).data.userId == request.auth.uid;
}
match /users/{userId} {
// Every people can read the users collection (might be in the sign in form)
allow read: if true;
// As the users creation is made in the client side, we have to make sure
// it meets these requirements
allow write: if isSignedIn() &&
isSameUser(userId) &&
request.resource.data.keys().hasOnly(['email', 'username', 'name', 'birthday']) &&
isValidUsername(request.resource.data.username) &&
isUsernameOwner(request.resource.data.username); // <------- If I remove this all works fine
}
问题
当我尝试注册时,我会得到";缺少或权限不足";。。。我认为问题出在函数isUsernameOwner((上,但我不知道我做错了什么。。。我是否错误地访问了用户名文档中的字段userId?如果不是,是否有可能批处理写入不按顺序进行?
Pd:注册过程使用批量写入(首先写入用户名,然后写入用户(
更新
这是我进行批量写入的javascript代码:
// Firebase.js
createUser = (email, password, username, name, birthday) => {
return this.auth
.createUserWithEmailAndPassword(email, password)
.then((currentUser) => {
// Get the user id
const userId = currentUser.user.uid;
// Get a new Firestore batched write
const batch = this.db.batch();
// Create the new username document in the usernames collection with the user's id as field
const usernameRef = this.db.collection("usernames").doc(username);
batch.set(usernameRef, { userId });
// Create the new user document in the users collection with all the relevant information
const userRef = this.db.collection("users").doc(userId);
birthday = firebase.firestore.Timestamp.fromDate(new Date(birthday)); // It is neccessary to convert the birthday to a valid Firebase Timestamp
const data = {
email,
username,
name,
birthday,
};
batch.set(userRef, data);
// Commit the batch
return batch.commit();
})
.catch((err) => {
throw err;
});
我认为问题在于您在安全规则全局函数中使用了get((。将其设为本地,然后使用getAfter等待批处理写入的"终止"。
在这里,您可以看到一篇可能对您的案例有用的帖子:Firebase安全规则在get((和getAfter((之间的差异
看看Doug的回答,他解释了get和getAfer之间的区别。