@cerbos/orm-mongoose

中文文档
3.0.0发布于 2026/08/04Apache-2.0TypeScriptCommonJS构建来源已验证近 30 天下载 3266

一个适配器库 赛博斯 查询计划( E)计划资源 API)反应并将其转换为 乌鸦 过滤器。 这是脱口秀

中文使用文档
文档目录11 节
  1. 如何运作
  2. 支持的运算符
  3. 履约合同
  4. 所需资源
  5. 系统要求
  6. 安装
  7. API 密码
  8. 映射器配置
  9. 用法实例
  10. 处理错误
  11. 限制

Cerbos + Mongoose ORM 适应器

一个适配器库 赛博斯 查询计划( E)计划资源 API)反应并将其转换为 乌鸦 过滤器。 它旨在与一个已经使用该软件的项目同时运行 Cerbos Java 脚本 SDK 以获取查询计划,从而将授权逻辑推倒到 MongoDB .

如何运作

  1. 使用 Cerbos 客户端(@cerbos/http 或者说 @cerbos/grpc打电话 planResources 并获得 PlanResourcesResponse。 。 。 .
  2. 提供 queryPlanToMongoose 以及一个可选的映射器 来描述 Cerbos 属性路径与您的文档计划的关系.
  3. 适配器走 Cerbos 表达式树,将支持的运算符翻译为 MongoDB 语法,然后返回 { kind, filters? }。 。 。 .
  4. 检查 result.kind数字 :
    • ALWAYS_ALLOWED:呼叫者可以查询,无需额外的过滤.
    • ALWAYS_DENIED:短路并返回空结果集.
    • CONDITIONAL: 用 result.filters。 。 。 .

您可以将适配器输出与现有的应用程序过滤器合并(例如,通过 $and)在发布Mongoose查询之前.

支持的运算符

类别运算符行为
逻辑and, (中文(简体) ), or, (中文(简体) ), not构建 $and, (中文(简体) ), $or,以及 $nor 组合.
比较eq, (中文(简体) ), ne, (中文(简体) ), lt, (中文(简体) ), le, (中文(简体) ), gt, (中文(简体) ), ge输出 $eq, (中文(简体) ), $ne, (中文(简体) ), $lt, (中文(简体) ), $lte, (中文(简体) ), $gt, (中文(简体) ), $gte 检查与绘图的字段.
成员in, (中文(简体) ), hasIntersection$in 在简单的列表中,或 $elemMatch 瞄准数组关系时; hasIntersection 支持一个直接阵列字段或一个 map 计划内投影.
字符串助手contains, (中文(简体) ), startsWith, (中文(简体) ), endsWith生成从正则表达式中逃出,这些表达式的目标为子字符串,前缀,或后缀.
存在助手isSet, (中文(简体) ), exists用途 $exists编号 :$ne: null 用于平板和 $elemMatch 用于收藏.
收藏助手filter, (中文(简体) ), lambda, (中文(简体) ), map, (中文(简体) ), all将 Cerbos 收藏表达式翻译为范围化 $elemMatch 过滤器和羊肉达变量映射到正确的嵌入路径. all 需要存储字段为数组.
算术和价值add, (中文(简体) ), sub, (中文(简体) ), mult, (中文(简体) ), div, (中文(简体) ), mod, (中文(简体) ), if, (中文(简体) ), size, (中文(简体) ), index, (中文(简体) ), get-field使用文档级别 MongoDB $expr 表达. division需要非零常分母;索引需要非负整数常数并添加每文档边框检查.
转换和匹配string, (中文(简体) ), double, (中文(简体) ), int, (中文(简体) ), timestamp, (中文(简体) ), matches使用被守护的MongoDB转换和正则表达式. Timerstamps在CEL即时范围内接受BSON日期或毫秒精确的RFC 3339字符串. Regex匹配接受一个经验证的通用的RE2/PCRE2子集.
等级hierarchy, (中文(简体) ), ancestorOf, (中文(简体) ), descendentOf, (中文(简体) ), overlaps使用字面前缀和祖先列表过滤器来翻译一个已绘制的scalar分级路径.

未列入上述原因的操作人员 queryPlanToMongoose 要掷出 Unsupported operator: <name>。 。 。 .

exists_one 响亮失败, 因为普通匹配过滤器无法为已失效元素保存精确匹配的红外线和 CEL 错误语义 .

当存储的 BSON 类型在 CEL 兼容源类型之外或解析失败时,转换失败关闭. double 财务报告和审定财务报表 int 接受字符串和数字 BSON 值,但不使用布尔; int 还拒绝BSON日期,而不是将其解释为毫秒. string 接受字符串、布尔值和数值。 失败的转换仍然被拒绝.

时间戳值必须在协调世界时的即时范围内下降(0001-01-01T00:00:00Z 结束 9999-12-31T23:59:59.999Z) (中文(简体) ). 字符串必须使用不超过三个分数-秒数的RFC 3339语法,与BSON Date的毫秒精度相匹配. 高精度或外程的字符串和 BSON 日期失败而关闭,而不是被默默地切入到不同的CEL瞬间.

matches 支持字节, .,则 *, (中文(简体) ), +,以及 ? 参数,领先 ^终端 $,并逃脱了regex元特征。 其他的构造失败关闭 。 一个终端 $ 被翻译为 PCRE2 的绝对文本端主播,因此MongoDB在最终新线之前无法匹配,保留了 RE2 语义.

履约合同

适配器对 Cerbos PDP 0.54.0 checkResource 使用20个敌对种子文件和真正的MongoDB 7和8个查询。 Spring Data适配器为这个相容快照定义了参考语义.

分类覆盖范围
甲骨文测试85 参考符合性动作外加regex,订购索引/get-field,和时间戳探测器(88个动作)
未关闭29项参考行动
已知的规划者差异has() cerbos计划员将缺失的属性折叠到 ALWAYS_ALLOWED时 checkResource 否认缺少属性文件 。 在计划员修好之前,请使用 R.attr.x != null 用于数据库支持的属性,而不是 has(R.attr.x)

失败的闭合套件包括内部精确的一要素、汇总表达式或外文件参考 $elemMatch,嵌入式收集计数,相关可变可变成员,不安全的分数/非无限算法,并否定了无法保存CEL三值误差语义的无效收集上游. 这些计划不是无声地贬低MongoDB过滤器.

所需资源

  • Cerbos > v0.16 + 两者之一 @cerbos/http 或者说 @cerbos/grpc 客户端

系统要求

  • 节点.js 22.0.0
  • Mong 9.x
  • MongoDB 7.0 或更新

安装

npm install @cerbos/orm-mongoose

API 密码

import {
  queryPlanToMongoose,
  PlanKind,
  type Mapper,
} from "@cerbos/orm-mongoose";

const result = queryPlanToMongoose({
  queryPlan, // PlanResourcesResponse from Cerbos
  mapper, // optional Mapper - see below
});

if (result.kind === PlanKind.CONDITIONAL) {
  await MyModel.find(result.filters);
}

PlanKind 从 @cerbos/core数字 :

export enum PlanKind {
  ALWAYS_ALLOWED = "KIND_ALWAYS_ALLOWED",
  ALWAYS_DENIED = "KIND_ALWAYS_DENIED",
  CONDITIONAL = "KIND_CONDITIONAL",
}

映射器配置

Cerbos 查询计划引用字段, 使用路径如 request.resource.attr.title。使用映射器将这些名称翻译为您 Mongoose 模型中的路径,并描述关系/收集,以便适配器生成 $elemMatch 需要时过滤器.

export type MapperConfig = {
  field?: string;
  nullable?: boolean;
  valueParser?: (value: any) => any;
  relation?: {
    name: string;
    type: "one" | "many";
    field?: string;
    fields?: Record<string, MapperConfig>;
  };
};

export type Mapper =
  | Record<string, MapperConfig>
  | ((key: string) => MapperConfig);
  • field 将单一 Cerbos 路径重写到 MongoDB 中不同的字段 .
  • nullable 声明存储 null 代表缺少 Cerbos 属性。 比较会添加一个非null守护符,因此MongoDB不会将CEL评价错误变成授权匹配. 不要设置为字段 null 是一个明确的 Cerbos 值.
  • valueParser 在过滤器构建过程中会转换叶子值。 当 Cerbos 计划中包含需要转换为 MongoDB 特定类型的字符串表达式时(例如将字符串转换为 ObjectId) (中文(简体) ). 解析器应用到每个值 eq, (中文(简体) ), ne, (中文(简体) ), lt, (中文(简体) ), le, (中文(简体) ), gt, (中文(简体) ), ge,以及 in 操作员。 也通过 fields 地图.
  • relation 描述嵌入式文档(type: "one")或数组(type: "many") (中文(简体) ). 何时 field 用于比较(例如匹配) createdBy.id 无 $elemMatch) (中文(简体) ).
  • fields 补给层覆盖,所以 lambda 表达式,例如 tag.name 可以被映射到正确的属性.

