Resources
First let's address what 'resources' and 'collections' you would have.
/users
and /permissions
a nice simple start, each of these is a collection of all the users and all the permissions respectively.
/users/{id}
and /permissions/{id}
, each of these is a single resource for a user or permission respectively.
- A user might have fields like "name", "sign-up-date", "id" etc.
- A permission might have fields like "name", "creation-date", "id" etc.
So far nice and simple. Regardless where you go from here, these two types of resources still exist as stand alone entities, a user can have no permissions and a permission can have no users. But now we need to link these together? First, let's show a concept that seems blow most people away with it's simplicity...
/users/{id}/name
can be used to return just the name of a user based on the ID. You don't have to support this behaviour, and if you did then really you shouldn't directly return the name as part of the 'user' resource (you should link to this specific name resource).
This concept can also be applied to the permissions. So we also add /users/{id}/permissions
, both as a resource that you can call GET
on, but also as a 'link' that is in the resource you GET
via /users/{id}
(and thus the hyper part of html starts to be used). So what does this return? It could be something like:
/permission/3
/permission/666
/permission/7
Are those resources 'under' the user, no. Do they need to be, no. So what if you GET
one of these permission resources?
name=admin
id=666
created-date=12/3/45
users=/permission/666/users
And there we go, with that last line, just like a user has a collection of permissions, a permission has a collection of users with it. (I think you can work out what that would look like)
Creation of Resources
In the first section I covered how these two types of resources relate to each other. Your question, however, is more about how to create these resources. Obviously, you could allow the operator (I'll say operator to avoid confusion with the 'user' resource) to create a user whilst also defining the permissions they should have:
{ "name" : "Frank",
"permissions" : [
...
]
}
The server will generate the 'id' and 'sign-up-date' for you. The list of permissions could allow for the 'id' or the 'name' to be used, the latter would require that the server ensures they are unique and also has the server do a look up. The only question at this point is, if the 'permission' is a new name... what does the server do? It could easily just create it, but what if it was a typo, or just a capitalisation issue?
Really, it should be IDs, and these should have to exist prior to creation of a user. A GUI could help an operator work out what those IDs are (present a list of 'role' names, but know how to send the POST
request with IDs).
As a side note, notice how nothing has stopped a user from being created with no permissions, and that the collection of permissions a user has can be modified later on as required.
Answering the Actual Question
It boils down two simple things. Firstly, you can have many URIs refer to the same resource; /permissions/666
might be the canonical URI, but if a user has that permission, you might also find it via /user/{userID}/permissions/666
, those two URIs can refer to the same resource on the server.
The second thing to think about, and this really does make the answer seem obvious (especially in this use case). How often are you creating permissions? You might make maybe 10, but then assign a few of them to thousands of users. So it seems shamefully silly to attempt to work out how to handle creating a permission and user resource in one request. And as I think I've shown, reusing it is not a problem.
TL;DR
You proposed solution number one is the way to go.
A much more challenging topic to cover is how to remove a permissions. Either from a single users or remove it entirely. But I've gone on long enough, so perhaps another answer can focus in on that detail specifically.