diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md
index 56359c93..59b728a9 100644
--- a/DEPRECATIONS.md
+++ b/DEPRECATIONS.md
@@ -13,6 +13,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| 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) | deprecated | - |
+| DEPPS10 | Config option `encodeParseObjectInCloudFunction` defaults to `true` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 7.0.0 (2024) | deprecated | - |
[i_deprecation]: ## "The version and date of the deprecation."
[i_removal]: ## "The version and date of the planned removal."
diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js
index a8795a4e..a2e62355 100644
--- a/spec/CloudCode.spec.js
+++ b/spec/CloudCode.spec.js
@@ -1353,7 +1353,27 @@ describe('Cloud Code', () => {
});
});
+ it('should not encode Parse Objects', async () => {
+ const user = new Parse.User();
+ user.setUsername('username');
+ user.setPassword('password');
+ user.set('deleted', false);
+ await user.signUp();
+ Parse.Cloud.define(
+ 'deleteAccount',
+ async req => {
+ expect(req.params.object instanceof Parse.Object).not.toBeTrue();
+ return 'Object deleted';
+ },
+ {
+ requireMaster: true,
+ }
+ );
+ await Parse.Cloud.run('deleteAccount', { object: user.toPointer() }, { useMasterKey: true });
+ });
+
it('allow cloud to encode Parse Objects', async () => {
+ await reconfigureServer({ encodeParseObjectInCloudFunction: true });
const user = new Parse.User();
user.setUsername('username');
user.setPassword('password');
diff --git a/src/Deprecator/Deprecations.js b/src/Deprecator/Deprecations.js
index 0afd98ff..2f698ad3 100644
--- a/src/Deprecator/Deprecations.js
+++ b/src/Deprecator/Deprecations.js
@@ -18,4 +18,5 @@
module.exports = [
{ optionKey: 'allowClientClassCreation', changeNewDefault: 'false' },
{ optionKey: 'allowExpiredAuthDataToken', changeNewDefault: 'false' },
+ { optionKey: 'encodeParseObjectInCloudFunction', changeNewDefault: 'true' },
];
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index b067412d..6477836e 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -210,6 +210,13 @@ module.exports.ParseServerOptions = {
action: parsers.booleanParser,
default: false,
},
+ encodeParseObjectInCloudFunction: {
+ env: 'PARSE_SERVER_ENCODE_PARSE_OBJECT_IN_CLOUD_FUNCTION',
+ help:
+ 'If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
\u2139\uFE0F The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.',
+ action: parsers.booleanParser,
+ default: false,
+ },
encryptionKey: {
env: 'PARSE_SERVER_ENCRYPTION_KEY',
help: 'Key for encrypting your files',
diff --git a/src/Options/docs.js b/src/Options/docs.js
index 2e139034..fdb62bb5 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -40,6 +40,7 @@
* @property {Number} emailVerifyTokenValidityDuration Set the validity duration of the email verification token in seconds after which the token expires. The token is used in the link that is set in the email. After the token expires, the link becomes invalid and a new link has to be sent. If the option is not set or set to `undefined`, then the token never expires.
For example, to expire the token after 2 hours, set a value of 7200 seconds (= 60 seconds * 60 minutes * 2 hours).
Default is `undefined`.
Requires option `verifyUserEmails: true`.
* @property {Boolean} enableAnonymousUsers Enable (or disable) anonymous users, defaults to true
* @property {Boolean} enableExpressErrorHandler Enables the default express error handler for all errors
+ * @property {Boolean} encodeParseObjectInCloudFunction If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
ℹ️ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.
* @property {String} encryptionKey Key for encrypting your files
* @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access.
* @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date.
diff --git a/src/Options/index.js b/src/Options/index.js
index 2008301c..a8414c65 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -202,6 +202,9 @@ export interface ParseServerOptions {
cacheAdapter: ?Adapter;
/* Adapter module for email sending */
emailAdapter: ?Adapter;
+ /* If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
ℹ️ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.
+ :DEFAULT: false */
+ encodeParseObjectInCloudFunction: ?boolean;
/* Public URL to your parse server with http:// or https://.
:ENV: PARSE_PUBLIC_SERVER_URL */
publicServerURL: ?string;
diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js
index da69d54e..bb4b959e 100644
--- a/src/Routers/FunctionsRouter.js
+++ b/src/Routers/FunctionsRouter.js
@@ -9,7 +9,7 @@ import { jobStatusHandler } from '../StatusHandler';
import _ from 'lodash';
import { logger } from '../logger';
-function parseObject(obj) {
+function parseObject(obj, config) {
if (Array.isArray(obj)) {
return obj.map(item => {
return parseObject(item);
@@ -18,21 +18,21 @@ function parseObject(obj) {
return Object.assign(new Date(obj.iso), obj);
} else if (obj && obj.__type == 'File') {
return Parse.File.fromJSON(obj);
- } else if (obj && obj.__type == 'Pointer') {
+ } else if (obj && obj.__type == 'Pointer' && config.encodeParseObjectInCloudFunction) {
return Parse.Object.fromJSON({
__type: 'Pointer',
className: obj.className,
objectId: obj.objectId,
});
} else if (obj && typeof obj === 'object') {
- return parseParams(obj);
+ return parseParams(obj, config);
} else {
return obj;
}
}
-function parseParams(params) {
- return _.mapValues(params, parseObject);
+function parseParams(params, config) {
+ return _.mapValues(params, item => parseObject(item, config));
}
export class FunctionsRouter extends PromiseRouter {
@@ -66,7 +66,7 @@ export class FunctionsRouter extends PromiseRouter {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid job.');
}
let params = Object.assign({}, req.body, req.query);
- params = parseParams(params);
+ params = parseParams(params, req.config);
const request = {
params: params,
log: req.config.loggerController,
@@ -126,7 +126,7 @@ export class FunctionsRouter extends PromiseRouter {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, `Invalid function: "${functionName}"`);
}
let params = Object.assign({}, req.body, req.query);
- params = parseParams(params);
+ params = parseParams(params, req.config);
const request = {
params: params,
master: req.auth && req.auth.isMaster,