如果您省略了映射器, 适配器会逐字使用查询计划路径, 只有当您的 Mongo 文档遵循 Cerbos 命名惯例时才有效 .

直接字段

const mapper: Mapper = {
  "request.resource.attr.aBool": { field: "aBool" },
  "request.resource.attr.aString": { field: "title" },
  "request.principal.attr.department": { field: "principalDepartment" },
};

关系和收藏

使用 relation 当绘制嵌入对象或阵列时. type: "one" 映射到嵌入/单一关系和结果的点化字段路径,同时 type: "many" 映射到数组并让适配器放出 $elemMatch 条件。 可选 fields 映射让您重命名 lambda 表达式中引用的嵌入属性 .

const mapper: Mapper = {
  "request.resource.attr.createdBy": {
    relation: {
      name: "createdBy",
      type: "one",
      field: "id",
    },
  },
  "request.resource.attr.tags": {
    relation: {
      name: "tags",
      type: "many",
      fields: {
        id: { field: "id" },
        name: { field: "name" },
      },
    },
  },
};

实际收集操作员

了解收集的操作员(filter, (中文(简体) ), exists, (中文(简体) ), hasIntersection, (中文(简体) ), map,以及 all)要求映射器声明与 type: "many"。适配器自动瞄准羊肉达变量并使用 fields 翻译表达式时的映射 tag.name数字 :

