Permissions on a rest API implementing HATEOAS - api

I'm trying to figure out the right way to handle permissions in a single page app that talks directly to several RESTful APIs, that implement HATEOAS.
As an example:
"As a user of my application I can view, start and pause jobs but not stop them."
The underlying rest API has the following resource:
/jobs/{id}
Which accepts GET and PUT. The GET returns a job model and the PUT accepts a job model as a request body in the form:
{
"_links" : {
"self" : "/jobs/12345678"
}
"id" : 12345678,
"description" : "foo job",
"state" : "STOPPED"
}
Accepted job states can be: dormant | running | paused | stopped.
The requirement says that on the UI I must have the buttons:
START, PAUSE, STOP
... and only display based on the logged in user's permissions.
From the API perspective everything works as the underlying logic on the server makes sure that the user cannot update the state to a STOPPED state when a request is made (a 401 is returned maybe).
What is the best way to inform the app / UI of the user's permissions, so it can hide any buttons that the user has no permission to action?
Should the API provide a list of permissions, maybe something like :
{
"_links" : {
"self" : "/permissions",
"jobs" : "/jobs"
}
"permissions" : {
"job" : ["UPDATE", "DELETE"],
"job-updates" : ["START", "PAUSE"]
}
}
OR should the API change so that the permissions are reflected in the HATEOS links maybe something like :
{
"_links" : {
"self" : "/jobs/12345678",
"start" : "/jobs/12345678/state?to=RUNNING",
"pause" : "/jobs/12345678/state?to=PAUSED",
}
"id" : 12345678,
"description" : "foo job",
"state" : "DORMANT"
}
Or should it be done in a completely different way?
UPDATE
I've found the following article which suggests an answer:
https://softwareengineering.stackexchange.com/questions/215975/how-to-handle-fine-grained-field-based-acl-permissions-in-a-restful-service

I would go with the latter: Imply permissions based on which links are present.
If the link isn't there, the user can't access the resource/perform the action. If it is, they can. That's what I'd do, because it's simple and clean and leaves little to the discretion of the front-end code. Decoupling, yo.
Alternatively, if you do want to include all the links in each response but explicitly specify which are allowed and which aren't, if you use a format such as HAL to write your links, you could extend it with a flag on each link like so:
{
"_links" : {
"self" : {
"href":"/jobs/12345678",
"allowed":false
},
"start" : {
"href":"/jobs/12345678/state?to=RUNNING",
"allowed":false
},
"pause" : {
"href":"/jobs/12345678/state?to=PAUSED",
"allowed":false
}
},
"id" : 12345678,
"description" : "foo job",
"state" : "DORMANT"
}

I would go with the latter. The reason I don't like the former is because you are creating extra work for the client by requiring it to figure out the mapping between permissions and the resources they permit access to. If you use hateoas and check for the presence of relation types, this mapping is done for you by the server. It also means the uris can change without breaking the client.
I recently wrote a blog post on this area:
https://www.opencredo.com/2015/08/12/designing-rest-api-fine-grained-resources-hateoas-hal/

You should be using forms, not links, to provide state transition hypermedia.
If you cannot provide forms in your media type, provide links to URIs which use another media type that supports forms, such as XHTML.
IANA has link relations for create-form, edit-form and delete-form for this purpose.
Also, please do not use start and pause as real link relations. If you define them yourself, they must be URIs (preferably HTTP URLs, but any URI under your control will suffice). start has a completely different meaning to what you're using it for, and pause is not defined.

Related

How to update old data with new data in Firebase?

I'm developing a chat app. In my app there are 4 nodes called User, Recent, Message, Group. I'm using Objective-C My message object looks like,
{
"createdAt" : 1.486618017521277E9,
"groupId" : "-KcWKeXXQ9tjYsYfCknx",
"objectId" : "-KcWKftK8GiMxxAnarL5",
"senderId" : "828949592937598976",
"senderImage" : "http://hairstyleonpoint.com/wp-content/uploads/2014/10/marcello-alvarez.png",
"senderName" : "John Doee",
"status" : "Seen",
"text" : "Hi all",
"type" : "text",
"updatedAt" : 1.486622011467733E9
}
When I'm updating a User, all message's senderName should be updated accordingly. Is there are way to do this via the code or Do I need to write a rule. I'm a newbie to the firebase. Please suggest me a way to do that. If It's possible to do with the rules, Please guide me on this.
It's not possible to do this via rules, so you have to manually iterate over all your data and update the senderName.
Anyways, I think you would probably be better off with saving {senderID: $someUserID} instead - like you would do in a relational database. The userID is static, so can change the user without having to update all the instances where you use it.

