@casl/prisma

中文文档
2.2.0发布于 2026/10/28MITTypeScriptESM + CJS构建来源已验证近 30 天下载 81.2万

允许根据 CASL 规则使用 Prisma 客户端查询可访问的记录

中文使用文档
文档目录12 节
  1. 安装
  2. 使用量
  3. 关于主题助手的说明
  4. 关于 Prisma 查询运行时解释器的说明
  5. Prisma 7 配置
  6. 查找可访问的记录
  7. Prisma 客户端扩展名
  8. 类型脚本支持
  9. Prisma 查询
  10. 自定义 Prisma 客户端输出路径( Prisma 7 默认)
  11. 想帮忙吗?
  12. 许可证

卡塞尔·普里斯马

@casl/prisma NPM version Support

此软件包允许定义 卡塞尔 权限在 普里斯马 使用 Prisma 的模型 WhereInput. 这在SQL世界的许可管理方面带来了很大的力量:

  1. 我们可以使用 Prisma 查询来定义权限, 无需再学习 MongoDB 查询语言 .
  2. 此外,我们可以问我们的SQL数据库的问题,例如:"哪些记录可以读取"或者"哪些记录可以更新".

安装

npm install @casl/prisma @casl/ability
# or
yarn add @casl/prisma @casl/ability
# or
pnpm add @casl/prisma @casl/ability

@casl/prisma 需要 Prisma 客户端 4.1.6.0 或稍后。 Prisma 客户端扩展为 createCaslExtension 需要添加到 Prisma 客户端的帮助 !

使用量

这个软件包与其它软件包有些不同,因为它提供了一个自定义 createPrismaAbility 配置用于使用 Prisma 检查权限的工厂函数 输入位置数字 :

import { User, Post, Prisma } from '@prisma/client';
import { Ability, AbilityBuilder, subject, type ForcedSubject, type TaggedSubject } from '@casl/ability';
import { createPrismaAbility, PrismaQuery } from '@casl/prisma';

type AppSubjects =
  | User & ForcedSubject<'User'>
  | Post & ForcedSubject<'Post'>
type AppAbility = Ability<[string, AppSubjects], PrismaQuery, TaggedSubject>;
const { can, cannot, build } = new AbilityBuilder<AppAbility>(createPrismaAbility);

can('read', 'Post', { authorId: 1 });
cannot('read', 'Post', { title: { startsWith: '[WIP]:' } });

const ability = build();
ability.can('read', 'Post');
ability.can('read', subject('Post', { title: '...', authorId: 1 })));

见 CASL 指南 学习如何定义能力。 除条件语言外,一切都是一样的.

如果您使用 Prisma 7 生成 Prisma 客户端 prisma-client 生成器, 从您生成的客户端路径导入模型类型( 例如 ) ./prisma/generated/client并创建一个小包装 @casl/prisma/runtime 如下所示.

关于主题助手的说明

ForcedSubject<'Post'> 在对象上声明标记 。 当主题结合只包含标记对象类型时,必须指定 TaggedSubject 作为第三个通用参数: Ability 或者说 PrismaAbility 还接受主题名称,例如: 'Post' 在许可检查中:

type AppAbility = Ability<[string, AppSubjects], PrismaQuery, TaggedSubject>;

TaggedSubject 用途 __caslSubjectType__ 在默认情况下,匹配 subject 帮手 如果你忽略了第三个通用参数, DefaultSubject 保留已存在的行为: 明确包含名称和标记对象类型, 例如 Ability<[string, 'User' | 'Post' | AppSubjects], PrismaQuery>。 。 。 .

因为Prisma在不披露任何类型信息的情况下返回了DTO对象,所以我们需要使用 subject 帮助手动提供该类型,因此CASL可以理解哪些规则适用于对象所传.

不幸的是,除了在所有模型中增加一栏之外,没有实现自动化的简单方法。 详情请检查 这个问题。 。 。 .

要了解更多关于对象类型的检测细节, 请读 CASL 主题类型检测

