Nestjs IsUnique custom validation (with database query) for email, username, etc

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys in this video we are going to implement a custom validator that can query the database and check whether a value is unique what is the use case for this kind of validator tech for example this username field according to this schema it's supposed to be unique that means we can't have two users with the same username what we can do is that when a request comes in to create a user we apply the custom validator that we check whether the username already exists that is our own custom validator if the username exists it's going to return a validation message saying hey that username already exists something like that to better understand the problem we are trying to solve let me show you my setup so here I have connected to a database named demo right and if I try to create a user first I'm going to start the This Server and funeral starts Dev that will start my project localhost 5000 so I'm going to open Postman and try to create a user wait for the server to start it is up send the request to create a user and I have an error okay so I need to tell type URL we have to find the entity let me just list it out here I have a user entity I will save and the server will start again send the request one more time you can see the user is created then the problem will arise when I try to get this user again with the same username because according to our database database this is database Let me refresh we have this user structure it says that username is a is a unique column right username is unique so if I try to send a request again the app is going to crash of course because of SQL error duplicates record for username so what we can do is to apply our validator that is going to handle checking that the username exists or not and return error message how are we going to do this we are going to make use of class validator which is quite common in nest.js projects but before our custom validator let's just validate the other fields first here I have these three Fields the ID is auto generated I'm going to leave that one the way it is I don't need this decorators what I want to do is come here and say this should be a string is string okay before we get to this point we need to first of all install the class validator package to install the package I'm over here at nest.js documentation I'll go to validation these are the dependencies I need class validator class Transformer I'll copy this over let me stop the server and install those packages I will pause and wait for the installation to complete now we have the packages installed let me go back here and apply some validation is string yeah username should be a string this should also be a string and this string but these two are optional according to my database my table structure right it is not arbitrary so this is is optional so is this guy as well is optional all right so let's see how this works and then we Implement our own custom validator I'm going to start the server again I will head over to postman and give this a try let me send a request that doesn't contain the username which is the required field by the way I think what we have is first name and last name right I will send the request and what we get is so the problem with the code is that I did not complete the setup for class validator we need to come here let me copy from documentation after installing the package we need to apply something in the main.ts file so I'm going to copy this and head over to this file apply Global pipes validation pipe this is going to make our validators to kick in the default the built-in validation as well as the custom one we're going to implement so the server is up again I will send the request you can see that the built-in validation works so our setup is okay now we'll go ahead and Implement our own custom validation constraint and The Decorator to apply that constraint for this let me have a folder because this can be shared across board called shared and inside here validation for the constraint we're going to create two things the constraints that we handle the actual validation logic and The Decorator which is not really required but just so we can apply our own validation similar to the way we use is string here or is optional Etc so first D is unique constraint dot TS for the constraints what we need to do is just to implement the validator constraint interface from class validator so I will say exports class is unique unique constraint implement validate constraints interface we are going to implement the methods from the interface the first method validate is where we do the logic of our validation at the end we just need to return a Boolean that is true or false true if the validation passes false if otherwise the second method is the message the user is going to see so whatever we return as the message here is what the user will see if the validation fails for the first one let me just hard code a result here I'm just going to add Code false then over here let me return a message like the record already exist then let's apply additional information here I'll say valid data constraint I'm going to give this a name you can give it any name you like so let me just give it the same name as this then the next thing is if you look here the validation can happen asynchronously as well so we can return a promise for that I need to declare here that this is going to be async so I'm going to say true I think because we are going to create the database and that is that is going to return a promise or it is going to be asynchronous operation so let me also put a thing here and no need for this guy because I know this is going to be asynchronous all right so we just have our constraint we are going to implement the actual logic later but now let's just test out the validation constraints record that we are going to implement a custom decorator letter for now I'm going to make use of add validate from class validator and pass in the constraint I will save that right now every request is going to fail because we had coded the return value and wait for the server to restart and send the request one more time you can see that we get that validation message from the custom constraint custom validator before we continue I want to have The Decorator function it is just going to make use of this validation constraint how do we do that we can Implement here or let me just create a different file let's call this is you need dot TS to do this I will just quickly grab an example from here to save us some time The Decorator it is going to look something like like this I'll copy that over paste it here and we change some stuff we handle the import and this says object is giving me error this also from class validator then over here we pass in the the constraints we are using for the validation is unique constraint another thing we can do is to give it a name let's call this is in is unique any name you want to give it and this should be is unique all right so now we have a decorator chord is unique let's go ahead and apply it in a similar way we applied the con the build invalidators over here I'm going to comment out this guy and I'll come here and say is unique if I save and run the code we are going to get the same exact results as we got here so I'm going to send the request one more time you can see we get exactly the same thing the only thing that this is kind of more concise to use all right let's go back to the constraints now and do the maintain which is to create database let us first understand the values we have here things we can work with value here refers to the value for that field where we apply the the constraint to for example over here the value refers to the value for username this this value oh we don't have username here assuming we have username username is John so the value is going to be John then we have um this for passing additional information it is optional so what I want to do is to go to this function here I want to pass my own custom values for example let's say let me Define a type so it is easier exports type is is unique constraints in fields you can name this anything you want to is equal to yeah is equal to we are going to have the table name which is going to be a string and we are going to have the column which is also going to be a string so what I want to do is wherever this decorator is applied the developer is going to specify the table to search and which column right this is up to you what you pass in how you write your own logic because I don't want this to be for only the user's table for example let's say we have another table we want to make use of this kind of easily constraint form we don't have to hard code the user service or user entity so um let's say options to be that guy then down here I want to pass it to the constraint but how can we access this in the constraints the input data let me go over to the is unique constraint I will rename this guy to add so it is shorter we can access it from the ads here let me show you in a moment const this I called is unique input is X dot constraint zero so if I go over to the function here you can see that it is the first item in this array in the constraint that is why over here I'm trying to access it at index 0. then table name and column name I would do I will do a console.log of what is inside there so you see it console.log of as table name column name I'll save that now our decorator complaints we need the table name which is going to be users and the column user name okay that should be just strings um oh man that is correct but I need to say use I need to set table name and I need to say color the color yeah so I will save and the server restarts I will make a request you can see what is inside the ax it has a number of information including the data we passed in the constraint right and you can see that we have access to to the table and column as we defined one thing you've probably noticed is that this this guy here seems redundant for for example this is username and we're also saying this is username so this is kind of optional right but the reason is for example what if what if this guy is like this so we can access the the property being targeted in this case the username it means that we can come to to this constraint here and instead of having this column here it is the same thing as const field to be equal to X dots property I will cancel that login property the field and I will head over to postman and send the request you can see that the field is username which is the same thing as the hard-coded value this is optional so you can customize anyhow you want to do it but the reason I did this is in case the field name is different from the column name in case this is something else you can specify the column name right so let's go ahead and talk about making the request to the database for talking to the database I'm going to let nest.js manage dependency injection for us so I'm going to come over and say Constructor Constructor and private read oh my God what was that read only entity manager entity manager from type o r m right we are making use of type wiring and mySQL database so this is similar way we can in a similar way we can have the dependency injection managed in other providers like by the way we can come here and say this is in check table in a similar way this can be done in in a service class or something like that so with the entity manager our job is easier once again I'm making use of entity manager instead of maybe user service or user repository something like that because this is not only for user user related stuff we can apply to any other field any other entity what I want to do is to use entity manager to Target this table and this color that's why I'm going this approach so down here I'm going to say const result to be equal to our weight this dot entitymanager dot get Repository for this table for that entity and create a query Builder the table name dot where the column name equals the target the value did I just do so this is supposed to this is not correct supposed to be like that and we say get one so we can just check whether the record exists but I'm going to modify that let me come down and do console.log of the results the results now if I try to run this it is not going to work I will explain in a moment I will try to send the request and we get an error this error happened because there are additional configuration we need to do for nextges to to start handling the dependency injection so the error is related to this guy that we are hoping that next years we handle inject it for us but you don't have to worry much about this it is just a one-time thing and it is straightforward to do let's do that configuration and come back to this file the configuration we need to do is to make use of this thing called use container the way I can explain it is that it helps for the dependency injection so we specify a module in this case app module that a nurse yes can take it off from there I don't know but you can you can read the documentation to get all the details right let me go ahead and go to over here the main.ts is where we apply this we get this use container from class validator and we select our module app module I will save that then let me go over to that module the next thing we need to do is to list out our our unique our constraints whatever constraint it is in this case is unique constraint in the list of providers let me go back to the constraint so this is our constraint listed in the list of providers for up in the app module and over here we use this use container select app module fall back on errors true okay let's just test this one more time I will send over the request I still get an error what does that mean I will find out what this error is and get back in a moment okay so this error is the ridiculous one I'm trying to access a table called users but my table name is user so I guess that's the error I will go to the detail here I will change this to user and save that wait for restart send the request so we don't get any error it says the result is no why is the result now let me check if I have a user with that name data okay I don't have a user with the name John but let me create one oh I cannot create one now because I hardcoded the the validation results I will go to the constraint now what I want to do is if there is a result will return false otherwise it will return true why is that so um do I have an error here no because if we find the record that means that value is not unique so we return false the validation fails otherwise we return true right I will go back now and send the request one more time and send your request no issue because the result is not found then let's try to send the request one more time you can see that our validation works right because it finds a user with username John so let me come back here and return this in a simpler way instead of getting the result because I'm not doing anything with this result so I'm just going to say exist to be good getting okay so this is going to be the same result the only difference is that we're not retrieving that data from the database it's going to return false if the record exists otherwise it returns true I'll give this one more try obviously it's going to work the same way you can see that we get result alright guys so from here you can do whatever you want to do once again let me just point out a few key things I'm making use of entity manager because I want to use this for whatever table for example if there's another table here called uh categories whatever categories right I can just change the table here and everything works the same one thing very important is to never use a user supplied value for your column field generally that is a bad practice so this is coming from from a value that I know that I wrote myself here and then the the validation constraint is where the actual logic happens this decorator is not really required as we have seen here because we can apply the same constraint right over here but with this decorator function we can customize things further right we can also customize this as well and it gives us a very simpler syntax to work with because you are making use of dependency injection from nest.js that's why we need this guy and then over here we also need to list out the the constraints in the provider's list alright guys I believe this has covered most of the things you need to know about writing custom validation making requests to database Etc I hope it makes sense until next time enjoy coding [Music]
Info
Channel: ZestMade
Views: 2,326
Rating: undefined out of 5
Keywords: nestjs unique validation, class-validator, nestjs validation, nestjs unique email validation, class-validator unique email, nestjs class-validator, nestjs custom validator
Id: Ey8QOhXKW8s
Channel Id: undefined
Length: 25min 58sec (1558 seconds)
Published: Wed Jul 26 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.