products v1.2 api returns both pool and airport pool. How to decide which one is applicable for user - uber-api

Upon calling the products api between 2 places, the product list contains pool, pool airport both. Even though the drop location is no where near airport. How do we decide which one to show the user
Similarly in some cases we get both uber go, go intercity in the response.

Related

REST API design: one endpoint with if/else logic or two separate role based endpoints

I have an API design/versioning conundrum.
Let's say I have an endpoint /api/customers which GETs all customers (ignore pagination). There's a twist though: if a regular user accesses this endpoint, they will only get the customers created by that user and no one else (I can check the access token and the sub field to determine who sent the request). Other usecase: if an admin accesses this endpoint, they should get ALL customers, regardless of who acquired them.
Now my question is from an API design perspective: is it better to have an if/else role check within the API controller itself to determine do I return ALL (admin) customers or specific (user) customers, OR should I differentiate between endpoints for the user and admin? I.e. admin only endpoint for all customers would be /api/admin/customers and regular users can still access their /api/customers?
In REST, it is normal to have multiple resources that share the same representations.
For example, the "authors' preferred version" of an academic paper is a mapping whose value changes over time, whereas a mapping to "the paper published in the proceedings of conference X" is static. These are two distinct resources, even if they both map to the same value at some point in time. The distinction is necessary so that both resources can be identified and referenced independently. A similar example from software engineering is the separate identification of a version-controlled source code file when referring to the "latest revision", "revision number 1.2.7", or "revision included with the Orange release." -- Fielding, 2000
It is perfectly consistent with that approach that you might have one resource for "all users", and another resource for "users created by Bob".
Where things get twisty is the case where you want to use the same resource identifier to provide different representations. That is, when Alice looks at "users created by me", she sees "users created by Alice", and when Bob looks at "users created by me", he sees "users created by Bob".
One possibility is to have "users created by me" redirect to the appropriate resource. It works, for values of "works" that permit extra round trips when the destination resource isn't already in the local cache.
In HTTP/2, server push may spare you some of that round trip pain.
The rules for shared caches should protect you from sending Alice's view of the "me" resource to Bob, and vice versa, but it is useful to be aware of the meanings of the various headers so that you don't inadvertently disable that protection.
Having different resources can be a problem in some "read your own writes" settings, because the caches won't know that an unsafe request has invalidated both resources. Bob creates a new user via a POST to "users created by me", and the corresponding cache entry is invalidated... but "all users" is a different cache key, and does not get invalidated. So if Bob looks at the all users view, he may see a previously cached copy without the changes that he just saw in his own view.
In some cases, it can make sense to consider sub-resources.
/api/customers
/api/customers#created-by-Alice
/api/customers#created-by-Bob
But if you are trying to reduce the amount of irrelevant data being exchanged, then that's not a good fit.
It should be same endpoint. Otherwise, each front-end which calling your API must have the same logic to determine the role and endpoint mapping.
It depends on your project.
If there's only 2 cases as you mentioned
only get customers created by that user for regular users
get all customers for admin users
then, it'd be better to use 1 endpoint by adding middleware to check current user role.
If you're plan to extend your project.
e.g. if admin users are also needed to get the customers created by that user, it'd better to create 2 endpoint. one for all customers, another one for current user's customers. like - api/customers/all, api/customers/me
I think /api/customers is fine for the cases mentioned. It's analogous to a web page request to index.html returning different content to different users.
If you want to extend it (e.g. Alice requesting Bob's list), you could support optional query params:
/api/customers?accessibleTo=bob
/api/customers?createdBy=bob
This would likely require an authorization check (Does Alice have access to Bob's list?), returning 403 (or 404, depending on your philosophy) when not authorized.
Also don't forget about caching. Avoid the possibility that two requests to the same URL (/api/customers) for different users will result in one user getting the other's list.

What is the best practice to get related/nested data from REST API?

For example: We have a User model, which in turn has several Company entities. I see 2 solutions:
1) Classical. Make an API like:
/users/
/users/3/
/users/3/companies/
and issue /users or companies request separately. However, if we need to have both user and his/her companies information in one view (on Angular2) - we need to send 2 requests to the server.
2) Put the related/nested data inside the level-1 object model. In request:
/users/3/
the server will provide information about the User, together with his Companies. In this case we get all information for 1 request. But again, the company has an unlimited number of Storage entities. What if they are required in one separate view?
I'm more inclined to the first option, but I'm confused by the description of the REST style: "The view must fully represent the resource." Satisfaction of this requirement can lead to a partition of the resource into child resources and, accordingly, to smaller representations. "
Please, help with advice, I doubt in connection with the lack of experience what decision will be correct in this case. Oh yes, I forgot, Backend on Django (Python) using Django-Rest-Framework - All this is a SaaS for ~ 1000 users.
Approach 1 is an an ideal approach for REST. But when it comes to designing APIs for the displaying information on the UI it involves much more than just partitioning the APIs as per resources.
So I would suggest including the Company information in the User API. But as you suggested Company object can have very large list of Storage objects, in this case I would recommend including only the necessary and sufficient fields of Company model into User API. So that you will be able to render one view. And then later when user expands the Company section then you can pull the left-over fields from /company/<id> API.
This way you will have lesser API calls for the hits where user doesn't look for Company details and your API will be light weight as well.

Access control based on data filtering instead of request authorization

