SvelteKit & PocketBase #5 - Input Validation (using Zod)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everyone my name is Hunter and welcome to the fifth episode of the spell kit and pocket base Series in this video we're finally going to be able to validate user inputs within our application and we'll accomplish this using Zod now I did already make a video covering form validation in spell k using Zod so please if Zod is a foreign word to you I would highly recommend going and watching that video first I'll leave a card in the top right as well as a link in the video description now before we actually get started with validating our forms there is something that I want to cover because the maintainer of pocket base is actually opened a pull request on my live stream project here uh mentioning the fact that we need to call auth refresh to ensure that the loaded cookie is valid so someone actually within our Discord brought up the concern of being able to manipulate the user ID inside of the cookie and then take action as that user right because instead of our code as it stands right now if we look at our hooks.server we can see that we have if event.locals.pb.osaur is valid right and all this is checking is to make sure that token isn't expired but it's not actually verifying that that user is associated with that token and therefore it shouldn't really be trusted right well if you have proper API roles set up in pocketbase like we do thus far then this really isn't too much of a concern right it's not a big security vulnerability but as soon as you add some type of external and I believe the maintainer mentions this here so this is not an issue if you're sending requests only to the pocket-based server but it's a good idea to validate the loaded off store State server sites you can safely trust these valid checks so if you want to show some private node slash third-party generated content based on that user being authenticated then you should certainly update this so we're going to update this because I don't see any issues with doing so and if we look here at the commits that he made Let's just check here but you see he's just adding a try and then setting if event.locos.pb.au store is valid if it is true then they want to run this auth refresh method here on the user's collection which will refresh that user ensuring that everything is good to go and then it will and then if not so if it throws an error here then we'll catch the error and then we'll clear the off store which is the same thing as logging that user out right so let's go ahead and take care of that so if we go into our hooks here at hooks.server.js all we're going to do is we're going to take in the cookies as we did before and we're going to set up a try and then we'll say if event dot locals.pv.store.isvalid which we actually have underneath I could have just copied this then what we want to do is we want to await event.locals.pb.collection users and then run the auth refresh method here and then so if this is good to go if it doesn't throw we want to set event.locals.user equal to the serialized non-pojos that we have down here so then we'll also catch here so we'll say catch and this underscore is basically saying that hey we're not going to do anything with the error if we catch it we just want to take action click log the user out I don't really care what the error is log them out so we'll say event.locals.pb.ausdore.clear and then we'll also set up van.locals.user equal to undefined and then what we can do is we can just remove all of this here and then I believe we should be good to go on that aspect so we can go ahead and test this out and make sure my application is running and it is and then we can go to our site here and I'll log in with one of my users okay so we are in fact logged in everything appears to be working as expected cool so let's go ahead and start off with our input slash form validation so one thing that we're definitely going to need first is to install Zod so we'll do npm install Dash D we can do Zod all right so once we have that installed now what we want to do is we actually want to Define some schemos and again if you don't know what a schema is go watch my other video on this I kind of walk you through the basics of this so you have a solid foundation otherwise this video will be two hours long so we're going to Define all of our schemas inside of lib and we're going to create a new file called schemas.js now you could do this in any of the files inside of the page.servers it doesn't really matter I just like to have them here it makes me feel good so the first thing that we're going to be validating is actually our login user schema right so the login user if we recall when we log out here we go to login with the user we just take in an email and a password right we want to make sure this is actually an email okay and the password we don't have to check for any specific requirements other than maybe the fact that it's actually a string but the email should be an email and we already have HTML form validation here but just to kind of show you that this could easily be manipulated if we go here and we change the type to text now I'm able to submit you know that here right so we want to be able to validate this regardless of what the HTML is doing okay so let's go ahead and Define a schema so the first thing I'm going to do is I'm going to import Z from Zod and then I'm going to export cons log in user schema right and this is what we're going to Define what we want the login data to look like the data that comes from that form to our server what are we expect it to look like right we're defining that structure here so it's going to be it's going to have an email right which is going to be a z dot string it's going to have a required error so if it's not passed at all we're going to say email is required and then we're going to set dot email and this message is going to be email must be a valid email so required error will show if the property is missing altogether and then email will show this message here will show if they type in a string like we just did instead of an actually properly formatted email okay and then we're going to set up a password which is going to be a z dot string it's just going to have a required error we're just going to say password is required okay so now what we're going to do is we're going to define a utility function that's going to take in some form data and the schema that we want to validate that form data against and it's going to return us back the form data values or object I guess you could say as well as the errors array so all the errors that are generated as well as the data itself and this will make sense here in just a second as to why we're doing this but we're going to come into our utils.js and we're going to export cons validate data it's going to be asynchronous it's going to take in form data which is going to be a form data object and then a schema which is going to be one of those schemas that we just defined we're going to set body equal to object Dot from entries and we're going to take form data here so it's going to turn the form data object into an actual JavaScript object and then what we're going to do is we're going to open up a try catch block because schema.parse or parsing within Zod will throw an error right so we can say const data equals schema.parse body so again just to cover what we're doing here we're taking in form data so raw form data from the form we're also taking in a schema right like we just created right here and then we're doing is we're going to be able to validate the data that was passed in against the schema okay and then if this is successful we want to return form data like this is data errors is null so null is intentionally blank undefined would be unintentionally blank right we are intentionally setting errors to blank here okay and then we want to catch the errors if it throws we're going to console log the error first just so we have an idea as to what it is in the console here and then we're going to set errors so const errors equals error.flatten and what this flattened method does and let me just pull up the Zod documentation here so you can see I believe I may have covered this in my other video but let me go to errors real quick so if we go to the error handling section here of the Zod we can see flattening errors and what flattening the errors will do will just make it a little bit of an easier way to receive the errors back into our front end and then properly match up the errors with the respective input field so we can see here that it's going to give us an object with field errors and then it will have a field errors object with all the properties that we passed into it right so we're passing in in this case in this logging case we're passing in an email and a password so if there was errors on both of these we would have email here password here with all the errors that it that it found right so that's where we're getting this from and then we're going to do is we're going to say return so if there's an error we want to return form data we want to return the body back right because data only exists if this was successful parse right so if it was able to successfully parse this then we have access to the parse data if not even return back what the User submitted so they can make their Corrections and try again without clearing out that form right and then we also want to just return errors as errors right okay so now what we need to do is we actually want to go into our page.server.js for our login page here and we're going to change the way that we're doing things right because if we look at our utils we're returning form data and errors right no matter what what we can do is instead of saying kant's body equals object documentaries here what we can do is we can say const form data errors equals await validate data which we need to import from lib slash utils we're going to pass in await request.form data and we're also going to pass in the login user schema which we need to import from Libs schemas okay so remember errors is only going is going to be no if there are no errors right so what we can do is we can immediately check to see if there's errors so if errors is true we're going to return invalid which comes from spell kit with a 400 we're going to say the data is the form data and the errors are going to be the errors dot field errors and remember this field errors comes from here right so right now this is the errors object we're getting the field errors out and we're returning those back to the client in the form of the form dot errors right and we'll look at that here in just a second okay so now we have to update our try catch block here we're actually authenticating the user so instead of being body dot email and body.password it's actually going to be formdata.email and form data.password so remember if it's invalid if there's a validation issue it's going to return before it ever hits here right so that should take care of that for us here now what we can do is let's actually go into our login page here and I can see that I'm not using these input components that we created in one of the previous episodes so let's go ahead and start to use that here so let's go into the top here and we'll import input from lib slash components and then I'm just going to take this div here I'm going to turn it into an input it's going to have a type of email an ID of email a label of email and a value of form dot data dot email and then we already are taking in form here at the top as you can see right so otherwise we'll just do nothing and I believe this is going to be the same thing but just to be safe here let's just add this we may actually want to adjust this later on okay so let's just check out our login form to make sure we didn't break something as you can see it got wider because we decided to make our components a bit bigger later on and there's another good reason why you want to make components so everything stays consistent across your application for this one we'll do type is going to be password right and this is going to be have an ID of password and a label of password and then we'll also adjust the value except this value is always going to be empty so we'll just leave that alone right because you don't want to return the password back to the client if they mess up the email they're going to retype the password in okay so now we also adjust some of these Max widths so we'll make all of these large where it's medium and then now our form looks pretty good here right so now if we attempt to submit something that is not an email obviously right now there's no errors being rendered anywhere right so let's go into our input and actually set up the ability to render out some errors so be able to pass in an errors array right an array of errors and then render out error messages for each one of those errors for any given input across our application so the first thing we'll do is we'll come up here and say export let errors and then underneath of the input itself we're going to say if errors foreign so if errors and then we'll say each errors as error and we'll set up a label so we'll say label is going to be 4 is going to be equal to the ID just as the label above is we'll have a class of label and then within the label we'll have a span tag which is going to have a class of label text Alt and text error and then we'll just pass the error here okay so for each error that's in that errors array that we're getting back from remember this is going to be an array of Errors so if there's only one it's only going to render one error out right for every single one of those errors that we get back if there is any errors at all we're going to render out an error label underneath of the input that's just going to have the contents of that error message in it it's going to be red it's going to look good so let's go ahead and give this a shot so we actually need to go back to our login page here and we need to pass in errors right so errors is going to be equal to form dot errors dot email same thing here we'll say errors equals form errors password and remember the form.airs.password is coming from if we go to our utils I'm sorry we go to our page.server.js here actually and we look here we're returning data and errors right so there's errors is being passed through that form which is here and then we're able to access the errors on that so we're saying hey if there's form errors.email I want to pass them here and then the input itself will take care of rendering those out okay so let's go ahead and give this a shot and we'll just be sneaky here and we'll adjust this input again so we'll make it not an email we'll actually change it to a type of text that way it lets me submit it and I will try to submit something here so I'll just type in a bunch of letters for the password I'll just type something random in if I hit log in you can see that the email must be a valid email so we are in fact getting validation working there obviously the password validation is not going to happen because of the fact that we're not really validating anything other than the fact that it's a string we'll take care of password validation on the register registration form which is what we are going to do next okay so let's take a look at the register form and see what we're working with here so we have a name email password and a password confirm so we obviously want to set some minimum requirements or minimum complexity levels for our passwords we also want to make sure that these two match we want to make sure that this is a proper string and if you recall we also want to make sure that the name doesn't have any special characters in it doesn't have any numbers necessarily so it should just be a strings and spaces right that's all it should have so let's go ahead and set up our schema for this so if we come into vs code here we can close out of login for now and we will go into our schemas file and we'll Define a register user schema and the first property is going to have is going to be a name it's going to be a z dot string it's going to have a required error and it's just going to say name is required it's also going to have dot regex right and this is a regular expression that we're using to check to make sure that the name can only contain letters and spaces and then the message for this is we'll pretty much tell them that right so name can only contain letters and spaces and again this is the message that gets rendered to the client or in the error message on our form if they violate this constraint we'll set a minimum length of two a maximum length of 64. and these values here are lining up with our database right so minimum two is what we set for the minimum and then maximum is 64. so this is lining up with pocket base to make sure that we're you know checking to make sure that we're not submitting anything it's just going to get rejected by pocket base when it gets there and then we'll trim off any white space at the end of a name now for the email we'll say Z dot string right we'll have a required error for this of course it's going to say email is required and it's going to be email then that should be good for that now we're getting the password now we're going to have a regular expression I'm actually going to copy over here but what this is going to do and you can look these up there's tons of them out there you could use depending on what you want for your application I just found a happy medium for our app here so it sets the password to a minimum of a characters at least one letter one number and one special character there's much more complex ones out there that you can use I just chose this one as it's a little bit complex but nothing too crazy so it's going to be a string it's obviously going to be required right it's gonna have a regex and I'm just going to copy this in here so you can see this is it that's why I didn't want to type it in and then we'll have a message here and we'll pretty much say exactly that right and then we're going to set up a password to confirm it's going to be essentially the exact same thing so we can just copy this here cheat a little bit confirm password is required and then we can just leave the message here like this and we'll change this to password confirm okay now there's one last thing that we need to do this we actually need to run a super refinement which essentially Zod gives us the ability to if I go back here to their website here and I look for super refined so if we look at refine by itself first we can see that we can provide custom validation logic via refinements and essentially what says to find our own custom issues and do things that Za doesn't come with out of the box right and that's what we're going to do to check to make sure these two passwords match up so we can set up dot super refined here and it's going to take in password confirm and password right and these are going to be the values from our Zod schema and then it's also going to take in the context right the current Zod context and what we're going to do is we're going to check if password confirm is not equal to password then we're going to do is we're going to say CTX or context.at issue so we're adding an issue here our own custom issue it's going to have a code of Z dot Zod issue code dot custom the message is going to say password and confirm password must match and the path is going to be what field is this error for in this case it's going to be for the password we're going to copy this one more time and we're going to set this to the password confirm right so it's going to pop up for both of these fields and that's all there is to it okay so you can do whatever you'd like here we'll get into more Super refinements in a bit when it comes to the images and whatnot so you're going to see how that works in that sense as well so it should be good to go here if we click save and then we need to come into our register page.server.js here and we to make some adjustments okay so if you noticed we actually didn't um add username to our schema right and that's because before we even generated schema and put our application through that extra efforts or through those extra efforts we want to make sure that the data is valid right so let's just take care of this first the username will be generated by our own function here so we know that it should be valid right no matter what if not we need to fix our function so let's just go here and do const form data and errors equals await validate data we'll pass in await request.form data as well as the schema which is going to be the register user schema here let me just fix these Imports up okay so we're in the same exact check we'll say if errors we're going to return invalid with a 400 we'll say data is form data and errors is errors dot field errors same exact thing you're going to start to see a pattern here I and this validate data function really makes our lives so much easier by taking care of a lot of the logic the try catch blocks and then also making it easy for us to check see if there's an error okay so then on our username piece here we're going to change this to formdata.name right and then here we're going to say dot form data and then here as well form data okay so now we should be able to go to our register page here and we're not using those inputs here either so let's just go ahead and create one starting with this one here we'll say input we'll have to import that in from lib slash components make sure this is wrapped in Brackets and we just have to do input Libs components here because we're taking care of those exports over there and then we'll have an ID or the type I guess for this one will be email the ID is going to be email the value is going to be equal to I guess we'll do label first label will be equal to email and then value will be equal to form data email and then we actually need to take in form here so export let form and then we can just copy this a few more times for the name password and confirm password so let's just go ahead and take all of these out here down to this piece and then I'll rename this one to name so it's going to be a type of text so I can just leave it blank ID will be name label will be named and then this will be name as well here this can remain an email for these two the types are going to be password ID is me password and then password confirm okay so we also need to pass in errors right so errors is going to be equal to form dot errors dot name for this one and then it'll be the same thing for the rest of these with their respective names okay so we have these good to go now I believe that should be all that we need at the moment to make this work so let's go ahead and test this out actually let's make our button Max with large here there we go everything looks a bit cleaner now so let's go ahead and test this out so if I just type in a single character for the name we should get a bunch of Errors back right it's going to tell me that the name must be at least two characters the email must be about email and then it also has the passwords regex expression matching here as well so let's actually type in some valid information so say Hunter and then I'll say this is one of my testimos I have set up by the way and then let's just type in a password that is does not meet the requirements when I hit register you can see the errors for these two Fields went away the values actually remained and we actually need to make sure that these values do not come back here the password so we actually go into our password Fields our inputs and we need to take value away from there okay so now if I try that again that's what should happen it should take the passwords away and then if we type in a password that does meet the requirements but doesn't match we should get password and confirm password must match okay so now let's actually make sure that these meet the requirements and they do in fact match and then we'll click register and then if we go into our pocket-based server here that's running on Port 8090 we're now going to see that a new user was created with my new email here and you can see that everything was good to go it's waiting on me to confirm my email which is fine but we're just focused on the form validation piece so that seemed to have worked all right so I think the next thing that we're going to do is we're going to update our added projects let me just log in with a valid user real quick then go to add a project we can see that okay now it's going to get a bit trickier right because we now have an image to work with so let's figure out how we can actually take care of this with Zod and form actions right so if we go into our schemas here we're going to define a new schema and it's going to be called create project schema again it's going to have a lot of the same properties it's going to have a name a tagline a URL and a description so let me just knock these out really quick foreign URL and description and now we want to validate our thumbnail right so how we can do that is we can set up a thumbnail property here it's going to be a z dot instance of in this case it's going to be a blob right because when it comes back to the server it's going to be a blob we're also going to have optional here meaning that it doesn't have to be passed and then we'll say dot super refine and actually let me save this so it formats properly I guess it won't just yet we're going to take in a value and context here same as did before except previously we just destructured the value so values here context here up here we actually just destructured that first argument and took out password and password confirm but in this case since we're just super refining this single field here we can just do it like so okay so then we can say if value then we want to say if about dot size right so right now we're going to check to see is this image bigger than our maximum that we set in Pocket base so if we come into pocket base and we go to projects settings thumbnail we can see the max file size in bytes is right here so we can just copy that if the size is greater than this which is five megabytes we're going to do contacts.att issue the code is going to be a z dot zot issue code dot custom and the message is going to be thumbnail must be less than five megabytes now we can also check to see if and we actually need to Define some image types right now we're going to check to make sure that this is the proper file type right because again we can set the accept option on our file input however it can be manipulated so we want to make sure that we're checking to make sure that the proper image types are here before we try to send them over to our servers we can just Define const image types here there may be a better way to do this this is just the way that I found to be the simplest okay so now we have this image types array right which is pretty much an array of all the types that we want to accept from this blob we can say if not image types dot includes brow DOT type right so the type of this blob when you go to thumbnail.type it should so image slash PNG image slash jpeg whatever if that if this array here does not include this right so this is basically not inside of this array then we want to add an issue so context.add issue should be familiar by now and we'll say unsupported file type and we'll add these supported formats here for the users okay and then also what we need to do is we actually need to pass in the user along with the create project schema here right so we can do is we can actually add user it's going to be Z dot string we could put a comma here and required error we'll just say user is required okay so now let's go into our register page.server here well I'm sorry not register uh the projects new page.server here and we can see that we're doing some checks here so we're checking to see if the thumbnail is zero if so we're going to delete the thumbnails that we're not accidentally overriding the thumbnail that we currently have if the user decides not to change it right so we'll do is we'll just do some something similar here so we're going to say Khan's body equals await request.form data right and then we're going to rename this thumbnail to we can just say thumb because we're going to have thumbnail in other locations have this function in a second here so we'll say if the thumbnailout size is zero then we want to delete that from body so body.delete and then we're going to say body dot append user is locals.user.id so now we can do is we can say cons form data and errors equals await validate data body and then we'll pass in the create project schema and we actually also need to import validate data from lib slash utils and then what we need to do is we actually need to strip thumbnail out of form data first before we check to see if there's any errors and I'll kind of explain this in just a second so if you type thumbnail here and then we dot rest equals form data we're just taking thumbnail out and then everything else is to is assigned to this rest variable here and then what we can do is say if errors say return invalid just as we have done in the past and data in this case is going to be rest errors will be errors dot field errors and the reason we're doing this right is because we can't return the thumbnail back it's not serializable right so we can't return that thumbnail back to the client in the form of data like this so we actually want to take it out return just rest so just the other properties right just name the tagline description but we also what we do want to include all the errors we do want to make use of that thumbnails error if there is one and we'll show you how to handle that here in just a second okay so right now we have an object that has all the properties that we need to create a project in pocketbase however pocketbase is going to be expecting that image to come across as multi-part form data right so we actually need to do is we need to install a little helper lib here and again there may be a better way to do this if there is feel free to leave a comment down below and I'll make sure to pin it if it will help the users um make this a bit simpler but we're just going to install object to form data and then we're going to do is at the top we're going to import serialize from object to form data and then we'll do is we'll come down here into our try block and then instead of just passing form data we'll pass in serialize form data just like that okay so now let's check this out so let's go into our application here and let me choose a file so I have a bunch of files here and you can see that I have a few that are over the thresholder I have one that's over the threshold so we have this engineering one here but first we actually need to update our page so let's go back here and do that first thankfully we're already using inputs this is a text area which we can just create essentially the same thing for so let's just take uh the text area on that page and we'll copy all of this here and we'll create a new component and we'll say text area dot svelte and then we'll take in a lot of the same properties that are here and then we'll just pass all of these to this like so so we have text area and I'm pretty much just copying a lot of the same things that we have in the input you could probably actually just use this component or use a soil component for this but again I'm just trying to um be as brief as I can in this coverage so we actually need to get this class here pass that in and then we have label which will go here and then four we'll take in the ID and then we'll also have the same errors down here okay so that should be good to go now so we should go to replace that text area here with a text area we have to obviously export it properly first so let's go here we'll import it and we'll be able to import that here just like so the ID will be description the label will be description and then this is the create project so the values for all of these will be equal to form dot data dot description we need to take inform at the top and then we'll do the same thing for all of these as well updating the names for each one and then for the file input though we can just easily do something here we can say if type is equal to file then we'll say something else otherwise we'll use this let me close this off here so we'll just take in the file input styling here okay so we're going to have the file input styling if it's equal to file if not we're going to have the regular input styling so we should be able to do the same thing here now with just inputs make sure we set the type to file and the value is actually just going to be empty but we will start to have errors so we'll say form dot errors dot thumbnail here and we'll copy this errors up to the rest of these like so then we actually need to close this input here okay there we go so let's check this out so everything looks the same to me so far we should be good to go so let's just give it a name so you can say pocket base and then we choose a file let's just choose one that's too big right let's just choose this engineering one here so now if we click on create project we're going to get an error so let's see what happens here cannot access form data before initialization so let's just check to see why that happened that's because if we see here we're doing form data.get instead of body.gets that's my bad so make sure we change this to body here like so and now let's try this again okay and then I'm gonna upload an image that's too big I'm going to click on create project we're going to see that same error message on all these fields or input fields and that's because we copied over the errors we forgot to change these you probably already caught that and changed them but if not be sure to change these to the respective names okay so now we're just getting the error messages on the thumbnail so the thumbnail must be less than five megabytes okay so the validation is occurring for the thumbnail and then if we do select one that is proper let me just make this a better description and then click on create project you will see now that we have a new project created the data was validated and we are good to go and again you can obviously go through and test all of these so I just try to change the name right now I'm obviously editing it so I don't have validation set up for editing it yet so let's go ahead and set that up now so Zod has something that's really cool so really the only thing that we don't need when editing this that we do need whenever we are creating this is the user okay so if we go to Zod here let me look at pick dot pick or dot omit I apologize we could see that all Zod schema objects have a pick and omit methods that return a modified version consider this recipe schema they Define a recipe here to keep only certain Keys use pick so we can just take out the name right or we can use omit to just take one of these out right take out one of these properties so that's what we're going to do for the update project schema now I have had issues with pick I'm not really too sure why but I have had issues with pick um and you'll see I don't actually use it in a place that I could here in the upcoming minutes um but I I run into issue with this sometimes so again if it happens to you it happens to me as well so let's go into schemas and we'll come down here we'll say export cons update project schema let me close out of that terminal over there we'll say create project schema dot omit and we'll say user is true so we basically are saying omit the user we want to keep everything else but the user right okay so now that we're omitting the user we have everything in create project schema except for the user right so now we should go to go into our let's close the others let's go into our projects edit page dot server and then we'll come down here to actions for update project we'll do the same thing so we'll change this to body here and here as well I will change this to thumb and then we'll come down here we'll say cons form data and errors just like we've done in the past equals await validate data body and the update project schema which comes from lib schemas and we can say here we can say validate data like so and that should be good to go there and then we also want to do the same thing with the thumbnail right so we're going to say cons thumbnail rest equals form data and that's again because you don't want to return that back with any errors to the client side right it's been returned invalid it'll actually throw an error if you try to so we haven't valid imported so we can say 400 and then we're going to have an object with data as rest and errors as errors dot field errors okay and then we also need to serialize this form data here so let's do serialize which comes from objective object to form data so we can say import serialize from object to form data at the top like so that way it'll serialize our image back up into multi-part form data so that pocket base will properly receive it and then I believe we should be go should be good to go here so let's just check out the page that's felt here for this and we want to make sure that we set the value now so instead of data.project.name as the first value we actually want this to be the second value so we want this the first value for all of these to be the form right so it takes priority so I'm just going to move all of these over and we actually want to update this text area altogether so for this one instead of saying data.project.name I'm going to say form Dot data.name and form dot data dot tagline and it also export that form here at the top make sure we get rid of those errors and then I can just take in make this a text area so we'll say text area it's going to have an ID of description a label of description or project description the value is going to be form data description or else it's going to be data.project.description and then it's also expecting something else for me let me see what that is heirs I believe so we'll say errors equals form errors dot description and then I need to import text area here at the top and then I need to make sure I have the proper errors on all of these as well and actually update the names this time to name and then tagline URL and then description and then for this thumbnail what we can do is we can leave this alone here we actually just leave this alone because of the fact that we are doing some extra things here with this it's not going to properly fit with our component so we'll do is we will come down here though and we'll probably just add the error labels so we can just say take this here then come down to underneath the input and then instead of checking for if errors we can say if form dot errors dot thumbnail and then we can say each form errors thumbnail as error and then this will be 4 is going to be data dot project dot thumbnail or I'm sorry data.project.id or the 4 is actually going to be thumbnail so we'll say 4 is equal to thumbnail then I think that should be good there so now we edit pocketbase if I try to not have a name here we'll see name is required okay so we know these are working right now what if I decide to delete this image here we now know no longer have an image it did retain this though right so we need to fix that because right now if I delete that thumbnail so let's just upload it again now all of my rest of my application is just messed up now so back end in one file and really I could probably just refresh this page here to get everything back but still we shouldn't have to deal with that right so let's upload pocket base back here go to edit let me click on delete we can see that the entire form gets reset right so let's see how we can actually fix that so if we come into our page that's felt here and we're going to Define loading is true I'm sorry loading is false we're going to actually set up a using hands Handler function so we'll do con submit update project we'll set loading to true as the function kicks off we'll take in results and update and then we'll say switch result.type we're checking the result types case of success we want to do what we want to await invalidate all if it was successful which we actually need to import from app slash navigation and then we'll break case of error we'll do is we'll just break and then for the defaults we'll await update and this comes from here right what this is going to do is going to update the form data with the data from the form and then what we'll set is loading equals false okay and then now we need to come down here to use the hands we need to say submit update project like so and then if we test this out we should be able to add an image here go back to edit project we can now click on this delete button here it deletes the pro it deletes the thumbnail we can then edit the tagline for example save changes now we're getting that automatic generated image that we had set up and then we can also upload something that is too big we can see that the error is not quite rendering out there so and it's because if we look here I misspelled thumbnail again thumbnail I continue to do that so now we have this here we should actually see that thumbnail must be less than five megabytes so it's up with the proper one again and you can see that we are good to go here on editing our projects so we have a couple more inputs still to validate so if we go to settings now we can see that we have name here obviously the updating of the profile we have the account for changing the email and the username and then we obviously have the password as well so let's go ahead and start with the updating of the accounts email and username so let me close out of all of this here except for schemas we'll come down here and we'll say export cons update email schema it's a z dot object and it has an email and then that's it for that one we can also go ahead and Define the username schema while we're here too and kind of take the take care of both those at the same time so we can say export cons update username schema and what we want to do is for username we actually want to run a regular expression again to make sure that they're not passing anything crazy we're just going to allow alphanumeric characters for our usernames we'll set the minimum to 3 and the maximum to 24. okay and then we have a message here that will essentially just tell them what this is pretty much already doing username can only contain alpha numeric you can say letters or numbers to make it more user friendly here okay so now we have a username schema and the email schema so let's go ahead and update those files and these are both in the my uh settings and then account settings here so I chose to do them together so we have the update email now so we already know the drill here we'll just say cons form data and then errors and then we'll import the schema we'll go ahead and update or grab the update username schema as well let me import validate data from our compo from our utils so again check to see if there's errors and then return invalid if not and then we need to update the request email change to form data.email instead of data.email everything else should be good to go here and then we can go move on to the username now again it's going to be the exact same thing pretty much just replacing a couple of the email Fields with username so we'll say form data and errors and then down here we're going to do get first list item username equals form data.username this is where we check to see if the user exists and then we also have to update this down here as well we'll say form data.username down here and then the rest of this can remain as is we should be good go there and then we already have some things set up over here so what we want to do is inside of our inputs we'll just say errors formed errors email and the value will remain at form data email here we'll copy this down for username as well we'll change this to username and then I think we should be good here as well so let's check this out so let's go to change email first uh we can also change the username here so we can enter the new username we can make this Iris one and that updates okay so now we have the username and the email setup we should go to now go and set up the password the same way essentially that we set up the passwords before so we're gonna do some copying pasting over here so let's go ahead and dive into that one let's go into our schemas and we'll just have an export const update so we'll say update password schema we'll come up here to our register schema we'll take password and confirm password as well as this super refinement here and then we actually have old password as well so I think it's is it password and just check the page really quick so password password confirm we also have old password so we can just make this a string that's going to be required that way that'll get caught if they don't type anything in there but then we're also going to still run our same regular Expressions here to make sure the password still meets those requirements and that those two passwords do in fact match before sending this to the server okay so we can go into that page.server here under security and then again we'll do the same thing we've been doing for a while now so we'll take informed data and errors and then here we're just going to return um errors is going to be errors.field errors and we're actually not going to return anything for the data because of the fact that we don't want to return those passwords back to the user we want them to retype them all in so we're just going to return errors here and then down here instead of doing data we'll do form data and that should be good to go here so let's test this out um what happened data is not defined let me import that I apologize okay so it appeared to work so let's do a login really quick awesome now if I try to change it to something that isn't as secure so let's do okay so it is not actually rendering the errors because we need to update that on the page again I apologize for that I'm getting a little bit ahead of myself here so we can say errors equals form dot errors dot old password we need to actually import or accept that prop export that form and then we'll do the same thing for these two here already and then now we can already see that the messages are actually rendering because they were there we just weren't actually displaying them so we can see that the password must be minimum a characters and contain at least one letter one number and one special character so try this one more time this one is going to be one that doesn't match so password and password confirm must match and now it logs me out and once you log back in with my new password and we are good to go awesome okay so for updating the profile I believe that's our last form to validate here not really too sure how long this video has gotten to at this point I wanted to be able to get to doing toasts and stuff but that might have to make it to the next video just because of the length of this but I think this is going to be good information for you all when building applications moving forward so let's move into our schemas here and first let's look at our profiles we have my profile so all we're doing here is just the name and the Avatar right and then Avatar what do we have set for the Avatar let's look at our users settings Avatar we have five Meg here as well we actually aren't accepting image slash webp so let me just do that here I'm not sure if we're doing that on the other one as well but let me just check we are okay cool so now for Avatar let's create a schema again we're essentially going to use the same thing as this here and then we'll say export cons update profile schema and the name actually I wonder if we could just do oh yeah I forgot so dot pick for some reason has an issue with me most of the time so I'm just going to copy name here so name must be these right and then we also want the thumbnail which will actually be an avatar so we'll say I don't really know why I made this narrow function so please forgive me it's me Z dot object and then we'll wrap that here then we'll uh paste in thumbnail which we're going to rename to Avatar so I think that should be good to go we'll rename this we'll say Avatar must be less than five Meg and that should be good to go as far as this schema goes so now we can go into the page.server and again do the same thing so we'll just make this we'll do this step first and then if we don't have an avatar uh it's optional right so we'll just say form data and errors and we're passing body here because this is the same thing right it's already we already accessed the form data so now we're just going to pass body here instead of doing it again and then we also need to import validate data and then we need to actually serialize that data so we're also going to import serialize from object to form data here and then we'll check to see if there's errors so data is actually going to be data or the formula without the Avatar so we'll say const Avatar and really we just have name but I'll just do rest here in case you just had to add any additional fields to your profiles and then errors will be errors dot field errors and then we'll come down here and we will say serialize this data here and this data is actually going to be form data and then everything else should be good to go from what I can see all right so let's go to edit my profile here under settings profile if I update this profile picture to something that's too big I actually need to update the page real quick so let's make sure we do that uh so we have the input for the file here which let's just add a label so let's grab one of the labels that we took from the project edit page right and we'll just do this here right because we have a custom input there so go back into our profile settings and then underneath of the inputs we'll say if form.airs.avatar it's gonna be four Avatar and then we need to take in form actually so let's say export live form and then for the first input here which is where is that for the name here it is we'll say form dot user I'm sorry form.data.name otherwise we're going to do data user.name disabled will be loading and then we'll also do errors equals form pairs name okay so if I just delete the name out and press update I should be getting an error here so let's see what's going on my console data is not defined so let's look here at the actual update profile so it's again inside the Avatar I need to change this to body dot delete Avatar and body dot get Avatar so now if I try to submit this cannot destruction property of Avatar of form data as it is undefined and that is because I am not awaiting a validate data method here sorry it's getting pretty late over here so apologize for me being a bit sloppy right now but now we're getting name is required here as an error so if I change this back updates when I update it you can see that it pretty much instantly updates look at pocket base to make sure we can see that that is in fact updating just really quick and then for images if we try to upload an image that's too big we see that Avatar must be less than five Meg we refresh the page the old Avatar is still there and ready for us to use okay so I think there's a couple things more that I want to do here so we're not actually checking on these Pages we don't actually have a load function set up to check to see if the user to throw a redirect to the login page right because only authenticated users should be accessing these Pages anyways um it should probably render out an error message I believe if they would try to access it just because the data is going to try to get when they access that page it's going to eventually throw from pug or from pocketbase but we can add these checks here to be safe I had somebody actually mention that in a comment below I believe I've maybe forgotten a few different uh small things here and there but as far as the projects themselves the project Pages these are meant to be like public pages right so right now this project says not found for some reason I'm not too sure why uh let's see here oh and that's because let's look here at our um my project item here that's the other thing I was going to fix is right here we have a bad link so it should be slash projects slash project ID when I change this now we can see that now we get the actual image we're looking for so I can click on this but these are meant to be public Pages again for this application this could be public content that you're sharing um it could be whatever right you could also make it private by just preventing users from accessing this unless they're the owner so however you want to do this again I'm just trying to cover as much as I can as far as crud goes as far as validating data protecting your routes and things of that nature so I think it's going to include this video hopefully in the next one we can move on to doing some more fun things like adding some toast here and there I'm trying to think about what else we are going to do prior to deployment but deployment is definitely something that's coming up as well so I look forward to those episodes and I will see you all in the next one foreign [Music] [Music]
Info
Channel: Huntabyte
Views: 5,852
Rating: undefined out of 5
Keywords: sveltekit, sveltekit tutorial, sveltekit crash course, sveltekit load functions, sveltekit endpoints, sveltekit routing, sveltekit form actions, sveltekit forms, sveltekit actions, form actions sveltekit, sveltekit API routes, svelte routes, pocketbase sveltekit, sveltekit pocketbase, pocketbase auth, pocketbase users, pocketbase tutorial, pocketbase ssr, pocketbase auth sveltekit, sveltekit zod, sveltekit input validation, sveltekit form validation, zod, zod validation
Id: Ct3TSEJeD8I
Channel Id: undefined
Length: 56min 23sec (3383 seconds)
Published: Mon Nov 28 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.