horizon icon indicating copy to clipboard operation
horizon copied to clipboard

Add more complex filtering using Validators

Open nbclark opened this issue 8 years ago • 3 comments

Currently using validators for read operations only serve to either validate all documents in the result set or trigger an error. Given the limited server-side filtering support, we've been a bit stuck with how to implement group ownership of documents, and restrict read access those documents only to the owners. The validator is close, but we want the server to be able to filter out documents from a result if the validator fails.

A proposed solution is a server option to enable validator filtering (as opposed to pure query blocking).

nbclark avatar Feb 10 '17 19:02 nbclark

Hi. Thank you so much for taking the time to look at the horizon project.

Can you please provide a use case or an example where your addition might help instead of blocking at query time (a simple example will suffice).

One more thing, do you believe that going forward with an option that might have performance implications is a good idea (please try to clarify in your answer).

Thanks in advance.

riyadhzen avatar Feb 13 '17 20:02 riyadhzen

Hey Riyadh,

Love the work you've done with horizon. We are looking to implement a variant of a chat application, where we want a conversation between 2 or more people, but want to restrict access to only those involved in the conversation. Typically we would model this as { userIDs: [1,2,3], createdBy: 1 }, or something to that effect.

With horizon, the whitelisting permissions are a bit simple, and restricting to a single owner is trivial (collection.findAll({user_id: userId()})). However, multiple owners does not appear to be supported.

The validator functionality on reads is approximately what we want (the ability to apply server-side logic to restrict queries). However, the restriction is a full block instead of a filter, so we have no way to construct a collection with Horizon with multiple owners, and restrict access from the server.

As far as performance implications, the pull request I submitted will not have any. The validator technique used to block iterates over the entire result set, and throws if an unauthorized document is encountered. My change does the same, except it replaces the throw with a filter.

Please let me know if you have further questions, and again thank you for all of your great work.

nbclark avatar Feb 15 '17 03:02 nbclark

Hi. I wonder if the following helps

lets say you have the following schema for users:

userSchema = {
  name: 'string',
  chatRooms: ['string'] // user allowed to chat only in these rooms
}

Now you can use the following validator function to allow users only to chat in rooms that they belong to (I assume that value contains name of chat room that it belongs to):

validator = """
  (context, value) => {
    if (context) { // context represents user in this case
      if (context.chatRooms && context.chatRooms.indexOf(value.chatRoom) !== -1){
         return true
      }
      return false
    }
    return false
  }
"""

I believe that this overcomes the following which you mentioned in your reply

However, the restriction is a full block instead of a filter, so we have no way to construct a collection with Horizon with multiple owners, and restrict access from the server.

this means that you can construct a chat room with multiple owners.

I hope that I didn't miss anything. cheers.

riyadhzen avatar Feb 18 '17 23:02 riyadhzen