LongCut logo

Better Auth Organizations – The Basics (Part 1)

By OrcDev

Summary

Topics Covered

  • Drizzle Beats Better Auth Migrations
  • Server Actions Trump Client APIs
  • Custom Switcher Enables Org Context
  • Database Hook Sets Default Org

Full Transcript

In this video, we are going to implement better o organizations. We're going to create this organization switcher where we can choose our current active

organization and also we are going to create this form where we can create a new organization. We are going to cover

new organization. We are going to cover all the basics for better o organizations. We are still not going to

organizations. We are still not going to work on things like invitations, roles or adding new members. That's why this video is called part one. Let's start.

We have here our better oath starter.

You have the GitHub repository in the description below if you need it. And we

are going to implement now organizations by better o. So we are going to docs.

Then here we are going to plugins and we are clicking on organization.

So here we have the start that we need for organizations and first thing we need to do is to add the organization

plugin inside of our o.ts file. So I'm

opening the code and here we are going to o.ts and we have our plugins right here. We

have next cookies because we need that one for next.js JS and we are going to add the organization plugin right here

and we are going to import it from here better off/plugins.

So I'm adding that one to our imports and that one is done. So now we can migrate our database because we are adding now organizations members and

bunch of new tables. We need to run new migrations. So this one is not going to

migrations. So this one is not going to work for our NexJS project because we are using Drizzle and I'll show you why.

We are going to our terminal. So here we are running the migrate and we are going to get an error that it can be used only with the Kaiselli adapter. So we need to

run MPX better o C cli generate. So we

are going to run that one and we are going to get a totally new schema inside of the O schema.ts. ts. So yes, we are going to create that one. And going here

now to o schema.ts, we can see that we have besides the usual user session account verification, we have organization, member and invitation

tables created inside of our author schema. So what are we going to do? I'm

schema. So what are we going to do? I'm

going to copy the entire schema from here and move it to our original schema inside of our schema.ts file. So I'm

going to paste it in right here. And

inside of our schema, I'm just going to add new tables organization member and invitation. So we are now exporting all

invitation. So we are now exporting all the tables. And now we can actually run

the tables. And now we can actually run our migrations. So let's go. Drizzle kit

our migrations. So let's go. Drizzle kit

push and this one is going to create inside of our database new tables. So

now it's done. So we can go now to neon and here we can see that we have account session user verification and if we refresh here it is. So now we have new

tables organization member invitation, and this one is pretty much ready for us to create our organizations. Let's return to our

organizations. Let's return to our documentation right here. And next thing we need to do is to add the client plugin inside of our oclient.ts file. So let's open that one.

file. So let's open that one.

Oclientient.ts.

Here we are going to put the plugin for organizationclient and we are going to import it from /client/plugins.

So that one is done and we can also delete the o schema.ts. We don't need that one because we copy pasted everything to our schema file right

here. And that's it. We successfully

here. And that's it. We successfully

implemented better o and everything that is left is to actually use the organizations now. So we have the API

organizations now. So we have the API here for creation of new organizations.

When we run this one, this organization is created on our current user that is creating it and that user is set as

owner. So let's now create the form for

owner. So let's now create the form for actually creating our new organization and putting it inside of our database.

So we are going to our dashboard page and here we are going to create a new button and that button is going to create new organizations for us. So here

I'm putting in the button from shed CN create organization like this we are now here going to implement dialogue from shed CN. So

let's here open the dialogue and we need to install it inside of our project. So

I'm running the mpxian latest add dialogue command and then we are just going to import this one inside of our

page right here and also the usage.

We're going to put it under the button.

And then I'm going to take this button and replace this open text and put as child. So that button is used for

child. So that button is used for opening our dialogue. So if we go to the project right here, we can see the create organization button and we are

just going to put here a little bit of gap and we are going to put this button to variant outline so it matches this one and if we click it we are opening

the dialogue. So that one is working

the dialogue. So that one is working fine. Now we need to create a form which