const mapper: Mapper = {
  "request.resource.attr.tags": {
    relation: {
      name: "tags",
      type: "many",
      fields: {
        name: { field: "name", nullable: true },
      },
    },
  },
};
  • exists 财务报告和审定财务报表 filter 将翻译条件包入 $elemMatch。 。 。 .
  • hasIntersection 既适用于平面阵列,也适用于对象阵列;当计划使用时 map(lambda(tag.name)) 适配器项目 tag.name 改为 tags.$elemMatch.name。 。 。 .
  • all 将 lambda 条件转换为否定条件 $elemMatch 因此,所有要素必须满足上游.
  • 一个赤裸的 map 表达式验证每个元素中引用的嵌入路径.

映射函数

如果您的映射遵循了可预测的模式, 您也可以提供函数 :

const mapper: Mapper = (path) => {
  if (path.startsWith("request.resource.attr.")) {
    return { field: path.replace("request.resource.attr.", "") };
  }
  if (path.startsWith("request.principal.attr.")) {
    return { field: `principal.${path.replace("request.principal.attr.", "")}` };
  }
  return { field: path };
};

数值解析

使用 valueParser 将 Cerbos 计划中的值转换成 MongoDB 所期望的类型。 一个常用的大小写是将字符串ID转换为 ObjectId数字 :

import { Types } from "mongoose";

const mapper: Mapper = {
  "request.resource.attr.id": {
    field: "_id",
    valueParser: (value) => new Types.ObjectId(value),
  },
};

valueParser 并且通过 fields 地图 :

const mapper: Mapper = {
  "request.resource.attr.createdBy": {
    relation: {
      name: "createdBy",
      type: "one",
      field: "id",
      fields: {
        id: {
          field: "id",
          valueParser: (value) => new Types.ObjectId(value),
        },
      },
    },
  },
};

用法实例

