我们尝试列出“事件”集合中的所有文档。 (/event/{eventId}
)
在每个事件的文档中,都存在一个属性“ users”(数组),其中包含所有用户的ID。
我们还有另一个集合“角色”,每个事件的每个用户的角色。 (/role/{eventId}/userRole/{userId}
)
我们有权参加一个活动
db.collection('event').doc(eventId).get()
但是当我们尝试(通过android和网络)进行类似
的查询时db.collection('event').where("users", "array-contains", user.uid).get()
我们得到了FirebaseError: Missing or insufficient permissions.
活动规则:
match /event/{eventId} {
allow read:
if isAuth() &&
inEvent(eventId, request.auth.uid);
allow create:
if isAuth() &&
checkEventName() &&
isOwner(database) &&
request.resource.data.users == [];
allow update:
if isAuth() &&
resource.data.ownerId == request.auth.uid &&
checkEventName() &&
isOwner(database) &&
request.resource.data.mediaCount == resource.data.mediaCount &&
request.resource.data.users == resource.data.users;
allow delete:
if false;
}
角色规则:
match /role/{roleId} {
allow read:
if isAuth();
allow write:
if false;
match /userRole/{userRoleId} {
allow read:
if isAuth() &&
userRoleId == request.auth.uid;
allow create:
if isAuth() &&
userRoleId == request.auth.uid &&
exists(/databases/$(database)/documents/event/$(roleId)) &&
request.resource.data.actual is number &&
request.resource.data.actual >= 0 &&
request.resource.data.actual <= 10 &&
request.resource.data.previous is number &&
request.resource.data.actual == request.resource.data.previous;
allow update:
if isAuth() &&
userRoleId == request.auth.uid &&
request.resource.data.actual == 0 &&
resource.data.actual != 0;
allow delete:
if false;
}
}
角色ID与事件ID相匹配。
在事件的读取规则中,我们具有inEvent(eventId,request.auth.uid)。 当我们写
function inEvent(eventID, userID) {
return true;
}
查询有效,但如果我们尝试类似的操作
return exists(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID));
或
return get(/databases/$(database)/documents/role/$(eventID)/userRole/$(userID)).data.actual >= 10;
我们总是会出现权限错误
我们已经检查了所有数据和规则,但是我们不明白为什么可以得到单个事件而不是列表。我们做错了什么?我们可以使用get()和exist()获得列表权限吗?
答案 0 :(得分:0)
首次添加侦听器时,将强制执行Firebase的安全规则。届时,服务器必须能够验证读取操作将永远仅返回您有权接收的文档。在当前规则中,这将要求服务器读取每个events
文档,然后检查每个文档的用户角色。这是不可扩展的操作,因此服务器不允许它并且拒绝读取。
这通常意味着您要保护的信息应该出现在您试图允许访问的文档中(或该文档下的子集合),或者位于当前用户的固定位置。对于您的情况,我能想到的最好的办法是在读取事件的情况下使用ACL,尽管即使这样,我仍然不确定是否可以对其建模,以便服务器可以进行静态评估。
另请参阅: