Learn how to achieve multitenancy inside of a Directus project using Roles and Relational Fields.
Speaker 0: Hi. Welcome back to the next episode of Short Hops. I'm your host Brian Gillespie. Today we are talking about how to achieve multi tenancy inside Directus. So tenancy is just using the same resources to serve multiple groups of users.
I think the term came from apartment buildings, maybe. Got multiple tenants that share have their own apartments, but they share the same resources. They share the same building. Maybe that's where it came from. But anyway, it is a very common convention in SaaS that we have multiple different accounts or teams or whatever you call your tenant collection using the same application, but each team needs to only see their individual resources or data in this case.
Achieving it inside Directus is pretty simple. There are 4 steps we're going to cover. Let's dive right in. Alright. So the first thing we're gonna do is create a tenant collection.
Now what you name this is totally up to you. You could call it teams, you could call it accounts, which is one of my personal preferences. But, you know, if you're coming from something like Laravel, I think out of the box, they have something called teams. So we can add a couple of additional fields if we need to. These system fields are really nice, just a quick little shortcut, but I'll go ahead and create a team collection here and we'll just give it a team name.
Right? So let's go in and create a team, we'll call it test team A, we'll save this. Let's go ahead and create another team, test team B. So now we have 2 teams, we've got our team tenant collection. Let's, let's mark this off on our list here.
Boom. Step 1, done. Alright. So the next step is to create a relationship between this tenant collection and our Directus users collection. So Directus users gets created whenever you bootstrap your Directus instance.
So if I'm looking at my data model, I'll find that under the Directus users here. And what kind of relationship you set up depends on how you want your tenancy model to work. So if users could belong to multiple teams, you're gonna use a many to many relationship. But if a user could belong to just one team, you could use a many to 1 or and the reverse one to many. So in this case, let's say we want users to belong to multiple teams or they could potentially belong to multiple teams.
Now in that case, we are going to create a many to many relationship. So I'll just search for that here. And inside Teams, let's call our field users and we are going to look for the Directus users collection. Right? So I'm inside my team's data model, go to the mini to mini relationship.
We'll create a new field called users, and the related collection is gonna be directus_users. Now I can show a link to that item, but if I open up the advanced section, I can see this junction collection that Directus is gonna create for me. I was calling this teams_directususers, and then we have the team's ID and the directus_usersid. Underscoreid. Too many.
I'm also gonna create the corresponding field on the Directus users collection as well. Great. So I'll just go ahead and save this and with that relationship out of the way, we can mark off step 2 of the process. Now step 3 is gonna be creating our actual data collections. And for each one of those collections, we need to create a many to one relationship back to our tenant collection.
So let's just keep this super simple and create a new collection called tasks. Very simple. I could even go in and, you know, add these system fields. Maybe we want to know who created the task, what date it was updated, and we'll just give this task a title. Right?
Great. The next thing we're gonna do here is add a mini to 1 relationship back to that tenant collection. So we're just gonna call this team and the related collection is gonna be called teams. We'll hit save and now we have that relationship that will allow us to filter out those permissions when we're making those API calls. Alright.
Great. So now if we just go in and let's create a couple of test task, A will assign that to test team a, and we'll create test task b. Go ahead and assign that to team b. Alright. Great.
So now we've got the collection, and for each one of our data collections, like, let's say I had projects and then tasks, I would add that same relationship, that many to one relationship back to my tenant collection. So with that out of the way, let's go ahead and mark this off. And then the last piece of the puzzle here is to set up our permissions inside Directus to restrict access based on the user's team. What what teams are the users included on? We wanna restrict access based on that.
So we're gonna go to our settings, go to access control, and let's create a new user or a new role, I should say. Let's call it user, and I'll enable app access here. You don't necessarily have to do that, You know, this is just to showcase the functionality. If you want them using the Directus app, you can. If it is API only, the API still respect these permission settings.
Alright. So what I'm gonna do here, I'm just gonna go ahead and enable all these permissions by default, and then I'm gonna go in and start restricting this. So our share functionality, I don't necessarily need. Maybe I don't even want these users to be able to delete tasks or things like that. We definitely want them to be able to create new tasks.
Maybe they can create new teams, But it when it comes to seeing tasks and editing task and seeing teams, we only want them to see the things that they are a part of. So how do we do that? We could go into our custom permissions in that case. So we'll just click on that and use custom, and then we will set up a filter rule. So here we are filtering the items that this particular user or this role which will apply to a user can have access to.
So in this case, we've got that team field and because we used a many to 1 relationship or a many to many relationship, we have to use the is one of because the actual users, the direct us the team and the direct us users, it could be an array of teams that they are a part of. Directus has these dynamic variables we can use as well. So dollar sign current underscore user in all caps will allow us to access the current logged in user. We'll go for the dot teams because that was the field that we specified on the user collection, and then we're looking through our junction table. So that is underscore teams teams underscore ID, and then we have ID.
So with this, and if I just copy this rule, we can apply that to the edit access as well. So I can go in and edit raw value. I could just paste this here, save it. Okay, great. So now if I were to create a new user, let's call them test user a, and just do test at example.com.
Give them a nice secure password, and I go into the role settings. We'll select the user role, save that, open up a incognito window so we get a fresh set of cookies, and let's just log in to this user and see what's actually available. Alright so we logged in we cannot see any particular tasks here. Now if I refresh the task I could see that, but we have not associated that user with an actual team yet. So if I scroll down to the bottom let's add that user to team A and we'll hit Save.
And now if I refresh this window we could see that that user has access to test task a, but they cannot see test task b, which is a part of the second team, which is test team b. Very simple. That is how you set up tenancy inside Directus. I hope this tip was helpful. Bring on some more questions.
I want to cover more of those for you.