4

I'm writing a note sharing app and I'm trying to find the best approach for the data structure to allow adding collaborators to user notes, while at the same time having sensible security rules for the structure in question.

What I have now is the following:

"users": {
   "johndoe": {
      "notes": {
        "note1Key",
        "note2Key"
      }
   },
   "jane": {
      "notes": {
        "note3Key",
        "note4Key",
        "note5Key"
      }
   }
   ...
},
"notes": {
  "note1Key": {
    // actual note data
  },
  "note2Key": {
    // actual note data
  },
  "note3Key": {
    // actual note data
  },
  ...
},
"shared": {
    "johndoe" : {
        "note5Key" : true,
        "note3Key" : true   
    },
    "jane" : {
        "note1Key" : true  
    }
    ...
}

When "John Doe" creates a note, the note is stored in notes/noteKey with read/write access granted to owner and collaborators added by the owner. Additionally the note's key is stored in user/johndoe/notes/noteKey, which can be read and written to only by him. When this user wants to add a collaborator ("Jane") to his note, this same note key is stored in shared/jane/noteKey which can be globally read & written to. This way, when listing each user's notes, I have to read from only 2 locations to list all notes a user has access to: user/johndoe/notes and shared/johndoe.

Is there a better approach? I don't like to have the shared index globally accessible, could I somehow limit it? Since one user can potentially collaborate with a big number of different users on different notes, I'm not really sure how to set the security rules, to limit the read/write access to this index.

I was thinking about reversing the shared node logic, to store note key's under it's respectful owners sub-nodes and including a list of collaborators like so: shared/jane/noteKey/collaborators/johndoe. This way I could have a global read rule and a more restrictive write rule (each user can only write in his own shared node), however this would greatly increase the complexity of listing all notes a user has access to.

Primoz
  • 67
  • 4

1 Answers1

1

You wanted to:

  1. allow adding owner & collaborators to user notes.
  2. list all notes a user owned.
  3. list all notes a user has access to.

You should have added collaborators list to each notes as follows:

{"rules":{

  "users": {
    "$user_id": {
        "profile_and_settings":{
           ".write":"auth != null && auth.uid == $user_id"
        },
        "owned_notes":{
           ".write":"auth != null && auth.uid == $user_id",
           "$note_id":{}
        },
        "accesssible_notes": {
           ".write":"auth != null",
           "$note_id":{}
        }
    }
  },

  "notes": {
    "$note_id": {

        // to edit this node: must authenticated, new entry or owner of this node.
        ".write":"auth != null && ( !data.exists() || data.child('owner').val() == auth.uid )",

        "owner":{
            ".validate":"newData.val() == auth.uid"
        },

        "collaborators":{
            "$user_id":{}
        },

        // ... other note data

    }
    //...
  }
}}

See related question:
Firebase rule: Do we have better ways to manage object ownership?

Community
  • 1
  • 1
Nik
  • 709
  • 4
  • 22