仅当用户自定义声明中存在特定的键/值对时,我才希望允许更新文档。用户自定义声明中可以有多个键/值对。
想象以下自定义声明已添加到用户:
{
theClubId: 3,
otherId: 2,
oneMoreId: -1
}
关键是现在称为俱乐部ID。该值是编码为整数的用户角色。他在俱乐部theClubId
中的角色为3,因此他应该能够在该俱乐部中编辑其他俱乐部成员的角色。
我在Firestore中创建了集合clubMembers
。它包含以下结构的多个文档:
{
uid: "some-uid",
clubIds: ["theClubId", "oneMoreId"],
clubData: {
theClubId: { role: 1 },
oneMoreId: { role: 1 }
},
cantChangeMe: "foobar"
}
如果满足以下条件,则用户只能更新此文档:
clubData
对象。这是自定义声明起作用的地方。cantChangeMe
)是只读的这很丑陋,但是有效。至少直到clubIds
数组大于3个项目为止。另外,这种方法限制用户每次更新最多只能编辑1个角色,但是由于用户一次只能登录一个俱乐部,所以很好。
function canUpdateMember() {
let claimKeys = request.auth.token.keys();
let didNotChangeForbiddenKeys = request.resource.data.diff(resource.data).affectedKeys().hasOnly(["clubData"]);
let affectedClubId = request.resource.data.clubData.diff(resource.data.clubData).affectedKeys();
let isMemberOfChangedClubMember = affectedClubId.hasAny(claimKeys);
let clubId0 = claimKeys[0];
let clubId1 = claimKeys[1];
let clubId2 = claimKeys[2];
let clubId0Result = [clubId0].toSet() == affectedClubId && request.auth.token[clubId0] >= 3 && innerValidation(request.resource.data.clubData[clubId0]);
let clubId1Result = [clubId1].toSet() == affectedClubId && request.auth.token[clubId1] >= 3 && innerValidation(request.resource.data.clubData[clubId1]);
let clubId2Result = [clubId2].toSet() == affectedClubId && request.auth.token[clubId2] >= 3 && innerValidation(request.resource.data.clubData[clubId2]);
return didNotChangeForbiddenKeys &&
affectedClubId.size() == 1 &&
isMemberOfChangedClubMember &&
(clubId0Result || clubId1Result || clubId2Result);
}
function innerValidation(clubObj) {
let accessLevelValid = clubObj.role <= 3 && clubObj.role >= -1;
return accessLevelValid;
}
由于.affectedKeys()
返回一个Set
,所以没有简单的方法来获取特定索引处的值。