From 0542f860f490035c3a3e4edb32b22767e3dec965 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Mon, 25 Apr 2016 21:33:11 -0400 Subject: [PATCH] Test case to ensure dashboard.parse.com won't break (#1636) * Test case to ensure dashboard.parse.com won't break * Adds volatile classes concept for _PushStatus * Fixes test --- spec/helper.js | 24 +++++++++++++++++++++++- src/Controllers/DatabaseController.js | 2 +- src/Controllers/SchemaController.js | 16 +++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/spec/helper.js b/spec/helper.js index 104c1753..0d6379fb 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -9,6 +9,7 @@ var facebook = require('../src/authDataManager/facebook'); var ParseServer = require('../src/index').ParseServer; var path = require('path'); var TestUtils = require('../src/index').TestUtils; +var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter'); var databaseURI = process.env.DATABASE_URI; var cloudMain = process.env.CLOUD_CODE_MAIN || './spec/cloud/main.js'; @@ -87,8 +88,29 @@ beforeEach(function(done) { return TestUtils.destroyAllDataPermanently().then(done, fail); }); +var mongoAdapter = new MongoStorageAdapter({ + collectionPrefix: defaultConfiguration.collectionPrefix, + uri: databaseURI, +}) + afterEach(function(done) { - Parse.User.logOut().then(() => { + mongoAdapter.getAllSchemas() + .then(allSchemas => { + allSchemas.forEach((schema) => { + var className = schema.className; + expect(className).toEqual({ asymmetricMatch: className => { + if (!className.startsWith('_')) { + return true; + } else { + // Other system classes will break Parse.com, so make sure that we don't save anything to _SCHEMA that will + // break it. + return ['_User', '_Installation', '_Role', '_Session', '_Product'].includes(className); + } + }}); + }); + }) + .then(() => Parse.User.logOut()) + .then(() => { return TestUtils.destroyAllDataPermanently(); }).then(() => { done(); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index fca02829..bda0b066 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -345,7 +345,7 @@ DatabaseController.prototype.create = function(className, object, { acl } = {}) return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'create')) .then(() => this.handleRelationUpdates(className, null, object)) .then(() => schemaController.enforceClassExists(className)) - .then(() => schemaController.getOneSchema(className)) + .then(() => schemaController.getOneSchema(className, true)) .then(schema => this.adapter.createObject(className, object, schemaController, schema)) .then(result => sanitizeDatabaseResult(originalObject, result.ops[0])); }) diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index 1c993d72..af56610b 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -93,6 +93,8 @@ const requiredColumns = Object.freeze({ const systemClasses = Object.freeze(['_User', '_Installation', '_Role', '_Session', '_Product', '_PushStatus']); +const volatileClasses = Object.freeze(['_PushStatus']); + // 10 alpha numberic chars + uppercase const userIdRegex = /^[a-zA-Z0-9]{10}$/; // Anything that start with role @@ -251,6 +253,15 @@ class SchemaController { this.data[schema.className] = schema.fields; this.perms[schema.className] = schema.classLevelPermissions; }); + + // Inject the in-memory classes + volatileClasses.forEach(className => { + this.data[className] = injectDefaultSchema({ + className, + fields: {}, + classLevelPermissions: {} + }); + }); }); } @@ -259,7 +270,10 @@ class SchemaController { .then(allSchemas => allSchemas.map(injectDefaultSchema)); } - getOneSchema(className) { + getOneSchema(className, allowVolatileClasses = false) { + if (allowVolatileClasses && volatileClasses.indexOf(className) > -1) { + return Promise.resolve(this.data[className]); + } return this._dbAdapter.getOneSchema(className) .then(injectDefaultSchema); }