我的数据库上有这个结构
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"
-> ...
我要在客户端注册用户,因此我不得不编写一些安全规则...
在我的客户代码中,我这样做:
- 将带有userId(文档数据)的用户名(文档ID)添加到用户名集合中
- 在用户集合中使用用户名和其他内容创建用户文档。
因此,我的安全规则如下:
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;
});
答案 0 :(得分:2)
我认为问题在于您正在安全规则全局函数中使用get()。将其设置为本地,然后使用getAfter来等待批处理写入的“终止”。
在这里您会看到一篇可能对您的案例有用的帖子:Firebase security rules difference between get() and getAfter()
只看道格的答案,他解释了get和getAfer之间的区别。