How to construct intersection in REST Hypermedia API?

This question is language independent. Let's not worry about frameworks or implementation, let's just say everything can be implemented and let's look at REST API in an abstract way. In other words: I'm building a framework right now and I didn't see any solution to this problem anywhere.
Question
How one can construct REST URL endpoint for intersection of two independent REST paths which return collections? Short example: How to intersect /users/1/comments and /companies/6/comments?
Constraint
All endpoints should return single data model entity or collection of entities.
Imho this is a very reasonable constraint and all examples of Hypermedia APIs look like this, even in draft-kelly-json-hal-07.
If you think this is an invalid constraint or you know a better way please let me know.
Example
So let's say we have an application which has three data types: products, categories and companies. Each company can add some products to their profile page. While adding the product they must attach a category to the product. For example we can access this kind of data like this:
GET /categories will return collection of all categories
GET /categories/9 will return category of id 9
GET /categories/9/products will return all products inside category of id 9
GET /companies/7/products will return all products added to profile page of company of id 7
I've omitted _links hypermedia part on purpose because it is straightforward, for example / gives _links to /categories and /companies etc. We just need to remember that by using hypermedia we are traversing relations graph.
How to write URL that will return: all products that are from company(7) and are of category(9)? In otherwords how to intersect /categories/9/products and /companies/7/products?
Assuming that all endpoints should represent data model resource or collection of them I believe this is a fundamental problem of REST Hypermedia API, because in traversing hypermedia api we are traversing relational graph going down one path so it is impossible to describe such intersection because it is a cross-section of two independent graph paths.
In other words I think we cannot represent two independent paths with only one path. Normally we traverse one path like A->B->C, but if we have X->Y and Z->Y and we want all Ys that come from X and Z then we have a problem.
So far my proposition is to use query strings: /categories/9/products?intersect=/companies/9 but can we do better?
Why do I want this?
Because I'm building a framework which will auto-generate REST Hypermedia API based on SQL database relations. You could think of it as a trans compiler of URLs to SELECT ... JOIN ... WHERE queries, but the client of the API only sees Hypermedia and the client would like to have a nice way of doing intersections, like in the example.
I don't think you should always look at REST as database representation, this case looks more of a kind of specific functionality to me. I think I'd go with something like this:
/intersection/comments?company=9&product=5
I've been digging after I wrote it and this is what I've found (http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api):
Sometimes you really have no way to map the action to a sensible RESTful structure. For example, a multi-resource search doesn't really make sense to be applied to a specific resource's endpoint. In this case, /search would make the most sense even though it isn't a resource. This is OK - just do what's right from the perspective of the API consumer and make sure it's documented clearly to avoid confusion.
What You want to do is to filter products in one of the categories ... so following Your example if we have:
GET /categories/9/products
Above will return all products in category 9, so to filter out products for company 7 I would use something like this
GET /categories/9/products?company=7
You should treat URI as link to fetch all data (just like simple select query in SQL) and query parameters as where, limit, desc etc.
Using this approach You can build complex and readable queries fe.
GET /categories/9/products?company=7&order=name,asc&offset=10&limit=20
All endpoints should return single data model entity or collection of
entities.
This is NOT a REST constraint. If you want to read about REST constraints, then read the Fielding dissertation.
Because I'm building a framework which will auto-generate REST
Hypermedia API based on SQL database relations.
This is a wrong approach and has nothing to do with REST.
By REST you describe possible resource state transitions (or operation call templates) by sending hyperlinks in the response. These hyperlinks consist of a HTTP methods and URIs (and other data which is not relevant now) if you build the uniform interface using the HTTP and URI standards, and we usually do so. The URIs are not (necessarily) database entity and collection identifiers and if you apply such a constraint you will end up with a CRUD API, not with a REST API.
If you cannot describe an operation with the combination of HTTP methods and already existing resources, then you need a new resource.
In your case you want to aggregate the GET /users/1/comments and GET /companies/6/comments responses, so you need to define a link with GET and a third resource:
GET /comments/?users=1&companies=6
GET /intersection/users:1/companies:6/comments
GET /intersection/users/1/companies/6/comments
etc...
RESTful architecture is about returning resources that contain hypermedia controls that offer state transitions. What i see here is a multistep process of state transitions. Let's assume you have a root resource and somehow navigate over to /categories/9/products using the available hypermedia controls. I'd bet the results would look something like this in hal:
{
_links : {
self : { href : "/categories/9/products"}
},
_embedded : {
item : [
{json of prod 1},
{json of prod 2}
]
}
}
If you want your client to be able to intersect this with another collection you need to provide to them the mechanism to perform this. You have to give them a hypermedia control. HAL only has links, templated links, and embedded as control types. let's go with links..change the response to:
{
_links : {
self : { href : "/categories/9/products"},
x:intersect-with : [
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 1",
title : "Company 6 products"
},
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 2",
title : "Company 5 products"
},
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 3",
title : "Company 7 products"
}
]
},
_embedded : {
item : [
{json of prod 1},
{json of prod 2}
]
}
}
Now the client just picks the right hypermedia control (aka link) based on the title field of the link.
That's the simplest solution. But you'll probably say there's 1000's of companies i don't want 1000's of links...well ok if that;s REALLY the case...you just offer a state transition in the middle of the two we have:
{
_links : {
self : { href : "/categories/9/products"},
x:intersect-options : { href : "URL to a Paged collection of all intersect options"},
x:intersect-with : [
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 1",
title : "Company 6 products"
},
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 2",
title : "Company 5 products"
},
{
href : "URL IS ABSOLUTELY IRRELEVANT!!! but unique 3",
title : "Company 7 products"
}
]
},
_embedded : {
item : [
{json of prod 1},
{json of prod 2}
]
}
}
See what i did there? an extra control for an extra state transition. JUST LIKE YOU WOULD DO IF YOU HAD A WEBPAGE. You'd probably put it in a pop up, well that's what the client of your app can do too with the result of that control.
It's really that simple...just think how you'd do it in HTML and do the same.
The big benefit here is that the client NEVER EVER needed to know a company or category id or ever plug that in to some template. The id's are implementation details, the client never knows they exist, they just executed Hypermedia controls..and that is RESTful.