Standard way to control access in a multi user service is to provide as many service methods as necessary, where each service method has concrete results and access permissions.
For example,
Moderator is authorized to call GetModerationAwaitingPosts service method to access posts from any visitor awaiting for moderation
Visitor is authorized to call GetOwnedPosts service method to access only his own posts including draft and moderation awaiting posts
Visitor is authorized to call GetModeratedPosts service method to access only moderated posts from all visitors
But there may be another approach - single service method GetPosts to request posts that the requester is allowed to see.
Any logged in user is authorized to call this method.
Posts are first filtered according to the role of the caller.
Then posts are filtered according to parameters passed in GetPosts method or filtered on client side.
This approach is used, for example, in WCF Data Services through Query Interceptors.
How is approach to filter data based on user inside service method named and treated in different architectures and methodologies, like SOA, REST, CQRS? Is it a solid solution?
Are there any books / articles where difference between these approaches is considered in details?
As for me, I find it really strange and unusual when results of a request depend on the requester.
Yes, there is an access control paradigm called attribute based access control (ABAC, abac) which implements data-based, context-based authorization that uses information about the user (role, department, age, location...) about the resource (owner, classification, type...) action (view, edit, delete), and context (time, IP address...)
ABAC will let you implement policies e.g.:
Medical use cases
doctors can view the medical records of patients they are assigned to
nurses can edit the medical journal of a patient in the same deparment
Finance use cases
A teller can view the accounts of those customers in their branch
A teller can approve a transfer up to their approval limit
ABAC provides an architecture as depicted below.
In the architecture you have the notion of a PEP or policy enforcement point which you can use to secure anything from GUIs, APIs, web services, micro-services, ESBs, and databases.
The PEP calls out to the PDP or policy decision point which is at the core of the architecture. The PDP uses a set of policies to determine whether access should be granted or denied. It can also use external sources of attributes, PIP or policy information points, to help in determining whether access should indeed be granted.
There is one language which implements ABAC today. This language is called XACML (xacml). XACML gives you:
the architecture
a policy language
a request / response scheme
With XACML you can create JSON authorization requests, send them off to the PDP and get a JSON response back. It's an extremely lightweight way of getting a response back.
This means you can either
grant or deny access to a given record, or
filter those records a user can get access to as stated in your requirement

Uber sandbox api returns duplicate ride request id for mutiple ride requests

I have created a session with sandbox_mode = True, with all scopes, including request, using uber_rides python library. The api calls work fine, but I get duplicate request_ids for mutiple ride requests(fired one after the other, and not concurrent). Though these requests are using the same lat, longs and product_id. Can it be possible that uber creates a ride id using lat, long ?
Is this okay ? Or am I actually missing something, and this should never happen ?
I think the issue you might be running into is that if you are already on a trip and you try to create a new one, the API will just return the trip details for your current trip. So I think what is happening is you're creating one trip, then trying to create another and you're getting back a "processing" status so it looks like you created a new trips, but its actually still the first trip.
You can verify this by creating a trip, checking the UUID, canceling the trip, then requesting a new one and seeing if the UUID is different.
Best,
Riche
product_id is based on the start_latitude/start_longitude or start_place_id parameters.
request_id is not (it's just a UUID identifying the ride request)
If you are doing multiple ride requests with the same OAuth Bearer token and you do not cancel the first ongoing ride request you are basically getting back the status details of the current ongoing trip.
According to Uber Help - CAN I REQUEST MORE THAN ONE UBER?
At this time, it’s not possible to request more than one ride from a
single account.
If your party cannot be accommodated by a single vehicle, have
multiple people in your group request rides. We offer vehicle options
accommodating up to 6 people in many cities.
If no one else in your group has an Uber account, you can invite them
to sign up from the main menu of your app. As a bonus, both you and
your friend will receive the referral promotion.
This also applies to the Uber API.
However, from my use of the Uber API I've noticed the following rate limiting headers sent back on some responses:
X-Rate-Limit-Limit-Concurrent-Trips: 10
X-Rate-Limit-Remaining-Concurrent-Trips: 10
so they probably plan to add the possibility of making concurrent ride requests from the same Uber rider.

How to manage business logic when building a REST API

I'm building a API Centric web application but I'm having trouble wrapping my head around some of the business logic.
Take this Use Case:
POST /companies -> User adds a new Company which has a Location
(Company Entity has a Location Entity which keeps the address of the company, A Company has one Location, a location can have multiple Companies)
PATCH/PUT /companies/{id} -> User edits a Company information (changes street name from Company->Location
I want my API to be able to check if there are already other companies on that Location.
If this is the case, I want the user the chose between editing the Location Entity (which will change then for all Companies on that Location) or create a new Location.
How do I send this choice back to the User in a RESTful manner?
easy :
PUT replace the entire resource if it exists or create a new resource if it doesnt exist. there is no choice to be made if you want to stay strictly REST( but you dont have to) .it's up to your users to check if the company exists with a GET before a put.
POST is suppose to replaced all the companies collection.
You could use PATCH however to update an existing company.
see : https://www.rfc-editor.org/rfc/rfc5789
The REST API or any strict service would provide a response based on a request. So the REST API can definitely respond back to the user if other companies are related to the location. But there is no way for the API to respond back with a choice. The API can respond back with some information and the user will need to make another request based on that information.
Instead, it is better to give the user the option to specify it upfront. So, the choice of whether related companies should be updated for the location is made upfront by the user as par of the request. For example, the user can specify this as a query param on the REST API and the service can take appropriate action based on that query param.