firebase规则:如何限制基于用户角色的访问 [英] firebase rules: how to restrict access based on user role

查看:169
本文介绍了firebase规则:如何限制基于用户角色的访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Firebase的新手,并试图了解安全规则。为此,我正在实施Project - Team Members - Tasks的典型功能。
每个项目都有一个团队负责人,多个成员和多个任务。

下面是我试图实现的结构和规则(又称需求) :

  /成员 - 每个成员都有{displayName,email,emailVerified} 
登录的用户应该能够从会员读取数据(获取所有用户的
显示名称)
任何登录用户应该能够更新他/她的记录

/项目 - 每个项目有{领导,成员{},姓名,任务{}}
任何登录的用户应该能够读取项目列表
任何登录用户应该能够读取成员列表(如果可能的话
仅适用于他们所在的项目)
任何登录用户都应该能够读取任务列表(如果可能的话,只有
为他们所在的项目)
只有团队领导应该能够更新项目细节,例如
- add / remo ve成员
- 添加/删除任务
- 更改项目名称

/任务 - {项目,状态,标题}
团队领导者/团队成员应该能够阅读任务
团队领导可以添加/编辑/删除任务
团队成员只能更新与其项目相关的任务状态
团队领导/团队成员应该能够过滤基于
任务状态(已完成/未完成)的项目任务

