组织管理
组织功能简化了用户访问和权限管理。通过分配角色和权限,可以简化项目管理、团队协作和合作伙伴关系。
安装
将插件添加到 auth 配置中
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
organization()
]
})
迁移数据库
运行迁移或生成模式,将必要的字段和表添加到数据库中。
npx @better-auth/cli migrate
npx @better-auth/cli generate
查看 Schema 部分以手动添加字段。
添加客户端插件
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
organizationClient()
]
})
使用
安装插件后,您就可以开始使用组织插件来管理组织的成员和团队。客户端插件将在 organization
命名空间下提供方法。服务器 api
将提供必要的端点来管理您的组织,并为您提供更简便的方式在您自己的后端调用这些功能。
组织
创建组织
const metadata = { someKey: "someValue" };const { data, error } = await authClient.organization.create({ name: "My Organization", // required slug: "my-org", // required logo: "https://example.com/logo.png", metadata, keepCurrentActiveOrganization: false,});
属性 | 描述 | 类型 |
---|---|---|
name | 组织名称。 | string |
slug | 组织标识符。 | string |
logo? | 组织logo。 | string |
metadata? | 组织元数据。 | Record<string, any> |
keepCurrentActiveOrganization? | 创建新组织后是否保持当前活跃组织为活跃状态。 | boolean |
限制可创建组织的用户
默认情况下,任何用户都可以创建组织。要限制此功能,请将 allowUserToCreateOrganization
选项设置为返回布尔值的函数,或直接设置为 true
或 false
。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
const auth = betterAuth({
//...
plugins: [
organization({
allowUserToCreateOrganization: async (user) => {
const subscription = await getSubscription(user.id)
return subscription.plan === "pro"
}
})
]
})
检查组织别名是否被占用
要检查组织别名是否已被占用,您可以使用客户端提供的 checkSlug
函数。该函数接收一个包含以下属性的对象:
const { data, error } = await authClient.organization.checkSlug({ slug: "my-org", // required});
属性 | 描述 | 类型 |
---|---|---|
slug | 要检查的组织别名。 | string |
组织创建钩子
您可以使用在组织创建前后运行的钩子来自定义组织创建流程。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
organization({
organizationCreation: {
disabled: false, // 设置为 true 可禁用组织创建
beforeCreate: async ({ organization, user }, request) => {
// 在组织创建前运行自定义逻辑
// 可选地修改组织数据
return {
data: {
...organization,
metadata: {
customField: "value"
}
}
}
},
afterCreate: async ({ organization, member, user }, request) => {
// 在组织创建后运行自定义逻辑
// 例如:创建默认资源、发送通知
await setupDefaultResources(organization.id)
}
}
})
]
})
beforeCreate
钩子在组织创建前运行。它接收以下参数:
organization
:组织数据(不包含 ID)user
:创建组织的用户request
:HTTP 请求对象(可选)
返回包含 data
属性的对象以修改将要创建的组织数据。
afterCreate
钩子在组织成功创建后运行。它接收以下参数:
organization
:已创建的组织(包含 ID)member
:创建者的成员记录user
:创建组织的用户request
:HTTP 请求对象(可选)
列出用户所属组织
要列出用户所属的组织,您可以使用 useListOrganizations
钩子。它提供了一种响应式的方式来获取用户所属的组织信息。
import { authClient } from "@/lib/auth-client"
function App(){
const { data: organizations } = authClient.useListOrganizations()
return (
<div>
{organizations.map(org => <p>{org.name}</p>)}
</div>
)
}
<script lang="ts">
import { authClient } from "$lib/auth-client";
const organizations = authClient.useListOrganizations();
</script>
<h1>组织列表</h1>
{#if $organizations.isPending}
<p>加载中...</p>
{:else if $organizations.data === null}
<p>未找到任何组织。</p>
{:else}
<ul>
{#each $organizations.data as organization}
<li>{organization.name}</li>
{/each}
</ul>
{/if}
<script lang="ts">;
export default {
setup() {
const organizations = authClient.useListOrganizations()
return { organizations };
}
};
</script>
<template>
<div>
<h1>组织列表</h1>
<div v-if="organizations.isPending">加载中...</div>
<div v-else-if="organizations.data === null">未找到任何组织。</div>
<ul v-else>
<li v-for="organization in organizations.data" :key="organization.id">
{{ organization.name }}
</li>
</ul>
</div>
</template>
或者,如果您不想使用钩子,也可以直接调用 organization.list
接口。
const { data, error } = await authClient.organization.list();
当前活跃组织
当前活跃组织是指用户正在使用的工作空间。默认情况下,当用户登录时,当前活跃组织设置为 null
。您可以在用户会话中设置当前活跃组织。
并非所有情况下都需要在会话中持久化当前活跃组织。您可以仅在客户端管理当前活跃组织。例如,多个标签页可以有不同的活跃组织。
设置当前活跃组织
您可以通过调用 organization.setActive
函数来设置当前活跃组织。这将为用户会话设置当前活跃组织。
在某些应用中,您可能需要取消设置当前活跃组织的能力。
这种情况下,您可以将 organizationId
设置为 null
来调用此端点。
const { data, error } = await authClient.organization.setActive({ organizationId: "org-id", organizationSlug: "org-slug",});
属性 | 描述 | 类型 |
---|---|---|
organizationId? | 要设置为活跃组织的组织ID。可以为 null 以取消设置当前活跃组织。 | string | null |
organizationSlug? | 要设置为活跃组织的组织别名。如果未提供 organizationId,可以设置为 null 以取消设置当前活跃组织。 | string |
要在创建会话时设置当前活跃组织,您可以使用数据库钩子。
export const auth = betterAuth({
databaseHooks: {
session: {
create: {
before: async(session)=>{
const organization = await getActiveOrganization(session.userId)
return {
data: {
...session,
activeOrganizationId: organization.id
}
}
}
}
}
}
})
使用当前组织
要获取用户的当前组织,您可以调用 useActiveOrganization
钩子。它会返回用户的当前组织。当当前组织发生变化时,钩子将重新评估并返回新的当前组织。
import { authClient } from "@/lib/auth-client"
function App(){
const { data: activeOrganization } = authClient.useActiveOrganization()
return (
<div>
{activeOrganization ? <p>{activeOrganization.name}</p> : null}
</div>
)
}
<script lang="ts">
import { authClient } from "$lib/auth-client";
const activeOrganization = authClient.useActiveOrganization();
</script>
<h2>当前组织</h2>
{#if $activeOrganization.isPending}
<p>加载中...</p>
{:else if $activeOrganization.data === null}
<p>未找到当前组织。</p>
{:else}
<p>{$activeOrganization.data.name}</p>
{/if}
<script lang="ts">;
export default {
setup() {
const activeOrganization = authClient.useActiveOrganization();
return { activeOrganization };
}
};
</script>
<template>
<div>
<h2>当前组织</h2>
<div v-if="activeOrganization.isPending">加载中...</div>
<div v-else-if="activeOrganization.data === null">无当前组织。</div>
<div v-else>
{{ activeOrganization.data.name }}
</div>
</div>
</template>
获取完整组织信息
要获取组织的完整详细信息,您可以使用 getFullOrganization
函数。
默认情况下,如果您不传递任何参数,它将使用当前活跃的组织。
const { data, error } = await authClient.organization.getFullOrganization({ organizationId: "org-id", organizationSlug: "org-slug", membersLimit: 100,});
属性 | 描述 | 类型 |
---|---|---|
organizationId? | 要获取的组织ID。默认情况下,将使用当前活跃的组织。 | string |
organizationSlug? | 要获取的组织slug。 | string |
membersLimit? | 要获取的成员数量限制。默认使用 membershipLimit 选项,该选项默认为 100。 | number |
更新组织信息
要更新组织信息,您可以使用 organization.update
const { data, error } = await authClient.organization.update({ data: { // required name: "updated-name", slug: "updated-slug", logo: "new-logo.url", metadata: { customerId: "test" }, }, organizationId: "org-id",});
属性 | 描述 | 类型 |
---|---|---|
data | 用于更新组织的部分数据列表。 | Object |
data.name? | 组织的名称。 | string |
data.slug? | 组织的slug。 | string |
data.logo? | 组织的徽标。 | string |
data.metadata? | 组织的元数据。 | Record<string, any> | null |
organizationId? | 要更新的组织ID。 | string |
删除组织
要删除用户拥有的组织,可以使用 organization.delete
方法
const { data, error } = await authClient.organization.delete({ organizationId: "org-id", // required});
属性 | 描述 | 类型 |
---|---|---|
organizationId | 要删除的组织 ID | string |
如果用户在指定组织中拥有必要的权限(默认为:所有者角色),所有成员、邀请信息以及组织信息都将被删除。
您可以通过 organizationDeletion
选项来配置组织删除的处理方式:
const auth = betterAuth({
plugins: [
organization({
organizationDeletion: {
disabled: true, // 完全禁用删除功能
beforeDelete: async (data, request) => {
// 删除组织前执行的回调函数
},
afterDelete: async (data, request) => {
// 删除组织后执行的回调函数
},
},
}),
],
});
邀请管理
要将成员添加到组织,首先需要向用户发送邀请。用户将通过邮件/短信收到邀请链接。一旦用户接受邀请,他们将被添加到组织中。
设置邀请邮件
要使成员邀请功能正常工作,我们首先需要为 better-auth
实例提供 sendInvitationEmail
函数。该函数负责向用户发送邀请邮件。
您需要构建邀请链接并将其发送给用户。该链接应包含邀请 ID,当用户点击链接时,该 ID 将与 acceptInvitation 函数一起使用。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
import { sendOrganizationInvitation } from "./email"
export const auth = betterAuth({
plugins: [
organization({
async sendInvitationEmail(data) {
const inviteLink = `https://example.com/accept-invitation/${data.id}`
sendOrganizationInvitation({
email: data.email,
invitedByUsername: data.inviter.user.name,
invitedByEmail: data.inviter.user.email,
teamName: data.organization.name,
inviteLink
})
},
}),
],
});
发送邀请
要邀请用户加入组织,您可以使用客户端提供的 invite
函数。该函数接收一个包含以下属性的对象:
const { data, error } = await authClient.organization.inviteMember({ email: "example@gmail.com", // required role: "member", // required organizationId: "org-id", resend: true, teamId: "team-id",});
属性 | 描述 | 类型 |
---|---|---|
email | 被邀请用户的邮箱地址。 | string |
role | 分配给用户的角色。可以是 admin 、member 或 guest 。 | string | string[] |
organizationId? | 邀请用户加入的组织 ID。默认为当前活跃组织。 | string |
resend? | 如果用户已被邀请,是否重新发送邀请邮件。 | boolean |
teamId? | 邀请用户加入的团队 ID。 | string |
- 如果用户已是组织成员,邀请将被取消。
- 如果用户已被邀请到该组织,除非
resend
设为true
,否则不会再次发送邀请。 - 如果
cancelPendingInvitationsOnReInvite
设为true
,当用户已被邀请到组织时,原邀请将被取消并发送新邀请。
接受邀请
当用户收到邀请邮件后,可以点击邀请链接接受邀请。邀请链接应包含邀请 ID,该 ID 将用于接受邀请。
请确保在用户登录后调用 acceptInvitation
函数。
const { data, error } = await authClient.organization.acceptInvitation({ invitationId: "invitation-id", // required});
属性 | 描述 | 类型 |
---|---|---|
invitationId | 要接受的邀请 ID。 | string |
邮箱验证要求
如果在组织配置中启用了 requireEmailVerificationOnInvitation
选项,用户在接受邀请前必须验证其邮箱地址。这增加了一层额外的安全保护,确保只有经过验证的用户才能加入您的组织。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
organization({
requireEmailVerificationOnInvitation: true,
async sendInvitationEmail(data) {
// ... 您的邮件发送逻辑
}
})
]
})
邀请接受回调
您可以配置 Better Auth,在邀请被接受时执行回调函数。这对于记录事件、更新分析、发送通知,或任何其他在有人加入组织时需要运行的自定义逻辑非常有用。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
organization({
async sendInvitationEmail(data) {
// ... 您的邀请邮件逻辑
},
async onInvitationAccepted(data) {
// 当邀请被接受时,此回调会被触发
},
}),
],
});
回调函数会接收到以下数据:
id
: 邀请 IDrole
: 分配给用户的角色organization
: 用户加入的组织invitation
: 邀请对象inviter
: 发送邀请的成员(包含用户详细信息)acceptedUser
: 接受邀请的用户
取消邀请
如果用户已发出邀请,可以使用此方法取消该邀请。
如果您想了解用户如何拒绝邀请,请查看此处。
await authClient.organization.cancelInvitation({ invitationId: "invitation-id", // required});
属性 | 描述 | 类型 |
---|---|---|
invitationId | 要取消的邀请ID | string |
拒绝邀请
如果用户收到了邀请但希望拒绝,此方法允许用户通过拒绝邀请来实现。
await authClient.organization.rejectInvitation({ invitationId: "invitation-id", // required});
属性 | 描述 | 类型 |
---|---|---|
invitationId | 要拒绝的邀请ID | string |
与接受邀请类似,当启用 requireEmailVerificationOnInvitation
选项时,拒绝邀请也需要进行邮箱验证。邮箱未验证的用户在尝试拒绝邀请时会收到错误提示。
获取邀请
要获取邀请信息,可以使用客户端提供的 organization.getInvitation
函数。您需要将邀请ID作为查询参数提供。
const { data, error } = await authClient.organization.getInvitation({ id: "invitation-id", // required});
属性 | 描述 | 类型 |
---|---|---|
id | 要获取的邀请ID | string |
列出邀请
要列出给定组织的所有邀请,可以使用客户端提供的 listInvitations
函数。
const { data, error } = await authClient.organization.listInvitations({ organizationId: "organization-id",});
属性 | 描述 | 类型 |
---|---|---|
organizationId? | 可选的组织ID,用于列出该组织的邀请。如果未提供,将默认使用用户的当前活跃组织。 | string |
列出用户邀请
要列出指定用户的所有邀请,您可以使用客户端提供的 listUserInvitations
函数。
const invitations = await authClient.organization.listUserInvitations()
在服务器端,您可以将用户 ID 作为查询参数传递。
const invitations = await auth.api.listUserInvitations({
query: {
email: "user@example.com"
}
})
email
查询参数仅在服务器端可用,用于查询特定用户的邀请。
成员
列出成员
要列出组织的所有成员,您可以使用 listMembers
函数。
const { data, error } = await authClient.organization.listMembers({ organizationId: "organization-id", limit: 100, offset: 0, sortBy: "createdAt", sortDirection: "desc", filterField: "createdAt", filterOperator: "eq", filterValue: "value",});
属性 | 描述 | 类型 |
---|---|---|
organizationId? | 可选的 organization ID,用于列出成员。如果未提供,将默认为用户当前活跃的组织。 | string |
limit? | 要返回的成员数量限制。 | number |
offset? | 起始偏移量。 | number |
sortBy? | 排序依据的字段。 | string |
sortDirection? | 排序方向。 | "asc" | "desc" |
filterField? | 筛选依据的字段。 | string |
filterOperator? | 筛选操作符。 | "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "contains" |
filterValue? | 筛选值。 | string |
移除成员
您可以使用 organization.removeMember
来移除成员
const { data, error } = await authClient.organization.removeMember({ memberIdOrEmail: "user@example.com", // required organizationId: "org-id",});
属性 | 描述 | 类型 |
---|---|---|
memberIdOrEmail | 要移除的成员的ID或邮箱。 | string |
organizationId? | 要从中移除成员的组织ID。如果未提供,将使用当前活跃组织。 | string |
更新成员角色
要更新组织中成员的角色,您可以使用 organization.updateMemberRole
。如果用户有权限更新该成员的角色,角色将被更新。
await authClient.organization.updateMemberRole({ role: ["admin", "sale"], // required memberId: "member-id", // required organizationId: "organization-id",});
属性 | 描述 | 类型 |
---|---|---|
role | 要应用的新角色。可以是字符串或字符串数组,表示角色。 | string | string[] |
memberId | 要应用角色更新的成员ID。 | string |
organizationId? | 成员所属的可选组织ID,用于应用角色更新。如果未提供,您必须提供会话头信息以获取当前活跃组织。 | string |
获取当前活跃成员
要获取当前活跃组织的成员信息,您可以使用 organization.getActiveMember
函数。此函数将返回用户在其当前活跃组织中的成员详细信息。
const { data: member, error } = await authClient.organization.getActiveMember();
添加成员
如果您想直接将成员添加到组织而不发送邀请,可以使用 addMember
函数,该函数只能在服务器端调用。
const data = await auth.api.addMember({ body: { userId: "user-id", role: ["admin", "sale"], // required organizationId: "org-id", teamId: "team-id", },});
属性 | 描述 | 类型 |
---|---|---|
userId? | 要添加为成员的用户 ID。如果提供 null ,则需要提供会话头信息。 | string | null |
role | 分配给新成员的角色。 | string | string[] |
organizationId? | 可选的传递的组织 ID。如果未提供,将默认为用户的当前活跃组织。 | string |
teamId? | 可选的团队 ID,用于将成员添加到该团队。 | string |
离开组织
要离开组织,您可以使用 organization.leave
函数。此函数将从组织中移除当前用户。
await authClient.organization.leave({ organizationId: "organization-id", // required});
属性 | 描述 | 类型 |
---|---|---|
organizationId | 成员要离开的组织 ID。 | string |
访问控制
组织插件提供了一个非常灵活的访问控制系统。您可以根据用户在组织中的角色来控制其访问权限。您可以根据用户的角色定义自己的权限集。
角色
默认情况下,组织中有三种角色:
owner
(所有者):默认创建组织的用户。所有者对组织拥有完全控制权,可以执行任何操作。
admin
(管理员):拥有管理员角色的用户对组织拥有完全控制权,但不能删除组织或更改所有者。
member
(成员):拥有成员角色的用户对组织的控制权有限。他们可以创建项目、邀请用户以及管理自己创建的项目。
一个用户可以拥有多个角色。多个角色以逗号(",")分隔的字符串形式存储。
权限
默认情况下,有三种资源,每种资源有两到三个操作。
organization(组织):
update
(更新) delete
(删除)
member(成员):
create
(创建) update
(更新) delete
(删除)
invitation(邀请):
create
(创建) cancel
(取消)
所有者对所有资源和操作拥有完全控制权。管理员对所有资源拥有完全控制权,但不能删除组织或更改所有者。成员除了读取数据外,对这些操作没有任何控制权。
自定义权限
该插件提供了一种简单的方式,为每个角色定义您自己的权限集。
创建访问控制
您首先需要通过调用 createAccessControl
函数并传递声明对象来创建访问控制器。声明对象应以资源名称作为键,以操作数组作为值。
import { createAccessControl } from "better-auth/plugins/access";
/**
* 确保使用 `as const`,以便 TypeScript 能正确推断类型
*/
const statement = {
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
创建角色
创建访问控制器后,您可以使用已定义的权限创建角色。
import { createAccessControl } from "better-auth/plugins/access";
const statement = {
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
const member = ac.newRole({
project: ["create"],
});
const admin = ac.newRole({
project: ["create", "update"],
});
const owner = ac.newRole({
project: ["create", "update", "delete"],
});
const myCustomRole = ac.newRole({
project: ["create", "update", "delete"],
organization: ["update"],
});
当您为现有角色创建自定义角色时,这些角色的预定义权限将被覆盖。要将现有权限添加到自定义角色中,您需要导入 defaultStatements
并将其与您的新声明合并,同时将角色的权限集与默认角色合并。
import { createAccessControl } from "better-auth/plugins/access";
import { defaultStatements, adminAc } from 'better-auth/plugins/organization/access'
const statement = {
...defaultStatements,
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
const admin = ac.newRole({
project: ["create", "update"],
...adminAc.statements,
});
将角色传递给插件
创建角色后,您可以将它们传递给客户端和服务器的组织插件。
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
import { ac, owner, admin, member } from "@/auth/permissions"
export const auth = betterAuth({
plugins: [
organization({
ac,
roles: {
owner,
admin,
member,
myCustomRole
}
}),
],
});
您还需要将访问控制器和角色传递给客户端插件。
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
import { ac, owner, admin, member, myCustomRole } from "@/auth/permissions"
export const authClient = createAuthClient({
plugins: [
organizationClient({
ac,
roles: {
owner,
admin,
member,
myCustomRole
}
})
]
})
访问控制使用
权限检查:
您可以使用 api
提供的 hasPermission
操作来检查用户的权限。
import { auth } from "@/auth";
await auth.api.hasPermission({
headers: await headers(),
body: {
permissions: {
project: ["create"] // 这必须与您的访问控制结构匹配
}
}
});
// 您也可以同时检查多个资源权限
await auth.api.hasPermission({
headers: await headers(),
body: {
permissions: {
project: ["create"], // 这必须与您的访问控制结构匹配
sale: ["create"]
}
}
});
如果您想从服务器端检查客户端用户的权限,可以使用客户端提供的 hasPermission
函数。
const canCreateProject = await authClient.organization.hasPermission({
permissions: {
project: ["create"]
}
})
// 您也可以同时检查多个资源权限
const canCreateProjectAndCreateSale = await authClient.organization.hasPermission({
permissions: {
project: ["create"],
sale: ["create"]
}
})
检查角色权限:
一旦您定义了角色和权限,为了避免从服务器检查权限,您可以使用客户端提供的 checkRolePermission
函数。
const canCreateProject = authClient.organization.checkRolePermission({
permissions: {
organization: ["delete"],
},
role: "admin",
});
// 您也可以同时检查多个资源权限
const canCreateProjectAndCreateSale = authClient.organization.checkRolePermission({
permissions: {
organization: ["delete"],
member: ["delete"]
},
role: "admin",
});
团队功能
团队功能允许您在组织内对成员进行分组。团队功能提供了额外的组织结构,可用于在更细粒度的级别上管理权限。
启用团队功能
要启用团队功能,请将 teams
配置选项传递给服务器和客户端插件:
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
organization({
teams: {
enabled: true,
maximumTeams: 10, // 可选:限制每个组织的团队数量
allowRemovingAllTeams: false // 可选:防止删除最后一个团队
}
})
]
})
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
organizationClient({
teams: {
enabled: true
}
})
]
})
管理团队
创建团队
在组织内创建一个新团队:
const { data, error } = await authClient.organization.createTeam({ name: "my-team", // required organizationId: "organization-id",});
属性 | 描述 | 类型 |
---|---|---|
name | 团队名称。 | string |
organizationId? | 将在其中创建团队的组织 ID。默认为当前活跃组织。 | string |
列出团队
获取组织中的所有团队:
const { data, error } = await authClient.organization.listTeams({ organizationId: "organziation-id",});
属性 | 描述 | 类型 |
---|---|---|
organizationId? | 要列出团队的组织 ID。默认为用户的当前活跃组织。 | string |
更新团队
更新团队的详细信息:
const { data, error } = await authClient.organization.updateTeam({ teamId: "team-id", // required data: { // required name: "我的新团队名称", organizationId: "此团队的新组织ID", createdAt: new Date(), updatedAt: new Date(), },});
属性 | 描述 | 类型 |
---|---|---|
teamId | 要更新的团队ID。 | string |
data | 包含更新选项的部分对象。 | Object |
data.name? | 要更新的团队名称。 | string |
data.organizationId? | 团队所属的组织ID。 | string |
data.createdAt? | 团队创建的时间戳。 | Date |
data.updatedAt? | 团队最后更新的时间戳。 | Date |
移除团队
从组织中删除一个团队:
const { data, error } = await authClient.organization.removeTeam({ teamId: "team-id", // required organizationId: "organization-id",});
属性 | 描述 | 类型 |
---|---|---|
teamId | 要移除的团队ID。 | string |
organizationId? | 团队所属的组织ID。如果未提供,将默认为用户的当前活跃组织。 | string |
设置活跃团队
将指定团队设置为当前活跃团队。如果 teamId
为 null
,则取消当前活跃团队。
const { data, error } = await authClient.organization.setActiveTeam({ teamId: "team-id",});
属性 | 描述 | 类型 |
---|---|---|
teamId? | 要设置为当前活跃团队的团队ID。 | string |
列出用户团队
列出当前用户所属的所有团队。
const { data, error } = await authClient.organization.listUserTeams();
列出团队成员
获取指定团队成员列表。
const { data, error } = await authClient.organization.listTeamMembers({ teamId: "team-id",});
属性 | 描述 | 类型 |
---|---|---|
teamId? | 需要返回成员的团队ID。如果未提供,则返回当前活跃团队的成员。 | string |
添加团队成员
向团队中添加成员。
const { data, error } = await authClient.organization.addTeamMember({ teamId: "team-id", // required userId: "user-id", // required});
属性 | 描述 | 类型 |
---|---|---|
teamId | 用户需要加入的团队ID。 | string |
userId | 需要添加为成员的用户ID。 | string |
移除团队成员
从团队中移除成员。
const { data, error } = await authClient.organization.removeTeamMember({ teamId: "team-id", // required userId: "user-id", // required});
属性 | 描述 | 类型 |
---|---|---|
teamId | 需要移除用户的团队ID。 | string |
userId | 需要从团队中移除的用户ID。 | string |
团队权限
团队遵循组织的权限系统。要管理团队,用户需要以下权限:
team:create
- 创建新团队team:update
- 更新团队详情team:delete
- 删除团队
默认情况下:
- 组织所有者和管理员可以管理团队
- 普通成员无法创建、更新或删除团队
团队配置选项
团队功能支持多种配置选项:
-
maximumTeams
:限制每个组织的团队数量teams: { enabled: true, maximumTeams: 10 // 固定数量 // 或 maximumTeams: async ({ organizationId, session }, request) => { // 基于组织计划的动态限制 const plan = await getPlan(organizationId) return plan === 'pro' ? 20 : 5 }, maximumMembersPerTeam: 10 // 固定数量 // 或 maximumMembersPerTeam: async ({ teamId, session, organizationId }, request) => { // 基于团队计划的动态限制 const plan = await getPlan(organizationId, teamId) return plan === 'pro' ? 50 : 10 }, }
-
allowRemovingAllTeams
:控制是否允许移除最后一个团队teams: { enabled: true, allowRemovingAllTeams: false // 禁止移除最后一个团队 }
团队成员
邀请成员加入组织时,可以指定团队:
await authClient.organization.inviteMember({
email: "user@example.com",
role: "member",
teamId: "team-id"
})
受邀成员在接受邀请后将被添加到指定的团队中。
数据库结构
启用团队功能后,数据库中将新增 team
和 teamMember
两张表。
表名:team
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个团队的唯一标识符 | |
name | string | - | 团队名称 |
organizationId | string | 所属组织的ID | |
createdAt | Date | - | 团队创建时间戳 |
updatedAt | Date | 团队最后更新时间戳 |
表名:teamMember
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个团队成员的唯一标识符 | |
teamId | string | 所属团队的唯一标识符 | |
userId | string | 用户ID | |
createdAt | Date | - | 团队成员创建时间戳 |
结构
组织插件会向数据库添加以下表:
组织(Organization)
表名:organization
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个组织的唯一标识符 | |
name | string | - | 组织的名称 |
slug | string | - | 组织的 slug |
logo | string | 组织的 logo | |
metadata | string | 组织的附加元数据 | |
createdAt | Date | - | 组织创建的时间戳 |
成员(Member)
表名:member
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个成员的唯一标识符 | |
userId | string | 用户的 ID | |
organizationId | string | 组织的 ID | |
role | string | - | 用户在组织中的角色 |
createdAt | Date | - | 成员加入组织的时间戳 |
邀请表
表名: invitation
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个邀请的唯一标识符 | |
string | - | 用户的邮箱地址 | |
inviterId | string | 邀请者的ID | |
organizationId | string | 组织的ID | |
role | string | - | 用户在组织中的角色 |
status | string | - | 邀请的状态 |
expiresAt | Date | - | 邀请的过期时间戳 |
如果启用了团队功能,你需要在邀请表中添加以下字段:
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
teamId | string | 团队的ID |
会话表
表名: session
你需要在会话表中再添加两个字段,用于存储当前活跃的组织ID和团队ID。
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
activeOrganizationId | string | 当前活跃组织的ID | |
activeTeamId | string | 当前活跃团队的ID |
团队(可选)
表名:team
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个团队的唯一标识符 | |
name | string | - | 团队名称 |
organizationId | string | 所属组织的 ID | |
createdAt | Date | - | 团队创建时间戳 |
updatedAt | Date | 团队更新时间戳 |
表名:teamMember
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
id | string | 每个团队成员的唯一标识符 | |
teamId | string | 所属团队的唯一标识符 | |
userId | string | 用户的 ID | |
createdAt | Date | - | 团队成员创建时间戳 |
表名:invitation
字段名称 | 类型 | Key | 描述 |
---|---|---|---|
teamId | string | 团队 ID |
自定义数据表结构
如需更改数据表名称或字段,您可以将 schema
选项传递给组织插件。
const auth = betterAuth({
plugins: [
organization({
schema: {
organization: {
modelName: "organizations", // 将组织表映射到 organizations
fields: {
name: "title" // 将 name 字段映射到 title
},
additionalFields: {
// 向组织表添加新字段
myCustomField: {
type: "string",
input: true,
required: false
}
}
}
}
})
]
})
附加字段
从 Better Auth v1.3 开始,您可以轻松地向 organization
(组织)、invitation
(邀请)、member
(成员)和 team
(团队)表添加自定义字段。
当您为模型添加额外字段时,相关的 API 端点将自动接受并返回这些新属性。例如,如果您向 organization
表添加了一个自定义字段,createOrganization
端点将在其请求和响应负载中根据需要包含此字段。
const auth = betterAuth({
plugins: [
organization({
schema: {
organization: {
additionalFields: {
myCustomField: {
type: "string",
input: true,
required: false
}
}
}
}
})
]
})
要推断附加字段,您可以使用 inferOrgAdditionalFields
函数。此函数将从 auth 对象类型中推断出附加字段。
import { createAuthClient } from "better-auth/client";
import { inferOrgAdditionalFields, organizationClient } from "better-auth/client/plugins";
import type { auth } from "@/auth" // 仅导入 auth 对象类型
const client = createAuthClient({
plugins: [organizationClient({
schema: inferOrgAdditionalFields<typeof auth>()
})]
})
如果您无法导入 auth 对象类型,可以不使用泛型来调用 inferOrgAdditionalFields
函数。此函数将从 schema 对象中推断出附加字段。
const client = createAuthClient({
plugins: [organizationClient({
schema: inferOrgAdditionalFields({
organization: {
additionalFields: {
newField: {
type: "string",
},
},
},
})
})]
})
// 使用示例
await client.organization.create({
name: "Test",
slug: "test",
newField: "123", // 这应该被允许
//@ts-expect-error - 此字段不可用
unavalibleField: "123", // 这应该不被允许
})
选项
allowUserToCreateOrganization: boolean
| ((user: User) => Promise<boolean> | boolean)
- 用于判断用户是否可以创建组织的函数。默认为 true
。可设置为 false
以限制用户创建组织。
organizationLimit: number
| ((user: User) => Promise<boolean> | boolean)
- 用户允许创建的最大组织数量。默认为 5
。可设置为任意数字或返回布尔值的函数。
creatorRole: admin | owner
- 创建组织的用户角色。默认为 owner
。可设置为 admin
。
membershipLimit: number
- 组织中允许的最大成员数量。默认为 100
。可设置为任意数字。
sendInvitationEmail: async (data) => Promise<void>
- 用于向用户发送邀请邮件的函数。
invitationExpiresIn : number
- 邀请链接的有效时长(单位:秒)。默认为 48 小时(2 天)。
cancelPendingInvitationsOnReInvite: boolean
- 当用户已被邀请到组织时,是否取消待处理的邀请。默认为 false
。
invitationLimit: number
| ((user: User) => Promise<boolean> | boolean)
- 用户允许发送的最大邀请数量。默认为 100
。可设置为任意数字或返回布尔值的函数。
requireEmailVerificationOnInvitation: boolean
- 在接受或拒绝邀请前是否需要验证邮箱。默认为 false
。启用后,用户必须先验证邮箱地址才能接受或拒绝组织邀请。