What is the REST best practice with PUT / PATCH and permissions? - rest

I'm working on a REST API and I cannot find any response to my question. Here is my problem :
On my application, I have severals user roles "Admin" and "User". Both can PUT / PATCH an entity "Agency", but they cannot modify same fields :
Admin can modify all fields
User can modify only "name" and "adress" fields
So my colleagues and I don't know how to choose between two options :
Create two endpoints PATCH /api/agency/{id} and PATCH /api/agency/{id}/restricted : first only allowed to admin, second for both but only update "name" and "adress" ? => this is simpler but it creates a new route to the world
Only one enpoint, that return a 403 response if a User try to update unauthorized field ? => this can be complex in the future if permissions rules become more complex, but only one endpoint is exposed...
Thanks a lot for your response, and pardon my english !

The second option is the REST way to do it. The URI shouldn't be indicating permissions/authorisation required to call it. If you want to indicate the allowed API calls then the correct mechanism is HATEOAS, which is a fundamental principle of REST.
I'm not sure I understand your argument that it can become complex in the future. I think the first option offers much more opportunity for increasing complexity. What if new roles come along in the future? What if the permissions become more granulated? In the first option your URI will change.

Related

Should an element in a REST API return its own ID?

What is the benefit of returning the ID of the element? Isn't it already part of the url and therefore known? I am not talking about using the REST API with HAL or something similiar.
api/employees/1
{
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
api/employees/1
{
"Name" : "Joe Bloggs",
"Department" : "IT"
}
I guess it makes sense to add more information regarding the usage of the API:
The API in question is a public API in a closed network (not internet). We provide sample clients but our customer write their own client for our API. The ID of an element is no sensitive information. The data is not about exmployees (as stated in the question) but about asset management.
The reason I am asking is, that customers are complaining that if they use some kind of middleware (whatever this is), they only receive the content of a element but do not have access to the url of the element (how?).
If you write your own client, is there any kind of situation where you can't get the ID based on the URL? Should we add the ID for people, who somehow do not have access to the url?
What is the client actually using the ID for? Presenting a product ID isn't that wrong IMO but does a user has to know the ID you store the user entity at in the DB when she uses an email to authenticate with the API anyways? So to answer the actual question: it depends. If the client, however, is using it to construct the next URI to invoke I strongly recommend to return links with meaningful relation names instead as this helps to decouple the client from the API as the client does not have to have a-priori knowledge of the API itself.
Depending on the resource it might not be benefitial to have an ascending ID as this might favor guessing attacks and also may lead to strange situation if you remove an item in the middle of the collection. Are the IDs of the subsequent items updated? Is a gap exposed between items? Usually UUIDs or the like are a much safer way to expose such information.
One further aspect to consider is that clients in an ideal REST environment should not interpret URIs itself but use the relation name the URI was returned for instead to determine whether to invoke that URI or not. A client which extracts an ID from an URI most likely has some a-priori knowledge of the API and is thus thighly coupled to that API and will with a certainty break if the API is ever going to be changed.
With that being said, there is the concept of URI patterns which should help a client in extracting things like IDs and names from URIs. Personally I'm not that keen on such things as they promote a misleading approach to the application of REST in an API design.
If you write your own client, is there any kind of situation where you can't get the ID based on the URL? Should we add the ID for people, who somehow do not have access to the url?
Extracting the ID of an URI requires knowledge of the URI structure. If you ever, at some later time, want to change the URI structure for whatever reason all clients that were built around that knowledge will break. URIs shouldn't contain content as the body is actually there for. As the ID seems to be content for some of the client include it in the response body. You are of course free to add some of the information to the URI though you shouldn't require clients on parsing that URI and extract the required information of it.

REST Api design for updating a single attribute of a resource

As from the specification of the project I am working, it is required to expose an API that allows to change the status of a user entity to be one of [ VALID | NOT_VALID | TO_VALIDATE ].
Current API for users have this path
/user/:user_id
my idea was to add a new sub-path for POST with url:
/user/:user_id/status
Since I want to update just a single value which design choice you would find to be the best?
Using the request's body (JSON)
Using the query string e.g. /user/:user_id/status?value=VALID
Creating three endpoints, one for each possible status' value:
/user/:user_id/status/valid
/user/:user_id/status/not_valid
/user/:user_id/status/to_validate
Thanks.
If status is something that is not query-able, then you could even have it as part of the user entity itself like /user/:user_id and do a PATCH (with the JSON payload) to update the status. Generally, people prefer nested paths if the sub-path can be queried as sub-resource on its own or updated independently. So if someone needs the status of a user, would he not expect that to come in the GET result of /user/:user_id? Or is he required to make another GET call to /user/:user_id/status? I think the /status path might not be a great idea.
Also, if you add something like status now, what will happen if you need to update name, address etc. in the future. We don't want to keep adding new sub-paths for every field right? Also having an enum-like sub-path in the URL path (valid/not_valid etc.) doesn't seem to be the right thing to do. If you include it in the JSON payload, it would come under the schema and you could version it nicely in case you make new additions to the enum. Having it as part of the URL means the clients now have to know about the new path as well.
On the other hand, you should also think about usability of the API. One rule of thumb I generally follow in designing REST APIs: I want my clients to integrate with my API in 2 minutes or so and I have to minimise the number of things he needs to know in order to successfully integrate. All standards and norms might come secondary to usability.

REST url for unique resource (url with singular ?)

I have a webserver with some configuration properties and I want to be able to change them using a REST API.
Example
{
"maxUsers" : 10,
"refreshPeriodInMin" : 5
}
I would like to represent this with a "configuration" object. According to REST principle I believe the best way to do it is :
GET/PUT/POST/DELETE /configurations/{id}
But in my case I have only one configuration object and I do not like the idea of have to query
GET /configurations
just for one object.
Because there is only one object the easiest solution I found is to use id=default
Would give something like
GET /configurations/default
Is there a better way to represent a "unique" resource ? As mentionned by djmorton in the comments would /configuration be correct in a REST world ?
Another solution I though about would be to have one object per property. This would give
GET /properties/maxUsers
Problem with that solution is that you need to know the name of property to be able to query it. PLus you will make several queries if you have multiple changes to make.
Keep the resource singular if it truly represents a singular thing. If you will only have one, there is no reason not to simply PUT to that resource when you want to create or update it, and GET from that resource when you want to retrieve it.
If it can not be deleted, return a 405 METHOD NOT ALLOWED on DELETE requests. If it can be deleted, a DELETE request to that resource is acceptable, after which GET requests can return a 404 NOT FOUND.
In many ways, adding an id element to the path like /configuration/default would probably confuse users because they might expect that they would be able to POST new configurations to /configuration in addition to the default one.
The key is to do something that is sensible and intuitive to consumers of the API.

REST API- Defining proper and intuitive URI

I'm tring to create a little registration app, that will be published as a REST API. It will allow users / systems to create an account on my system. They will pass in a username and a password.
According to the rules that i've read, the "/" in a URI must be used to indicate a hierarchical relationship.
So I'm wondering if this type of a URI follows the rules, and is intuitive enough:
POST http://myregistrations.com/users/user/{user_id},{password}
GET http://myregistrations.com/users/user/{user_id}
PUT http://myregistrations.com/users/user/{user_id},{password}
DELETE http://myregistrations.com/users/user/{user_id}
or should i remove the "users" part from the URI? In that case, if I want to get "all" users, i could just do the following:
GET http://myregistrations.com/user/
DELETE http://myregistrations.com/user/ ** i might not allow this but just for discussion purposes...
And the rest of the methods would look like this:
POST http://myregistrations.com/user/{user_id},{password}
GET http://myregistrations.com/user/{user_id}
PUT http://myregistrations.com/user/{user_id},{password}
DELETE http://myregistrations.com/user/{user_id}
I don't want to over complicate things... but I also want to make sure I follow conventions.
I am leaning towards the second example, where I don't have "users". Given that each part of the URI should map to an addressable resource, and that I won't be allowing batch updates to accounts, having a concept of "users" seems useless at this time. I might be missing something though.
Maybe I'm just splitting hairs. I've been reading other posts here too about defining REST APIs... but I haven't found anything yet.
Thanks.
You can have both concepts (user and users) with a single API. The URI /users/user seems convoluted to me.
Over-simplified example:
Post one user:
POST /user/{user_id,password}
Post multiple users:
POST /user/[{user_id,password},{user_id,password}]
Get one user:
GET /user/{user_id}
Response: {user_name} or [{user_name}]
Get multiple users:
GET /user/{search_user_name}
Response: [{user_name},{user_name},{user_name}]
Typically plural is how you reference a resource so users in this case and not user. This is what you're routes should look like to follow the REST pattern.
POST http://myregistrations.com/users/ --> The post payload should contain: {user_id},{password}
GET http://myregistrations.com/users/{user_id} --> The user_id is in the URL
PUT http://myregistrations.com/users/{user_id} --> The user_id is in the URL
DELETE http://myregistrations.com/users/{user_id} --> The user_id is in the url
I don't want to over complicate things...
I have bad news for you, you've already overcomplicated things. The REST clients know nothing about the URI structure, because they follow hyperlinks annotated with semantic metadata. The clients check this metadata instead of the URI structure.

What's the best to do when you need a verb using REST api?

I'm exposing a REST API, and It's amazingly easy and smooth to work with as long as you do CRUD (Create, Update, Delete). But I have this Tickets which return a list of tickets (get), a Ticket/{id} which get a particular item (get) and an activate method (put) that change the ticket status from not activated to activated.
Now I'm in need to give the REST 'consumer' the ability to do something like (in ws will be called: GetAndActivateRandomTicket() and it keeps me wondering, what that should be described as on REST ? Is it a post? A put? A get? The Goal is to get a random amount of tickets and set their status to active. Something like a get & put at the same time but without knowing before hand the {id} for the put.
Should it be /Tickets?activate=true&amount=5 ? What verb? Should I expose a verb instead of a noun? What is the 'best practices' on this issue?
If repeating the operation does something different (e.g., activates a different ticket) then it is not idempotent. Non-idempotent operations always map to POST (or a custom verb) in a RESTful architecture.
Some resources are easily identifiable and exist in the domain. Some however are a bit tricky as you pointed out. But ROA (resource oriented architecture) takes some getting used to. Anything can be made a resource including transactions, sessions and other such non-domain entities :)
In your case you seem to have an 'algorithmic' resource - selecting a random amount of tickets and activating them. I'm sure this 'randomness' has some way of selecting tickets which is not purely random else there'll be wasted computation with getting already activated set of tickets.
So I'm not sure how your activation is happening - does someone select activate against a bunch of tickets (checkboxes) or just part of 'data packet' without human intervention?
You description seems to hint the latter - so a good practice is to do what you just said:
Multiple options on the URL:
/Tickets?amountToActivate=5;activate (Note the semicolon and just the 'word' activate)
/Tickets?amountToActivate=5&activate=true (Note: I personally feel the above is better since =true is actually redundant, it's an artifact of non-restful URIs where most folks would explicitly state = true - it's as good as just writing 'activate' in the URL (implies true) absence would imply false :)
Your resource IS algorithmic and the human 'consumer of the URL' when reading it would instantly understand the former URL, =true may not be well understood, but that's just me perhaps. There is a tendency to also use the latter since most frameworks are able to parse query parameters and split by '&' and semicolons may just require some work
In case if there is manual intervention you can break it into two parts:
GET: /Tickets?fetchRandomAmountOfTickets=100 (since it's algorithmic)
PUT: /Tickets (the activation 'update' part of PUT for list of tickets that you 'GOT' above)
Hope this helps :)
First of all GET should be idempotent and never make any changes to the resource. Activating a resource should be done using a PUT.
What I would do is create a resource URL like /Tickets/Random that as a result to a GET returns an HTTP 303 to redirect the user to a randomly determined actual resource URL like /Tickets/12345. The user can then activate this ticket using a PUT. All the user app needs to know is the /Tickets/Random URL and he can keep on activating tickets as long as there are any there.
I extracted this :
Anything can be made a resource including transactions, sessions and other such non-domain entities :)
and went with :
TicketActivation resource.
[POST] with a query parameter of amount will return a set of random tickets activated.
and return the resource url as such that you can get like /ticket/id=1,2,3,4,5
[GET] will return tickets as normaly with an optional filter of id to return multiple tickets
[PUT] will use the filter of id also and set activation true or false depending on parameter.
so I can do :
[post]
/ticket/activation/?amount=5
resource returned will be something like /ticket?id=1,2,3,4,5
so I can issue a get on it.
[get]
/ticket?id=1,2,3,4,5
[put]
/ticket/activation?id=1,2,3,4,5&deActivate [OR]
/ticket/activation?id=1,2,3,4,5&activate
I guess this is the most elegant and also RESTfull and clear solution to this problem, I wanted to share for future reference. Also if you think there is a problem with this approach feel free to comment on it.