ProductReadyProductReady

系统管理面板

管理系统管理员并访问管理控制面板

系统管理面板

系统管理面板提供了一个集中的界面,用于管理系统管理员和系统级操作。只有被授予系统管理员权限的用户才能访问。

访问控制:只有明确授予系统管理员权限的用户才能访问此面板。默认情况下,没有用户拥有管理员访问权限。


快速概览

功能

  • ✅ 管理系统管理员(添加/删除)
  • ✅ 跨所有空间的用户管理
  • ✅ AI 代理任务监控
  • ✅ 系统日志和设置
  • ✅ 基于角色的访问控制

路由/systemadmin

授权:每次请求都进行服务器端和客户端检查


访问面板

要求

要访问系统管理面板,用户必须:

  1. 已通过身份验证(已登录)
  2. 其用户 ID 在 systemAdmins 表中

演示模式

对于开发和测试,您可以在不进行授权的情况下访问面板:

/systemadmin?demo=1

演示模式绕过授权检查。切勿在生产环境中启用。


管理系统管理员

授予管理员访问权限

通过数据库(初始设置):

INSERT INTO systemAdmins (user_id, created_at, updated_at)
VALUES ('user-id-here', NOW(), NOW());

通过 UI(如果您已有访问权限):

  1. 导航到 /systemadmin/systemadmins
  2. 点击"添加系统管理员"
  3. 通过电子邮件搜索用户
  4. 选择用户
  5. 点击"添加管理员"

撤销管理员访问权限

通过 UI

  1. 导航到 /systemadmin/systemadmins
  2. 在列表中找到用户
  3. 点击删除(垃圾桶)图标
  4. 确认操作

通过数据库

DELETE FROM systemAdmins WHERE user_id = 'user-id-here';

面板部分

用户管理

路由/systemadmin/users

查看和管理平台上的所有用户:

  • 列出所有注册用户
  • 编辑用户详情(姓名、电子邮件)通过内联编辑对话框
  • 查看用户详情(姓名、电子邮件、注册日期)
  • 删除用户(需确认)
  • 点击任意用户行查看详细用户信息

编辑用户

  1. 点击用户旁边的编辑(铅笔)图标
  2. 在对话框中更新用户的姓名或电子邮件
  3. 点击"保存更改"以应用

所有用户管理操作都需要系统管理员权限,并受 systemAdminProcedure 中间件保护。

用户详情页面

路由/systemadmin/users/:id

点击用户列表中的任意用户查看其详细信息:

个人资料信息

  • 用户头像、姓名和电子邮件
  • 用户角色(管理员/用户)
  • 用户 ID
  • 电子邮件验证状态
  • 注册日期和最后更新时间

用户 Profile

  • Profile ID
  • 当前 Space ID(用户当前所在的工作空间)

主要空间

  • 用户作为所有者的组织
  • 空间计划和创建日期

组织成员资格

  • 用户所属的所有组织
  • 在每个组织中的角色(所有者、管理员、成员)
  • 每个组织的加入日期

通知记录

  • 发送给该用户的所有通知的完整历史记录
  • 包括邮箱验证、密码重置和邀请通知
  • 每条通知的已读/未读状态
  • 每条通知的时间戳

这为与用户的所有系统通信提供了完整的审计追踪。

系统管理员

路由/systemadmin/systemadmins

管理谁拥有系统管理员权限:

  • 查看所有当前系统管理员
  • 通过搜索用户添加新的系统管理员
  • 删除系统管理员权限
  • 查看管理员访问权限的授予时间

AI 代理任务

路由/systemadmin/agent-tasks

监控平台上的 AI 代理任务:

  • 查看所有代理任务
  • 检查任务状态和进度
  • 调试任务失败

AI 代理产物

路由/systemadmin/artifacts

查看 AI 代理生成的输出:

  • 浏览所有产物
  • 跟踪产物创建
  • 监控存储使用情况

系统设置

路由/systemadmin/settings

配置系统范围的设置:

  • 应用程序配置
  • 功能标志
  • 环境变量

日志

路由/systemadmin/logs

访问系统日志以进行调试:

  • 应用程序日志
  • 错误跟踪
  • 审计跟踪

Bonus 模板

路由/systemadmin/bonus-templates

管理促销活动的 Bonus 额度模板:

  • 创建/编辑/删除 Bonus 模板
  • 设置 Bonus 类型(AI Credits、Posts、Storage)
  • 配置数量和有效期
  • 设置适用计划(Free、Pro、Enterprise)
  • 切换启用状态

使用场景

  • 新用户欢迎奖励
  • 促销活动
  • 客户留存奖励

兑换码

路由/systemadmin/redemption-codes

管理促销和兑换码:

  • 创建单个或批量兑换码
  • 选择奖励类型:
    • 计划码:将用户升级到指定计划(Free/Pro/Enterprise)
    • Bonus 码:从模板发放 Bonus 额度
  • 设置最大兑换次数和过期日期
  • 查看兑换历史
  • 导出 CSV

