Query Permissions

I have a query:

query AllUserNames{allUserNames}

defined as:

allUserNames: [String!]! @resolver(name: "all_user_names")

in the schema.

Index is defined as:

{
  name: "all_user_names",
  unique: false,
  serialized: true,
  source: "User",
  values: [
    {
      field: ["data", "username"]
    }
  ]
}

Resolver is defined as:

{
  name: "all_user_names",
  role: Role("all_user_names"),
  body: Query(
    Lambda(
      [],
      Select(
        "data",
        Map(
          Paginate(Match(Index("all_user_names"))),
          Lambda("x", Get(Var("x")))
        )
      )
    )
  )
}

Role is defined as:

{
  ref: Role("all_user_names"),
  ts: 1598854142753000,
  name: "all_user_names",
  privileges: [
    {
      resource: Collection("User"),
      actions: {
        read: true,
        write: false,
        create: false,
        delete: false,
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Index("all_user_names"),
      actions: {
        unrestricted_read: false,
        read: true
      }
    }
  ],
  membership: []
}

The http header uses a valid token (that validates similarly configured queries).
The query (allUserNames) gives error:

{
  "errors": [
    {
      "message": "Insufficient privileges to perform the action.",
      "extensions": {
        "code": "permission denied"
      }
    }
  ]
}

What have I incorrectly configured to prevent this query from having access permission? thanks …

Hi @FreeRoss!

does the token you say is valid have call privileges for the the UDF? So, is it either an admin or server key, or is it a logged in token with the added privileges?

Hi @FreeRoss

the resolver looks wrong, using Get, you expect the index to return set of Ref. But the index you defined returns strings.
You should slightly change to:

{
  name: "all_user_names",
  role: Role("all_user_names"),
  body: Query(
    Lambda(
      [],
      Select(
        "data",
        Map(
          Paginate(Match(Index("all_user_names"))),
          Lambda("x", Var("x"))
        )
      )
    )
  )
}

Even the role, you miss the privilege fro calling functions:

{
  name: "all_user_names",
  privileges: [
    {
      resource: Collection("Users"),
      actions: {
        read: true,
        write: false,
        create: false,
        delete: false,
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Index("all_user_names"),
      actions: {
        unrestricted_read: false,
        read: true
      }
    },
    {
      resource: Function("all_user_names"),
      actions: {
        call: true
      }
    }
  ],
  membership: []
}

Hope this fix the issue.

Luigi

1 Like

Hi Luigi.
I removed the ‘Get’. I attempted to add the privilege for calling functions to the “all_user_names” role, however the UI doesn’t list “all_user_names” as an available function in the dropdown. In the original tutorial the function calling privilege was added with:

CreateRole({
  name: "logged-in",
  privileges: [
  {
    resource: Function('all_user_names'),
    actions: {
      call: true
    }
  }
  ],
  membership: [{
    resource: Collection("User")
  }]
})

and it was adding the User membership that enables the token to authorize access to ‘all_user_names’. The tutorial then instructs:

Update(Function("all_user_names"), { name: "all_user_names",
  body: Query(Lambda([],Select("data", Paginate(Match(Index("all_user_names"), []))))),
  role: Role("all_user_names")
})

I changed this to:

{
  name: "all_user_names",
  role: Role("all_user_names"),
  body: Query(
    Lambda(
      [],
      Select(
        "data",
        Map(Paginate(Match(Index("all_user_names"))), Lambda("x", Var("x")))
      )
    )
  )
}

as suggested.
The ‘logged-in’ role FQL:

{
  ref: Role("logged-in"),
  ts: 1599117447770000,
  name: "logged-in",
  privileges: [
    {
      resource: Ref(Ref("functions"), "all_user_names"),
      actions: {
        call: true
      }
    },
    {
      resource: Ref(Ref("functions"), "create_new_ranking"),
      actions: {
        call: true
      }
    },
    {
      resource: Ref(Ref("functions"), "create_new_player"),
      actions: {
        call: true
      }
    },
    {
      resource: Ref(Ref("functions"), "create_new_userjoinedranking"),
      actions: {
        call: true
      }
    },
    {
      resource: Ref(Ref("functions"), "all_players"),
      actions: {
        call: true
      }
    },
    {
      resource: Ref(Ref("functions"), "all_rankings"),
      actions: {
        call: true
      }
    }
  ],
  membership: [
    {
      resource: Collection("User")
    },
    {
      resource: Collection("Ranking")
    },
    {
      resource: Collection("Player")
    },
    {
      resource: Collection("UserJoinedRanking")
    }
  ]
}

Do you know why the UI doesn’t list “all_user_names” as an available function in the dropdown in the “all_user_names” role configuration screen?
How can I add that function (if that is still what I need to do) to the role config?
thanks …

@ptpaterson … thanks for your response. It’s a logged in token with the added privileges. I have given, I believe, the relevant details in the reply to Luigi above …

Further to my first reply, I tried adding the ‘all_user_names’ function ‘manually’ in the shell:

CreateRole({
  name: "all_user_names",
  privileges: [
    {
      resource: Collection("Users"),
      actions: {
        read: true,
        write: false,
        create: false,
        delete: false,
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Index("all_user_names"),
      actions: {
        unrestricted_read: false,
        read: true
      }
    },
    {
      resource: Function("all_user_names"),
      actions: {
        call: true
      }
    }
  ],
  membership: [
    {
      resource: Collection("User")
    }
  ]
})

However that gives me:

Error: [
  {
    "position": [],
    "code": "validation failed",
    "description": "document data is not valid.",
    "failures": [
      {
        "field": [
          "privileges",
          "0",
          "resource"
        ],
        "code": "invalid reference",
        "description": "Cannot read reference."
      }
    ]
  }
]

Is there another way for me to add the function privilege to the ‘all_user_names’ role or does the problem lie elsewhere? thanks …

Hi @FreeRoss,

There’s a typo I guess, one you said

Collection('Users') 

And after:

Collection('User') 

Not sure how the collection is named, but the error is probably here.

Luigi

Thanks Luigi. It’s name should be ‘User’, so I successfully updated the role with that. However, I still get the permissions error:

{
  "errors": [
    {
      "message": "Insufficient privileges to perform the action.",
      "extensions": {
        "code": "permission denied"
      }
    }
  ]
}

which I didn’t get the first time I went through the tutorial. I have tried deleting the role and re-implementing it (with both the original function update code and your suggested revision) and reviewed the tutorial steps a number of times. I am reading the article on authorization suggested by @databrecht, but, currently, I am unable to see why the original tutorial setup (query on ‘all_user_names’) doesn’t now work with a token that works for other queries.
I understand that you may have given me all the assistance you are currently able to. However, if anything further does occur, please don’t hesitate to suggest as I feel I should be able to, at least, be on top of a seemingly simple query like this and any pointers may nudge me in the right direction. Thanks …
UPDATE: self-solved
I needed to rename the index to allUserNames (perhaps to match the schema definition).