
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
Complete source code available till this point of lesson is available at
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
In this lesson, we explore the implementation of email and password authentication through server actions. With the Mongoose and Edge case resolved, we can now focus on creating server action handlers that manage authentication checks, validation, and error handling effectively.
action.ts
.use server
directive is added to ensure that server actions are server-side only.action
function uses generics to manage different types of parameters based on the specific server action being called.Zod
error instances.00:00:02 To implement our email and password authentication, we're no longer blocked by that Mongoose and Edge network edge case.
00:00:09 So from here on, we'll be using more server actions.
00:00:12 And as we have created a handler for API calls, this one right here for the fetch.
00:00:19 We can create a perfect server action by adding authentication checks, validation filters, and proper error handling.
00:00:27 So let's do the same thing for server actions by creating a new file within the handlers folder and let's call it action.ts.
00:00:36 Each one of our server actions will have some common things, like authorization, validation, database connection, and error handling.
00:00:44 So together, let's create this server action handler that'll make our life easier.
00:00:50 First things first, I'm going to immediately add the use server directive at the top because server actions only get called on the server.
00:00:58 Then I'll create a type called action options.
00:01:03 It's going to get in the generic T type.
00:01:06 And it's going to be equal to a type where we have access to params of a type T.
00:01:13 We have a schema, which is going to be optional of a type Zod schema coming from Zod of a type T.
00:01:21 And we'll also have an optional authorize parameter.
00:01:25 So we can say authorize?
00:01:27 Is equal to a boolean variable.
00:01:29 So is it an authorization action?
00:01:31 I know that we have a lot of Ts right here, but think of it like this.
00:01:34 We're going to pass some generic params into each server action, and then based on those params, and then we want to create a dot schema specifically based
00:01:45 on those params.
00:01:46 That's why this has to remain a generic parameter, because it's going to be different for every server action.
00:01:51 For example, for user validation, this will contain the user data.
00:01:55 For account, it'll create a count.
00:01:57 For creating a question, it'll be question params.
00:02:00 Now, we can create a new async function, action, that's going to accept the t, which is a generic parameter, and it'll accept params,
00:02:11 schema, and authorize, by default equal to false.
00:02:17 And these are going to be of a type, action options, to which we pass the t parameter.
00:02:23 Within here, if we have access to a schema, and we have access to params, that means that we can try doing something with this server action.
00:02:33 So I'll open up a try and catch block.
00:02:36 If there is an error, we can say if error is an instance of zod error coming from zod, then we can return a new validation error,
00:02:49 which we created before, to which we can pass the error.flatten dot field errors as record of string, and then an array of strings.
00:03:02 That's just how errors are formed.
00:03:04 And I think we have done this a couple of times so far.
00:03:06 If the error is not an instance of ZotError, then we're going to return a new basic error where we can say schema validation failed.
00:03:19 And in the try, we can actually try to validate the schema by saying schema.parse and we're going to parse those programs that we pass into the function.
00:03:29 I know this might be a bit confusing so far because we're just creating a generic action function which will recall many,
00:03:36 many times throughout this application.
00:03:38 So trust me, once we actually do end up calling it, it'll all start making sense.
00:03:42 After this if check, if the validation is good, we can try to generate a new session by defining a session like this coming from nextAuth.
00:03:53 Or it might be null, and at the start it will indeed be equal to null.
00:03:58 So here we're just setting the type.
00:04:00 The type of the session is either a nextAuth session or null.
00:04:04 If authorize is true, in that case, we want to set the session to be equal to await auth.
00:04:12 So before we try to make any kind of a server action, we want to try to authorize the user by importing this from add forward slash auth.
00:04:21 Then if we don't have access to a session, we want to return a new error.
00:04:27 But this time it'll be an unauthorized error, which we have created the template for before.
00:04:33 Now we can exit this part and we can try to connect to the database by saying await dbconnect.
00:04:42 And if we do all of that successfully, that means a couple of things.
00:04:46 It means that our schema validation for this specific server action has passed, which means that we have no errors in terms of the params we're passing
00:04:55 into the function.
00:04:56 And this also means that we are successfully authorized.
00:05:01 And it also means that we have successfully connected to the database.
00:05:06 If that is true, we can return an object containing the params and the session.
00:05:12 And then we can proceed doing whatever that server action was supposed to be doing.
00:05:18 So let me repeat that one more time.
00:05:20 What we're doing here is a couple of things.
00:05:22 We're first checking whether the schema and params are provided and validated.
00:05:31 Second, we're checking whether the user is authorized.
00:05:34 And third, we're connecting to a database.
00:05:37 And finally, if all of that is true, we're returning the params and the session.
00:05:42 I'll leave this comment right here in case you need to revisit that.
00:05:47 because I know that this function is a bit abstract, and I hope it makes sense.
00:05:52 But if it doesn't, don't worry at all, because we'll end up calling this hundreds of times throughout this application, so you'll know it by heart very,
00:06:01 very soon.
00:06:02 With that said, let's just run export default action, so we can use it in many places later on.
00:06:10 One of those places will be the email and password signup, which we'll implement in the next lesson.
00:06:16 So for now, I'll just commit implement action handler, and we are ready to move to the next lesson.