import { GRPC as Cerbos } from "@cerbos/grpc";
import mongoose from "mongoose";
import {
  queryPlanToMongoose,
  PlanKind,
  type Mapper,
} from "@cerbos/orm-mongoose";

await mongoose.connect("mongodb://127.0.0.1:27017/test");
const cerbos = new Cerbos("localhost:3592", { tls: false });
const MyModel = mongoose.model("MyModel", /* ... schema ... */);

const mapper: Mapper = {
  "request.resource.attr.title": { field: "title" },
  "request.resource.attr.owner": {
    relation: { name: "owner", type: "one", field: "id" },
  },
  "request.resource.attr.tags": {
    relation: {
      name: "tags",
      type: "many",
      fields: { name: { field: "name" } },
    },
  },
};

const queryPlan = await cerbos.planResources({
  principal: { id: "user1", roles: ["USER"] },
  resource: { kind: "document" },
  action: "view",
});

const result = queryPlanToMongoose({ queryPlan, mapper });

if (result.kind === PlanKind.ALWAYS_DENIED) {
  return [];
}

const filters = result.kind === PlanKind.CONDITIONAL ? result.filters : {};
const records = await MyModel.find(filters);

如果您已经拥有应用程序特定标准,您可以使用 $and数字 :

const filters = result.kind === PlanKind.CONDITIONAL ? result.filters : {};
await MyModel.find({ $and: [filters ?? {}, { archived: false }] });

处理错误

queryPlanToMongoose 在以下情景中抛出描述性错误 :

  • 计划不是Cerbos的 PlanKind 数值(Invalid query plan.) (中文(简体) ).
  • 有条件的计划省略 operator编号 :operands 结构Invalid Cerbos expression structure) (中文(简体) ).
  • 计划中列出的操作人员未执行(Unsupported operator: <name>) (中文(简体) ).
  • 面向收集的操作员(map, (中文(简体) ), filter, (中文(简体) ), exists, (中文(简体) ), all使用时没有 relation 映射器,或带有 映射器宣布 type: "one" 地点 type: "many" 需要(例如: map operator requires a relation mapping) (中文(简体) ).
  • 计划中的Lambda表达式有误(例如缺少一个可变的操作结果) Lambda variable must have a name) (中文(简体) ).
  • 值操作不符合预期类型,例如, hasIntersection 提供非阵列值.

及早弥补这些错误有助于使适配器和你的Cerbos政策保持同步.

限制

  • exists_one 而不是无声地贬低 exists。 。 。 .
  • 收集上游中的集合表达式、来自羊肉的外文件引用以及否定无效的收集宏失败,因为 $elemMatch 无法保存其 CEL 范围界定和三值错误语义.
  • 未列出的运算符 支持的运算符 (例如搜索、模式、平面数学帮助器、原子数操作、复合键等)没有执行,将投掷 Unsupported operator。 。 。 .
  • 翻译可能使用文档级别 $expr,但从不需要多阶段聚合管道.

版本与发布记录

@cerbos/orm-mongoose 共发布 9 个版本,首次发布于 2023/06/28;过去 12 个月发布了 3 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.0.0latest2026/08/043 个月前
2.1.02026/02/029 个月前
2.0.22025/11/1811 个月前
0.1.22023/07/193 年前
0.1.12023/07/193 年前
0.1.02023/07/193 年前

关于 @cerbos/orm-mongoose 的常见问题

@cerbos/orm-mongoose 是什么?

一个适配器库 赛博斯 查询计划( E)计划资源 API)反应并将其转换为 乌鸦 过滤器。 这是脱口秀

如何安装 @cerbos/orm-mongoose?

在项目目录运行 npm install @cerbos/orm-mongoose,或使用 pnpm add / yarn add / bun add。

@cerbos/orm-mongoose 支持 TypeScript 吗?

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

@cerbos/orm-mongoose 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@cerbos/orm-mongoose 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cerbos/orm-mongoose 可以商用吗?

@cerbos/orm-mongoose 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@cerbos/orm-mongoose 的下载量有多少?

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

@cerbos/orm-mongoose 还在维护吗?

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