2016-08-02 4 views
1

Firebaseを初めて使い、セキュリティルールを理解しようとしています。これについては、Project - Team Members - Tasksの典型的な機能を実装しています。 各プロジェクトにはチームリーダー、複数のメンバー、複数のタスクがあります。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 
} 

現在、私は評価している:私は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) 

:ここ

は、私は(要件別名)を実装しようとしている構造とルールです .read機能私はまだ .writeの機能をテストしていません。

特定のプロジェクトに対してMembersのリスト(メンバー 'displayName)を取得できます。 しかし、プロジェクトのタスクの詳細(/Tasks)を取得しているうちに、権限が拒否されました。

のルールは、Tasks.writeルールと同じです。しかし、私がエラーになったとき、私はそれを現行のルールに変更しました(つまり、認証されたユーザーはProject1 - Project1のタスクをプロジェクトのキーと読むことができます)。それでも私は許可が拒否されています。私が"auth != null"だけを保持するなら、私は仕事を読むことができますが、それは私が望むものではありません。

上記の要件を実装するためにFirebaseルールにどのような変更を加える必要があるか理解してくれる人がいますか?

答えて

1

ここでさまざまな組み合わせを試した後、私が見つけたものがあります。

orderByChild('project').equalTo(projectKey)/Tasksにアクセスしようとしましたが、プロジェクトに関連するタスクの詳細を取得しようとしていました。しかし、これを行うと、.readルールは/Tasksレベルで実行され、そのレベルには'project'という名前の子がありません。 'project'は、/Tasks/<taskId>/projectで入手できます。拒否されたとしてもorderByChild('project').equalTo(projectKey)/Tasksにアクセスし、このルールに

"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 

許可を与える:だから私はTaskルールを変更する必要があります。これは、/Tasksレベルで定義された.readルールが存在しないためです。だから私は/Projects/<projectId>/Tasksとそれぞれのに反復するプログラムロジックを変更する必要があります。私がこれを行うと、.readルールが正しく評価され、ユーザーはそれらが所属するプロジェクトのタスクの詳細にのみアクセスできます。そして、クライアント側でこれらのタスクの詳細を処理して、完了したタスクと完了していないタスクを分ける必要があります。

私はまだ.write.validateのルールを確認していません。しかし一方で、私は誰かが私の理解を確認するか、それを訂正するのを待つでしょう。

関連する問題