2016-08-02 13 views
1

Ich bin neu in Firebase und versuchen, die Sicherheitsregeln zu verstehen. Dazu implementiere ich die typische Funktionalität von Projekt - Teammitglieder - Aufgaben. Jedes Projekt wird einen Teamleiter, mehrere Mitglieder und mehrere Aufgaben haben. HierFirebase-Regeln: wie Zugriff basierend auf Benutzerrolle eingeschränkt werden

ist die Struktur und Regeln, die ich versuche, (auch bekannt als Requirements) zu implementieren:

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

I Setup Firebase Regeln folgende haben:

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

Derzeit bin ich die Bewertung der .read Funktionalität. Ich habe die Funktionalität .write noch nicht getestet.

Ich bin in der Lage, Members Liste (Mitglieder 'displayName) für ein bestimmtes Projekt zu bekommen. Aber beim Abrufen von Projekt-Details (von /Tasks) erhalte ich den Fehler "Berechtigung verweigert".

Beachten Sie, dass ich .read Regel wie .write Regel für Tasks verwenden möchte. Aber als ich einen Fehler bekam, änderte ich ihn in die aktuelle Regel (so dass jeder authentifizierte Benutzer die Aufgaben lesen kann für Project1 - Project1 ist der Schlüssel eines Projekts). Selbst dann bekomme ich die Erlaubnis verweigert. Wenn ich nur "auth != null" behalte, kann ich die Aufgaben lesen, aber das ist nicht was ich will.

Kann mir jemand helfen zu verstehen, welche Änderungen ich an den Firebase-Regeln vornehmen sollte, um die oben genannten Anforderungen zu erfüllen?

Antwort

1

Nach dem Ausprobieren verschiedener Kombinationen hier ist, was ich herausgefunden habe.

Ich habe versucht, auf /Tasks mit orderByChild('project').equalTo(projectKey) zugreifen, um Details von Aufgaben im Zusammenhang mit einem Projekt zu erhalten. Aber wenn ich dies tue, wird die .read Regel auf /Tasks Ebene ausgeführt und es gibt kein Kind mit dem Namen 'project' auf dieser Ebene. 'project' ist verfügbar unter /Tasks/<taskId>/project. Also muss ich die Task Regel ändern:

"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 

Auch bei dieser Regel den Zugriff auf /Tasks mit orderByChild('project').equalTo(projectKey) Erlaubnis gibt, verweigert. Dies liegt daran, dass jetzt keine .read Regel unter /Tasks definiert ist. Also muss ich die Programmlogik ändern, um auf /Projects/<projectId>/Tasks und für jeden taskId Zugriff /Tasks/<taskId> zu iterieren. Wenn ich dies tue, wird die .read Regel ordnungsgemäß ausgewertet und Benutzer können auf Aufgabendetails nur für die Projekte zugreifen, denen sie angehören. Und dann muss ich diese Aufgabendetails auf der Clientseite verarbeiten, um abgeschlossene und nicht abgeschlossene Aufgaben zu trennen.

Ich bin noch zu verifizieren .write und .validate Regeln. Aber in der Zwischenzeit warte ich darauf, dass jemand mein Verständnis bestätigt oder korrigiert.

Verwandte Themen