Add config for objectId size (#3950)

* Add objectId config property, default to 10

* Update Config constructor

* Add test for backwards compatibility when changing objectId size
This commit is contained in:
Steven Shipton
2017-06-27 11:22:43 +01:00
committed by Natan Rolnik
parent bd6816c14c
commit 51d2dd92cb
9 changed files with 64 additions and 8 deletions

View File

@@ -63,6 +63,10 @@ describe('newObjectId', () => {
expect(cryptoUtils.newObjectId().length).toBeGreaterThan(9);
});
it('returns result with required number of characters', () => {
expect(cryptoUtils.newObjectId(42).length).toBe(42);
});
it('returns unique results', () => {
expect(givesUniqueResults(() => cryptoUtils.newObjectId(), 100)).toBe(true);
});

View File

@@ -23,11 +23,55 @@ describe('rest create', () => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(typeof obj.objectId).toEqual('string');
expect(obj.objectId.length).toEqual(10);
expect(obj._id).toBeUndefined();
done();
});
});
it('can use custom _id size', done => {
config.objectIdSize = 20;
rest.create(config, auth.nobody(config), 'Foo', {})
.then(() => database.adapter.find('Foo', { fields: {} }, {}, {}))
.then((results) => {
expect(results.length).toEqual(1);
var obj = results[0];
expect(typeof obj.objectId).toEqual('string');
expect(obj.objectId.length).toEqual(20);
done();
});
});
it('is backwards compatible when _id size changes', done => {
rest.create(config, auth.nobody(config), 'Foo', {size: 10})
.then(() => {
config.objectIdSize = 20;
return rest.find(config, auth.nobody(config), 'Foo', {size: 10});
})
.then((response) => {
expect(response.results.length).toEqual(1);
expect(response.results[0].objectId.length).toEqual(10);
return rest.update(config, auth.nobody(config), 'Foo', {objectId: response.results[0].objectId}, {update: 20});
})
.then(() => {
return rest.find(config, auth.nobody(config), 'Foo', {size: 10});
}).then((response) => {
expect(response.results.length).toEqual(1);
expect(response.results[0].objectId.length).toEqual(10);
expect(response.results[0].update).toEqual(20);
return rest.create(config, auth.nobody(config), 'Foo', {size: 20});
})
.then(() => {
config.objectIdSize = 10;
return rest.find(config, auth.nobody(config), 'Foo', {size: 20});
})
.then((response) => {
expect(response.results.length).toEqual(1);
expect(response.results[0].objectId.length).toEqual(20);
done();
});
});
it('handles array, object, date', (done) => {
const now = new Date();
var obj = {

View File

@@ -73,6 +73,7 @@ export class Config {
this.generateSessionExpiresAt = this.generateSessionExpiresAt.bind(this);
this.generateEmailVerifyTokenExpiresAt = this.generateEmailVerifyTokenExpiresAt.bind(this);
this.revokeSessionOnPasswordReset = cacheInfo.revokeSessionOnPasswordReset;
this.objectIdSize = cacheInfo.objectIdSize;
}
static validate({

View File

@@ -141,6 +141,7 @@ class ParseServer {
revokeSessionOnPasswordReset = defaults.revokeSessionOnPasswordReset,
schemaCacheTTL = defaults.schemaCacheTTL, // cache for 5s
enableSingleSchemaCache = false,
objectIdSize = defaults.objectIdSize,
__indexBuildCompletionCallbackForTests = () => {},
}) {
// Initialize the node client SDK automatically
@@ -262,7 +263,8 @@ class ParseServer {
pushWorker,
pushControllerQueue,
hasPushSupport,
hasPushScheduledSupport
hasPushScheduledSupport,
objectIdSize
});
Config.validate(AppCache.get(appId));

View File

@@ -187,7 +187,7 @@ RestWrite.prototype.setRequiredFieldsIfNeeded = function() {
// Only assign new objectId if we are creating new object
if (!this.data.objectId) {
this.data.objectId = cryptoUtils.newObjectId();
this.data.objectId = cryptoUtils.newObjectId(this.config.objectIdSize);
}
}
}

View File

@@ -52,7 +52,7 @@ function statusHandler(className, database) {
export function jobStatusHandler(config) {
let jobStatus;
const objectId = newObjectId();
const objectId = newObjectId(config.objectIdSize);
const database = config.database;
const handler = statusHandler(JOB_STATUS_COLLECTION, database);
const setRunning = function(jobName, params) {
@@ -103,7 +103,7 @@ export function jobStatusHandler(config) {
});
}
export function pushStatusHandler(config, objectId = newObjectId()) {
export function pushStatusHandler(config, objectId = newObjectId(config.objectIdSize)) {
let pushStatus;
const database = config.database;

View File

@@ -256,5 +256,10 @@ export default {
},
"middleware": {
help: "middleware for express server, can be string or function"
},
"objectIdSize": {
env: "PARSE_SERVER_OBJECT_ID_SIZE",
help: "Sets the number of characters in generated object id's, default 10",
action: numberParser("objectIdSize")
}
};

View File

@@ -35,9 +35,8 @@ export function randomString(size: number): string {
}
// Returns a new random alphanumeric string suitable for object ID.
export function newObjectId(): string {
//TODO: increase length to better protect against collisions.
return randomString(10);
export function newObjectId(size: number = 10): string {
return randomString(size);
}
// Returns a new random hex string suitable for secure tokens.

View File

@@ -32,5 +32,6 @@ export default {
expireInactiveSessions: true,
revokeSessionOnPasswordReset: true,
schemaCacheTTL: 5000, // in ms
userSensitiveFields: ['email']
userSensitiveFields: ['email'],
objectIdSize: 10
}