2

I'm having troubles finding a way to hide user emails from everyone, except the owner (user has access to only his email). Is there a way to hide a certain document field, for a certain roles?

Here is an example I found that creates a role with dynamic access to the whole User collection:

CreateRole({
  name: "tier1_role",
  membership: {
    resource: Collection("User"),
    predicate: Query(
      Lambda("userRef",
        // User attribute based rule:
        // It grants access only if the User has TIER1 role.
        // If so, further rules specified in the privileges
        // section are applied next.
        Equals(Select(["data", "role"], Get(Var("userRef"))), "TIER1")
      )
    )
  },
  privileges: [
    {
      // Note: 'allUsers' Index is used to retrieve the
      // documents from the File collection. Therefore,
      // read access to the Index is required here as well.
      resource: Index("allUsers"),
      actions: { read: true }
    }
  ]
})

I tried to change it a bit, but I wasn't able to set up field-level access.

Let's say I'd set up FaunaDB with GraphQL schema below.

enum UserRole {
  TIER1
}

type User {
  email: String! @unique
  username: String! @unique
  role: UserRole!
}

type Query {
  allUsers: [User!]
}

type Mutation {
  addUsers(new_users: [UserInput]): [User]
    @resolver(name: "add_users", paginated: false)
}

How do create a FaunaDB role in such a way that all of the users (except the current one) in resulting array from allUsers query, will not have email field?

I could break User collection into two: one is public, the other is accessible to a document owner, but this sounds wrong.

I'm new to the noSQL concept, so maybe I'm looking at this problem from the wrong perspective?

Mike M
  • 21
  • 3

1 Answers1

1

it's a request that came up a few times. You probably want to do this straight in FaunaDB's ABAC role system but although it provides row-level security, hiding a specific field is currently not provided yet. The feedback has been logged though, we will look into it.

The current way to do this is to split out Users from Accounts and fetch Users instead of Accounts. It would be useful to have something like hidden fields though in the future.

If you think of it, in this case, it does make sense to split authentication information from User information. You never know that you might offer another way to authentication in the future. I still recall from the Phoenix Framework book that they do it there was well and considered it a good practice.

You could also make a thin wrapper using Apollo in a serverless function and filter out these fields when you pass through the results. There is a guide that explains how to build such a thin Apollo middleware that just delegates to FaunaDB https://www.gatlin.io/blog/post/social-login-with-faunadb-and-auth0

Brecht De Rooms
  • 1,802
  • 7
  • 15
  • 1
    I actually did as your suggestion says, as a temporary solution, until a way to hide fields is found. But it turn out to be good enough, it does its job, plus your answer made me sure it's one of the correct ways of doing it. Thank you for your reply! I'll answer with code snippets later. – Mike M Apr 24 '20 at 19:27