- 稳定性
- 稳定
- 作用域
- 全局
- 边界
- packages/platform/db
查询 · packages/platform/db
RLS已启用apps/web/app/posts/page.tsx
// Tenant context resolved by @nebutra/tenant middleware
const ctx = getCurrentTenant();
const posts = await prisma.post.findMany({
where: {
tenantId: ctx.tenant.id,
published: true,
},
orderBy: { publishedAt: "desc" },
take: 5,
});
// → Prisma client wrapped with withRls(prisma, ctx.tenant.id)
// → PostgreSQL enforces RLS via SET LOCAL app.tenant_id
查询结果
通过行级安全按租户隔离
| id | title | tenant_id | published_at |
|---|---|---|---|
| pst_01HF…a3k | Launching multi-tenant RLS | tenant_a | 2026-05-21 |
| pst_01HF…b7m | Migrating off shared schemas | tenant_a | 2026-05-18 |
| pst_01HF…c2q | Internal roadmap (draft) | tenant_b | 2026-05-17 |
| pst_01HF…d9s | Customer-only changelog | tenant_c | 2026-05-15 |
| pst_01HF…e4w | RFC: schema-per-tenant | tenant_b | 2026-05-12 |
RLS 在数据库层屏蔽其他租户的行,应用永远看不到它们。
可见行
847
tenant_a 内
RLS 隐藏
12,401
其他租户
使用方式db.ts
typescriptdb.ts
1import { prisma } from "@nebutra/db";
2
3// Wrapped Prisma client — RLS enforced via withRls() per request.
4const posts = await prisma.post.findMany({
5 where: { tenantId: ctx.tenant.id, published: true },
6 include: { author: true },
7 orderBy: { publishedAt: "desc" },
8 take: 20,
9});
10
11await prisma.$transaction(async (tx) => {
12 await tx.post.update({ where: { id }, data: { published: true } });
13 await tx.auditLog.create({ data: { action: "post.publish", postId: id } });
14});