REST API Design for Updating Object Graph

I'm designing a REST API and am looking for the recommended best practice for updating object graphs. My question is best explained in an example, so let's say that I have a GET resource as follows:
URI: /people/123
This URI returns an object graph like this:
{
"name":"Johnny",
"country":{"id":100,"name":"Canada"},
"likes":[
{"id":5,"name":"Fruit"},
{"id":100,"name":"Sports"}
]
}
When allowing the API consumer to update this resource, how would you expect the object to be updated via PUT or PATCH? Updating the "name" property is pretty straightforward, but I'm not certain about "country" or "likes", as the consumer can only only change the relationship to other objects and not create new ones.
Here is one way to request the update:
{
"name":"Bob",
"countryId":200
"likeIds":[3,10,22]
}
This update will change the resource to the following:
{
"name":"Bob",
"country":{"id":200,"name":"United States of America"},
"likes":[
{"id":3,"name":"Cars"},
{"id":10,"name":"Planes"},
{"id":22,"name":"Real Estate"}
]
}
This design explicitly and clearly asks the consumer to only update the "IDs" of the "Person", but I'm concerned that the object graph for a PUT/PATCH looks different than the GET, making the API hard to learn and remember. So another option is to request the PUT/PATCH as follows:
{
"name":"Bob",
"country":{"id":100},
"likes":[
{"id":3},
{"id":10},
{"id":22}
]
}
This will yield the same change as the previous update and does not alter the object graph. However, it doesn't make it clear to the API consumer that only the "IDs" can be updated.
In this scenario, which approach is recommended?
In my opinion you should stay with the same structure for both, GET and PUT requests. Why? Because it's quite common to map JSON/XML data into objects, and most (if not all) software that do the actual mapping work best if JSON schema is always the same.
So your webservice should accept a following JSON code:
{
"name":"Joe",
"country":{"id":200,"name":"United States of America"},
"likes":[
{"id":5,"name":"Fruit"}
]
}
However it doesn't have to take into account the country name and may focus only on the country id.

