One to many relationship in REST design - rest

I have to tables users and teams. The application logic is such that every user should belong to atleast one team(No default here, user can initially belong to any team)
If I am using RESTful APIs to create users resource, should I send the info about user's team in this API itself.
POST /api/users
Or should I make 2 requests
POST /api/users
PUT /api/teams/{id}
If I use the second logic, there is an inconsistency in database if second API is never called.
What is the right thing to do in case of REST design?

What about POST /api/teams/{id}/users.
The URI is self explanatory, you are posting a user directly in a the appropriate team.

Related

Is it normal to create 2 unrelated(different) resources in one request?

When a user offers friendship to another user, he automatically subscribes to him. How to implement this in REST Api?
2 different entities(aggregates) are created in one request: Friendship (with OFFERED status) and Subscription, but the endpoint is called /friendships. Is it normal that there is such a side effect as a subscription? Or should I implement it differently?
Are there recommendations for such situations?
I want the logic to remain the same: automatic subscription occurs when a friendship is offered. Not otherwise.
In my opinion, adding a subscription when adding a friendship is your own application logic (which can be changed in future based on how yours users like it). It has nothing to do with the endpoint and /friendships is perfectly fine.

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.

Should I have multiple views/endpoints of a resource in a RESTful service?

Let's say I'm creating a RESTful service to handle orders for my warehouse over the web.
I want to allow customers to create accounts
I want a customer admin to be able to create accounts for other users in their office
I want to allow customer users to create orders
I want a site administrator to be able to create and manage all customer accounts
I want a site administrator to be able to create and manage all users
I want a site administrator to be able to create and manage all orders
Given these requirements. My initial thoughts are to design endpoints in this manner.
# to request a new customer account
/customers/request {POST}
# create and view customers - limited to admins
/customers {GET, POST}
# view customer info, update a customer
/customers/{customer_id} {GET, PATCH}
# create and view orders for a customer
/customers/{customer_id}/orders {GET, POST}
# view and update order for a customer
/customers/{customer_id}/orders/{order_id} {GET, PATCH}
I feel pretty confident that those path's make sense and follow the general restful ideas. However, I'm not sure how to handle the users endpoint. The problem is, I want customer admins to be able to create users that can use their customer account to create orders. Where do customer admins POST to to accomplish this? I had a couple of ideas.
Following this answer, I thought about this.
# creation of users always done through this endpoint no matter what the
# authenticated user's role is
/users { GET, POST }
# associate user with customer
/customers/{customer_id}/user_memberships { GET, POST }
The problem with this approach is how does the admin of the customer account get the ID of the user to associate with the customer account. Any GET request on /users would be filtered by retrieving only users who are part of their customer account. However, because the user would be created before the membership, they would never be able to view the user.
I also though about just having two endpoints to create users.
# create a user for a customer account
/customers/{customer_id}/users {GET, POST}
# root users endpoint only accessible to admins
/users {GET, POST}
# return same user
/users/1
/customers/{customer_id}/users/1
It essentially boils down to using the customer url prefix as a means of authorization. It seems a little strange to have two endpoints invalidating the other. What if the root endpoints were only views of the subresource endpoints?
# view all users in system - admin only
/users {GET}
# create & view admin users
/admin/users {GET, POST}
# create internal office users
/locations/{location_id}/users { GET, POST }
# create customer users
/customers/{customer_id}/users { GET, POST }
In this case, we could still cache GET responses on the sub resources as they would not change unless there was a POST or PATCH/DELETE on the specific id of a subresource.
This style also seems to make sense for orders. Admins can view all orders even though they technically belong to a customer.
# admin can view all orders
/orders?customer_id=1234
/orders
I kind of like the idea of the root resource being a view of subresources allowing for easier authorization based on the url.
So, I guess after all of that, my real question is:
Is having multiple endpoints representing the same resource a problem even if one of them is just an aggregate view of the subresources and does not permit the creation of a resource through that endpoint?
You shouldn't mix the design of your API, REST principles, and the need for authorization. You should design your API in a way that makes it:
easy to use
easy to maintain
easy to understand
A RESTful approach to API design tries to address these different concerns. A RESTful approach is about identifying the objects you have, their state, and their possible transition.
And that's where it stops. Now, you wonder about authorization. You want to be able to control what a user can do on given records depending on who the user is (an administrator, a customer,...) and what the targeted resource is (a customer record...).
What you need to do is deploy an authorization framework on top of your REST API in a loosely-coupled way. In other words, you want to externalize authorization. You definitely not want to build authorization straight into your API. Imagine that suddenly you have new authorization rules / constraints: you would have to recode your API. In doing so you'd break all the clients. That would lead to poor user experience.
So, we've identified you need to externalize authorization. Great. What are the different ways to do so? This depends on the language and framework you use.
You can use:
Spring Security in Java
Yii in PHP
CanCan in Ruby
... and many more
You could also implement your own filters, for instance a Servlet filter in Java in front of your REST endpoints.
Lastly, you can turn to a full-blown attribute-based authorization model based on XACML. There are several open-source and vendor alternatives. If you are not familiar with attribute-based access control or XACML, have a look at the following links:
ABAC explained by NIST
XACML
With XACML, you define policies centrally e.g:
Administrators can view all customer accounts
Administrators can modify a customer account he/she is assigned to
Customers can view and edit their own account only
The policies are then evaluated in an authorization service (in XACML that's known as a policy decision point). The authorization service exposes a binary authorization API which your API can call out to: can user Alice view record foo?.
Using externalized authorization based on policies and using XACML, you achieve a loose coupling between your business logic (your business API) and the authorization logic which you can more easily maintain and update.
According to my understanding, for ex. u want that for particular customerId you want that this customer only view its users not will be able to create its user which will only be created by admin, so this can be done using spring security as well and this definitely creates the problem so u have to categorize the customer according to your requirement.

REST: how to pass dependent resources when creating a new resource?

I'm currently figuring out a way how to build our REST webservice so resources can be linked to other resources at creation time. Take the following scenario.
We have /user/123/ who sits in the collection /company/456/users/ and also in the global users collection at /user/123/
When I want to add a new user to company 456 I perform a POST to /company/456/users/ to add it to this collection. But what if the user resource depends on more than only the company? Lets say for example that the user resource also tracks address information on the user so it might also depend on the /country/12/ resource. How can I pass the dependency on the country to the REST webservice. Should I just pass a country_id in the payload of the POST request?
What is considered best-practice for the RESTful approach to managing links to other resources?
Ummm... posting to /company/456/users/ does not look right to me...
What about posting to /users, or even better to /user/{newid}?
From there, you can either just create a user, and maybe add links in another moment, or you can specify all the links as url-encoded parameters (or in the payload, but I prefer the former... it just looks cleaner to me, but this is only my personal opinion):
POST /users?company_id=456&county_id=12
or
POST /users?company_id=456
or
POST /users

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.