Prisma Studio is not an admin panel

Prisma Studio is not an admin panel

Prisma Studio 并不是一个管理后台

If you build with Prisma, you already know Prisma Studio. Run one command and you get a clean, visual way to browse and edit rows in your database. It’s genuinely useful, and I reach for it every day while developing. 如果你使用 Prisma 进行开发,那你一定很熟悉 Prisma Studio。只需运行一条命令,你就能获得一个简洁、可视化的界面来浏览和编辑数据库中的行。它确实非常实用,我在日常开发中每天都会用到它。

But somewhere between “I need to look at my data” and “I need to let a support agent safely edit a customer’s record in production,” Prisma Studio quietly stops being the right tool. It was never trying to be that tool. It’s a database viewer. An admin panel is something else, and the gap between the two is exactly the part that matters once real people and real permissions are involved. 但当你的需求从“我需要查看数据”转变为“我需要让客服人员安全地编辑生产环境中的客户记录”时,Prisma Studio 就不再是合适的工具了。它本身就不是为了这个目的设计的,它只是一个数据库查看器。管理后台是另一回事,而这两者之间的差距,正是涉及真实用户和权限控制时最关键的部分。

I ended up building a small package to fill that gap for my own Express + Prisma apps. Writing it forced me to be precise about what an admin panel actually adds on top of a database browser. Here’s the distinction as I now understand it. A database browser shows rows. An admin panel governs them. 为了填补这个空白,我为自己的 Express + Prisma 应用构建了一个小型包。在编写它的过程中,我不得不明确管理后台在数据库浏览器之上到底增加了什么。以下是我对两者区别的理解:数据库浏览器负责展示数据行,而管理后台负责管理它们。

Prisma Studio connects to your database and shows you everything. That’s the point of it, and it’s also why you’d never hand it to a non-engineer or expose it in production. It has no concept of who is looking, what they’re allowed to do, or which rows they’re allowed to touch. An admin panel’s whole job is those three questions. Prisma Studio 连接到你的数据库并展示所有内容。这就是它的核心价值,也是为什么你绝不会把它交给非技术人员或在生产环境中暴露它的原因。它没有“谁在查看”、“他们被允许做什么”或“他们可以触碰哪些行”的概念。而管理后台的全部工作就是解决这三个问题。