How to implement a simple RestKit callback interface?

I'll start by saying that I'm really new (about two days now) to iPhone dev and Objective-C. I'm still getting used to the syntax, memory management, etc.
I'm trying to use RestKit to interact with a server which allows JSON REST requests. After issuing a GET request I get data of the form:
GET : /api/beast/1/
{
'species' : 'elephant',
'resource_uri' : 'api/beasts/1/',
'owner' : '/api/beastmaster/3/',
'name' : 'Stampy'
}
GET : /api/beastmaster/3/
{
'resource_uri' : '/api/beastmaster/3/'
'first_name' : 'Bart',
'last_name' : 'Simpson'
}
The thing is that the owner property of the beast objects is sometimes populated with the resource URI string and sometimes with an actual full json representation of the object, as follows:
{
'species' : 'elephant',
'resource_uri' : 'api/beasts/1/',
'owner' : {
'resource_uri' : '/api/beastmaster/3/'
'first_name' : 'Bart',
'last_name' : 'Simpson'
},
'name' : 'Stampy'
}
What I want to do is to provide an easy to use interface to request the owner property asynchronously, it should check whether it already has a full representation of the object, and in that case execute the callback immediately or, if it doesn't, issue the appropriate GET request and execute the callback when the response arrives.
If this was JavaScript, some ways to achieve this may be:
//Alternative 1
beast.getOwner(function(owner){
console.log("Owner is: " + owner);
});
//Alternative 2
beast.get("owner", {
'success' : function(){...},
'error' : function(){...}
});
Most RestKit examples I've seen implement the protocol to handle the response on the same object that executes the request. I don't like this because in this case one class may require various related object properties (which would be obtained asynchronously).
What would be the best way to achieve the desired behaviour providing a simple and clear interface for the other programmers which would be using the model classes to develop the rest of the app? Maybe using blocks?
Well, as far as I can see from your JSON response, there has been a design irregularity. It seems complex enough to put 1-2 hour extra research and 1-2 hour extra coding just for that. My fast solution is to change the model view to have a consistent value whether owner : "uri" or owner : { ownerObjectProperty: value }.
The slow solution would be, you would have 2 values in your mapped object. 1st one would be NSString *rawValueForOwner, 2nd is OwnerObject* ownerObject.
You would map owner JSON value into rawValueForOwner mapped object via protocols. Parsing the value and deducting if it starts with "{" then parse that rawValueForOwner into an object via RestKit manual parsing methods. If it doesn't start with "{" then make an another call to your RESTful server to fetch the object then again link beast and owner into each other manually.
I would have taken the high way :)
This link contains how to parse JSON string into an object... Deserializing local NSString of JSON into objects via RestKit (no network download)

How to implement a permissions system like highrise or facebook

Hey I am looking to implement a permissions system like in highrise or facebook.
The issue with such an problem is that permissions have to defined on a instance of the object(visibility). Off the top of my head i can think of saving user_ids, or group_ids in a hash for every record. Is that the best way to do it?
I am using mongodb so that should make it easier. Although we can switch to sql also (highrise probably does it with sql).
Edit: I ended up writing a gem that works with mongoid, you can read more about it here
#Abhishiv: given this task, I would implement some form of convention for setting access by field.
Given an object like the following:
{
name : "me",
user : "me01234",
salary : "100",
address : "123 Nowhere drive"
}
I would add permissions by doing something like this:
{
name : "me",
user : "me01234",
salary : "100",
address : "123 Nowhere drive"
p_salary : [ 'g/accounting', 'g/management', 'u/owner' ]
p_address : [ 'g/accounting', 'g/hr', 'u/me' ]
}
With conventions like this, you can maintain document-level access permissions. And it's pretty easy to see how to program such a thing.
Now typically you want access permissions on both the object and the collection itself. This keeps the whole process much more DRY. For such a thing, I would simply build a "permissions" collection that contains default permissions for each other collection in the DB.
Off the top of my head, I don't know of any framework that does this "out of the box". I would look at Mongoid and MongoMapper and see if this type of detail isn't appropriate for a plug-in.
Look into Cancan: https://github.com/ryanb/cancan
Have you tried declarative authorization?