Reputation: 3278
I have three different models as User
, PermissionSet
and Permission
. These models represent their SQL tables respectively.
User
has a many-to-one association PermissionSet
, a user may have one PermissionSet
or none. PermissionSet
s would be owned by none or many User
s.
PermissionSet
has many-to-many association with Permission
s. A Permission
could be owned by multiple PermissionSet
s or none, where PermissionSet
s may own multiple Permission
s or none at all.
So I created four tables: users
, permission_sets
, permissions
and a junction table, permission_sets_permissions
.
I need to persist the changes made in a User
's PermissionSet
. This is handled by a model called PermissionSetGrant
, which has its own table, permission_set_grants
.
What is the best way to alter the Permission
s of a PermissionSet
with a RESTful API, based on HTTP and JSON?
For example, is it a good way to modify a PermissionSet
with such request:
PUT /api/v1/permission_sets/7
// Payload
{
"permission_set": {
// Assume these properties of the entity aren't changed
"name": "default",
"description": "Default permission set.",
// Here we're changing the permissions
"permission_ids": [
24,
27,
35
]
}
}
-> 200 OK
or add permissions with an extra REST path instead?
POST /api/v1/permission_sets/7/permissions
// Payload
{
"permission": 24
}
-> 201 CREATED
and when we need to delete that permission
DELETE /api/v1/permission_sets/7/permissions/24
-> 203 ACCEPTED
I would also add that the request is idempotent and deterministic from the client's aspect. The number of permissions is 100, at least. Hence, batch operations will be performed in second approach.
Upvotes: 3
Views: 728
Reputation: 26129
Your current solution is okay I think. If all you want to connect permissions with permissions sets, then you can use multiple ids to describe collections instead of using the payload for the same, e.g.
PUT /api/v1/permission_sets/1+2+3/permissions/4+5+6/
DELETE /api/v1/permission_sets/1+2+3/permissions/4+5+6/
If I were you I would not stuck by hierarchical URI design, it is inconvenient by most of the time.
PUT /api/v1/permissions/4+5+6/into/permission/sets/1+2+3/
DELETE /api/v1/permissions/4+5+6/from/permission/sets/1+2+3/
Be aware that there are not REST constraints about URI design, since REST operates with hyperlinks and machine clients. So from a client perspective it does not matter what structure the URI has as long as it can be described with an URI template. The only thing you have to keep in mind, that there is n:1 relation between URIs and resources, so multiple URIs can identify the same resource, but a single URI cannot identify multiple resources.
Upvotes: 1
Reputation: 5770
If you're going to allow the update of such a large number of permissions at once, then PATCH
might be your friend:
Looking at the RFC 6902 (which defines the Patch standard), from the client's perspective the API could be called like
PATCH /api/v1/permission_sets/7
[
{ "op": "add", "path": "/permission_ids", "value": [ "24", "27", "35" ]}
]
However, PATCH
is not an idempotent method unfortunately (and neither is POST
, for pretty much the same obvious reason), so by exclusion you're left with the PUT
, which is fine, just a bit more verbose than the PATCH
(the client has to PUT
the whole object, including the whole collection of permission_ids).
Upvotes: 0