创建兑换码

  1. 导航到 /systemadmin/redemption-codes
  2. 点击"创建兑换码"或"批量创建"
  3. 选择奖励类型(计划或 Bonus)
  4. 配置兑换码设置
  5. 分享给用户

开发设置

种子数据

种子脚本创建一个默认的系统管理员用户:

pnpm db:seed

默认管理员凭据

  • 电子邮件:admin@productready.dev
  • 密码:随机生成(在 seed 输出中显示)
  • 访问:/systemadmin

生产环境建议

方式一:从首次 seed 日志获取密码

  • 首次运行 db:seed 时,随机生成的管理员密码会打印在日志中
  • 请务必保存此密码,后续 seed 不会再显示
  • 适用于:本地开发、可查看日志的部署环境

方式二:通过环境变量强制设置密码

  • .env 或 K8s secrets 中设置:
    SYSTEM_ADMIN_PASSWORD=YourSecurePassword123!
  • 运行 pnpm db:seed,密码会被强制更新
  • 适用于:K8s、Docker 等容器化部署(日志可能丢失或不可见)

seed 脚本逻辑:

  • 账户不存在 → 使用 SYSTEM_ADMIN_PASSWORD 或随机生成
  • 账户已存在 + 设置了 SYSTEM_ADMIN_PASSWORD → 强制更新密码
  • 账户已存在 + 未设置 SYSTEM_ADMIN_PASSWORD → 保持现有密码不变

数据库架构

systemAdmins 表结构:

export const systemAdmins = pgTable(
  "systemAdmins",
  {
    userId: text("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull(),
    updatedAt: timestamp("updated_at", { mode: "date" })
      .defaultNow()
      .notNull()
      .$onUpdate(() => new Date()),
  },
  (table) => ({
    pk: primaryKey({ columns: [table.userId] }),
  }),
);

主要特性

  • 每个用户一个管理员条目(userId 上的主键)
  • 级联删除:删除用户会删除其管理员权限
  • 用于审计跟踪的时间戳

API 集成

tRPC 路由器

systemAdmins 路由器提供类型安全的 API 端点:

import { trpc } from '~/lib/trpc/client';

// 列出所有系统管理员
const { data } = trpc.systemAdmins.list.useQuery();

// 检查用户是否是系统管理员
const { data: isAdmin } = trpc.systemAdmins.isSiteAdmin.useQuery({
  userId: 'user-id'
});

// 将用户添加为系统管理员
const addMutation = trpc.systemAdmins.add.useMutation({
  onSuccess: () => {
    // 管理员添加成功
  }
});

// 删除系统管理员权限
const removeMutation = trpc.systemAdmins.remove.useMutation({
  onSuccess: () => {
    // 管理员删除成功
  }
});

授权中间件

对于受保护的仅限管理员的路由:

import { siteAdminProcedure } from '~/server/trpc';

export const adminOnlyRouter = createTRPCRouter({
  sensitiveOperation: siteAdminProcedure
    .input(z.object({ id: z.string() }))
    .mutation(async ({ ctx, input }) => {
      // 这只会在用户是系统管理员时执行
      // ctx.isSiteAdmin 在这里保证为 true
    }),
});

安全注意事项

访问控制

  1. 服务器端验证:每个 /systemadmin 页面在服务器上检查授权
  2. tRPC 中间件:受保护的过程在执行前验证管理员状态
  3. 数据库约束:外键确保管理员是有效用户
  4. 失败时重定向:未经授权的用户被重定向到 /dashboard?error=unauthorized

最佳实践

  • 最小权限原则:仅在必要时授予管理员访问权限
  • 定期审计:定期审查管理员列表
  • 立即撤销:不再需要时立即删除管理员访问权限
  • 审计日志:跟踪所有管理员权限更改(即将推出)

切勿共享系统管理员凭据。每个管理员应使用自己的帐户。


故障排除

无法访问管理面板

问题:访问 /systemadmin 时被重定向到仪表板

解决方案

  1. 验证您已登录
  2. 检查您的用户 ID 是否在 systemAdmins 表中:
    SELECT * FROM systemAdmins WHERE user_id = 'your-user-id';
  3. 使用演示模式进行测试:/systemadmin?demo=1

找不到管理员用户

问题:无法将用户添加为管理员

可能的原因

  • 用户在数据库中不存在
  • 用户 ID 不正确
  • 数据库连接问题

解决方案

-- 验证用户是否存在
SELECT id, email FROM users WHERE email = 'user@example.com';

未应用迁移

问题systemAdmins 表不存在

解决方案

cd apps/productready
pnpm db:migrate

相关文档


下一步

  • 为管理员权限更改添加审计日志
  • 实现超越管理员/非管理员的基于角色的权限
  • 为权限更改添加电子邮件通知
  • 创建管理员活动仪表板

On this page