关于 Prisma 查询运行时解释器的说明

@casl/prisma 用途 播音员 解释 Prisma 输入位置 在 JavaScript 运行时。 然而,没有多少说明:

  • 未实现 JSON 列的平等
  • 未实现数组/列表列的等同性(尽管操作符喜欢) has, (中文(简体) ), hasSome 财务报告和审定财务报表 hasEvery 足够多了)
  • 在确定关系条件时,总是指定一个操作员(every, (中文(简体) ), none, (中文(简体) ), some, (中文(简体) ), is 或者说 isNot(中文(简体) )

口译员投出a ParsingQueryError 如果它接收到查询操作器的无效参数,或者如果某些操作没有被支持.

Prisma 7 配置

Prisma 7 将连接细节移动到 prisma.config.ts 不再装入 .env 文件自动。 在您的方案上添加配置 prisma generate 继续工作 :

// prisma.config.ts
import 'dotenv/config';
import { defineConfig } from 'prisma/config';

export default defineConfig({
  schema: './schema.prisma',
  datasource: {
    // fall back to a local URL so generate does not fail in CI
    url: process.env.DATABASE_URL ?? 'postgresql://postgres:postgres@localhost:5432/postgres',
  },
});

如果你坚持遗产 prisma-client-js 生成器, 默认 @prisma/client 导入继续工作.

查找可访问的记录

一个不错的特征 普里斯马 财务报告和审定财务报表 卡塞尔 整合就是我们能够从数据库中获取所有记录,我们的用户可以访问. 要做到这一点,只是使用 accessibleBy 帮助函数 :

// ability is a PrismaAbility instance created in the example above

const accessiblePosts = await prisma.post.findMany({
  where: accessibleBy(ability).ofType('Post')
});

该函数接受 Ability 实例和实例 action (违约) read),返回实例 AccessibleRecords 带有 ofType 用于接受 Prisma 模型名称并返回从权限规则汇总的对象的方法 WhereInput。 。 。 .

重要:如果用户无法访问任何帖子, .ofType 返回一个特殊的空条件。 如果您直接传递给 Prisma 客户端, 无需 createCaslExtension,Prisma 拒绝查询,因为该条件包含一个内部标记字段. 这使得被拒绝的访问被关闭.

把这个与商业逻辑条件结合起来,只需要使用 AND数字 :

const accessiblePosts = await prisma.post.findMany({
  where: {
    AND: [
      accessibleBy(ability).ofType('Post'),
      { /* business related conditions */ }
    ]
  }
})

为当前Prisma扩展执行,设置 accessibleBy(...) 在复合条件下,例如 AND: [...] 允许更快地对空条件检测到短路.

Prisma 客户端扩展名

createCaslExtension 地址 这个问题 通过让Prisma客户端将 CASL 的空条件作为空查询结果处理,而不是丢弃被禁错误.

重要内容: 请确保将此扩展添加到您用于 CASL 保护查询的 Prisma 客户端实例中。 否则,某些CASL限制可能应用不当.

添加为其它常规扩展 :

import { PrismaClient } from '@prisma/client';
import { createCaslExtension } from '@casl/prisma';

const prisma = new PrismaClient().$extends(createCaslExtension());

有了这个扩展,带有空 CASL 条件的操作返回同样类型的"无记录"结果 Prisma 用户通常期望:

const posts = await prisma.post.findMany({
  where: accessibleBy(ability).ofType('Post')
});
// posts === []

需要匹配记录的单一记录操作,例如 findFirstOrThrow, (中文(简体) ), findUniqueOrThrow, (中文(简体) ), update,以及 delete,将会以“没有找到...”错误的记录来拒绝.

类型脚本支持

软件包是用TypeScript编写的,它提供了全面的IDE提示并编译了时间验证.

一定要打电话 prisma generate。 。 。 . @casl/prisma 使用 Prisma 生成的类型, 因此如果客户端没有生成, 将没有任何效果 .

此外,还有几个帮助者使与Prisma和CASL合作变得容易:

