Lesson Description

The "RBAC Permissions" Lesson is part of the full, Permission Systems that Scale course featured in this preview video. Here's what you'd learn in this lesson:

Kyle builds out a role-based permissions map in TypeScript, assigning specific permissions to each user role, then creates a simple "can" function to look up whether a user has a given permission, and refines the project read permission into more granular options to handle department-based access rules.

Preview

Transcript from the "RBAC Permissions" Lesson

[00:00:00]
>> Kyle Cook: Next, we need to essentially create that map, so we can call this map whatever we want. I'm just going to call this permissions by role. Just like that, and since again we're in TypeScript, we can type what we want this to look like, which will give us good errors and warnings in our code, so we're going to be using a record type that's an object in JavaScript, and we specifically want the first value of our record, the key, to be the role, so we can get that from our user type.

[00:00:23]
And we can get the role from here, that essentially is just admin, editor, author, and a viewer, and then we can say that we want the value of this object to be an array of all the permissions we have, which is that enum up here, so it's going to be an array of these different values. Now if we give that a quick close, we can set that to a new object, and immediately we actually get errors because we don't have all the keys being defined.

[00:00:43]
We need to define all the keys which we get nice autocomplete for because we're using TypeScript. So for example, we can come in here with admin, set it to an array of permissions, and then we can do that for all of the rest of these as well, so we have admin. Author Editor, and we have our viewer, and now all we need to do is just put the permissions each one of those user roles has access to directly into them.

[00:01:05]
So we know our admin has permission for everything, so I'm just going to come and copy all of our permissions. Put them directly inside of here, and we'll just put a comma after each one since we're in an array here. There we go. So now our admin has permission to do everything. If you wanted, you could create like a super role or permission that's like manage all or something like that, so you don't need to hard code all these in there, but since we're going to be evolving past the system quite soon, I'm just going to be putting all their permissions directly inside of here.

[00:01:32]
Now we need to do the exact same thing with all the rest of our permissions, so let's go down into our author. We know the author cannot create any projects, they can't update or delete any projects, but they can create documents, they can read documents, they can update documents, and they cannot delete documents. So that's everything for our author. Our editor is pretty much the exact same thing, but they cannot create documents, so we'll remove that from them, and our viewer is again pretty much the same thing as our editor, but they have no update permission at all, they only have read level permissions.

[00:02:00]
So now we've created that mapping between all the different permissions we have and what roles they're associated with, and now we can write that simple can function. And this can function is just pretty much a simple lookup. Let's make sure that we export this function, and we want to make sure we're passing in a user, which is going to be a user object, and to make this even easier on us, the only thing we care about for a user is their role, so I'm going to use a TypeScript utility called pick to just pick out only the role property.

[00:02:29]
So that says all we need to do is pass it an object that has a role property associated with it, nothing else matters. Also, since sometimes when we get our current user, for example, if we come into here, you notice when we call get current user, it could return to us a user that is null. We'll also accept null as a parameter in here just to make it easier to use this, so we don't have to do null checks before we call this function, we can just make it accept.

[00:02:52]
A null user as well, so now our user is either going to be a role or it's just going to be null. Then we can take in whatever permission we want to check, which we know is of that permission type we just created, and now essentially we have a function that takes in a user's role or null and the permission we want to check. First of all, in our application, users that are not logged in have access to nothing, so if the user is equal to null, then we just want to return that they don't have access, so we will turn false from this function.

[00:03:20]
Otherwise, we can do a really simple lookup, so we can take our permissions. By role, we can look up the specific role that we want, which is our user.role, and we can just check, does it include the permission that we're passing in, a single one line statement that now handles all the different permission checks inside of our application. Now, we do have a few problems though in our application, and that's that our project read permission is a little bit more complicated than just a true false statement.

[00:03:49]
For example, admins can read all projects, but authors, editors and viewers can only read projects that are either part of their own department or that are part of a global department. So we actually need to expand this read permission slightly. So we're going to have a read all permission that just allows you to read everything. We're also going to have a Read permission specifically for anything that's in your own department.

[00:04:09]
So if your department matches the project department, that's what this is associated with, and we're also going to have a permission for anything that is in a global department. So if the department is equal to null, then we have this global department come in. And this is something you'll start to notice as your application becomes more complex. It's not just simple, can read, cannot read, it's going to be can read in this specific situation or can update only if this is true.

[00:04:32]
So in our case, the only thing that's restricting us is the project reading abilities. So now we can come through, we can say we want to read all the projects here for our author, they can read anything that is global, or they can read anything that is in their own department as well, and these exact same permissions apply to our editor and our viewer, so let's just make sure we copy that down as well, clean up all of our different commas that we have, we don't want that one there or there.

[00:04:59]
There we go, and it looks like. Didn't quite get my copy paste correct. There we go, cause this one should have both of those permissions and same thing here. So now we've just broken down that project read permission. Instead of reading everything, it's going to say, OK, you can either read everything or you can read things in the global department where the department is null for the project, or you can read only things that are within your own department.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now