feat: Deprecation DEPPS12: Database option allowPublicExplain defaults to false (#9975)
BREAKING CHANGE: This release changes the MongoDB database option `allowPublicExplain` default to `false` (Deprecation DEPPS12).
This commit is contained in:
@@ -15,7 +15,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
|
||||
| DEPPS9 | Rename LiveQuery `fields` option to `keys` | [#8389](https://github.com/parse-community/parse-server/issues/8389) | 6.0.0 (2023) | 7.0.0 (2024) | removed | - |
|
||||
| DEPPS10 | Encode `Parse.Object` in Cloud Function and remove option `encodeParseObjectInCloudFunction` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 9.0.0 (2026) | removed | - |
|
||||
| DEPPS11 | Replace `PublicAPIRouter` with `PagesRouter` | [#7625](https://github.com/parse-community/parse-server/issues/7625) | 8.0.0 (2025) | 9.0.0 (2026) | removed | - |
|
||||
| DEPPS12 | Database option `allowPublicExplain` will default to `true` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.5.0 (2025) | 9.0.0 (2026) | deprecated | - |
|
||||
| DEPPS12 | Database option `allowPublicExplain` defaults to `false` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.5.0 (2025) | 9.0.0 (2026) | removed | - |
|
||||
|
||||
[i_deprecation]: ## "The version and date of the deprecation."
|
||||
[i_removal]: ## "The version and date of the planned removal."
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('Deprecator', () => {
|
||||
});
|
||||
|
||||
it('logs deprecation for nested option key with dot notation', async () => {
|
||||
deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }];
|
||||
deprecations = [{ optionKey: 'databaseOptions.testOption', changeNewDefault: 'false' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logger = require('../lib/logger').logger;
|
||||
@@ -60,14 +60,14 @@ describe('Deprecator', () => {
|
||||
});
|
||||
|
||||
it('does not log deprecation for nested option key if option is set manually', async () => {
|
||||
deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }];
|
||||
deprecations = [{ optionKey: 'databaseOptions.testOption', changeNewDefault: 'false' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
|
||||
const Config = require('../lib/Config');
|
||||
const config = Config.get('test');
|
||||
// Directly test scanParseServerOptions with nested option set
|
||||
Deprecator.scanParseServerOptions({ databaseOptions: { allowPublicExplain: true } });
|
||||
Deprecator.scanParseServerOptions({ databaseOptions: { testOption: true } });
|
||||
expect(logSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5369,7 +5369,7 @@ describe('Parse.Query testing', () => {
|
||||
const query = new Parse.Query('_User');
|
||||
query.equalTo('objectId', user.id);
|
||||
query.explain();
|
||||
const result = await query.find();
|
||||
const result = await query.find({ useMasterKey: true });
|
||||
// Validate
|
||||
expect(result.executionStats).not.toBeUndefined();
|
||||
});
|
||||
@@ -5533,11 +5533,8 @@ describe('Parse.Query testing', () => {
|
||||
);
|
||||
|
||||
it_id('c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f')(it_only_db('mongo'))(
|
||||
'explain works with and without master key by default',
|
||||
'explain requires master key by default',
|
||||
async () => {
|
||||
const logger = require('../lib/logger').logger;
|
||||
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer({
|
||||
databaseAdapter: undefined,
|
||||
databaseURI: 'mongodb://localhost:27017/parse',
|
||||
@@ -5546,21 +5543,20 @@ describe('Parse.Query testing', () => {
|
||||
},
|
||||
});
|
||||
|
||||
// Verify deprecation warning is logged when allowPublicExplain is not explicitly set
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/DeprecationWarning.*databaseOptions\.allowPublicExplain.*false/)
|
||||
);
|
||||
|
||||
const obj = new TestObject({ foo: 'bar' });
|
||||
await obj.save();
|
||||
|
||||
// Without master key
|
||||
// Without master key - should fail
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.explain();
|
||||
const resultWithoutMasterKey = await query.find();
|
||||
expect(resultWithoutMasterKey).toBeDefined();
|
||||
await expectAsync(query.find()).toBeRejectedWith(
|
||||
new Parse.Error(
|
||||
Parse.Error.INVALID_QUERY,
|
||||
'Using the explain query parameter requires the master key'
|
||||
)
|
||||
);
|
||||
|
||||
// With master key
|
||||
// With master key - should succeed
|
||||
const queryWithMasterKey = new Parse.Query(TestObject);
|
||||
queryWithMasterKey.explain();
|
||||
const resultWithMasterKey = await queryWithMasterKey.find({ useMasterKey: true });
|
||||
|
||||
@@ -17,5 +17,4 @@
|
||||
*/
|
||||
module.exports = [
|
||||
{ optionKey: 'enableInsecureAuthAdapters', changeNewDefault: 'false' },
|
||||
{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' },
|
||||
];
|
||||
|
||||
@@ -1144,7 +1144,7 @@ module.exports.DatabaseOptions = {
|
||||
help:
|
||||
'Set to `true` to allow `Parse.Query.explain` without master key.<br><br>\u26A0\uFE0F Enabling this option may expose sensitive query performance data to unauthorized users and could potentially be exploited for malicious purposes.',
|
||||
action: parsers.booleanParser,
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
appName: {
|
||||
env: 'PARSE_SERVER_DATABASE_APP_NAME',
|
||||
|
||||
@@ -751,7 +751,7 @@ export interface DatabaseOptions {
|
||||
/* Set to `true` to disable validation of index fields. When disabled, indexes can be created even if the fields do not exist in the schema. This can be useful when creating indexes on fields that will be added later. */
|
||||
disableIndexFieldValidation: ?boolean;
|
||||
/* Set to `true` to allow `Parse.Query.explain` without master key.<br><br>⚠️ Enabling this option may expose sensitive query performance data to unauthorized users and could potentially be exploited for malicious purposes.
|
||||
:DEFAULT: true */
|
||||
:DEFAULT: false */
|
||||
allowPublicExplain: ?boolean;
|
||||
/* An array of MongoDB client event configurations to enable logging of specific events. */
|
||||
logClientEvents: ?(LogClientEvent[]);
|
||||
|
||||
@@ -37,7 +37,7 @@ async function runFindTriggers(
|
||||
const { isGet } = options;
|
||||
|
||||
if (restOptions && restOptions.explain && !auth.isMaster) {
|
||||
const allowPublicExplain = config.databaseOptions?.allowPublicExplain ?? true;
|
||||
const allowPublicExplain = config.databaseOptions?.allowPublicExplain ?? false;
|
||||
|
||||
if (!allowPublicExplain) {
|
||||
throw new Parse.Error(
|
||||
|
||||
Reference in New Issue
Block a user