Skip to content

Commit 70ddfd8

Browse files
committed
clean up merge conflicts
2 parents a10dd67 + 4c7bdaa commit 70ddfd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4135
-353
lines changed

.github/workflows/encryption-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches: ['master']
66
pull_request:
7-
branches: [ 'master' ]
7+
branches: [ 'master', 'csfle' ]
88
workflow_dispatch: {}
99

1010
permissions:

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,4 @@ notes.md
7272
list.out
7373

7474
data
75-
*.pid
75+
fle-cluster-config.json

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
8.15.0 / 2025-05-16
2+
===================
3+
* feat: CSFLE support #15390 [baileympearson](https://github.com/baileympearson)
4+
* feat: add strictFilter option to findOneAndUpdate (#14913) #15402 #14913 [muazahmed-dev](https://github.com/muazahmed-dev)
5+
* feat(error): set cause to MongoDB error reason on ServerSelection errors #15420 #15416
6+
* fix(model): make bulkSave() rely on document.validateSync() to validate docs and skip bulkWrite casting #15415 #15410
7+
* types: stricter projection typing with 1-level deep nesting #15418 #15327 #13840 [pshaddel](https://github.com/pshaddel)
8+
* docs: emphasize automatic type inference in TypeScript intro and statics/methods, remove duplicated statics.md #15421
9+
110
8.14.3 / 2025-05-13
211
===================
312
* types(schema): allow post('init') #15413 #15412 #15333

docs/field-level-encryption.md

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,141 @@ The resulting document will look similar to the following to a client that doesn
1616

1717
You can read more about CSFLE on the [MongoDB CSFLE documentation](https://www.mongodb.com/docs/manual/core/csfle/) and [this blog post about CSFLE in Node.js](https://www.mongodb.com/developer/languages/javascript/client-side-field-level-encryption-csfle-mongodb-node/).
1818

19-
Note that Mongoose does **not** currently have any Mongoose-specific APIs for CSFLE.
20-
Mongoose defers all CSFLE-related work to the MongoDB Node.js driver, so the [`autoEncryption` option](https://mongodb.github.io/node-mongodb-native/5.6/interfaces/AutoEncryptionOptions.html) for `mongoose.connect()` and `mongoose.createConnection()` is where you put all CSFLE-related configuration.
21-
Mongoose schemas currently don't support CSFLE configuration.
19+
## Automatic FLE in Mongoose
2220

23-
## Setting Up Field Level Encryption with Mongoose
21+
Mongoose supports the declaration of encrypted schemas - schemas that, when connected to a model, utilize MongoDB's Client Side
22+
Field Level Encryption or Queryable Encryption under the hood. Mongoose automatically generates either an `encryptedFieldsMap` or a
23+
`schemaMap` when instantiating a MongoClient and encrypts fields on write and decrypts fields on reads.
24+
25+
### Encryption types
26+
27+
MongoDB has two different automatic encryption implementations: client side field level encryption (CSFLE) and queryable encryption (QE).
28+
See [choosing an in-use encryption approach](https://www.mongodb.com/docs/v7.3/core/queryable-encryption/about-qe-csfle/#choosing-an-in-use-encryption-approach).
29+
30+
### Declaring Encrypted Schemas
31+
32+
The following schema declares two properties, `name` and `ssn`. `ssn` is encrypted using queryable encryption, and
33+
is configured for equality queries:
34+
35+
```javascript
36+
const encryptedUserSchema = new Schema({
37+
name: String,
38+
ssn: {
39+
type: String,
40+
// 1
41+
encrypt: {
42+
keyId: '<uuid string of key id>',
43+
queries: 'equality'
44+
}
45+
}
46+
// 2
47+
}, { encryptionType: 'queryableEncryption' });
48+
```
49+
50+
To declare a field as encrypted, you must:
51+
52+
1. Annotate the field with encryption metadata in the schema definition
53+
2. Choose an encryption type for the schema and configure the schema for the encryption type
54+
55+
Not all schematypes are supported for CSFLE and QE. For an overview of supported BSON types, refer to MongoDB's documentation.
56+
57+
### Registering Models
58+
59+
Encrypted schemas can be registered on the global mongoose object or on a specific connection, so long as models are registered before the connection
60+
is established:
61+
62+
```javascript
63+
// specific connection
64+
const GlobalUserModel = mongoose.model('User', encryptedUserSchema);
65+
66+
// specific connection
67+
const connection = mongoose.createConnection();
68+
const UserModel = connection.model('User', encryptedUserSchema);
69+
```
70+
71+
### Connecting and configuring encryption options
72+
73+
Field level encryption in Mongoose works by generating the encryption schema that the MongoDB driver expects for each encrypted model on the connection. This happens automatically when the model's connection is established.
74+
75+
Queryable encryption and CSFLE require all the same configuration as outlined in the [MongoDB encryption in-use documentation](https://www.mongodb.com/docs/manual/core/security-in-use-encryption/), except for the schemaMap or encryptedFieldsMap options.
76+
77+
```javascript
78+
const keyVaultNamespace = 'client.encryption';
79+
const kmsProviders = { local: { key } };
80+
await connection.openUri(`mongodb://localhost:27017`, {
81+
// Configure auto encryption
82+
autoEncryption: {
83+
keyVaultNamespace: 'datakeys.datakeys',
84+
kmsProviders
85+
}
86+
});
87+
```
88+
89+
Once the connection is established, Mongoose's operations will work as usual. Writes are encrypted automatically by the MongoDB driver prior to sending them to the server and reads are decrypted by the driver after fetching documents from the server.
90+
91+
### Discriminators
92+
93+
Discriminators are supported for encrypted models as well:
94+
95+
```javascript
96+
const connection = createConnection();
97+
98+
const schema = new Schema({
99+
name: {
100+
type: String, encrypt: { keyId }
101+
}
102+
}, {
103+
encryptionType: 'queryableEncryption'
104+
});
105+
106+
const Model = connection.model('BaseUserModel', schema);
107+
const ModelWithAge = model.discriminator('ModelWithAge', new Schema({
108+
age: {
109+
type: Int32, encrypt: { keyId: keyId2 }
110+
}
111+
}, {
112+
encryptionType: 'queryableEncryption'
113+
}));
114+
115+
const ModelWithBirthday = model.discriminator('ModelWithBirthday', new Schema({
116+
dob: {
117+
type: Int32, encrypt: { keyId: keyId3 }
118+
}
119+
}, {
120+
encryptionType: 'queryableEncryption'
121+
}));
122+
```
123+
124+
When generating encryption schemas, Mongoose merges all discriminators together for all of the discriminators declared on the same namespace. As a result, discriminators that declare the same key with different types are not supported. Furthermore, all discriminators for the same namespace must share the same encryption type - it is not possible to configure discriminators on the same model for both CSFLE and Queryable Encryption.
125+
126+
## Managing Data Keys
127+
128+
Mongoose provides a convenient API to obtain a [ClientEncryption](https://mongodb.github.io/node-mongodb-native/Next/classes/ClientEncryption.html)
129+
object configured to manage data keys in the key vault. A client encryption can be obtained with the `Model.clientEncryption()` helper:
130+
131+
```javascript
132+
const connection = createConnection();
133+
134+
const schema = new Schema({
135+
name: {
136+
type: String, encrypt: { keyId }
137+
}
138+
}, {
139+
encryptionType: 'queryableEncryption'
140+
});
141+
142+
const Model = connection.model('BaseUserModel', schema);
143+
await connection.openUri(`mongodb://localhost:27017`, {
144+
autoEncryption: {
145+
keyVaultNamespace: 'datakeys.datakeys',
146+
kmsProviders: { local: '....' }
147+
}
148+
});
149+
150+
const clientEncryption = Model.clientEncryption();
151+
```
152+
153+
## Manual FLE in Mongoose
24154

25155
First, you need to install the [mongodb-client-encryption npm package](https://www.npmjs.com/package/mongodb-client-encryption).
26156
This is MongoDB's official package for setting up encryption keys.

docs/typescript.md

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,46 @@ This guide describes Mongoose's recommended approach to working with Mongoose in
88

99
To get started with Mongoose in TypeScript, you need to:
1010

11-
1. Create an interface representing a document in MongoDB.
12-
2. Create a [Schema](guide.html) corresponding to the document interface.
13-
3. Create a Model.
14-
4. [Connect to MongoDB](connections.html).
11+
1. Create a [Schema](guide.html).
12+
2. Create a Model.
13+
3. [Connect to MongoDB](connections.html).
14+
15+
```typescript
16+
import { Schema, model, connect } from 'mongoose';
17+
18+
// 1. Create a Schema corresponding to the document interface.
19+
const userSchema = new Schema({
20+
name: { type: String, required: true },
21+
email: { type: String, required: true },
22+
avatar: String
23+
});
24+
25+
// 2. Create a Model.
26+
const User = model('User', userSchema);
27+
28+
run().catch(err => console.log(err));
29+
30+
async function run() {
31+
// 3. Connect to MongoDB
32+
await connect('mongodb://127.0.0.1:27017/test');
33+
34+
const user = new User({
35+
name: 'Bill',
36+
email: 'bill@initech.com',
37+
avatar: 'https://i.imgur.com/dM7Thhn.png'
38+
});
39+
await user.save();
40+
41+
const email: string = user.email;
42+
console.log(email); // 'bill@initech.com'
43+
}
44+
```
45+
46+
## Using Generics
47+
48+
By default, Mongoose automatically infers the shape of your documents based on your schema definition.
49+
However, if you modify your schema after your `new Schema()` call (like with plugins) then Mongoose's inferred type may be incorrect.
50+
For cases where Mongoose's automatic schema type inference is incorrect, you can define a raw document interface that tells Mongoose the type of documents in your database as follows.
1551

1652
```typescript
1753
import { Schema, model, connect } from 'mongoose';
@@ -67,8 +103,6 @@ const user: HydratedDocument<IUser> = new User({
67103
});
68104
```
69105

70-
## ObjectIds and Other Mongoose Types
71-
72106
To define a property of type `ObjectId`, you should use `Types.ObjectId` in the TypeScript document interface. You should use `'ObjectId'` or `Schema.Types.ObjectId` in your schema definition.
73107

74108
```ts
@@ -106,4 +140,4 @@ However, before you do, please [open an issue on Mongoose's GitHub page](https:/
106140

107141
## Next Up
108142

109-
Now that you've seen the basics of how to use Mongoose in TypeScript, let's take a look at [statics in TypeScript](typescript/statics-and-methods.html).
143+
Now that you've seen the basics of how to use Mongoose in TypeScript, let's take a look at [methods in TypeScript](typescript/statics-and-methods.html).

0 commit comments

Comments
 (0)