Most of the apps today are multi-user, and Wasp has first-class support for it, so let's see how to add it to our Todo app!
Let's define a Todo list (luckily we have an app for that now ;)) to get this done:
- Add Wasp entity
Authpage where users will login/signup (React component + Wasp page declaration + Wasp route declaration).
ext/MainPage.jsso that it requires login/signup.
- Add Prisma relation between
- Modify our queries and actions so that they work only with the tasks belonging to the authenticated user.
- Add logout button.
Adding entity User
First, let's define entity
to propagate the schema change (we added User).
Next, we want to tell Wasp that we want full-stack authentication in our app, and that it should use entity
User for it:
What this means for us is that Wasp now offers us:
createNewUser()on the server (we can use it in actions).
- React hook
context.useras an argument within query/action.
Before we start with React, let's first add one more action:
It will be just a wrapper for
createNewUser() for now, but it does one important thing: it declares that it uses
User entity, so our queries will be correctly updated/invalidated when we sign up new user via
Ok, that was easy!
To recap, so far we have created:
authdeclaration thanks to which Wasp gives us plenty of auth functionality.
signUpaction, via which we can create a new user.
Now, let's consider how are we going to handle the situation when user is not logged in.
What we can do is check in the MainPage.js if user is logged in.
If not, we will instruct them to go to the special
/auth page where they can sign up or log in.
If they succeed, we will send them back to the
While approach like this might be overly-simplistic for the real-world app, it will serve us well for this simple tutorial!
Creating Auth page
First, let's define the
Auth page, where we will use
login actions to authenticate a new user.
Auth page declaration in Wasp:
Auth page React component (lots of code, but most of it is just form):
Updating Main page to check if user is authenticated
Finally, let's modify
MainPage.js so that it sends user to Auth page if they are not logged in:
Ok, time to try out how this works!
Now, we can again run
Try going to
/ in our web app -> it will now ask you to log in, and if you follow the link, you will end up at
Once you log in or sign up, you will be sent back to
/ and you will see the todo list.
Let's now see how things look in the database! Run:
We see there is a user and that its password is already hashed! Wasp took care of this for us.
However, you will notice, if you try logging in with different users and creating tasks, that all users are still sharing tasks. That is because we did not yet update queries and actions to work only on current user's tasks, so let's do that next!
Defining User-Task relation in entities
First, let's define User-Task (one-to-many) relation (check prisma docs on relations):
We modified entities by adding User-Task relation, so let's run
to create a database schema migration and apply it to the database.
Task optional (via
?) because that allows us to keep the existing tasks, which don't have a user assigned, in the database.
This is not recommended because it allows unwanted state in the database (what is the purpose of the task not belonging to anybody?) and normally we would not make these fields optional.
Instead, we would do a data migration to take care of those tasks, even if it means just deleting them all.
However, for this tutorial, for the sake of simplicity, we will stick with this.
Updating operations to forbid access to non-authenticated users
Next, let's update the queries and actions to forbid access to non-authenticated users and to operate only on currently logged in user's tasks:
Due to how Prisma works, we had to convert
updateTask action to be able to specify user id in
Right, that should be it!
and everything should work as expected now! Each user has their own tasks only they can see and edit.
Try playing around with our app, adding a few users and some tasks. Then run:
You will see that each user has its own tasks, just as we specified in our code!
Last, but not the least, let's add logout functionality:
This is it, we have working authentication system and our app is multi-user!