管理员
Better Auth 的管理员插件
管理员插件为您的应用程序提供了一套用户管理的管理功能。它允许管理员执行各种操作,如创建用户、管理用户角色、禁止/解禁用户、模拟用户身份等。
安装
在您的 auth 配置中添加插件
使用管理员插件时,将其添加到您的 auth 配置中。
import { betterAuth } from "better-auth"
import { admin } from "better-auth/plugins"
export const auth = betterAuth({
// ... 其他配置选项
plugins: [
admin()
]
})Migrate the database
Run the migration or generate the schema to add the necessary fields and tables to the database.
npx auth migratenpx auth generateSee the Schema section to add the fields manually.
添加客户端插件
接下来,在您的身份验证客户端实例中包含管理员客户端插件。
import { createAuthClient } from "better-auth/client"
import { adminClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
adminClient()
]
})使用
在执行任何管理员操作之前,用户必须使用管理员帐户进行身份验证。管理员是指分配了 admin 角色的任何用户,或者其 ID 包含在 adminUserIds 选项中的任何用户。
创建用户
允许管理员创建新用户。
const { data: newUser, error } = await authClient.admin.createUser({ email: "user@example.com", // required password: "some-secure-password", // required name: "James Smith", // required role: "user", data: { customField: "customValue" },});emailstringrequiredThe email of the user.
passwordstringrequiredThe password of the user.
namestringrequiredThe name of the user.
rolestring | string[]A string or array of strings representing the roles to apply to the new user.
dataRecord<string, any>Extra fields for the user. Including custom additional fields.
列出用户
允许管理员列出数据库中所有用户。
All properties are optional to configure. By default, 100 rows are returned, you can configure this by the limit property.
const { data: users, error } = await authClient.admin.listUsers({ query: { searchValue: "some name", searchField: "name", searchOperator: "contains", limit: 100, offset: 100, sortBy: "name", sortDirection: "desc", filterField: "email", filterValue: "hello@example.com", filterOperator: "eq", },});searchValuestringThe value to search for.
searchField"email" | "name"The field to search in, defaults to email. Can be email or name.
searchOperator"contains" | "starts_with" | "ends_with"The operator to use for the search. Can be contains, starts_with or ends_with.
limitstring | numberThe number of users to return. Defaults to 100.
offsetstring | numberThe offset to start from.
sortBystringThe field to sort by.
sortDirection"asc" | "desc"The direction to sort by.
filterFieldstringThe field to filter by.
filterValuestring | number | boolean | string[] | number[]The value to filter by.
filterOperator"eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "in" | "not_in" | "contains" | "starts_with" | "ends_with"The operator to use for the filter.
Query Filtering
listUsers 支持多种过滤操作符,包括 eq、contains、starts_with 和 ends_with。
分页
listUsers 函数支持分页,响应中会返回用户列表和元数据。返回字段如下:
{
users: User[], // 返回的用户数组
total: number, // 过滤和搜索后用户总数
limit: number | undefined, // 查询中提供的 limit
offset: number | undefined // 查询中提供的 offset
}如何实现分页
使用 total、limit 和 offset 计算:
- Total pages:
Math.ceil(total / limit) - Current page:
(offset / limit) + 1 - Next page offset:
Math.min(offset + limit, (total - 1))– The value to use asoffsetfor the next page, ensuring it does not exceed the total number of pages. - Previous page offset:
Math.max(0, offset - limit)– The value to use asoffsetfor the previous page (ensuring it doesn’t go below zero).
示例用法
获取第二页,每页 10 个用户:
import { authClient } from "@/lib/auth-client";
const pageSize = 10;
const currentPage = 2;
const users = await authClient.admin.listUsers({
query: {
limit: pageSize,
offset: (currentPage - 1) * pageSize
}
});
const totalUsers = users.total;
const totalPages = Math.ceil(totalUsers / pageSize)获取用户
通过 ID 获取用户信息。
const { data, error } = await authClient.admin.getUser({ query: { id: "user-id", // required },});idstringrequiredThe id of the user you want to fetch.
Returns
On success, data contains the user object. On failure, error is populated by code, message, status, and statusText.
type GetUserResponse = {
data: User | null;
error: null | {
message: string;
status: number; // HTTP 状态码
statusText: string;
code: string;
}设置用户角色
更改用户角色。
const { data, error } = await authClient.admin.setRole({ userId: "user-id", role: "admin", // required});userIdstringThe user id which you want to set the role for.
rolestring | string[]requiredThe role to set, this can be a string or an array of strings.
设置用户密码
更改用户密码。
const { data, error } = await authClient.admin.setUserPassword({ newPassword: 'new-password', // required userId: 'user-id', // required});newPasswordstringrequiredThe new password.
userIdstringrequiredThe user id which you want to set the password for.
更新用户
更新用户详情。
const { data, error } = await authClient.admin.updateUser({ userId: "user-id", // required data: { name: "John Doe" }, // required});userIdstringrequiredThe user id which you want to update.
dataRecord<string, any>requiredThe data to update.
禁止用户
await authClient.admin.banUser({ userId: "user-id", // required banReason: "Spamming", banExpiresIn: 60 * 60 * 24 * 7,});userIdstringrequiredThe user id which you want to ban.
banReasonstringThe reason for the ban.
banExpiresInnumberThe number of seconds until the ban expires. If not provided, the ban will never expire.
解禁用户
解除用户禁止状态,允许用户重新登录。
await authClient.admin.unbanUser({ userId: "user-id", // required});userIdstringrequiredThe user id which you want to unban.
列出用户会话
列出用户所有会话。
const { data, error } = await authClient.admin.listUserSessions({ userId: "user-id", // required});userIdstringrequiredThe user id.
撤销用户会话
const { data, error } = await authClient.admin.revokeUserSession({ sessionToken: "session_token_here", // required});sessionTokenstringrequiredThe session token which you want to revoke.
撤销用户所有会话
撤销用户的所有会话。
const { data, error } = await authClient.admin.revokeUserSessions({ userId: "user-id", // required});userIdstringrequiredThe user id which you want to revoke all sessions for.
模拟用户
此功能允许管理员创建一个模拟指定用户的会话。该会话将在浏览器会话结束或达到 1 小时后失效。您可以通过设置 impersonationSessionDuration 选项更改此时长。
const { data, error } = await authClient.admin.impersonateUser({ userId: "user-id", // required});userIdstringrequiredThe user id which you want to impersonate.
默认情况下,管理员不能模拟其他管理员用户。若要允许此操作,请为角色授予 impersonate-admins 权限:
const superAdmin = ac.newRole({
...adminAc.statements,
user: ["impersonate-admins", ...adminAc.statements.user],
});旧版选项 allowImpersonatingAdmins 仍受支持,但已弃用,将在未来版本中移除。
停止模拟用户
停止模拟用户,继续使用管理员账号。
await authClient.admin.stopImpersonating();删除用户
从数据库中彻底删除用户。
const { data: deletedUser, error } = await authClient.admin.removeUser({ userId: "user-id", // required});userIdstringrequiredThe user id which you want to remove.
访问控制
管理员插件提供了高度灵活的访问控制系统,允许您基于用户角色管理权限。您可以定义自定义权限集以满足需求。
角色
默认情况下,有两个角色:
admin:具有管理员角色的用户对其他用户拥有完全控制权。
user:具有用户角色的用户对其他用户无任何控制权。
一个用户可以拥有多个角色。多个角色以逗号(",")分隔字符串存储。
权限
默认情况下,有两个资源及最多六种权限。
user:
create list set-role ban impersonate impersonate-admins delete set-password
session:
list revoke delete
拥有管理员角色的用户对所有资源和操作拥有完全控制权。拥有用户角色的用户对任何操作均无控制权。
自定义权限
该插件提供简便的方式为每个角色定义自己的权限集。
Create Access Control
You first need to create an access controller by calling the createAccessControl function and passing the statement object. The statement object should have the resource name as the key and the array of actions as the value.
import { createAccessControl } from "better-auth/plugins/access";
/**
* 确保使用 `as const`,以便 TypeScript 正确推断类型
*/
const statement = {
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement); 为减小包体积,请确保从 better-auth/plugins/access 导入,而非 better-auth/plugins。
Create Roles
创建完访问控制器后,即可为定义的权限创建角色。
import { createAccessControl } from "better-auth/plugins/access";
export const statement = {
project: ["create", "share", "update", "delete"], // <-- 创建角色可用的权限
} as const;
export const ac = createAccessControl(statement);
export const user = ac.newRole({
project: ["create"],
});
export const admin = ac.newRole({
project: ["create", "update"],
});
export const myCustomRole = ac.newRole({
project: ["create", "update", "delete"],
user: ["ban"],
}); When you create custom roles for existing roles, the predefined permissions for those roles will be overridden. To add the existing permissions to the custom role, you need to import defaultStatements and merge it with your new statement, plus merge the roles' permissions set with the default roles.
import { createAccessControl } from "better-auth/plugins/access";
import { defaultStatements, adminAc } from "better-auth/plugins/admin/access";
const statement = {
...defaultStatements,
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement);
const admin = ac.newRole({
project: ["create", "update"],
...adminAc.statements,
});Pass Roles to the Plugin
Once you have created the roles you can pass them to the admin plugin both on the client and the server.
import { betterAuth } from "better-auth"
import { admin as adminPlugin } from "better-auth/plugins"
import { ac, admin, user } from "@/auth/permissions"
export const auth = betterAuth({
plugins: [
adminPlugin({
ac,
roles: {
admin,
user,
myCustomRole
}
}),
],
});You also need to pass the access controller and the roles to the client plugin.
import { createAuthClient } from "better-auth/client"
import { adminClient } from "better-auth/client/plugins"
import { ac, admin, user, myCustomRole } from "@/auth/permissions"
export const client = createAuthClient({
plugins: [
adminClient({
ac,
roles: {
admin,
user,
myCustomRole
}
})
]
})访问控制用法
拥有权限:
const { data, error } = await authClient.admin.hasPermission({ userId: "user-id", permission: { "project": ["create", "update"] } /* Must use this, or permissions */, permissions,});userIdstringThe user id which you want to check the permissions for.
permissionRecord<string, string[]>Optionally check if a single permission is granted. Must use this, or permissions.
permissionsRecord<string, string[]>Optionally check if multiple permissions are granted. Must use this, or permission.
示例用法:
import { authClient } from "@/lib/auth-client";
const canCreateProject = await authClient.admin.hasPermission({
permissions: {
project: ["create"],
},
});
// 也可以同时检查多个资源权限
const canCreateProjectAndCreateSale = await authClient.admin.hasPermission({
permissions: {
project: ["create"],
sale: ["create"]
},
});If you want to check a user's permissions server-side, you can use the userHasPermission action provided by the api to check the user's permissions.
import { auth } from "@/lib/auth"
await auth.api.userHasPermission({
body: {
userId: 'id', // 用户 id
permissions: {
project: ["create"], // 必须匹配访问控制中的结构
},
},
});
// 也可以直接传递角色
await auth.api.userHasPermission({
body: {
role: "admin",
permissions: {
project: ["create"], // 必须匹配访问控制中的结构
},
},
});
// 也可以同时检查多个资源权限
await auth.api.userHasPermission({
body: {
role: "admin",
permissions: {
project: ["create"], // 必须匹配访问控制中的结构
sale: ["create"]
},
},
});Check Role Permission:
注意此函数不会直接检查当前登录用户权限,而是检查指定角色拥有哪些权限。该函数为同步函数,调用时无需 await。
import { authClient } from "@/lib/auth-client";
const canCreateProject = authClient.admin.checkRolePermission({
permissions: {
user: ["delete"],
},
role: "admin",
});
// 也可以同时检查多个资源权限
const canDeleteUserAndRevokeSession = authClient.admin.checkRolePermission({
permissions: {
user: ["delete"],
session: ["revoke"]
},
role: "admin",
});架构
该插件为 user 表添加以下字段:
并在 session 表中添加一个字段:
电子邮件枚举保护
如果您使用 电子邮件枚举保护(requireEmailVerification 或 autoSignIn: false),您需要配置 customSyntheticUser,在伪造的注册响应中包含管理员插件字段:
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
customSyntheticUser: ({ coreFields, additionalFields, id }) => ({
...coreFields,
// 管理员插件字段(按架构顺序)
role: "user", // 或您配置的 defaultRole
banned: false,
banReason: null,
banExpires: null,
...additionalFields,
id,
}),
},
plugins: [admin()],
});选项
默认角色
用户的默认角色。默认为 user。
admin({
defaultRole: "regular",
});Admin Roles
管理员角色
指定哪些角色被视为管理员角色。默认为 ["admin"]。自定义角色(例如 superadmin)必须在自定义访问控制中定义。
admin({
// 需要在自定义访问控制中的 `roles` 里定义 `superadmin`
adminRoles: ["admin", "superadmin"],
});Note: The adminRoles option is not required when using custom access control (via ac and roles). When you define custom roles with specific permissions, those roles will have exactly the permissions you grant them through the access control system.
Warning: When not using custom access control, only admin and user exist as valid roles. Any role that isn't in the adminRoles list will not be able to perform admin operations.
管理员用户 ID
您可以传入一个管理员用户 ID 数组,默认为 []
admin({
adminUserIds: ["user_id_1", "user_id_2"]
})如果用户 ID 在 adminUserIds 列表中,他们将能执行任何管理员操作。
impersonationSessionDuration
模拟会话的持续时长,单位秒。默认为 1 小时。
admin({
impersonationSessionDuration: 60 * 60 * 24, // 1 天
});默认禁止原因
管理员创建用户时的默认禁止原因。默认为 No reason。
admin({
defaultBanReason: "Spamming",
});默认禁止过期时间
管理员创建用户时的默认禁止过期时间,单位秒。默认为 undefined(即禁止永不过期)。
admin({
defaultBanExpiresIn: 60 * 60 * 24, // 1 天
});禁止用户消息
禁止用户尝试登录时显示的消息。默认为 "You have been banned from this application. Please contact support if you believe this is an error."
admin({
bannedUserMessage: "自定义禁止用户提示信息",
});