以下Firebase规则:

  {
rules:{
Members:{
.read:auth!= null,
$ mid:{
.write:auth!= null&& auth.uid == $ mid

},//会员
Projects:{
.read:auth!= null,
//只有团队领导可以编辑项目细节
.write:auth!= null&& auth.uid == data.child('Lead')。val(),
// Lead和Name是必填字段
.validate:newData.hasChildren(['Lead' 'Name']),
Name:{
.validate:newData.isString()&& newData.val()。length> 0

Lead:{
.validate:root.child('Members /'+ newData.val())。exists()
},
Members:{
$ mid:{
.validate:root.child('Members /'+ $ mid).exists()


$ $ $ b $ $ b $ $ b $$ validate:root.child('Tasks /'+ $ tid ).exists()

}
},//项目
任务:{
//只有当前用户是团队铅或项目的成员
.read:(auth!= null)&& (data.child('project').val()=='Project1'),
.write:auth!= null&& ('Projects /'+ newData.child('project').val()+'/ Lead')。val()== auth.uid || root.child('Projects /'+ newData。 ('project')。val()+'/ Members /'+ auth.uid).exists()),
.validate:newData.hasChildren(['project','status' ,'title']),
status:{
.validate:newData.isString()&& newData.val()。length> 0
},
//如果团队成员正在保存项目,只允许更改状态
title:{
.validate:(root.child ('Projects /'+ newData.parent()。child('project').val()+'/ Lead')。val()== auth.uid)? newData.isString()&& newData.val()。length> 0:data.exists()&& data.val()== newData.val()

} //任务
} //规则
}

目前我正在评估 .read 功能,我没有测试 .write 功能。



我可以得到成员列表(成员' displayName
但是当获取项目的任务细节(从 / Tasks )我得到权限被拒绝的错误。

请注意,我想使用 .read 规则与 .write 规则为任务。但是,当我得到错误,我改变它当前的规则(所以,任何经过身份验证的用户可以读取 Project1 - Project1 是项目的关键任务),即使这样,如果我只保留auth!= null,那么我可以读取任务,但这不是我想要的。



有人可以帮我理解wh我应该对Firebase规则做出修改,以实现上面给出的要求吗? 解决方案

我试图用 orderByChild来访问 / Tasks

('project')。equalTo(projectKey),以获得与项目相关的任务的细节。但是当我这样做时, .read 规则在 / Tasks 级别执行,并且没有名为'project''project' / Tasks /< taskId> / project 中可用。所以我需要将任务规则更改为:

 任务 :{
$ tid:{
//只有当前用户是团队负责人或项目成员时,才允许读/写
.read:auth!= null& amp ;&(root.child('Projects /'+ data.child('project').val()+'/ Lead').val()== auth.uid || root.child('Projects /' + data.child('project').val()+'/ Members /'+ auth.uid).exists()),
.write:auth!= null&&( ('Projects /'+ newData.child('Projects')。 ('project')。val()+'/ Members /'+ auth.uid).exists()),
.validate:newData.hasChildren(['project','status', 'title']),
status:{
.validate:newData.isString()& newData.val()。length> 0
},
//如果团队成员正在保存项目,允许更改只有状态
title:{
.validate:(项目/'+ newData.parent()。child('project')。val()+' / Lead')。val()== auth.uid)? newData.isString()&& newData.val()。length> 0:data.exists()&& data.val()== newData.val()

}
} //任务

即使使用此规则,通过 orderByChild('project')。equalTo(projectKey)来访问 / Tasks code>给予permission权限,这是因为现在在 / Tasks 级别没有定义 .read 。因此,我需要改变程序逻辑来迭代 / Projects /< projectId> /任务,并为每个 taskId access / Tasks /< taskId> 当我这样做的时候, .read 可以只访问他们所属项目的任务细节,然后我需要在客户端处理这些任务细节,以分离已完成和未完成的任务。

我还没有验证 .write .validate 规则,但同时我会等待某人确认我的理解或更正。


I'm new to Firebase and trying to understand the security rules. For this I'm implementing typical functionality of Project - Team Members - Tasks. Each project will have a team leader, multiple members and multiple tasks.

Here is the structure and rules that I'm trying to implement (a.k.a. Requirements):

/Members - each member has { displayName, email, emailVerified }
    any logged in user should be able to read data from Members (to get the 
        display names of all users)
    any logged in user should be able to update his/her record

/Projects - each project has { Lead, Members{}, Name, Tasks{} }
    any logged in user should be able to read the list of projects
    any logged in user should be able to read the list of members (if possible
        only for the projects where they are part of)
    any logged in user should be able to read the list of tasks (if possible only 
        for the projects where they are part of)
    only the team leader should be able to update project details i.e.
        - add / remove members
        - add / remove tasks
        - change project title

/Tasks - { project, status, title }
    team leader / team members should be able to read the tasks
    team leader can add/edit/delete tasks
    team members can update only status (of a task that is associated with their project)
    team leader / team members should be able to filter project tasks based on 
    task status (completed / not completed)

I've setup following Firebase rules:

{
 "rules": {
    "Members": {
        ".read": "auth != null",
        "$mid" : {
            ".write": "auth != null && auth.uid == $mid"
        }
    }, // Members
    "Projects": {
        ".read": "auth != null",
        // only team lead can edit project details
        ".write": "auth != null && auth.uid == data.child('Lead').val()",
        // Lead and Name are mandatory fields
        ".validate": "newData.hasChildren(['Lead', 'Name'])",
        "Name": {
            ".validate": "newData.isString() && newData.val().length > 0"
        },
        "Lead": {
            ".validate": "root.child('Members/' + newData.val()).exists()"
        },
        "Members": {
            "$mid": {
                ".validate": "root.child('Members/' + $mid).exists()"
            }
        },
        "Tasks": {
            "$tid": {
                ".validate": "root.child('Tasks/' + $tid).exists()"
            }
        }
    }, // Projects
    "Tasks": {
        // allow read / write only if current user is team lead or a member of the project
        ".read": "(auth != null) && (data.child('project').val() == 'Project1')",
        ".write": "auth != null && ( root.child('Projects/' + newData.child('project').val() + '/Lead').val() == auth.uid || root.child('Projects/' + newData.child('project').val() + '/Members/' + auth.uid).exists() )",
        ".validate": "newData.hasChildren(['project', 'status', 'title'])",
        "status": {
            ".validate": "newData.isString() && newData.val().length > 0"
        },
        // if team member is saving the item, allow changes only to status
        "title": {
            ".validate": "(root.child('Projects/' + newData.parent().child('project').val() + '/Lead').val() == auth.uid) ? newData.isString() && newData.val().length > 0 : data.exists() && data.val() == newData.val()"
        }
    } // Tasks
 } // rules
}

Currently I'm evaluating the .read functionality. I've not tested .write functionality yet.

I'm able to get Members list (members' displayName) for a given project. But while getting project's task details (from /Tasks) I'm getting permission denied error.

Note that I would like to use .read rule same as .write rule for Tasks. But as I was getting error, I changed it to the current rule (such that, any authenticated user can read the tasks for Project1 - Project1 is the key of a project). Even then I'm getting permission denied. If I keep only "auth != null" then I'm able to read the tasks but that's not what I want.

Can someone help me understand what changes should I make to the Firebase rules so as to implement the requirements given above?

解决方案

After trying out different combinations here is what I've found out.

I was trying to access /Tasks with orderByChild('project').equalTo(projectKey) so as to get details of tasks associated with a project. But when I do this, the .read rule gets executed at /Tasks level and there is no child named 'project' at that level. 'project' is available at /Tasks/<taskId>/project. So I need to change the Task rule as:

"Tasks": {
    "$tid": {
        // allow read / write only if current user is team lead or a member of the project
        ".read": "auth != null && ( root.child('Projects/' + data.child('project').val() + '/Lead').val() == auth.uid || root.child('Projects/' + data.child('project').val() + '/Members/' + auth.uid).exists() )",
        ".write": "auth != null && ( root.child('Projects/' + newData.child('project').val() + '/Lead').val() == auth.uid || root.child('Projects/' + newData.child('project').val() + '/Members/' + auth.uid).exists() )",
        ".validate": "newData.hasChildren(['project', 'status', 'title'])",
        "status": {
            ".validate": "newData.isString() && newData.val().length > 0"
        },
        // if team member is saving the item, allow changes only to status
        "title": {
            ".validate": "(root.child('Projects/' + newData.parent().child('project').val() + '/Lead').val() == auth.uid) ? newData.isString() && newData.val().length > 0 : data.exists() && data.val() == newData.val()"
        }
    }
} // Tasks

Even with this rule accessing /Tasks with orderByChild('project').equalTo(projectKey) gives permission denied. This is because now there is no .read rule defined at /Tasks level. So I need to change the program logic to iterate on /Projects/<projectId>/Tasks and for each taskId access /Tasks/<taskId>. When I do this, the .read rule gets evaluated properly and user can access tasks details only for the projects that they are part of. And then I need to process these task details at the client side to separate out completed and non-completed tasks.

I'm yet to verify .write and .validate rules. But meanwhile I'll wait for someone to confirm my understanding or correct it.

这篇关于firebase规则:如何限制基于用户角色的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