Tho*_*man 2 firebase firebase-security firebase-authentication google-cloud-firestore
我知道有很多关于使用安全规则在 firestore 上创建角色系统的线程,但我仍然无法做到这一点。我希望能够拥有三种不同的角色,以及三种不同的访问级别。
我找到了谷歌关于此主题的文档(https://firebase.google.com/docs/firestore/solutions/role-based-access),但我不希望每个用户和机构都有每个经理或管理员,因为那是太多的重复数据。此外,角色应适用于组织内的任何地方,每个子集合不应有所不同。
我的数据库:
organisations{
organisation1{
<data about organisation>
establishments{
establishment1{
<data about establishment>
}
establishment2{
<data about establishment>
}
}
people{
user1{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
user2{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
}
}
organisation2{
<data about organisation>
establishments{
establishment1{
<data about establishment>
}
establishment2{
<data about establishment>
}
}
people{
user1{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
documents{
some documents
}
}
user2{
<data about user>
userId: <UID from authentication>
accountType: <Administrator, Manager or Employee>
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这很多,但它可能会帮助别人更好地理解我的问题。管理员(帐户类型为管理员的人员)应该能够在组织(组织 1 或组织 2)内的任何位置进行读写操作。经理应该只能读取所有内容,但不能写入,除非它是他们自己的数据(因此他们可以读取任何内容,但具有与员工相同的写入权限,他们只能写入文档以及这些文档的子集合中的任何位置request.auth.uid作为userId字段,例如organization2中的user1应该能够写入user1的文档,以及任何子集合中的每个文档)
我目前有以下内容,我想我需要得到这样的东西:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
//Access levels:
//Medewerker: Can only see their own user document and all subcollections
//Beheerder: Can see any document within the organisation
//Administrator: Can see and do everything
function getAccountType(orgId, userId) {
return get(/databases/$(database)/documents/organisations/$(orgId)/people/$(userId)).data.accountType;
}
function isAdmin(orgID){
return getAccountType(orgID, request.auth.uid) == "Administrator";
}
function isBeheerder(orgID){
return getAccountType(orgID, request.auth.uid) == "Beheerder";
}
function isOwnData(userId){
return request.auth.uid == userId;
}
function authenticated(){
return request.auth != null;
}
match /organisations/{orgID} {
//Administrator rule goes here
allow write: if authenticated() && (isAdmin(resource.data.organisationId));
//Beheerder rule goes here
allow read: if authenticated() && (isAdmin(resource.data.organisationId) || isBeheerder(resource.data.organisationId));
match /people/{userID} {
//Medewerker rule goes here
allow read: if authenticated() && (isAdmin(resource.data.organisationId) || isBeheerder(resource.data.organisationId) || isOwnData(resource.data.userId));
allow update: if authenticated() && (isAdmin(resource.data.organisationId) || isOwnData(resource.data.userId));
allow create, delete: if authenticated() && (isAdmin(resource.data.organisationId));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我现在拥有的代码不会给出错误,但它的行为并不符合我的预期。当我使用管理员帐户登录时,我首先只能看到我自己的用户记录。如果我使用 Beheerder 或 Medewerker 帐户登录,我根本得不到任何记录,甚至连我自己的记录也没有。另外,如果我将帐户更改回管理员,我将无法恢复自己的记录。有什么方法可以解决这个问题/我的代码有什么问题吗?另外,我是否需要在每个文档中提供组织 ID,或者是否有解决方法?我当前的代码确实有这个。感谢您的帮助!
由于这个问题比较大,这里有两点:
\n完整的开源示例在这里,如果需要,请随意克隆/分叉和贡献。
\nFirestore模型
\n访问级别详细信息:
\n行政
\n主持人
\norganizations/orgId/peoples/userId/documents/*)日工
\norganizations/orgId/peoples/userId/documents/*),而不是组织或机构organizations/orgId/peoples/userId/documents/*)firestore.rules(解释)
\nfunction getAccountType(orgId, userId) {\n return get(/databases/$(database)/documents/organizations/$(orgId)/peoples/$(userId)).data.accountType;\n}\nRun Code Online (Sandbox Code Playgroud)\n这会查询参数中给定组织的参数中给定用户的角色。将其包含在参数中可以轻松地将其与request.data或 一起使用id匹配规则中的
function isAdmin(orgID){\n return getAccountType(orgID, request.auth.uid) == "admin";\n}\nRun Code Online (Sandbox Code Playgroud)\n检查当前登录用户是否request.auth.uid具有参数中给定组织的“管理员”角色。
match /organizations/{orgID} {\n allow read: if authenticated() && (isAdmin(orgID) || isModerator(orgID));\nRun Code Online (Sandbox Code Playgroud)\n仅当用户登录并且是管理员或版主时才允许读取。
\n完整规则可用在此处查看
\n遵守干净的规则:
\nisAdmin()\nisManager()\nisPeon()\nRun Code Online (Sandbox Code Playgroud)\n您稍后可以轻松使用和阅读:
\nmatch /reminders/{reminderId} {\n allow read: if authenticated() && (isAdmin(resource.data.organizationId) || isManager(...) || isPeon(...));\n allow write: if authenticated() && (isAdmin(request.resource.data.organizationId) || isManager(...));\n allow delete: if authenticated() && isAdmin(resource.data.organizationId);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n为您的规则设置单元测试(\xe2\x9a\xa0\xef\xb8\x8f 很重要),因此更容易对其进行迭代并检查一切是否按预期工作。\n此处的测试示例,使用以下命令运行它jest。
| 归档时间: |
|
| 查看次数: |
517 次 |
| 最近记录: |