Skip to content

Commit

Permalink
Merge 9cd2986 into 32fc45d
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis authored Mar 16, 2021
2 parents 32fc45d + 9cd2986 commit e88fc9a
Show file tree
Hide file tree
Showing 38 changed files with 673 additions and 937 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ ___
## Unreleased (Master Branch)
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.5.0...master)
### Breaking Changes
Leveraging database real-time hooks, schema caching has been drastically improved. These improvements allows for reduced calls to the DB, faster queries and prevention of memory leaks. A breaking change can occur if you are horizontally scaling Parse Server (multiple Parse Server instances connecting to the same DB). Set `databaseOptions: { enableSchemaHooks: true }` parameter in [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (`enableSingleSchemaCache` and `schemaCacheTTL` have been removed). If you are horizontal scaling instances connected to MongoDB, you must use replica set clusters with WiredTiger, see [ChangeStream](https://docs.mongodb.com/manual/changeStreams/#availability)

The new schema cache uses a singleton object that is stored in-memory. In a horizontally scaled environment, if you update the schema in one instance the DB hooks will update the schema in all other instances. `databaseOptions: { enableSchemaHooks: true }` enables the DB hooks. If you have multiple server instances but `databaseOptions: { enableSchemaHooks: false }`, your schema maybe out of sync in your instances (resyncing will happen if an instance restarts). (Diamond Lewis, SebC) [#7214](https://github.com/parse-community/parse-server/issues/7214)
- Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html) (dblythy, Manuel Trezza) [#7071](https://github.com/parse-community/parse-server/pull/7071)
### Notable Changes
- Added Parse Server Security Check to report weak security settings (Manuel Trezza, dblythy) [#7247](https://github.com/parse-community/parse-server/issues/7247)
Expand Down
3 changes: 2 additions & 1 deletion resources/buildConfigDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function getENVPrefix(iface) {
'PasswordPolicyOptions' : 'PARSE_SERVER_PASSWORD_POLICY_',
'FileUploadOptions' : 'PARSE_SERVER_FILE_UPLOAD_',
'SecurityOptions': 'PARSE_SERVER_SECURITY_',
'DatabaseOptions': 'PARSE_SERVER_DATABASE_'
}
if (options[iface.id.name]) {
return options[iface.id.name]
Expand Down Expand Up @@ -168,7 +169,7 @@ function parseDefaultValue(elt, value, t) {
if (type == 'NumberOrBoolean') {
literalValue = t.numericLiteral(parsers.numberOrBoolParser('')(value));
}
const literalTypes = ['Object', 'SecurityOptions', 'PagesRoute', 'IdempotencyOptions','FileUploadOptions','CustomPagesOptions', 'PagesCustomUrlsOptions', 'PagesOptions'];
const literalTypes = ['Object', 'SecurityOptions', 'PagesRoute', 'IdempotencyOptions','FileUploadOptions','CustomPagesOptions', 'PagesCustomUrlsOptions', 'PagesOptions', 'DatabaseOptions'];
if (literalTypes.includes(type)) {
const object = parsers.objectParser(value);
const props = Object.keys(object).map((key) => {
Expand Down
58 changes: 0 additions & 58 deletions spec/EnableSingleSchemaCache.spec.js

This file was deleted.

4 changes: 3 additions & 1 deletion spec/LogsRouter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapte

const loggerController = new LoggerController(new WinstonLoggerAdapter());

describe('LogsRouter', () => {
describe_only(() => {
return process.env.PARSE_SERVER_LOG_LEVEL !== 'debug';
})('LogsRouter', () => {
it('can check valid master key of request', done => {
// Make mock request
const request = {
Expand Down
31 changes: 31 additions & 0 deletions spec/MongoStorageAdapter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const fakeClient = {
describe_only_db('mongo')('MongoStorageAdapter', () => {
beforeEach(done => {
new MongoStorageAdapter({ uri: databaseURI }).deleteAllClasses().then(done, fail);
Config.get(Parse.applicationId).schemaCache.clear();
});

it('auto-escapes symbols in auth information', () => {
Expand Down Expand Up @@ -314,6 +315,8 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
await user.signUp();

const database = Config.get(Parse.applicationId).database;
await database.adapter.dropAllIndexes('_User');

const preIndexPlan = await database.find(
'_User',
{ username: 'bugs' },
Expand Down Expand Up @@ -546,5 +549,33 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
});
});
});

describe('watch _SCHEMA', () => {
it('should change', async done => {
const adapter = new MongoStorageAdapter({
uri: databaseURI,
collectionPrefix: '',
mongoOptions: { enableSchemaHooks: true },
});
await reconfigureServer({ databaseAdapter: adapter });
expect(adapter.enableSchemaHooks).toBe(true);
spyOn(adapter, '_onchange');
const schema = {
fields: {
array: { type: 'Array' },
object: { type: 'Object' },
date: { type: 'Date' },
},
};

await adapter.createClass('Stuff', schema);
const myClassSchema = await adapter.getClass('Stuff');
expect(myClassSchema).toBeDefined();
setTimeout(() => {
expect(adapter._onchange).toHaveBeenCalled();
done();
}, 5000);
});
});
}
});
4 changes: 1 addition & 3 deletions spec/ParseGraphQLController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ describe('ParseGraphQLController', () => {

beforeEach(async () => {
if (!parseServer) {
parseServer = await global.reconfigureServer({
schemaCacheTTL: 100,
});
parseServer = await global.reconfigureServer();
databaseController = parseServer.config.databaseController;
cacheController = parseServer.config.cacheController;

Expand Down
22 changes: 10 additions & 12 deletions spec/ParseGraphQLSchema.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ describe('ParseGraphQLSchema', () => {
const appId = 'test';

beforeEach(async () => {
parseServer = await global.reconfigureServer({
schemaCacheTTL: 100,
});
parseServer = await global.reconfigureServer();
databaseController = parseServer.config.databaseController;
parseGraphQLController = parseServer.config.parseGraphQLController;
parseGraphQLSchema = new ParseGraphQLSchema({
Expand Down Expand Up @@ -68,7 +66,7 @@ describe('ParseGraphQLSchema', () => {
const graphQLSubscriptions = parseGraphQLSchema.graphQLSubscriptions;
const newClassObject = new Parse.Object('NewClass');
await newClassObject.save();
await databaseController.schemaCache.clear();
await parseServer.config.schemaCache.clear();
await new Promise(resolve => setTimeout(resolve, 200));
await parseGraphQLSchema.load();
expect(parseClasses).not.toBe(parseGraphQLSchema.parseClasses);
Expand Down Expand Up @@ -426,14 +424,14 @@ describe('ParseGraphQLSchema', () => {
log: defaultLogger,
appId,
});
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const types1 = parseGraphQLSchema.graphQLTypes;
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const user = new Parse.Object('User');
await user.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const types2 = parseGraphQLSchema.graphQLTypes;
const queries2 = parseGraphQLSchema.graphQLQueries;
Expand All @@ -456,14 +454,14 @@ describe('ParseGraphQLSchema', () => {
});
const car1 = new Parse.Object('Car');
await car1.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const types1 = parseGraphQLSchema.graphQLTypes;
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const car2 = new Parse.Object('car');
await car2.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const types2 = parseGraphQLSchema.graphQLTypes;
const queries2 = parseGraphQLSchema.graphQLQueries;
Expand All @@ -486,13 +484,13 @@ describe('ParseGraphQLSchema', () => {
});
const car = new Parse.Object('Car');
await car.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const cars = new Parse.Object('cars');
await cars.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const queries2 = parseGraphQLSchema.graphQLQueries;
const mutations2 = parseGraphQLSchema.graphQLMutations;
Expand Down Expand Up @@ -532,7 +530,7 @@ describe('ParseGraphQLSchema', () => {

await data.save();

await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
await parseGraphQLSchema.load();

const queries1 = parseGraphQLSchema.graphQLQueries;
Expand Down Expand Up @@ -569,7 +567,7 @@ describe('ParseGraphQLSchema', () => {

await data.save();

await parseGraphQLSchema.databaseController.schemaCache.clear();
await parseGraphQLSchema.schemaCache.clear();
await parseGraphQLSchema.load();

const mutations = parseGraphQLSchema.graphQLMutations;
Expand Down
Loading

0 comments on commit e88fc9a

Please sign in to comment.