One potential hiccup with our application is the fact that literally anyone can do literally anything in our application. This is… a major security hole! This was expected though, as we wanted to make this thing first work. But now’s the time we lock things down!
Appwrite gives us the ability to set granular permissions where we’re able to define exactly who we want to access and what. In our case, we want anyone to see the events, but we don’t want everyone to create events, only people who are logged in (you can customize this). And we don’t want just anyone logged in (or out) to delete events, we only want Admins or specific users to be able to delete any of the events.
Here we’ll work through configuring our granular permission where we’ll start off with locking down adding events including Documents and Files to only logged in users. Once that’s accomplished, we’ll create a new Team for Admins, which will allow us to designate specific users that we want to be able to give additional access to where in this case, we’ll provide the ability for Admins to delete events.
What You’ll Learn
Instructor: [0:00] Authentication is all ready to go, but now let's talk about setting granular permissions. Inside of the app we have the ability to log people in, and even customize their experience if they're considered unauthenticated.
[0:10] We have a few issues here. While guest users don't have that button to add a new event, I can easily go to the events new page where I can submit the form. Even if I could protect the route itself, it still wouldn't be considered best practice because somebody could still potentially hit the endpoint and create those new events.
[0:26] On top of that, if we go to an individual event page, we have this nice delete button to delete an event, but I don't want just any logged-in user to be able to delete an event, I only want admins to do so. We're going to take advantage of granular permissions so that we can lock down feature access and only show things in the UI to people who have access to use and view them.
[0:46] Let's start off on the Add Event page. Like I mentioned before, if we're not logged in, we still have access to submit this form. Once I fill out my event form and click submit, we can see that I had full access to submit this event.
[0:58] Even more troubling, I had this Delete Event button that's fully accessible for somebody to click and use. We can see that it even showed up on the home page and everything. To solve this, let's first head over to the Appwrite dashboard and go to the Databases page.
[1:10] Once we navigate to Events, Events, or wherever your collection is stored, let's head over to the settings tab. If I scroll down, we can see all the permissions that I currently have available for my particular database.
[1:23] Early in the course, we knew what we were doing. We were setting up the ability for literally anybody to create, read, or delete any item. Clearly, we're now at the point that we want to lock this down. We don't want just anybody to be able to do those things. We only want certain people to be able to do those.
[1:37] Let's start to fix this where we do want everybody to be able to read the events, but we don't want anybody to be able to create or delete the events, so let's click Update.
[1:46] With that updated, if I head back to the new event form, update the event details and submit that, we can see in the DevTools console that we get a bunch of 401 errors, meaning our user does not have the ability to submit a new event. In particular, we're a guest, so we don't have that permission.
[2:02] The problem is if I am a logged in user and I go to try to add a new event, if I now try to submit this form, we can see that we get those same 401 errors, which is not a good thing because we want our logged in users to be able to submit an event.
[2:15] Heading back to our database collection settings, we want to update our permissions so that any logged in user can be able to create an event. Let's start off by clicking Add Role, where we can see all the available options for the different types of roles that we can select.
[2:29] In our case, we want all users to be able to do a particular thing. We want these users to not only read documents, we want them to be able to create documents.
[2:38] Now, just to point out, because anybody can actually read the document, we don't technically need to have it for our users, but it's nice to just have it there in case maybe we want to remove any access in the future. Let's hit Update on that, and if I try to submit again, we can see this time it worked perfectly fine. I was able to create that new event as a logged-in user.
[2:57] Now, just to make sure that the unauthenticated person can still not submit an event, let's head back to that form inside of incognito, where I'm going to try to submit that event. We can see that we still get a 401 as we should.
[3:09] At this point, not only can we prevent people from going to the AddNewEvent page, we're locking down our API to not let them be able to submit anything at all. Let's head back to our event page, where we can see that we still have that deleteEvent button.
[3:22] While if we click it, we do get those 401 errors preventing somebody from deleting the document, if we refresh the page, we'll notice that it looks like the event image was successfully deleted. Back inside of app, we only updated these permissions for our database.
[3:37] If we head back over to storage, navigate to our images bucket, and then go to settings, we can scroll down to our permissions where we can see that still anybody can do any of those things. Let's do the same thing that we did for documents, where we only want anybody to be able to read.
[3:50] Let's uncheck the Create and the Delete, where we'll add a new role. We're going to select all users, and we're going to say we want them to not only read, we want them to create, and then we can hit update. Now we'll come back and clean up this reference in a little bit.
[4:03] Let's head over to another event, where now let's try to delete this event. We see we get all the 401s, but if we refresh the page, we can see that we still get that image. Similarly, if we try to do that as a logged-in user, we also get prevented from deleting and our full event is intact.
[4:17] The logical next step is I want to be able to create admins so that I can give them permission to be able to delete the event. So far, if you're like me, I've only logged in using one email address. While I can probably set up this user as an admin, it probably makes sense to have different accounts, so that I can test the flow between a standard logged-in user and an admin.
[4:36] Before we kick things off, I'm going to log in as a different user. Now that I have a separate account, I want to make this firstname.lastname@example.org an admin. The way that we can do this inside of the app right is by using the team's feature. Now, as we'll later see, you can even get more granular than just teams, and have roles on top of teams.
[4:54] For now, we're going to stick with this team's concept, where I'm going to go ahead and create a new team. I'm going to enter a name of admin and then click Create. Now I currently have zero members of this team, so I want to go ahead and add my new user to this team.
[5:06] I'm going to navigate to the members section, where here I want to create a membership. Now here I want to enter in the email address for the person I want to make an admin. Once filled in, we can see that I can optionally add roles. Now roles are going to be a way to have even more granular of permission.
[5:21] Maybe I create a team for Livebeat and maybe as part of Livebeat, there's somebody who has the admin role. Either method will work, it depends on how complex you need for your organization. For our application, we're good with just a team called admins. I'm going to go ahead and create that membership.
[5:37] If we head back to the main off-page, go to users, and go to that admin user, we can go to the memberships tab and we can see that this user is now listed as an admin. Now let's configure our database and our stores, to take advantage of our admin team.
[5:51] First, let's head over to databases, where I'm going to go to my events, events, where I'm going to head into the Settings tab.
[5:57] If I scroll back down to my permissions, I'm going to click addRole once again, where we see we have the option to select teams. Now as we should suspect, our admin team shows up. Let's go ahead and select that admin team, click create, where now we can say that we want our admins to literally be able to do anything inside of the app.
[6:16] Similarly, if we go to storage, images, and under settings, if we go to these permissions, we want to add a new role, select teams, hit our admin, click create, give them permission to do all the things within our application. Now while I'm still logged in as my admin account, I'm going to scroll down to the bottom, go to one of my events.
[6:36] I need to make sure I lock this event down, so I'm going to go ahead and delete it. We can see that we're taken right back to the event home, where we no longer have that event. Now, for this other one, because I have an image reference inside of the database, I probably just want to handle that manually.
[6:49] I can find that event, make sure that I delete that document, but now we can confirm as a guest, I cannot delete this event, nor can I submit an event. As a standard logged-in user, I also can't delete this event, but I can submit a new event, and have it show up within the application. As an admin, I can do all those things and even delete the event.
[7:09] Now we have one problem though, why even show this button to begin with, if we can't use it? The next lesson, we'll learn how to get all the teams that a user is a part of so that we can make sure that we only show that button if they're an admin.