Mongoose adapter :: Cerbos Authorization Management Platform // Documentation
Mongoose adapter
| This documentation is for an as-yet unreleased version of Cerbos PDP. Choose 0.53.0 from the version picker at the top right or navigate to https://docs.cerbos.dev for the latest version. |
The @cerbos/orm-mongoose package converts a Cerbos PlanResources response into a MongoDB filter compatible with Mongoose’s find() method.
Requirements
- Cerbos >= v0.16
@cerbos/httpor@cerbos/grpcclient- Mongoose 8.x or 9.x
- MongoDB 5.0+
- Node.js >= 20.0.0
Installation
npm install @cerbos/orm-mongoose
Supported operators
| Category | Operators |
|---|---|
| Logical | and, or, not — mapped to $and, $or, $nor |
| Comparison | eq, ne, lt, le, gt, ge — mapped to $eq, $ne, $lt, $lte, $gt, $gte |
| Membership | in, hasIntersection — $in for simple lists, $elemMatch for array relations |
| String | contains, startsWith, endsWith — escaped regular expressions |
| Existence | isSet, exists, exists_one — $exists/$ne: null for scalars, $elemMatch for collections |
| Collection | filter, lambda, map, all — scoped $elemMatch filters with lambda variable resolution |
exists_one behaves as "at least one element matches". Enforcing "exactly one" requires an aggregation pipeline, which is outside the scope of this adapter. |
Usage
import { queryPlanToMongoose, PlanKind } from "@cerbos/orm-mongoose";
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);
Combine with existing application filters using $and:
await MyModel.find({ $and: [filters ?? {}, { archived: false }] });
Field mapper
const 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" } },
},
},
};
field— rewrites a Cerbos path to a different field name in MongoDBvalueParser— transforms leaf values during filter construction (for example, converting strings toObjectId)relation— describes embedded documents (type: "one") or arrays (type: "many")fields— nested overrides for lambda expressions such astag.name
Value parsing
Use valueParser to convert values from the query plan into types MongoDB expects:
import { Types } from "mongoose";
const mapper = {
"request.resource.attr.id": {
field: "_id",
valueParser: (value) => new Types.ObjectId(value),
},
};
Collection operators
Collection-aware operators (filter, exists, exists_one, hasIntersection, map, all) require the mapper to declare the relation with type: "many". The adapter scopes lambda variables and uses the fields map when translating expressions:
exists,exists_one,filter— wrap the condition in$elemMatchhasIntersection— supports both scalar arrays and arrays of objects; projects nested paths via$elemMatchall— converts the lambda condition into a negated$elemMatchso all elements must satisfy the predicate