7

I've been trying to design a RESTful API and have had most of my questions answered, but there is one aspect of permissions that I'm struggling with.

Different roles may have different permissions and different representations of a resource. For example, an Admin or the user himself may see more fields in his own User representation vs another less-privileged user. This is achieved simply by changing the representation on the backend, ie: deciding whether or not to include those fields.

Additionally, some actions may be taken on a resource by some users and not by others. This is achieved by deciding whether or not to include those action items as links, eg: edit and delete links. A user who does not have edit permissions will not have an edit link.

That covers nearly all of my permission use cases, but there is one that I've not quite figured out. There are some scenarios whereby for a given representation of an object, all fields are visible for two or more roles, but only a subset of those roles my edit certain fields.

An example:

{
    "person": {
        "id": 1,
        "name": "Bob",
        "age": 25,
        "occupation": "software developer",
        "phone": "555-555-5555",
        "description": "Could use some sunlight.."
    }
}

Given 3 users: an Admin, a regular User, and Bob himself (also a regular User), I need to be able to convey to the front end that:

Admins may edit all fields, Bob himself may edit all fields, but a regular User, while they can view all fields, can only edit the description field. I certainly don't want the client to have to make the determination (or even, for that matter, to have any notion of the roles involved) but I do need a way for the backend to convey to the client which fields are editable.

I can't simply use a combination of representation (the fields returned for viewing) and links (whether or not an edit link is availble) in this scenario since it's more finely grained.

Has anyone solved this elegantly without adding the logic directly to the client?

Jason McClellan
  • 173
  • 1
  • 4

2 Answers2

4

How about adding specific permissions as 'links' in your resource representation. Basically, letting the client know what attributes are available to the updated (by regular users). Both Admin and Self are non-regular users which are allowed to edit everything. Based on your example that regular users can edit only the 'description' field, here are my thoughts:

{
    "person": {
        "id": 1,
        "name": "Bob",
        "age": 25,
        "occupation": "software developer",
        "phone": "555-555-5555",
        "description": "Could use some sunlight.."
        "_links": {
           "href": "/person/1",
           "method": "PUT",
           "attributes": ["description"]
        }
    }
}
Aziz Shaikh
  • 427
  • 4
  • 10
  • 1
    That seems like a valid approach. The more I go through this the more I find that HATEOAS is unattainable other than with html and a human end-user. The client still needs too much pre-determined information. But, that's okay. This still allows me to keep all the control logic in the backend and standardize the client. Thanks! – Jason McClellan Oct 31 '13 at 16:14
  • @JasonMcClellan Did you end up using this solution? – Catskul Mar 06 '15 at 18:46
  • @Catskul I use a similar solution. I don't break out the href, method, etc., I accept that entirely discoverable RESTful APIs are a pipe dream so the client must have some knowledge of the API its working with. I do use a _links object to provide which actions are available though, and it's a key:value pair where the key is the action name and the value is the URL endpoint for that. So, "delete", "edit", etc. would be action examples. The client then bases its logic around which links exist in the response for each object. – Jason McClellan Mar 07 '15 at 19:48
1

Another option is to have another resource (i.e. /permissions/userResource/user/1) that will return fields that user is allowed to modify or view.

{

read: [id,name,age,occupation,etc],

write: [description]

}

I think this is similar to above suggestion.

  • This is would require the client to make API calls for every single resource they want to know about, right? – dwjohnston May 06 '22 at 01:16