【问题标题】:firebase rules: how to restrict access based on user rolefirebase 规则:如何根据用户角色限制访问
【发布时间】:2016-12-08 02:38:28
【问题描述】:

我是 Firebase 的新手,正在尝试了解安全规则。为此,我正在实现项目的典型功能 - 团队成员 - 任务。 每个项目将有一个团队负责人、多个成员和多个任务。

这是我正在尝试实施的结构和规则(也称为要求):

/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)

我已经设置了以下 Firebase 规则:

{
 "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
}

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

我可以获得给定项目的Members 列表(成员的displayName)。 但是在获取项目的任务详细信息(来自/Tasks)时,我收到了权限被拒绝错误。

请注意,我想对Tasks 使用与.write 相同的.read 规则。但是当我遇到错误时,我将其更改为当前规则(这样,任何经过身份验证的用户都可以读取 Project1 的任务 - Project1 是项目的关键)。即便如此,我的许可也被拒绝了。如果我只保留"auth != null",那么我可以阅读任务,但这不是我想要的。

谁能帮助我了解我应该对 Firebase 规则进行哪些更改以实现上述要求?

【问题讨论】:

    标签: firebase firebase-realtime-database firebase-security


    【解决方案1】:

    在尝试了不同的组合之后,我发现了。

    我试图用orderByChild('project').equalTo(projectKey) 访问/Tasks 以获取与项目相关的任务的详细信息。但是当我这样做时,.read 规则将在/Tasks 级别执行,并且在该级别没有名为'project' 的子级。 'project' 可在/Tasks/<taskId>/project 获得。所以我需要把Task规则改成:

    "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
    

    即使使用此规则访问 /TasksorderByChild('project').equalTo(projectKey) 也会拒绝权限。这是因为现在在/Tasks 级别没有定义.read 规则。所以我需要更改程序逻辑以迭代/Projects/<projectId>/Tasks 并为每个taskId 访问/Tasks/<taskId>。当我这样做时,.read 规则得到正确评估,用户只能访问他们所属项目的任务详细信息。然后我需要在客户端处理这些任务细节,以分离出已完成和未完成的任务。

    我尚未验证 .write.validate 规则。但同时我会等待有人确认我的理解或纠正它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 2014-11-30
      • 2015-10-01
      • 1970-01-01
      相关资源
      最近更新 更多