The package I built mounts a React UI at /admin and a guarded JSON API under /admin/api/* on your existing Express app. Every single request through that API runs the same pipeline, in the same order: authentication → permission check → tenant scope → validation → Prisma mutation/query → optional audit event. 我构建的这个包会在你现有的 Express 应用中挂载一个位于 /admin 的 React UI,以及位于 /admin/api/* 下受保护的 JSON API。通过该 API 的每一个请求都会按顺序执行相同的流水线:身份验证 → 权限检查 → 租户范围限制 → 数据校验 → Prisma 变更/查询 → 可选的审计事件。

That ordering is the entire difference. A database browser skips straight to the mutation. An admin panel refuses to run the mutation until it knows the request is authenticated, permitted, scoped to the right tenant, and valid. 这种顺序上的差异就是一切。数据库浏览器直接跳到变更操作,而管理后台在确认请求已通过身份验证、拥有权限、限定在正确的租户范围内且数据合法之前,会拒绝执行任何变更。

Permissions and scope are two different questions

权限与范围是两个不同的问题

This was the design decision I care most about, because collapsing these two into one is how data leaks happen. Permissions decide which actions a role may take. Can an editor delete a post? Can a support agent create a user? Scope decides which rows a role may see or act on. A support agent for Tenant A should never be able to read, update, or delete Tenant B’s records — even for actions they’re otherwise fully permitted to perform. 这是我最看重的设计决策,因为将这两者混为一谈正是导致数据泄露的原因。权限决定了角色可以执行哪些操作(例如:编辑者可以删除文章吗?客服可以创建用户吗?),而范围决定了角色可以看到或操作哪些行。Tenant A 的客服绝不应该能够读取、更新或删除 Tenant B 的记录——即使他们拥有执行这些操作的权限。

Keeping these separate means “you may edit users” and “you may edit these users” are enforced independently. Scope is applied everywhere it needs to be: lists, single reads, updates, deletes, the choices offered in relation dropdowns, and custom actions. It’s the kind of thing that’s easy to get 90% right and have the last 10% be a cross-tenant data breach, so the test suite specifically checks that Tenant A cannot view, update, or delete Tenant B’s records. Prisma Studio has no place to even express this idea. There’s no role, so there’s nothing to scope. 将两者分开意味着“你可以编辑用户”和“你可以编辑这些用户”是独立执行的。范围限制被应用在所有必要的地方:列表、单条读取、更新、删除、关联下拉菜单中的选项以及自定义操作。这类功能很容易做到 90% 正确,但剩下的 10% 可能会导致跨租户数据泄露,因此测试套件专门检查了 Tenant A 是否无法查看、更新或删除 Tenant B 的记录。Prisma Studio 甚至没有地方来表达这种逻辑,因为它没有角色概念,也就无法进行范围限制。

Auth that doesn’t touch your users table

不触碰你用户表的身份验证

Built-in authentication is optional, and when you use it, it deliberately stays out of your application’s own data. It uses separate ExpressAdminUser and ExpressAdminSession models rather than reading or modifying your app’s user and session records. Your admins and your end users are different populations, and mixing them is a recipe for accidents. 内置的身份验证是可选的,当你使用它时,它会刻意避开你应用自身的数据。它使用独立的 ExpressAdminUserExpressAdminSession 模型,而不是读取或修改你应用的用户和会话记录。你的管理员和终端用户是不同的人群,将他们混在一起极易引发事故。

The built-in auth ships with an admin login page, database-backed sessions, a createsuperuser CLI command, HttpOnly / SameSite=Lax cookies, and sign-in throttling. If you already have an auth system you’d rather use, you can bring that instead. 内置的身份验证功能包括管理员登录页面、基于数据库的会话、createsuperuser 命令行工具、HttpOnly / SameSite=Lax Cookie 以及登录频率限制。如果你已经有想用的身份验证系统,也可以直接接入。

Audit logging you own

你所拥有的审计日志

After a successful mutation, the library can emit safe event metadata so you have a record of who changed what. Deliberately, it does not ship its own audit table. You own where those events go and how long they live, because audit storage is a policy decision that belongs to your application, not to a library. 在变更操作成功后,该库可以发出安全的事件元数据,让你记录下“谁修改了什么”。它刻意没有内置审计表。你拥有这些事件的存储位置和保留期限,因为审计存储属于应用层面的策略决策,而不属于库本身。

What it is not — and this part is important

它不是什么——这一点很重要

I want to be honest about the boundaries, because the fastest way to disappoint someone is to let them think this is something it isn’t. It is not a CMS and not a general-purpose internal-tools platform. Today, writes support scalar fields plus selecting a single belongsTo foreign key. 我想坦诚地说明它的边界,因为让别人产生误解是让人失望的最快方式。它不是 CMS,也不是通用的内部工具平台。目前,写入操作仅支持标量字段以及选择单个 belongsTo 外键。

That means: 这意味着:

  • No nested writes (不支持嵌套写入)
  • No many-to-many editors (不支持多对多编辑器)
  • No hasMany inline tables (不支持一对多内联表)
  • No file uploads (不支持文件上传)
  • No rich text or custom widgets (不支持富文本或自定义组件)
  • No exports (不支持导出)
  • No built-in audit-history UI (没有内置的审计历史 UI)

It currently supports Prisma 7.5.x only. If you need those things, you need a heavier tool, and that’s a completely reasonable place to land. What this package does is take the narrow, common, security-sensitive case - schema-driven CRUD that respects permissions and tenant boundaries - and do that part carefully. 它目前仅支持 Prisma 7.5.x。如果你需要上述功能,你需要更强大的工具,这完全合理。这个包所做的是专注于狭窄、常见且对安全性敏感的场景——即遵循权限和租户边界的模式驱动 CRUD——并把这一部分做好。

The one-line version

一句话总结

Prisma Studio answers “what’s in my database?” An admin panel answers “who is allowed to change what, and did we record it?” Both are worth having. They’re just not the same tool, and reaching for the database browser when you needed the governance layer is a mistake you usually only notice after it’s cost you something. Prisma Studio 回答的是“我的数据库里有什么?”,而管理后台回答的是“谁被允许修改什么,以及我们是否记录了这些操作?”两者都很有价值,但它们不是同一个工具。当你需要治理层时却去使用数据库浏览器,这通常只有在付出代价后才会意识到是一个错误。