Skip to content

Commit 3e99324

Browse files
committed
Merge branch 'master' into IslandRhythms/gh-14164
2 parents c4ca444 + 3bd67a8 commit 3e99324

18 files changed

+223
-51
lines changed

docs/guides.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ integrating Mongoose with external tools and frameworks.
4141
* [Transactions](transactions.html)
4242
* [MongoDB Driver Deprecation Warnings](deprecations.html)
4343
* [Testing with Jest](jest.html)
44-
* [SSL Connections](tutorials/ssl.html)
44+
* [TLS/SSL Connections](tutorials/ssl.html)
4545
* [MongoDB Client Side Field Level Encryption](field-level-encryption.html)
4646

4747
## Other Guides

docs/layout.pug

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ html(lang='en')
6262
- if ([`${versions.versionedPath}/docs/connections`, `${versions.versionedPath}/docs/tutorials/ssl`].some(path => outputUrl.startsWith(path)))
6363
ul.pure-menu-list
6464
li.pure-menu-item.sub-item
65-
a.pure-menu-link(href=`${versions.versionedPath}/docs/tutorials/ssl.html`, class=outputUrl === `${versions.versionedPath}/docs/tutorials/ssl.html` ? 'selected' : '') SSL Connections
65+
a.pure-menu-link(href=`${versions.versionedPath}/docs/tutorials/ssl.html`, class=outputUrl === `${versions.versionedPath}/docs/tutorials/ssl.html` ? 'selected' : '') TLS/SSL Connections
6666
li.pure-menu-item.sub-item
6767
a.pure-menu-link(href=`${versions.versionedPath}/docs/models.html`, class=outputUrl === `${versions.versionedPath}/docs/models.html` ? 'selected' : '') Models
6868
- if ([`${versions.versionedPath}/docs/models`, `${versions.versionedPath}/docs/change-streams`].some(path => outputUrl.startsWith(path)))

docs/migrating_to_8.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ There's a few noteable changes in MongoDB Node driver v6 that affect Mongoose:
7171

7272
1. The `ObjectId` constructor no longer accepts strings of length 12. In Mongoose 7, `new mongoose.Types.ObjectId('12charstring')` was perfectly valid. In Mongoose 8, `new mongoose.Types.ObjectId('12charstring')` throws an error.
7373

74+
1. Deprecated SSL options have been removed
75+
76+
- `sslCA` -> `tlsCAFile`
77+
- `sslCRL` -> `tlsCRLFile`
78+
- `sslCert` -> `tlsCertificateKeyFile`
79+
- `sslKey` -> `tlsCertificateKeyFile`
80+
- `sslPass` -> `tlsCertificateKeyFilePassword`
81+
- `sslValidate` -> `tlsAllowInvalidCertificates`
82+
- `tlsCertificateFile` -> `tlsCertificateKeyFile`
83+
7484
<h2 id="removed-findoneandremove"><a href="#removed-findoneandremove">Removed <code>findOneAndRemove()</code></a></h2>
7585

7686
In Mongoose 7, `findOneAndRemove()` was an alias for `findOneAndDelete()` that Mongoose supported for backwards compatibility.

docs/tutorials/ssl.md

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,40 @@
1-
# SSL Connections
1+
# TLS/SSL Connections
22

