Which layer should I use to factorize the existence checking of a ressource? - nestjs

I'm trying to factorize the fact that for all routes that are similar to : /ressources/:id/* we should always check the ressource existence.
I'm not sure how to do it the proper NestJS.
Should I use a middleware, a guard or even pipes (it can be seen as a kind of validation) ?
Hope my question is clear enough,
Thanks in advance

I would say that a pipe is a proper spot in this case, as a guard will return a 403 and a middleware runs the query to your database before you've authenticated the request. You can also use DI in the pipe to make the queries to the database easier, and use the pipe only on the body or request param, depending on how you want to handle things.

Related

Is it a good idea to make one graphql response type for all queries and mutations?

What if we make one type that includes all state user can get from the backend. Lets call it AppState.
And there will be only one query getAppState, and all mutations will return AppState as well so that clients can access any field they need, and if you use apolloClient, clients' cache will update automatically.
We can get all state on user login without any problem.
Is it a bad idea?
Following this pattern would exactly contradict the reasoning behind the existence of GraphQL itself.
The idea is for your queries and mutations to exactly fit a pre-defined expected outcome. If you actually implemented such a concept, unless you provide all the data a query or mutation expects, it will throw an error. Subsequently, if you would actually end up trying it, you will quickly realize how cluttered and resource-heavy it actually is. Imagine fetching all your databases with each request because of this schema .... that would be awful.

Should I use a nestjs pipe, guard or I should go for an interceptor?

Well I have a few pipes in the application I'm working on and I'm starting to think they actually should be guards or even interceptors.
One of them is called PincodeStatusValidationPipe and its job as simple as snow. It checks the cache for a certain value if that value is the one expected then it returns what it gets otherwise it throws the FORBIDEN exception.
Another pipe is called UserExistenceValidationPipe it operates on the login method and checks if a user exists in DB and some other things related to that user (e.g. wheter a password expected in the login method is present and if it does then whether it matches that of the retrieved user) otherwise it throws appropriate exceptions.
I know it's more of a design question but I find it quite important and I would appreciate any hints. Thanks in advance.
EDIT:
Well I think UserExistenceValidationPipe is definitely not the best name choice, something like UserValidationPipe fits way better.
If you are throwing a FORBIDEN already, I would suggest migrating the PincodeStatusValidationPipe to be PincodeStatusValidationGuard, as returning false from a guard will throw a FORBIDEN for you. You'll also have full access to the Request object which is pretty nice to have.
For the UserExistenceValidationPipe, a pipe is not the worst thing to have. I consider existence validation to be a part of business logic, and as such should be handled in the service, but that's me. I use pipes for data validation and transformation, meaning I check the shape of the data there and pass it on to the service if the shape looks correct.
As for interceptors, I like to use those for logging, caching, and response mapping, though I've heard of others using interceptors for overall validators instead of using multiple pipes.
As the question is mostly an opinionated one, I'll leave the final decision up to you. In short, guards are great for short circuiting requests with a failure, interceptors are good for logging, caching, and response mapping, and pipes are for data validation and transformation.

Creating Similar Routes with Different Parameters in Nodejs

I did a google search, but I could not find what I really need.
I need to query an API, which have the same route, but with different parameters.
Example:
router.get('/items/:query, function(){})
In this case, I would search for all items
router.get('/items/:id, function(){})
Here, I would look for a specific item
At the core of your issue is that you are trying to specify two different resources at the same location. If you design your API to adhere to restful principles you'll see why that's not a wise choice. Here are two good starting points:
https://en.wikipedia.org/wiki/Representational_state_transfer
http://www.restapitutorial.com/lessons/whatisrest.html
In restful api's the root resource represents the item collection:
/api/items
...and when you specify an id that indicates you want only one item:
/api/items/abc123
If you really still want to accomplish what you asked in your question you'll need to add a url parameter like /items/query?query=true or /items/abc123?detail=true but this will be confusing to 99% of web developers who ever look at your code.
Also I'm not sure if you really meant this, but when you pass a variable named "query" to the server that seems to indicate that you're going to send a SQL query (or similar data definition language) from the client into the server. This is a dangerous practice for several reasons - it's best to leave all of this type of code on your server.
Edit: if you really absolutely positively have to do it this way then maybe have a query parameter that says ?collection=true. This would at least be understood by other developers that might have to maintain the code in future. Also make sure you add comments to explain why you weren't able to implement rest so you're not leaving behind a bad reputation :)
The issue is that without additional pattern matching there isn't a way Express will be able to distinguish between /items/:query and /items/:id, they are the same route pattern, just with different aliases for the parameter.
Depending on how you intend to structure your query you may want to consider having the route /items and then use query string parameters or have a separate /items/search/:query endpoint.

how to implement postprocess filtering of response as middleware in node?

As part of authorization-rules I'd like to centralize logic as to what fields of a json-response are returned to the user.
To me, it makes sense to somehow implement this as some sort of postprocess-filter implemented in node-middleware.
Apart from the question whether it's considered good practice to change the output of a REST-endpoint based on some authorization-rules (I'm not sure, please share if you've got a strong opinion), I'm uncertain how to implement such a post-process filter.
I tried to implement it by listening to response.finish and have the filter kick in, but that's too late. i.e.: the response was already send.
Instead, what would be considered best practice for post-processing responses in Node?
you can perform your data operations at any part of communication chain, so if require to do some post data filter you can do your CRUD operations in a middle ware and then filter it in other step something like
AUTHENTICATION-(next)->AUTHORIZATION-(next)->OPERATIONS-(next)->LIMITS-(next)->RESPONSE
where each step except RESPONSE reffers to a middleware that will alter the request object with the pertinent information to pass to the next middleware

Returning a Status from the Domain

In our domain-driven application, we use a type called ServiceResponse<> to send data between layers of our application - specifically, one is returned by every method in the domain. As of right now, it encapsulates the data (if any) which was returned from the method, or any errors that it may have generated.
My question, then, is this: is it an acceptable practice to add fields to this object that may be useful in other layers of the application? For example, is it good form to add a Status or StatusCode field to it that may be interpreted later by the service layer for use as an HTTP status code (with or without some mapping)?
It sounds like a fine place to me. The idea that every method returns a "response" of some sort smells a bit like trying to decouple too much, but there are some cases where such extreme decoupling is warranted.
In any case, the ServiceResponse could easily have a status, and if it needed one, that is where I would put it.

Resources