管理员
Admin 插件为你的应用提供了一套用户管理的管理功能。它允许管理员执行各种操作,如创建用户、管理用户角色、封禁/解封用户、模拟用户以及更多操作。
【The Admin plugin provides a set of administrative functions for user management in your application. It allows administrators to perform various operations such as creating users, managing user roles, banning/unbanning users, impersonating users, and more.】
安装
【Installation】
将插件添加到你的认证配置
要使用管理员插件,请将其添加到你的身份验证配置中。
import { betterAuth } from "better-auth"
import { admin } from "better-auth/plugins"
export const auth = betterAuth({
// ... other config options
plugins: [
admin()
]
})迁移数据库
运行迁移或生成架构,以向数据库添加必要的字段和表。
npx @better-auth/cli migratenpx @better-auth/cli 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()
]
})用法
【Usage】
在执行任何管理员操作之前,用户必须使用管理员账户进行身份验证。管理员是指被分配了 admin 角色的任何用户,或者其 ID 包含在 adminUserIds 选项中的任何用户。
【Before performing any admin operations, the user must be authenticated with an admin account. An admin is any user assigned the admin role or any user whose ID is included in the adminUserIds option.】
创建用户
【Create User】
允许管理员创建新用户。
【Allows an admin to create a new user.】
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" },});| Prop | Description | Type |
|---|---|---|
email | The email of the user. | string |
password | The password of the user. | string |
name | The name of the user. | string |
role? | A string or array of strings representing the roles to apply to the new user. | string | string[] |
data? | Extra fields for the user. Including custom additional fields. | Record<string, any> |
列出用户
【List Users】
允许管理员列出数据库中的所有用户。
【Allows an admin to list all users in the database.】
所有属性都是可选配置的。默认情况下返回 100 行,你可以通过 limit 属性进行配置。
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", },});| Prop | Description | Type |
|---|---|---|
searchValue? | The value to search for. | string |
searchField? | The field to search in, defaults to email. Can be email or name. | "email" | "name" |
searchOperator? | The operator to use for the search. Can be contains, starts_with or ends_with. | "contains" | "starts_with" | "ends_with" |
limit? | The number of users to return. Defaults to 100. | string | number |
offset? | The offset to start from. | string | number |
sortBy? | The field to sort by. | string |
sortDirection? | The direction to sort by. | "asc" | "desc" |
filterField? | The field to filter by. | string |
filterValue? | The value to filter by. | string | number | boolean |
filterOperator? | The operator to use for the filter. | "eq" | "ne" | "lt" | "lte" | "gt" | "gte" |
查询过滤
【Query Filtering】
listUsers 函数支持多种筛选操作符,包括 eq、contains、starts_with 和 ends_with。
【The listUsers function supports various filter operators including eq, contains, starts_with, and ends_with.】
分页
【Pagination】
listUsers 函数通过在用户列表旁返回元数据来支持分页。响应包括以下字段:
【The listUsers function supports pagination by returning metadata alongside the user list. The response includes the following fields:】
{
users: User[], // Array of returned users
total: number, // Total number of users after filters and search queries
limit: number | undefined, // The limit provided in the query
offset: number | undefined // The offset provided in the query
}如何实现分页
【How to Implement Pagination】
要对结果进行分页,请使用 total、limit 和 offset 值来计算:
【To paginate results, use the total, limit, and offset values to calculate:】
- 总页数:
Math.ceil(total / limit) - 当前页:
(offset / limit) + 1 - 下一页偏移量:
Math.min(offset + limit, (total - 1))– 用作下一页offset的值,确保其不超过总页数。 - 上一页偏移量:
Math.max(0, offset - limit)– 用作上一页offset的值(确保其不小于零)。
示例用法
【Example Usage】
获取第二页,每页 10 个用户:
【Fetching the second page with 10 users per page:】
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)设置用户角色
【Set User Role】
更改用户的角色。
【Changes the role of a user.】
const { data, error } = await authClient.admin.setRole({ userId: "user-id", role: "admin", // required});| Prop | Description | Type |
|---|---|---|
userId? | The user id which you want to set the role for. | string |
role | The role to set, this can be a string or an array of strings. | string | string[] |
设置用户密码
【Set User Password】
更改用户的密码。
【Changes the password of a user.】
const { data, error } = await authClient.admin.setUserPassword({ newPassword: 'new-password', // required userId: 'user-id', // required});| Prop | Description | Type |
|---|---|---|
newPassword | The new password. | string |
userId | The user id which you want to set the password for. | string |
更新用户
【Update user】
更新用户的详细信息。
【Update a user's details.】
const { data, error } = await authClient.admin.updateUser({ userId: "user-id", // required data: { name: "John Doe" }, // required});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to update. | string |
data | The data to update. | Record<string, any> |
封禁用户
【Ban User】
禁止用户,阻止其登录,并撤销其所有现有会话。
【Bans a user, preventing them from signing in and revokes all of their existing sessions.】
await authClient.admin.banUser({ userId: "user-id", // required banReason: "Spamming", banExpiresIn: 60 * 60 * 24 * 7,});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to ban. | string |
banReason? | The reason for the ban. | string |
banExpiresIn? | The number of seconds until the ban expires. If not provided, the ban will never expire. | number |
解除用户封禁
【Unban User】
解除用户的封禁,允许他们重新登录。
【Removes the ban from a user, allowing them to sign in again.】
await authClient.admin.unbanUser({ userId: "user-id", // required});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to unban. | string |
列出用户会话
【List User Sessions】
列出用户的所有会话。
【Lists all sessions for a user.】
const { data, error } = await authClient.admin.listUserSessions({ userId: "user-id", // required});| Prop | Description | Type |
|---|---|---|
userId | The user id. | string |
撤销用户会话
【Revoke User Session】
撤销用户的特定会话。
【Revokes a specific session for a user.】
const { data, error } = await authClient.admin.revokeUserSession({ sessionToken: "session_token_here", // required});| Prop | Description | Type |
|---|---|---|
sessionToken | The session token which you want to revoke. | string |
撤销用户的所有会话
【Revoke All Sessions for a User】
撤销用户的所有会话。
【Revokes all sessions for a user.】
const { data, error } = await authClient.admin.revokeUserSessions({ userId: "user-id", // required});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to revoke all sessions for. | string |
模拟用户
【Impersonate User】
此功能允许管理员创建一个模拟指定用户的会话。该会话将保持活动状态,直到浏览器会话结束或达到 1 小时。你可以通过设置 impersonationSessionDuration 选项来更改此持续时间。
【This feature allows an admin to create a session that mimics the specified user. The session will remain active until either the browser session ends or it reaches 1 hour. You can change this duration by setting the impersonationSessionDuration option.】
const { data, error } = await authClient.admin.impersonateUser({ userId: "user-id", // required});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to impersonate. | string |
停止冒充用户
【Stop Impersonating User】
要停止冒充用户并继续使用管理员账户,你可以使用 stopImpersonating
【To stop impersonating a user and continue with the admin account, you can use stopImpersonating】
await authClient.admin.stopImpersonating();删除用户
【Remove User】
从数据库中彻底删除用户。
【Hard deletes a user from the database.】
const { data: deletedUser, error } = await authClient.admin.removeUser({ userId: "user-id", // required});| Prop | Description | Type |
|---|---|---|
userId | The user id which you want to remove. | string |
访问控制
【Access Control】
管理员插件提供了一个高度灵活的访问控制系统,让你可以根据用户的角色管理权限。你可以定义自定义的权限集以满足你的需求。
【The admin plugin offers a highly flexible access control system, allowing you to manage user permissions based on their role. You can define custom permission sets to fit your needs.】
角色
【Roles】
默认情况下,有两个角色:
【By default, there are two roles:】
admin:具有管理员角色的用户可以完全控制其他用户。
user:具有用户角色的用户无法控制其他用户。
一个用户可以拥有多个角色。多个角色以逗号(“,”)分隔的字符串形式存储。
权限
【Permissions】
默认情况下,有两个资源,每个资源最多有六个权限。
【By default, there are two resources with up to six permissions.】
用户:
create list set-role ban impersonate delete set-password
会话:
list revoke delete
具有管理员角色的用户对所有资源和操作拥有完全控制权。具有用户角色的用户对这些操作没有控制权。
【Users with the admin role have full control over all the resources and actions. Users with the user role have no control over any of those actions.】
自定义权限
【Custom Permissions】
该插件提供了一种简便的方法,让你可以为每个角色定义自己的权限集。
【The plugin provides an easy way to define your own set of permissions for each role.】
创建访问控制
你首先需要通过调用 createAccessControl 函数并传入语句对象来创建一个访问控制器。语句对象应该以资源名称作为键,以动作数组作为值。
import { createAccessControl } from "better-auth/plugins/access";
/**
* make sure to use `as const` so typescript can infer the type correctly
*/
const statement = {
project: ["create", "share", "update", "delete"],
} as const;
const ac = createAccessControl(statement); 创建角色
一旦你创建了访问控制器,就可以创建具有你定义的权限的角色。
import { createAccessControl } from "better-auth/plugins/access";
export const statement = {
project: ["create", "share", "update", "delete"], // <-- Permissions available for created roles
} as const;
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"],
}); 当你为现有角色创建自定义角色时,这些角色的预定义权限将被覆盖。要将现有权限添加到自定义角色中,你需要导入 defaultStatements 并将其与你的新声明合并,同时将角色的权限集合与默认角色合并。
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,
});将角色传递给插件
一旦你创建了角色,就可以将它们传递给客户端和服务器上的管理员插件。
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
}
}),
],
});你还需要将访问控制器和角色传递给客户端插件。
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
}
})
]
})访问控制使用
【Access Control Usage】
有权限:
要检查用户的权限,你可以使用客户端提供的 hasPermission 函数。
【To check a user's permissions, you can use the hasPermission function provided by the client.】
const { data, error } = await authClient.admin.hasPermission({ userId: "user-id", permission: { "project": ["create", "update"] } /* Must use this, or permissions */, permissions,});| Prop | Description | Type |
|---|---|---|
userId? | The user id which you want to check the permissions for. | string |
permission? | Optionally check if a single permission is granted. Must use this, or permissions. | Record<string, string[]> |
permissions? | Optionally check if multiple permissions are granted. Must use this, or permission. | Record<string, string[]> |
使用示例:
【Example usage:】
const canCreateProject = await authClient.admin.hasPermission({
permissions: {
project: ["create"],
},
});
// You can also check multiple resource permissions at the same time
const canCreateProjectAndCreateSale = await authClient.admin.hasPermission({
permissions: {
project: ["create"],
sale: ["create"]
},
});如果你想在服务器端检查用户的权限,可以使用 api 提供的 userHasPermission 操作来检查用户的权限。
【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 "@/auth";
await auth.api.userHasPermission({
body: {
userId: 'id', //the user id
permissions: {
project: ["create"], // This must match the structure in your access control
},
},
});
// You can also just pass the role directly
await auth.api.userHasPermission({
body: {
role: "admin",
permissions: {
project: ["create"], // This must match the structure in your access control
},
},
});
// You can also check multiple resource permissions at the same time
await auth.api.userHasPermission({
body: {
role: "admin",
permissions: {
project: ["create"], // This must match the structure in your access control
sale: ["create"]
},
},
});检查角色权限:
在客户端使用 checkRolePermission 函数来验证给定的 角色 是否具有特定的 权限。在定义了角色及其权限之后,这非常有用,因为它允许你在不需要联系服务器的情况下进行权限检查。
【Use the checkRolePermission function on the client side to verify whether a given role has a specific permission. This is helpful after defining roles and their permissions, as it allows you to perform permission checks without needing to contact the server.】
请注意,此函数不会直接检查当前登录用户的权限。相反,它会检查指定角色被分配了哪些权限。该函数是同步的,因此调用时无需使用 await。
【Note that this function does not check the permissions of the currently logged-in user directly. Instead, it checks what permissions are assigned to a specified role. The function is synchronous, so you don't need to use await when calling it.】
const canCreateProject = authClient.admin.checkRolePermission({
permissions: {
user: ["delete"],
},
role: "admin",
});
// You can also check multiple resource permissions at the same time
const canDeleteUserAndRevokeSession = authClient.admin.checkRolePermission({
permissions: {
user: ["delete"],
session: ["revoke"]
},
role: "admin",
});架构
【Schema】
此插件向 user 表添加以下字段:
【This plugin adds the following fields to the user table:】
| Field Name | Type | Key | Description |
|---|---|---|---|
| role | string | 用户的角色。默认值为 `user`。管理员将具有 `admin` 角色。 | |
| banned | boolean | 指示用户是否被封禁。 | |
| banReason | string | 用户被封禁的原因。 | |
| banExpires | date | 用户封禁到期的日期。 |
并在 session 表中添加一个字段:
【And adds one field in the session table:】
| Field Name | Type | Key | Description |
|---|---|---|---|
| impersonatedBy | string | The ID of the admin that is impersonating this session. |
选项
【Options】
默认角色
【Default Role】
用户的默认角色。默认值为 user。
【The default role for a user. Defaults to user.】
admin({
defaultRole: "regular",
});管理员角色
【Admin Roles】
那些在没有使用自定义访问控制时被视为管理员角色的角色。默认为“[”admin“]'。
【The roles that are considered admin roles when not using custom access control. Defaults to ["admin"].】
admin({
adminRoles: ["admin", "superadmin"],
});注意: 当使用自定义访问控制(通过 ac 和 roles)时,adminRoles 选项 不是必需的。当你定义具有特定权限的自定义角色时,这些角色将仅拥有你通过访问控制系统授予它们的权限。
警告: 当不使用自定义访问控制时,任何不在 adminRoles 列表中的角色将无法执行管理员操作。
管理员用户 ID
【Admin userIds】
你可以传递一个应视为管理员的 userId 数组。默认值为 []
【You can pass an array of userIds that should be considered as admin. Default to []】
admin({
adminUserIds: ["user_id_1", "user_id_2"]
})如果用户在 adminUserIds 列表中,他们将能够执行任何管理员操作。
【If a user is in the adminUserIds list, they will be able to perform any admin operation.】
冒充会话持续时间
【impersonationSessionDuration】
模拟会话的持续时间(以秒为单位)。默认值为 1 小时。
【The duration of the impersonation session in seconds. Defaults to 1 hour.】
admin({
impersonationSessionDuration: 60 * 60 * 24, // 1 day
});默认封禁原因
【Default Ban Reason】
由管理员创建的用户的默认封禁原因。默认为 No reason。
【The default ban reason for a user created by the admin. Defaults to No reason.】
admin({
defaultBanReason: "Spamming",
});默认封禁到期时间
【Default Ban Expires In】
默认情况下,由管理员创建的用户的封禁将在指定秒数后到期。默认值为 undefined(意味着封禁永不过期)。
【The default ban expires in for a user created by the admin in seconds. Defaults to undefined (meaning the ban never expires).】
admin({
defaultBanExpiresIn: 60 * 60 * 24, // 1 day
});被禁止的用户消息
【bannedUserMessage】
当被禁止的用户尝试登录时显示的消息。默认消息为“你已被禁止使用此应用。如果你认为这是错误,请联系支持。”
【The message to show when a banned user tries to sign in. Defaults to "You have been banned from this application. Please contact support if you believe this is an error."】
admin({
bannedUserMessage: "Custom banned user message",
});允许冒充管理员
【allowImpersonatingAdmins】
是否允许冒充其他管理员用户。默认值为 false。
【Whether to allow impersonating other admin users. Defaults to false.】
admin({
allowImpersonatingAdmins: true,
});