mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
feat: Deprecate GraphQL Playground that exposes master key in HTTP response (#10112)
This commit is contained in:
+3
-1
@@ -18,7 +18,9 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
|
||||
| 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) | changed | - |
|
||||
| DEPPS13 | Config option `enableInsecureAuthAdapters` defaults to `false` | [#9667](https://github.com/parse-community/parse-server/pull/9667) | 8.0.0 (2025) | 9.0.0 (2026) | changed | - |
|
||||
| DEPPS14 | Config option `pages.encodePageParamHeaders` defaults to `true` | [#10063](https://github.com/parse-community/parse-server/issues/10063) | 9.4.0 (2026) | 10.0.0 (2027) | deprecated | - |
|
||||
| DEPPS15 | Config option `readOnlyMasterKeyIps` defaults to `['127.0.0.1', '::1']` | [#10115](https://github.com/parse-community/parse-server/pull/10115) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
|
||||
| DEPPS15 | Config option `readOnlyMasterKeyIps` defaults to `['127.0.0.1', '::1']` | [#10115](https://github.com/parse-community/parse-server/pull/10115) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
|
||||
| DEPPS16 | Remove config option `mountPlayground` | [#10110](https://github.com/parse-community/parse-server/issues/10110) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
|
||||
| DEPPS17 | Remove config option `playgroundPath` | [#10110](https://github.com/parse-community/parse-server/issues/10110) | 9.5.0 (2026) | 10.0.0 (2027) | deprecated | - |
|
||||
|
||||
[i_deprecation]: ## "The version and date of the deprecation."
|
||||
[i_change]: ## "The version and date of the planned change."
|
||||
|
||||
@@ -103,4 +103,50 @@ describe('Deprecator', () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('logs deprecation for removed key when option is set', async () => {
|
||||
deprecations = [{ optionKey: 'exampleKey', changeNewKey: '', solution: 'Use something else.' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logger = require('../lib/logger').logger;
|
||||
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer({ exampleKey: true });
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
`DeprecationWarning: The Parse Server option '${deprecations[0].optionKey}' is deprecated and will be removed in a future version. ${deprecations[0].solution}`
|
||||
);
|
||||
});
|
||||
|
||||
it('does not log deprecation for removed key when option is not set', async () => {
|
||||
deprecations = [{ optionKey: 'exampleKey', changeNewKey: '', solution: 'Use something else.' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer();
|
||||
expect(logSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs deprecation for mountPlayground when set', async () => {
|
||||
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer({ mountPlayground: true, mountGraphQL: true });
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
optionKey: 'mountPlayground',
|
||||
changeNewKey: '',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('does not log deprecation for mountPlayground when not set', async () => {
|
||||
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer();
|
||||
expect(logSpy).not.toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
optionKey: 'mountPlayground',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,4 +31,14 @@ module.exports = [
|
||||
changeNewDefault: '["127.0.0.1", "::1"]',
|
||||
solution: "Set 'readOnlyMasterKeyIps' to the IP addresses that should be allowed to use the read-only master key, or to '[\"127.0.0.1\", \"::1\"]' to restrict access to localhost.",
|
||||
},
|
||||
{
|
||||
optionKey: 'mountPlayground',
|
||||
changeNewKey: '',
|
||||
solution: "Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client such as Apollo Sandbox, GraphiQL, or Insomnia with custom request headers.",
|
||||
},
|
||||
{
|
||||
optionKey: 'playgroundPath',
|
||||
changeNewKey: '',
|
||||
solution: "Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client such as Apollo Sandbox, GraphiQL, or Insomnia with custom request headers.",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -20,11 +20,17 @@ class Deprecator {
|
||||
const solution = deprecation.solution;
|
||||
const optionKey = deprecation.optionKey;
|
||||
const changeNewDefault = deprecation.changeNewDefault;
|
||||
const changeNewKey = deprecation.changeNewKey;
|
||||
|
||||
// If default will change, only throw a warning if option is not set
|
||||
if (changeNewDefault != null && Utils.getNestedProperty(options, optionKey) == null) {
|
||||
Deprecator._logOption({ optionKey, changeNewDefault, solution });
|
||||
}
|
||||
|
||||
// If key will be removed or renamed, only throw a warning if option is set
|
||||
if (changeNewKey != null && Utils.getNestedProperty(options, optionKey) != null) {
|
||||
Deprecator._logOption({ optionKey, changeNewKey, solution });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +113,7 @@ class Deprecator {
|
||||
|
||||
// Compose message
|
||||
let output = `DeprecationWarning: The Parse Server ${type} '${key}' `;
|
||||
output += changeNewKey ? `is deprecated and will be ${keyAction} in a future version.` : '';
|
||||
output += changeNewKey != null ? `is deprecated and will be ${keyAction} in a future version.` : '';
|
||||
output += changeNewDefault
|
||||
? `default will change to '${changeNewDefault}' in a future version.`
|
||||
: '';
|
||||
|
||||
@@ -404,7 +404,7 @@ module.exports.ParseServerOptions = {
|
||||
},
|
||||
mountPlayground: {
|
||||
env: 'PARSE_SERVER_MOUNT_PLAYGROUND',
|
||||
help: 'Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production',
|
||||
help: 'Deprecated. Mounts the GraphQL Playground which is deprecated and will be removed in a future version. The playground exposes the master key in the browser. Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client with custom request headers.',
|
||||
action: parsers.booleanParser,
|
||||
default: false,
|
||||
},
|
||||
@@ -429,7 +429,7 @@ module.exports.ParseServerOptions = {
|
||||
},
|
||||
playgroundPath: {
|
||||
env: 'PARSE_SERVER_PLAYGROUND_PATH',
|
||||
help: 'Mount path for the GraphQL Playground, defaults to /playground',
|
||||
help: 'Deprecated. Mount path for the GraphQL Playground. The playground is deprecated and will be removed in a future version.',
|
||||
default: '/playground',
|
||||
},
|
||||
port: {
|
||||
|
||||
+2
-2
@@ -77,11 +77,11 @@
|
||||
* @property {Union} middleware middleware for express server, can be string or function
|
||||
* @property {Boolean} mountGraphQL Mounts the GraphQL endpoint
|
||||
* @property {String} mountPath Mount path for the server, defaults to /parse
|
||||
* @property {Boolean} mountPlayground Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production
|
||||
* @property {Boolean} mountPlayground Deprecated. Mounts the GraphQL Playground which is deprecated and will be removed in a future version. The playground exposes the master key in the browser. Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client with custom request headers.
|
||||
* @property {Number} objectIdSize Sets the number of characters in generated object id's, default 10
|
||||
* @property {PagesOptions} pages The options for pages such as password reset and email verification.
|
||||
* @property {PasswordPolicyOptions} passwordPolicy The password policy for enforcing password related rules.
|
||||
* @property {String} playgroundPath Mount path for the GraphQL Playground, defaults to /playground
|
||||
* @property {String} playgroundPath Deprecated. Mount path for the GraphQL Playground. The playground is deprecated and will be removed in a future version.
|
||||
* @property {Number} port The port to run the ParseServer, defaults to 1337.
|
||||
* @property {Boolean} preserveFileName Enable (or disable) the addition of a unique hash to the file names
|
||||
* @property {Boolean} preventLoginWithUnverifiedEmail Set to `true` to prevent a user from logging in if the email has not yet been verified and email verification is required. Supports a function with a return value of `true` or `false` for conditional prevention. The function receives a request object that includes `createdWith` to indicate whether the invocation is for `signup` or `login` and the used auth provider.<br><br>The `createdWith` values per scenario:<ul><li>Password signup: `{ action: 'signup', authProvider: 'password' }`</li><li>Auth provider signup: `{ action: 'signup', authProvider: '<provider>' }`</li><li>Password login: `{ action: 'login', authProvider: 'password' }`</li><li>Auth provider login: function not invoked; auth provider login bypasses email verification</li></ul>Default is `false`.<br>Requires option `verifyUserEmails: true`.
|
||||
|
||||
@@ -342,11 +342,11 @@ export interface ParseServerOptions {
|
||||
:ENV: PARSE_SERVER_GRAPHQL_PUBLIC_INTROSPECTION
|
||||
:DEFAULT: false */
|
||||
graphQLPublicIntrospection: ?boolean;
|
||||
/* Mounts the GraphQL Playground which exposes the master key in the browser - never use this option in production
|
||||
/* Deprecated. Mounts the GraphQL Playground which is deprecated and will be removed in a future version. The playground exposes the master key in the browser. Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client with custom request headers.
|
||||
:ENV: PARSE_SERVER_MOUNT_PLAYGROUND
|
||||
:DEFAULT: false */
|
||||
mountPlayground: ?boolean;
|
||||
/* Mount path for the GraphQL Playground, defaults to /playground
|
||||
/* Deprecated. Mount path for the GraphQL Playground. The playground is deprecated and will be removed in a future version.
|
||||
:ENV: PARSE_SERVER_PLAYGROUND_PATH
|
||||
:DEFAULT: /playground */
|
||||
playgroundPath: ?string;
|
||||
|
||||
+1
-1
@@ -460,7 +460,7 @@ class ParseServer {
|
||||
if (options.mountPlayground) {
|
||||
parseGraphQLServer.applyPlayground(app);
|
||||
logging.getLogger().warn(
|
||||
'GraphQL Playground is enabled and exposes the master key in the browser. The playground is a developer tool and should not be used in production. Use Parse Dashboard for production environments.'
|
||||
'GraphQL Playground is deprecated and will be removed in a future version. It exposes the master key in the browser. Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client with custom request headers.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user