fine. Now we need to create a form which we are going to put inside of this dialogue. And inside of our components

dialogue. And inside of our components we already have the forms directory. So

there we're going to create a new create organization form.tsx

organization form.tsx and here we're going to use react hook forms. So we are going back to shed cn and we are searching for forms. Here it is. We already have it installed because

is. We already have it installed because we are using it for login signup and other things. So we can just start from

other things. So we can just start from here. So I'm adding here the use client

here. So I'm adding here the use client importing zod and our form schema. So we

can return to our better off. We need

name and slug and logo. We're going to skip logo for now. So let's put in just name and slug. Those are both

just strings. So here we're putting name

just strings. So here we're putting name and also slug like this. Then we can return to shed cnen documentation. We

need to add zod resolver and use form.

So adding that one here on the top of our file and we are also adding the form and onsubmit inside of our component. So

I'm going to copy the whole component from here. We are just going to call it

from here. We are just going to call it create organization form. Here we are putting name and slug. I'm going to remove these comments from here. And

last thing, we just need to add our forms button and inputs. We are

importing that right here. And we are putting it in inside of our component.

So here we are just going to add return brackets and we are returning our form.

We are going to put here the name instead of this username and we're also going to add slug.

So here we're letting AI do its thing.

Nice. So here we have I'm just going to put my org for the placeholder. We can

remove the descriptions. We don't need that one. And here we can remove the

that one. And here we can remove the import also to remove this empty space. Nice.

So this one now looks good. Only thing

left is here on submit. We need to put that API from better o. So it's this one. Let's copy it and paste it right

one. Let's copy it and paste it right here. So we are just going to leave this

here. So we are just going to leave this logo to be hardcoded. This function

needs to be an async function.

Okay. And we're putting values and slug to be the values from our form. And

we're also going to put here a try catch.

And we need some toast messages. So here

we're going to put toast success.

Importing toast from Soner. And also

here we need toast error. And we are going to add quickly one loading state is loading.

AI knows exactly what I need. So we

added is loading. And we are going to put it set is loading here to true. And

finally to set it as false. And on our button we are going to put it to be disabled while loading. And instead of creating text, we are putting loader

two. And that one is just going to be

two. And that one is just going to be size four and animate spin. And now we just need to put this form inside of our dialogue. So here we're going to change

dialogue. So here we're going to change the title to create organization and description as well. So here we're

going to put our form inside of that dialogue. And now it's ready to be

dialogue. And now it's ready to be tested. So we are going back and here

tested. So we are going back and here creating organization. It's opening our

creating organization. It's opening our form right here. Let's just put this spacing to a little bit less like this

for nice. And now we can create our new

for nice. And now we can create our new organization. So I'm going to create my

organization. So I'm going to create my organization and I'm going to put my org as slug. And we are creating our

as slug. And we are creating our organization. And we are going to get

organization. And we are going to get the toast organization created successfully. Nice. So if we go to our

successfully. Nice. So if we go to our database and we go to organizations, we can see that it is really created successfully. We have everything here

successfully. We have everything here and inside of our members, we can see my user ID and I'm the owner of the organization. We have also the

organization. We have also the organization ID. So the whole logic is

organization ID. So the whole logic is working perfectly well and we can now actually know in which organization am I

inside of our application right here. So

we can now display our active organization here and we are also going to create a switcher that we can choose which organization is currently active.

So if you get back to better o documentation we can see here that we have API also for setting the active organization and we need to say we need

to send the organization ID. So we are going to use this one. We can also use the slug if that one is easier but we are just going to create server action

where we are going to get all our organizations. So let's create server

organizations. So let's create server actions for our organizations. Here we

have the server directory. Inside we

have users. And we are going to create organizations.ts.

organizations.ts.

Here we are going to create a new method get organizations. And this one is bad.

get organizations. And this one is bad.

AI doesn't know what is he doing. So we

are going to add here use server because these are server actions. And we need first our current user that is logged

in. So to do that we are going to now

