2016-08-02 68 views
1

我是Firebase的新手,并试图了解安全规则。为此,我正在实施项目 - 团队成员 - 任务的典型功能。每个项目都有一个团队负责人,多个成员和多个任务。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) 

我设置以下火力地堡规则:

{ 
"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)我得到权限拒绝错误。

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

有人能帮助我理解我应该如何更改Firebase规则以实现上述要求?

回答

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)给出许可被拒绝。这是因为现在没有.read规则定义在/Tasks级别。所以我需要改变程序逻辑以迭代/Projects/<projectId>/Tasks和每个taskId访问/Tasks/<taskId>。当我这样做时,.read规则会得到正确评估,并且用户只能访问他们所属项目的任务详细信息。然后我需要在客户端处理这些任务细节以分离完成和未完成的任务。

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

相关问题