Keep active organisation stored between refresh.

Hi guys, I noticed that when the user signs in, the active organisation is set to null, as per the documentation. Is there a way to bypass this? So that once a user creates an org, or signs in, it automatically sets their last used organisation to their active one? Not sure if this is achievable from the config, and if not, what would you guys suggest I do? Thanks
11 Replies
Hakai
Hakai•3mo ago
You can use a before database hook on session for adding an activeOrganizationId to your session object databaseHooks: { session: { create: { before: async(session)=>{ const organization = await getActiveOrganization(session.userId) return { data: { ...session, activeOrganizationId: organization.id } } } } } }
Hakai
Hakai•3mo ago
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
Codex 🧃
Codex 🧃OP•3mo ago
So I should extend the session object to take an activeOrganizationId? Or should I call the underline better-auth APIs to set the users active organization? I don't think the session object takes an activeOrganizationId property
Hakai
Hakai•3mo ago
Once you activate the organization plugin and generate the schema the session schema already gets a new field called activeOrganizationId. You can set this using the authClient.organization.setActive({...}) helper or during login using the database hook which I posted earlier Did you generate a new auth-schema after using the organization plugin? npx @better-auth/cli generate You should see a new schema with the activeOrganizationId field
Codex 🧃
Codex 🧃OP•2mo ago
So my schema does have this property, but its weird I dont get this typed, only on the authClient. Not the biggest issue in the world, my main concern is how do I store what the activeOrganization is currently, when the user signs out. I can of course update a DB record with this data, and when they sign back in, I can pull that org ID from the record and set the current org. Is this the best solution?
Hakai
Hakai•2mo ago
That is precisely what I've implemented in my project
export async function getActiveOrganization(userId: string) {
const memberUser = await db.query.member.findFirst({ where: eq(member.userId, userId) });

if (!memberUser)
return null;

const activeOrganization = await db.query.organization.findFirst({
where: (field, op) => (
op.and(
op.eq(field.id, memberUser.organizationId),
)
),
});

return activeOrganization;
}
export async function getActiveOrganization(userId: string) {
const memberUser = await db.query.member.findFirst({ where: eq(member.userId, userId) });

if (!memberUser)
return null;

const activeOrganization = await db.query.organization.findFirst({
where: (field, op) => (
op.and(
op.eq(field.id, memberUser.organizationId),
)
),
});

return activeOrganization;
}
And then in the databaseHooks:
databaseHooks: {
session: {
create: {
before: async(session)=>{
const organization = await getActiveOrganization(session.userId)
return {
data: {
...session,
activeOrganizationId: organization?.id
}
}
}
}
}
}
databaseHooks: {
session: {
create: {
before: async(session)=>{
const organization = await getActiveOrganization(session.userId)
return {
data: {
...session,
activeOrganizationId: organization?.id
}
}
}
}
}
}
Hakai
Hakai•2mo ago
but its weird I dont get this typed, only on the authClient.
Did you add the organizationClient plugin on the authClient instance? it's a different import from the server plugin. It's import { organizationClient } from "better-auth/client/plugins". Once you add this your session object should have the activeOrganizationId. It should look something like this
No description
Hakai
Hakai•2mo ago
Once you do that you can also infer the type like so: export type Session = typeof authClient.$Infer.Session.session and you should see all these types infered:
type Session = {
id: string;
userId: string;
expiresAt: Date;
createdAt: Date;
updatedAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
impersonatedBy?: string | null | undefined;
activeOrganizationId?: string | null | undefined;
}
type Session = {
id: string;
userId: string;
expiresAt: Date;
createdAt: Date;
updatedAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
impersonatedBy?: string | null | undefined;
activeOrganizationId?: string | null | undefined;
}
Codex 🧃
Codex 🧃OP•2mo ago
Sorry for the late reply, but looking at your getActiveOrganization function, this returns the first org found that the user is part of.. not the last one that they last set as their active one
Hakai
Hakai•2mo ago
Correct, you can always have a seperate column to store the last active org or something like that, this is what I needed for my use case hence the example. You could store the lastActiveOrgId or something like that in the member table or something like that and update it everytime they log out
Codex 🧃
Codex 🧃OP•2mo ago
Yeah will probs do that, just need to get these typings sorted

Did you find this page helpful?