2016-08-02 1 views
1

Я новичок в Firebase и пытаюсь понять правила безопасности. Для этого я реализую типичную функциональность Project - Team Members - Tasks. В каждом проекте будет руководитель команды, несколько участников и несколько задач.правила 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), я получаю разрешение на отказ в ошибке.

Обратите внимание, что я хотел был бы использовать .read Правило такое же как .write правило для Tasks. Но по мере того как я получал ошибку, я изменил ее на существующее правило (таким образом, любой аутентифицированный пользователь может читать задачи для Project1 - Project1 - это ключ проекта). Даже тогда я получаю разрешение отказано. Если я сохраню только "auth != null", тогда я смогу прочитать задания, но это не то, что я хочу.

Может кто-нибудь помочь мне понять, какие изменения следует внести в правила Firebase, чтобы реализовать требования, приведенные выше?

ответ

1

После тестирования различных комбинаций вот что я узнал.

Я пытался получить доступ к /Tasks с помощью orderByChild('project').equalTo(projectKey), чтобы получить подробную информацию о задачах, связанных с проектом. Но когда я это делаю, правило .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 

Даже с этим правилом доступа /Tasks с orderByChild('project').equalTo(projectKey) дает разрешение на отказ. Это связано с тем, что теперь нет правила .read, определенного на уровне /Tasks. Поэтому мне нужно изменить логику программы на итерацию на /Projects/<projectId>/Tasks и для каждого taskId доступа /Tasks/<taskId>. Когда я это делаю, правило .read оценивается правильно, и пользователь может получить доступ к деталям задач только для тех проектов, в которых они являются частью. И тогда мне нужно обработать эти детали задачи на стороне клиента, чтобы отделить выполненные и незавершенные задачи.

Я еще не подтвердил .write и .validate правил. Но пока я буду ждать, пока кто-то подтвердит мое понимание или исправит это.