Skip to content

Commit 8bc201d

Browse files
rhuanbarretodplewis
authored andcommitted
#6101 Let users define objectId (#6177)
* #6101 Let users define objectId * Add `allowCustomObjectId` to PS Option * Add checking in objectId creation * Add test * Update docs * Update definition * Change default to false * throw on empty, null, undefined * better tests * unused async * removed comment * retain comment * Linting fix according to contributing spec.
1 parent 7944ef1 commit 8bc201d

File tree

5 files changed

+97
-11
lines changed

5 files changed

+97
-11
lines changed

spec/rest.spec.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,66 @@ describe('rest create', () => {
4444
});
4545
});
4646

47+
it('should use objectId from client when allowCustomObjectId true', async () => {
48+
config.allowCustomObjectId = true;
49+
50+
// use time as unique custom id for test reusability
51+
const customId = `${Date.now()}`;
52+
const obj = {
53+
objectId: customId,
54+
};
55+
56+
const {
57+
status,
58+
response: { objectId },
59+
} = await rest.create(config, auth.nobody(config), 'MyClass', obj);
60+
61+
expect(status).toEqual(201);
62+
expect(objectId).toEqual(customId);
63+
});
64+
65+
it('should throw on invalid objectId when allowCustomObjectId true', () => {
66+
config.allowCustomObjectId = true;
67+
68+
const objIdNull = {
69+
objectId: null,
70+
};
71+
72+
const objIdUndef = {
73+
objectId: undefined,
74+
};
75+
76+
const objIdEmpty = {
77+
objectId: '',
78+
};
79+
80+
const err = 'objectId must not be empty, null or undefined';
81+
82+
expect(() =>
83+
rest.create(config, auth.nobody(config), 'MyClass', objIdEmpty)
84+
).toThrowError(err);
85+
86+
expect(() =>
87+
rest.create(config, auth.nobody(config), 'MyClass', objIdNull)
88+
).toThrowError(err);
89+
90+
expect(() =>
91+
rest.create(config, auth.nobody(config), 'MyClass', objIdUndef)
92+
).toThrowError(err);
93+
});
94+
95+
it('should generate objectId when not set by client with allowCustomObjectId true', async () => {
96+
config.allowCustomObjectId = true;
97+
98+
const {
99+
status,
100+
response: { objectId },
101+
} = await rest.create(config, auth.nobody(config), 'MyClass', {});
102+
103+
expect(status).toEqual(201);
104+
expect(objectId).toBeDefined();
105+
});
106+
47107
it('is backwards compatible when _id size changes', done => {
48108
rest
49109
.create(config, auth.nobody(config), 'Foo', { size: 10 })

src/Options/Definitions.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ module.exports.ParseServerOptions = {
1717
action: parsers.booleanParser,
1818
default: true,
1919
},
20+
allowCustomObjectId: {
21+
env: 'PARSE_SERVER_ALLOW_CUSTOM_OBJECT_ID',
22+
help: 'Enable (or disable) custom objectId, defaults to false',
23+
action: parsers.booleanParser,
24+
default: false,
25+
},
2026
allowHeaders: {
2127
env: 'PARSE_SERVER_ALLOW_HEADERS',
2228
help: 'Add headers to Access-Control-Allow-Headers',

src/Options/docs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @interface ParseServerOptions
33
* @property {Any} accountLockout account lockout policy for failed login attempts
44
* @property {Boolean} allowClientClassCreation Enable (or disable) client class creation, defaults to true
5+
* @property {Boolean} allowCustomObjectId Enable (or disable) custom objectId, defaults to false
56
* @property {String[]} allowHeaders Add headers to Access-Control-Allow-Headers
67
* @property {Adapter<AnalyticsAdapter>} analyticsAdapter Adapter module for the analytics
78
* @property {String} appId Your Parse Application ID

src/Options/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ export interface ParseServerOptions {
102102
:ENV: PARSE_SERVER_ALLOW_CLIENT_CLASS_CREATION
103103
:DEFAULT: true */
104104
allowClientClassCreation: ?boolean;
105+
/* Enable (or disable) custom objectId
106+
:ENV: PARSE_SERVER_ALLOW_CUSTOM_OBJECT_ID
107+
:DEFAULT: false */
108+
allowCustomObjectId: ?boolean;
105109
/* Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication
106110
:ENV: PARSE_SERVER_AUTH_PROVIDERS */
107111
auth: ?any;

src/RestWrite.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,32 @@ function RestWrite(
4646
this.storage = {};
4747
this.runOptions = {};
4848
this.context = {};
49-
if (!query && data.objectId) {
50-
throw new Parse.Error(
51-
Parse.Error.INVALID_KEY_NAME,
52-
'objectId is an invalid field name.'
53-
);
54-
}
55-
if (!query && data.id) {
56-
throw new Parse.Error(
57-
Parse.Error.INVALID_KEY_NAME,
58-
'id is an invalid field name.'
59-
);
49+
50+
if (!query) {
51+
if (this.config.allowCustomObjectId) {
52+
if (
53+
Object.prototype.hasOwnProperty.call(data, 'objectId') &&
54+
!data.objectId
55+
) {
56+
throw new Parse.Error(
57+
Parse.Error.MISSING_OBJECT_ID,
58+
'objectId must not be empty, null or undefined'
59+
);
60+
}
61+
} else {
62+
if (data.objectId) {
63+
throw new Parse.Error(
64+
Parse.Error.INVALID_KEY_NAME,
65+
'objectId is an invalid field name.'
66+
);
67+
}
68+
if (data.id) {
69+
throw new Parse.Error(
70+
Parse.Error.INVALID_KEY_NAME,
71+
'id is an invalid field name.'
72+
);
73+
}
74+
}
6075
}
6176

6277
// When the operation is complete, this.response may have several

0 commit comments

Comments
 (0)