2016-08-02 99 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規則。但同時我會等待某人確認我的理解或糾正。

相關問題