审计日志

通过自动审计日志记录,跟踪并查询应用中的身份验证事件。

Better Auth 基础设施会自动收集您应用中的身份验证事件审计日志。一旦您添加了 dash() 插件,事件即会在无需额外配置的情况下被追踪。

审计日志的收集方式

dash() 插件会挂载到您的 Better Auth 实例中,自动记录发生的事件。无需手动插桩——注册、登录、密码更改等操作均会被捕获。

import { betterAuth } from "better-auth";
import { dash } from "@better-auth/infra";

export const auth = betterAuth({
  plugins: [
    dash(),
  ],
});

就这样。dash() 激活后,审计日志会自动被收集。

跟踪事件

事件触发条件
user_signed_up新用户注册
user_profile_updated用户更新个人资料
user_profile_image_updated用户更改头像
user_email_verified邮箱验证完成
user_banned用户被封禁
user_unbanned用户解封
user_deleted用户账户删除

获取审计日志

客户端设置

在您的认证客户端中添加 dashClient():

import { createAuthClient } from "better-auth/client";
import { dashClient } from "@better-auth/infra/client";

export const authClient = createAuthClient({
  plugins: [dashClient()],
});

获取当前用户的审计日志

返回 当前用户 的审计事件。用于终端用户活动以及调用方为普通成员的组织视图。

查询参数

参数类型描述
limitnumber每页结果数(最大 100,默认 50)
offsetnumber分页偏移量(默认 0)
organizationIdstring按组织筛选
identifierstring按标识符筛选
eventTypestring按事件类型筛选
userIdstring按用户 ID 筛选
userobject带有 ID 的用户对象
sessionobject带有用户的会话对象

基本查询

const session = await authClient.getSession();

const logs = await authClient.dash.getAuditLogs({
  session: session.data,
  limit: 50,
  offset: 0,
});

logs.data?.events;  // 审计日志事件数组
logs.data?.total;   // 总数量
logs.data?.limit;   // 每页大小
logs.data?.offset;  // 当前偏移量

按事件类型筛选

返回当前用户的登录审计日志。

const signIns = await authClient.dash.getAuditLogs({
  session: session.data,
  eventType: "user_signed_in",
});

按组织筛选

返回当前用户在指定组织范围内的审计日志。

const orgLogs = await authClient.dash.getAuditLogs({
  session: session.data,
  organizationId: "org_123",
});

组合筛选

您可以组合筛选条件以获得更具体的结果(例如,当前用户在特定组织中的所有登录事件)。

const orgSignIns = await authClient.dash.getAuditLogs({
  session: session.data,
  organizationId: "org_123",
  eventType: "user_signed_in",
});

您也可以将结果限制为特定标识符(例如,当前用户在特定组织和邮箱下的所有事件)。

const orgSignIns = await authClient.dash.getAuditLogs({
  session: session.data,
  organizationId: "org_123",
  identifier: "[email protected]",
});

注意:标识符是事件的唯一值。例如,电子邮件地址、用户名等。

分页

结果是分页返回的。如果您需要获取多页内容,可以使用 limit 和 offset 参数对结果进行分页:

async function fetchAllUserAuditLogEvents(session: unknown) {
  const limit = 100;
  let offset = 0;
  const allEvents = [];

  while (true) {
    const result = await authClient.dash.getAuditLogs({
      session: session.data,
      limit,
      offset,
    });
    
    const events = result.data?.events ?? [];
    allEvents.push(...events);

    if (events.length < limit) break;
    offset += limit;
  }

  return allEvents;
}

获取全部审计日志

返回当前用户拥有 管理员 或 所有者 访问权限的组织的所有审计事件。用于需要跨您管理的组织查看活动的管理员式仪表盘。 您必须使用 组织插件,以便评估成员角色。

查询参数

参数类型描述
limitnumber每页结果数(最大 100,默认 50)
offsetnumber分页偏移量(默认 0)
organizationIdstring将结果限制为一个组织(您必须是所有者或管理员)
userIdstring限制为您以所有者或管理员身份管理的组织中某一用户的活动
eventTypestring按事件类型筛选
identifierstring匹配 eventData.identifier(组织范围内的主体标识)
sessionobject带有用户的会话对象

基本查询

const session = await authClient.getSession();

const activity = await authClient.dash.getAllAuditLogs({
  session: session.data,
  limit: 50,
  offset: 0,
});

activity.data?.events;
activity.data?.total;
activity.data?.limit;
activity.data?.offset;

按组织筛选

返回指定组织的所有审计事件:

const orgActivity = await authClient.dash.getAllAuditLogs({
  session: session.data,
  organizationId: "org_123",
});

按用户筛选

返回跨组织的指定用户的所有审计事件:

const userActivity = await authClient.dash.getAllAuditLogs({
  session: session.data,
  userId: "user_456",
});

按事件类型筛选

返回跨组织的指定事件类型的所有审计事件:

const events = await authClient.dash.getAllAuditLogs({
  session: session.data,
  eventType: "member_invited",
});

组合筛选

您可以组合筛选条件以获得更具体的结果(例如,指定组织和事件类型的所有审计事件)。

const orgEvents = await authClient.dash.getAllAuditLogs({
  session: session.data,
  organizationId: "org_123",
  eventType: "member_invited",
});

分页

结果是分页返回的。如果您需要获取多页内容,可以使用 limit 和 offset 参数对结果进行分页:

async function fetchAllAuditLogs(session: unknown) {
  const limit = 100;
  let offset = 0;
  const allEvents = [];

  while (true) {
    const result = await authClient.dash.getAllAuditLogs({
      session: session.data,
      limit,
      offset,
    });
    
    const events = result.data?.events ?? [];
    allEvents.push(...events);

    if (events.length < limit) break;
    offset += limit;
  }

  return allEvents;
}