in. So to do that we are going to now this is good. So we need session from our current user and for that we need

headers. Here it is like this. So we are

headers. Here it is like this. So we are going to import headers from our next headers. And now we have the session

headers. And now we have the session from our current user. And if there is no session we are just going to redirect

our users to /lo. That one sounds like a good idea. Then here we are going to

good idea. Then here we are going to call our current user from our database just like this. So we are going to import database from Drizzle equals from

Drizzle OM and user from our schema here. So now we have the current user

here. So now we have the current user which is currently logged in and if he's not there we are just going to again redirect to our login and this is

something that we are going to use many times. So this is really good to create

times. So this is really good to create a new here for example get current user method and there we put just this one

and we return that session and our current user. So here we just

need to import of course all these dependencies that we need and this user here as well equals from

Drizz and DB from Drizzle. Nice. So now

we can get our current user instead of this we can just say current user equals get current user from the users.ts

server actions file. And now we can actually find our organizations. And to

do that we first need to find members where our user is in the database. So

for that we are just going to search for our user ID. And then for organizations we are going to check how many

organizations are there for our user.

And this one is going to return all the organizations that we need and that our user is part of. Just one word of caution, you can use of course the API

for this. So here on better o we have

for this. So here on better o we have list users organization but this one is using o client and this one can be used only in client components. Our case

right here that we created can be used in server components and it's much better of course because all data here is cached and you're calling it only

once. So I prefer more to call it from

once. So I prefer more to call it from the server actions like this to have it working on server components. But if we

need it, of course, we can call this one in client components if there is some case that we need to list our user organizations. And we can now inside of

organizations. And we can now inside of our dashboard page call our organizations. So here we are calling

organizations. So here we are calling get organizations. We have our user here

get organizations. We have our user here logged in. We need to turn this into an

logged in. We need to turn this into an async function in order to wait it. And

here we can for example list our current organizations.

So we can just put it like this to see if it's working or not. And now here we can see that we have my organization listed. So this is coming from our

listed. So this is coming from our database. And that one is working just

database. And that one is working just fine. Awesome. So let's now remove this

fine. Awesome. So let's now remove this list here and we are going to create the organization switcher. So, we are going

organization switcher. So, we are going to put it inside of our header. So, I'm

opening the header. This one is imported inside of our main layout. So, I'm going to take this header from here and put it

on our main page because we don't want the organization switcher to be seen when the user is not logged in. So this

one is going to be just for the main page but the layout we need to remove the header from here and we are going to

create a new layout inside of our dashboard directory. So here creating

dashboard directory. So here creating layout.tsx

layout.tsx and we are going to put here children and header right here. So if we

now go to our project, we still have the header. But if we type in something

header. But if we type in something here, this one is seen in our dashboard.

But if we go to our local host, it's not there. So that one is working great.

there. So that one is working great.

Awesome. And we can now put here our organization switcher inside of our header. So for that we need select. I'm

header. So for that we need select. I'm

going again to shed CNN and we are typing in select. Then we are going to

implement it inside of our terminal and we are just going to add it. So

first let's create here inside the components the organization switcher.

Organization switcher.tsx DSX

switcher.tsx DSX and here I'm going to put the select and also I'm going to copy the usage right here. So we can export organization

here. So we can export organization switcher and here put the usage inside of our component and this component is going to

be a client component because we are going to use the O client from better o in order to set our active organizations. So we are going to the

organizations. So we are going to the better o API and here we have set active organization. So I'm just going to copy

organization. So I'm just going to copy this one and I'm going to create a new handle change organization. So we are sending

change organization. So we are sending the organization ID and we are just going to use this one. So I'm going to import client like this and instead of

this organization ID, we are just going to pass the organization ID from our select. So now here we need

select. So now here we need organizations and we picked that one up with our server actions. So here I'm going to create a new interface

organization switcher props and we are going to import the organizations for this one inside of our schema.

And if we go to organizations here I'm going to export type organization and that one is going to be infer select