3-
Mongoose supports connecting to [MongoDB clusters that require SSL connections](https://www.mongodb.com/docs/manual/tutorial/configure-ssl/). Setting the `ssl` option to `true` in [`mongoose.connect()`](../api/mongoose.html#mongoose_Mongoose-connect) or your connection string is enough to connect to a MongoDB cluster using SSL:
3+
Mongoose supports connecting to [MongoDB clusters that require TLS/SSL connections](https://www.mongodb.com/docs/manual/tutorial/configure-ssl/). Setting the `tls` option to `true` in [`mongoose.connect()`](../api/mongoose.html#mongoose_Mongoose-connect) or your connection string is enough to connect to a MongoDB cluster using TLS/SSL:
44

55
```javascript
6-
mongoose.connect('mongodb://127.0.0.1:27017/test', { ssl: true });
6+
mongoose.connect('mongodb://127.0.0.1:27017/test', { tls: true });
77

88
// Equivalent:
9-
mongoose.connect('mongodb://127.0.0.1:27017/test?ssl=true');
9+
mongoose.connect('mongodb://127.0.0.1:27017/test?tls=true');
1010
```
1111

12-
The `ssl` option defaults to `false` for connection strings that start with `mongodb://`. However,
13-
the `ssl` option defaults to `true` for connection strings that start with `mongodb+srv://`. So if you are using an srv connection string to connect to [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), SSL is enabled by default.
12+
The `tls` option defaults to `false` for connection strings that start with `mongodb://`. However,
13+
the `tls` option defaults to `true` for connection strings that start with `mongodb+srv://`. So if you are using an srv connection string to connect to [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), TLS/SSL is enabled by default.
1414

15-
If you try to connect to a MongoDB cluster that requires SSL without enabling the `ssl` option, `mongoose.connect()`
16-
will error out with the below error:
15+
If you try to connect to a MongoDB cluster that requires TLS/SSL without enabling the `tls`/`ssl` option, `mongoose.connect()` will error out with the below error:
1716

1817
```no-highlight
1918
MongooseServerSelectionError: connection <monitor> to 127.0.0.1:27017 closed
2019
at NativeConnection.Connection.openUri (/node_modules/mongoose/lib/connection.js:800:32)
2120
...
2221
```
2322

24-
## SSL Validation
23+
## TLS/SSL Validation
2524

26-
By default, Mongoose validates the SSL certificate against a [certificate authority](https://en.wikipedia.org/wiki/Certificate_authority) to ensure the SSL certificate is valid. To disable this validation, set the `sslValidate` option
27-
to `false`.
25+
By default, Mongoose validates the TLS/SSL certificate against a [certificate authority](https://en.wikipedia.org/wiki/Certificate_authority) to ensure the TLS/SSL certificate is valid. To disable this validation, set the `tlsAllowInvalidCertificates` (or `tlsInsecure`) option to `true`.
2826

2927
```javascript
3028
mongoose.connect('mongodb://127.0.0.1:27017/test', {
31-
ssl: true,
32-
sslValidate: false
29+
tls: true,
30+
tlsAllowInvalidCertificates: true,
3331
});
3432
```
3533

36-
In most cases, you should not disable SSL validation in production. However, `sslValidate: false` is often helpful
37-
for debugging SSL connection issues. If you can connect to MongoDB with `sslValidate: false`, but not with
38-
`sslValidate: true`, then you can confirm Mongoose can connect to the server and the server is configured to use
39-
SSL correctly, but there's some issue with the SSL certificate.
34+
In most cases, you should not disable TLS/SSL validation in production. However, `tlsAllowInvalidCertificates: true` is often helpful
35+
for debugging SSL connection issues. If you can connect to MongoDB with `tlsAllowInvalidCertificates: true`, but not with
36+
`tlsAllowInvalidCertificates: false`, then you can confirm Mongoose can connect to the server and the server is configured to use
37+
TLS/SSL correctly, but there's some issue with the certificate.
4038

4139
For example, a common issue is the below error message:
4240

@@ -45,17 +43,14 @@ MongooseServerSelectionError: unable to verify the first certificate
4543
```
4644

4745
This error is often caused by [self-signed MongoDB certificates](https://medium.com/@rajanmaharjan/secure-your-mongodb-connections-ssl-tls-92e2addb3c89) or other situations where the certificate sent by the MongoDB
48-
server is not registered with an established certificate authority. The solution is to set the `sslCA` option, which essentially sets a list of allowed SSL certificates.
46+
server is not registered with an established certificate authority. The solution is to set the `tlsCAFile` option, which essentially sets a list of allowed SSL certificates.
4947

5048
```javascript
5149
await mongoose.connect('mongodb://127.0.0.1:27017/test', {
52-
ssl: true,
53-
sslValidate: true,
50+
tls: true,
5451
// For example, see https://medium.com/@rajanmaharjan/secure-your-mongodb-connections-ssl-tls-92e2addb3c89
5552
// for where the `rootCA.pem` file comes from.
56-
// Please note that, in Mongoose >= 5.8.3, `sslCA` needs to be
57-
// the **path to** the CA file, **not** the contents of the CA file
58-
sslCA: `${__dirname}/rootCA.pem`
53+
tlsCAFile: `${__dirname}/rootCA.pem`,
5954
});
6055
```
6156

@@ -66,7 +61,7 @@ MongooseServerSelectionError: Hostname/IP does not match certificate's altnames:
6661
```
6762

6863
The SSL certificate's [common name](https://knowledge.digicert.com/solution/SO7239.html) **must** line up with the host name
69-
in your connection string. If the SSL certificate is for `hostname2.mydomain.com`, your connection string must connect to `hostname2.mydomain.com`, not any other hostname or IP address that may be equivalent to `hostname2.mydomain.com`. For replica sets, this also means that the SSL certificate's common name must line up with the [machine's `hostname`](../connections.html#replicaset-hostnames).
64+
in your connection string. If the SSL certificate is for `hostname2.mydomain.com`, your connection string must connect to `hostname2.mydomain.com`, not any other hostname or IP address that may be equivalent to `hostname2.mydomain.com`. For replica sets, this also means that the SSL certificate's common name must line up with the [machine's `hostname`](../connections.html#replicaset-hostnames). To disable this validation, set the `tlsAllowInvalidHostnames` option to `true`.
7065

7166
## X.509 Authentication
7267

@@ -76,39 +71,38 @@ If you're using [X.509 authentication](https://www.mongodb.com/docs/drivers/node
7671
// Do this:
7772
const username = 'myusername';
7873
await mongoose.connect(`mongodb://${encodeURIComponent(username)}@127.0.0.1:27017/test`, {
79-
ssl: true,
80-
sslValidate: true,
81-
sslCA: `${__dirname}/rootCA.pem`,
82-
authMechanism: 'MONGODB-X509'
74+
tls: true,
75+
tlsCAFile: `${__dirname}/rootCA.pem`,
76+
authMechanism: 'MONGODB-X509',
8377
});
8478

8579
// Not this:
8680
await mongoose.connect('mongodb://127.0.0.1:27017/test', {
87-
ssl: true,
88-
sslValidate: true,
89-
sslCA: `${__dirname}/rootCA.pem`,
81+
tls: true,
82+
tlsCAFile: `${__dirname}/rootCA.pem`,
9083
authMechanism: 'MONGODB-X509',
91-
auth: { username }
84+
auth: { username },
9285
});
9386
```
9487

9588
## X.509 Authentication with MongoDB Atlas
9689

97-
With MongoDB Atlas, X.509 certificates are not Root CA certificates and will not work with the `sslCA` parameter as self-signed certificates would. If the `sslCA` parameter is used an error similar to the following would be raised:
90+
With MongoDB Atlas, X.509 certificates are not Root CA certificates and will not work with the `tlsCAFile` parameter as self-signed certificates would. If the `tlsCAFile` parameter is used an error similar to the following would be raised:
9891

9992
```no-highlight
10093
MongoServerSelectionError: unable to get local issuer certificate
10194
```
10295

103-
To connect to a MongoDB Atlas cluster using X.509 authentication the correct option to set is `tlsCertificateKeyFile`. The connection string already specifies the `authSource` and `authMechanism`, and the DNS `TXT` record would supply the parameter and value for `sslValidate`, however they're included below as `connect()` options for completeness:
96+
To connect to a MongoDB Atlas cluster using X.509 authentication the correct option to set is `tlsCertificateKeyFile`. The connection string already specifies the `authSource` and `authMechanism`, however they're included below as `connect()` options for completeness:
10497

10598
```javascript
10699
const url = 'mongodb+srv://xyz.mongodb.net/test?authSource=%24external&authMechanism=MONGODB-X509';
107100
await mongoose.connect(url, {
108-
sslValidate: true,
101+
tls: true,
102+
// location of a local .pem file that contains both the client's certificate and key
109103
tlsCertificateKeyFile: '/path/to/certificate.pem',
110104
authMechanism: 'MONGODB-X509',
111-
authSource: '$external'
105+
authSource: '$external',
112106
});
113107
```
114108

lib/helpers/indexes/getRelatedIndexes.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const hasDollarKeys = require('../query/hasDollarKeys');
4+
35
function getRelatedSchemaIndexes(model, schemaIndexes) {
46
return getRelatedIndexes({
57
baseModelName: model.baseModelName,
@@ -46,7 +48,9 @@ function getRelatedIndexes({
4648

4749
return indexes.filter(index => {
4850
const partialFilterExpression = getPartialFilterExpression(index, indexesType);
49-
return !partialFilterExpression || !partialFilterExpression[discriminatorKey];
51+
return !partialFilterExpression
52+
|| !partialFilterExpression[discriminatorKey]
53+
|| (hasDollarKeys(partialFilterExpression[discriminatorKey]) && !('$eq' in partialFilterExpression[discriminatorKey]));
5054
});
5155
}
5256

lib/schema/array.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,14 +638,14 @@ handle.$and = createLogicalQueryOperatorHandler('$and');
638638
handle.$nor = createLogicalQueryOperatorHandler('$nor');
639639

640640
function createLogicalQueryOperatorHandler(op) {
641-
return function logicalQueryOperatorHandler(val) {
641+
return function logicalQueryOperatorHandler(val, context) {
642642
if (!Array.isArray(val)) {
643643
throw new TypeError('conditional ' + op + ' requires an array');
644644
}
645645

646646
const ret = [];
647647
for (const obj of val) {
648-
ret.push(cast(this.casterConstructor.schema, obj, null, this && this.$$context));
648+
ret.push(cast(this.casterConstructor.schema ?? context.schema, obj, null, this && this.$$context));
649649
}
650650

651651
return ret;

lib/schema/bigint.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,14 @@ SchemaBigInt.prototype.castForQuery = function($conditional, val, context) {
212212
return this.applySetters(null, val, context);
213213
}
214214

215-
return this.applySetters(val, context);
215+
try {
216+
return this.applySetters(val, context);
217+
} catch (err) {
218+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
219+
err.path = this.$fullPath;
220+
}
221+
throw err;
222+
}
216223
};
217224

218225
/**

lib/schema/boolean.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,14 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val, context) {
256256
return this.applySetters(null, val, context);
257257
}
258258

259-
return this.applySetters(val, context);
259+
try {
260+
return this.applySetters(val, context);
261+
} catch (err) {
262+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
263+
err.path = this.$fullPath;
264+
}
265+
throw err;
266+
}
260267
};
261268

262269
/**

lib/schema/buffer.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,16 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val, context) {
279279
}
280280
return handler.call(this, val);
281281
}
282-
const casted = this.applySetters(val, context);
282+
283+
let casted;
284+
try {
285+
casted = this.applySetters(val, context);
286+
} catch (err) {
287+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
288+
err.path = this.$fullPath;
289+
}
290+
throw err;
291+
}
283292
return casted ? casted.toObject({ transform: false, virtuals: false }) : casted;
284293
};
285294

lib/schema/date.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,14 @@ SchemaDate.prototype.$conditionalHandlers = {
407407

408408
SchemaDate.prototype.castForQuery = function($conditional, val, context) {
409409
if ($conditional == null) {
410-
return this.applySetters(val, context);
410+
try {
411+
return this.applySetters(val, context);
412+
} catch (err) {
413+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
414+
err.path = this.$fullPath;
415+
}
416+
throw err;
417+
}
411418
}
412419

413420
const handler = this.$conditionalHandlers[$conditional];

0 commit comments

Comments
 (0)