Prisma 查询

它是一种通用类型,提供 Prisma.ModelWhereInput 以一般方式。 我们需要通过 一个命名的模型:

import type { User } from '@prisma/client';
import type { ForcedSubject } from '@casl/ability';
import type { PrismaQuery } from '@casl/prisma';

// almost the same as Prisma.UserWhereInput except that it's a higher order type
type UserWhereInput = PrismaQuery<User & ForcedSubject<'User'>>;

自定义 Prisma 客户端输出路径( Prisma 7 默认)

普丽斯玛7's prisma-client 生成器将客户端写入自定义目录, 所以 @prisma/client 不再再出口您的项目类型。 将 CASL 点在生成的客户端上, 并使用一个建在上的小包装 @casl/prisma/runtime数字 :

// schema.prisma
generator client {
  provider = "prisma-client"
  output   = "../src/generated/client"
}
// prisma.config.ts
import { defineConfig } from 'prisma/config';

export default defineConfig({
  schema: './schema.prisma',
  datasource: { url: process.env.DATABASE_URL! },
});
// src/casl-prisma.ts
import {
  accessibleBy,
  createPrismaAbility,
  ParsingQueryError,
  prismaQuery,
  type PrismaQueryOf,
  type WhereInputOf,
} from '@casl/prisma/runtime';
import type { Ability, ForcedSubject, TaggedSubject } from "@casl/ability";
import type { Prisma, Post, User } from './generated/client';

export { accessibleBy, createPrismaAbility, ParsingQueryError, prismaQuery };

export type PrismaQuery<T extends ForcedSubject<any> = ForcedSubject<any>> =
  PrismaQueryOf<Prisma.TypeMap, T>;
export type WhereInput<TModelName extends Prisma.ModelName> =
  WhereInputOf<Prisma.TypeMap, TModelName>;
export type AppSubjects =
  | User & ForcedSubject<'User'>
  | Post & ForcedSubject<'Post'>
;

export type AppAbility = Ability<['create' | "read" | "update" | "delete", 'all' | AppSubjects], PrismaQuery, TaggedSubject>

在您的应用程序中使用此包装而非导入 @casl/prisma 直接说 如果你坚持遗产 prisma-client-js prisma 6.x 兼容性生成器, 默认值 @casl/prisma 进入点继续工作.

想帮忙吗?

想要提交错误, 提供一些代码, 还是改进文档 ? 不错! 阅读指南 捐款。 。 。 .

如果你想帮助我们 维持我们的社区和项目,考虑 成为开放集体的出资人

见 支助CASL 详情

许可证

MIT 许可证

版本与发布记录

@casl/prisma 共发布 30 个版本,首次发布于 2021/05/10;过去 12 个月发布了 9 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.2.0latest2026/10/2811 天前
2.1.02026/10/2811 天前
2.0.22026/07/074 个月前
2.0.12026/05/225 个月前
2.0.02026/05/215 个月前
2.0.0-rcnext2026/05/086 个月前

其他发布通道:alpha → 2.0.0-alpha.3,next → 2.0.0-rc。

关于 @casl/prisma 的常见问题

@casl/prisma 是什么?

允许根据 CASL 规则使用 Prisma 客户端查询可访问的记录

如何安装 @casl/prisma?

在项目目录运行 npm install @casl/prisma,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@casl/ability(^7.0.0)、@prisma/client(^4.16.0 || ^5.0.0 || ^6.0.0 || ^7.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@casl/prisma 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@casl/prisma 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@casl/prisma 可以商用吗?

@casl/prisma 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@casl/prisma 的下载量有多少?

根据 npm 官方下载统计,@casl/prisma 在 2026/10/09 – 2026/11/07 这 30 天内被下载 812,299 次,日均约 27,077 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@casl/prisma 还在维护吗?

最新版本 2.2.0 发布于 2026/10/28(11 天前);至今共发布 30 个版本,其中过去 12 个月发布了 9 个;首次发布于 2021/05/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。