from our table right here. So now if we go back to our switcher, we can import the organization type from our schema

right here. So we know exactly what are

right here. So we know exactly what are we receiving as props inside of our organization switcher. And here we can

organization switcher. And here we can map through our organizations. And on

our select we can put on value change handle change organization and default value is going to be our current

organization. And to get that one, we

organization. And to get that one, we can here use use active organization. So

I'm going to copy this one and we are going to put it inside of our component here active organization. And we are

going to put for our default value active organization ID. And now if we go to our header and put in the

organization switcher right here, we're also going to call organizations inside of our header. And we can remove that organizations

from our page. It is is it already removed from our dashboard page actually here? Yeah, we can remove this one. We

here? Yeah, we can remove this one. We

don't need it. And if we go back to our project, we have here our organization picker and we can see already that we

have actually my organization inside of our select box. So if I refresh, we are not getting yet the current organization. Let's see what's wrong.

organization. Let's see what's wrong.

Let's add first the try catch inside of our handle change organization. So here

I'm going to put try and catch here and also toast if something is wrong and here success if we switched our

organization successfully and there is also an error from the better off API. So we can here return the error in case there is one. So let's

try again. Now here I'm going to change the organization my organization organization switched successfully. So

it is working. Maybe it's because we don't have other organizations. So let's

create a new one here. I'm going to create orcs and slug is going to be orcs. Create organization.

orcs. Create organization.

Awesome. So we created a new one. And

now here we can see the new organization inside of our select. And if we select it, organization switched successfully.

Nice. But it's still not showing the current one. Okay. So we need to change

current one. Okay. So we need to change something. Let's first in our header put

something. Let's first in our header put here justify between. So this one is actually on the left and we probably

need with full here. There it is. Nice.

So we have now our switcher right here.

And we need to just see our current active organization. It's an interesting

active organization. It's an interesting bug we have here. So let's try to display actually our active organization. So here I'm going to put

organization. So here I'm going to put if active organization just to display it. And here I'm going to close my

it. And here I'm going to close my fragments. So let's see if we have it.

fragments. So let's see if we have it.

Okay. So we have our current organization here displayed. So that's

good. It's not the problem with the API.

is a problem with our oh it's here instead of default value we need just value and now I think it's going to work so if I refresh yeah now we have works

nice so if I choose my organization then organization switch successfully successfully and if you refresh we are getting again my organization and that

one is working properly now and we need to add one more thing when the user logs in active organization by default is null

So there is one really great database hook here. It is that is helping us to

hook here. It is that is helping us to set the active organization to whatever organization we want. So we are going to our o.ds

our o.ds and here we are just going to put our database hook. So here we are getting

database hook. So here we are getting the organization get active organization. Basically we need to

organization. Basically we need to create this method for us. We have the session with the user ID. So everything

we need to do is just to get the first organization that we can with the get active organization. So we are going

active organization. So we are going again to our server actions file and here we are going to create a new get active organization method and here we

are getting the organization by the organization ID. This one is not good.

organization ID. This one is not good.

We need our actual member user and we are going to get it from our member table with our user ID. And then for our

active organization, we are just going to take the first organization that we can by our member user organization ID.

So now we can get back to our o.ts and here everything is set. So we have our get active organization.

So now we can get back to our o.ts and we are going to import get active organization. Here we are just going to

organization. Here we are just going to put a question mark and we can test it out. So here I'm going to log out. We

out. So here I'm going to log out. We

are going to log in again and we should get that my organization as our default organization when we are

logged in. Here it is and we have my

logged in. Here it is and we have my organization as the active organization.

So it's working perfectly. I hope you enjoyed warriors. In part two, we are

enjoyed warriors. In part two, we are going to work on members CRUD and roles who can create, delete, update organizations and other things. Some big

table with members that we can add, edit member, remove, leave the organization, etc. So, tell me in the comments below, how do you like this series so far? And

for more content like this, as always, join the mighty horde.

Loading...

Loading video analysis...