Namespace design patterns for socket.io API - rest

I'm in the process of developing a websocket API using socket.io, on top of an existing REST API.
There are a couple of main models at the moment - User and Order.
For someone with customer level permissions, they can subscribe to the socket.io namespace /Customers and the room :customer-id and they will only see create/update/delete events for Orders they own.
For someone with admin level permissions, I was thinking they could subscribe to the /Orders namespace and the room :order-id to only see events for a particular order.
However, this has some problems:
Admins cannot see create events, since they have an ID which is not determined until creation
If I open up the /Orders namespace to all events, this could potentially grow in size massively as the app scales (seeing all events from all orders, regardless if they are rendered on screen)
Is there any type of common abstraction/grouping for websocket based APIs to limit the events that an admin will be subscribed to?

Take a look at https://github.com/facundoolano/socketio-auth to check the user authenticated and possibly groups and permissions.

Related

RESTful API Design based on the RBAC model

The problem to face lies in the design of a RESTful API that can manage requests from multiple roles in an RBAC-based solution.
Currently we have different resources that can be accessed from different users, which can have one or more roles grouped according to their privileges.
The API we're trying to define must be as clear as possible to the client but without the overhead of adding additional metadata to the URL that could damage and even conflict with the REST practices and definitions. Therefore, we must avoid at all costs include information about the roles inside the URL. The plan is to use JWT tokens that carry in their payloads the info needed to know which permissions has the user making the request.
Having raised our current situation, let's provide an example and state the problem to solve:
Suppose we have * financiers * and * providers * as users with some roles who both want to access ** attentions ** (our resource). Should we add before the resource ** attentions ** information about the * user * whose trying to access the resource?
The endpoints in that case should be defined (as an example) as:
https://example.com/api/v1/financiers/:id/attentions
https://example.com/api/v1/providers/:id/attentions
This way we're attempting to inform the respective controllers that we want the ** attentions ** for that specific role / user which are, in some way, a sub-resource of them.
On the other hand, we could simply implement a much simpler endpoint as follows:
https://example.com/api/v1/attentions
The logic about which attentions return from the database should be now implemented in an unique method that must handle this two roles (and potentially new ones that could come up in the following features). All the information needed must be obtained from the payload from the token, exposing a much more generic API and freeing the web client from the responsibility of which endpoint call depending on the role.
I want to highlight that the attentions are managed in a Microservices Architecture and, hence, the logic to retrieve them is gathered in a single service. The cost of the API Gateway to route the two (and potentially more) of the endpoints from the first solution is a variable not to discard in our specific situation.
Having exposed our current situation:
Which we'll be the best approach to handle this issue?
Is there another alternative not contemplated that could ease the role management and provide a clean API to expose to the client?
In the second solution, is correct to return only the attentions accessible to that specific user based on the roles that it has? Isn't it counterintuitive to access an endpoint and only get some of the resources from that collection (and not all) based on its role?
I hope that someone could clarify the approach we're taking as there are little and none literature that I've found regarding this issue.
There there are multiple solutions for such kind of filtration, and developer have to select one depending on given situation.
As per my experience I can list following.
Structure
When data can't be accessed directly and developer has to use a relation (i.e a table JOIN). In that case URL have to include both the main and sub entities. Before going with this approach a good check is to ask, if the same URL can be used with POST ?
Example
If we have to fetch list of roles assigned to a specific user or want to assign additional roles then we can use
GET users/:uid/roles
POST users/:uid/roles
Security
With Multi-tenant systems where each user can have his/her private resources, i.e other users are prohibited from accessing those resources. Developer should save tenancy information and to filter the resources according to current authentication, without bothering client or requiring any additional info in URL
Example
Phone album of the user
GET photos
POST photos
Search
If it is not security or structure related but client still want to filter the result set depending on his scenario. then developer should use query-string for the filtration.
Example
Client have to fetch messages from his/her inbox or outbox or want messages which are not yet read. or he/she want to search his/her inbox
GET messages?folder=inbox
GET messages?folder=inbox&status=unread
GET messages?search=nasir

REST API for multiple consumers

For exmaple: We have a REST API which provides data for multiple consumers. The most case is like: Frontend (accessable for everyone), admin/management (for admins only), mobile app.
These ones differs in the response data which the REST API delivers. For example, in the admin request, the API should respond the email of the user. In the frontend not. Or the mobile app, shouldnt receive unnecessary data, which are not displayed in the views.
My idea was to set adapters in front of the REST API, but this won't work, if you don't have multiple domains available (e.g. api.xyz.com, api-manage.xyz.com).
I think this is a common way, which most of the app needs. I don't want to build multiple APIs to cover this case.
Is there any way on the application side, for example with middleware? Or I know there is a role based approach, but I dont think, this is enought abstract, because the role doesnt decide which device it is.
There is a little solution:
Role based decision which fields the user can be retrieve. Additionally the consumer has to put a header, or a queryparam like "frontend", "admin", "mobile", to identify which data will be returned. This is independent of the "which the user is able". It's just for optimization.
Are there any other solutions?
Your API should not know about your clients but it should offer the possibility for the clients to do what they want/need. Let's say you need to display a list of product with details. On the desktop you might bring 100 products but in mobile only 10. So the api need to provide a configurable paging. Also in the desktop you might get more information than on mobile. So here if you have an entity product, in the desktop you will get all the fields( multiple attributes for example) but for the mobile you get only the name and one attribute (for example the price) to minimize the payload size.
So the API need to be generic but give clients possibility to use it based on their needs.

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.

One to many relationship in REST design

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.

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