Skip to content

Commit ebfdd67

Browse files
authored
Merge branch 'master' into node-8
2 parents 9006107 + 550b69e commit ebfdd67

26 files changed

+1514
-948
lines changed

.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
[libs]
88

99
[options]
10+
suppress_comment= \\(.\\|\n\\)*\\@flow-disable-next

CHANGELOG.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,39 @@
11
## Parse Server Changelog
22

33
### master
4-
[Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.0...master)
4+
[Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.2...master)
5+
6+
### 2.7.2
7+
[Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.2...2.7.1)
8+
9+
#### Improvements:
10+
* Improved match aggregate
11+
* Do not mark the empty pushs as failed
12+
* Support pointer in aggregate query
13+
* Introduces flow types for storage
14+
* Postgres: Refactoring of Postgres Storage Adapter
15+
* Postgres: Support for multiple projection in aggregate
16+
* Postgres: performance optimizations
17+
* Adds infos about vulnerability disclosures
18+
* Adds ability to login with email when provided as username
19+
20+
#### Bug Fixes
21+
* Scrub Passwords with URL Encoded Characters
22+
* Fixes issue affecting using sorting in beforeFind
23+
24+
#### Dependency Updates:
25+
* [[email protected]](https://www.npmjs.com/package/commander)
26+
* [[email protected]](https://www.npmjs.com/package/semver)
27+
* [[email protected]](https://www.npmjs.com/package/pg-promise)
28+
* [[email protected]](https://www.npmjs.com/package/ws)
29+
* [[email protected]](https://www.npmjs.com/package/mime)
30+
* [[email protected]](https://www.npmjs.com/package/parse)
31+
32+
##### Devevelopment Dependencies Updates:
33+
* [[email protected]](https://www.npmjs.com/package/nodemon)
34+
* [[email protected]](https://www.npmjs.com/package/flow-bin)
35+
* [[email protected]](https://www.npmjs.com/package/jasmine)
36+
* [[email protected]](https://www.npmjs.com/package/cross-env)
537

638
### 2.7.1
739
[Full Changelog](https://github.com/parse-community/parse-server/compare/2.7.1...2.7.0)

package.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-server",
3-
"version": "2.7.1",
3+
"version": "2.7.2",
44
"description": "An express module providing a Parse-compatible API server",
55
"main": "lib/index.js",
66
"repository": {
@@ -24,25 +24,25 @@
2424
"@parse/simple-mailgun-adapter": "1.0.1",
2525
"bcryptjs": "2.4.3",
2626
"body-parser": "1.18.2",
27-
"commander": "2.12.1",
27+
"commander": "2.13.0",
2828
"deepcopy": "0.6.3",
2929
"express": "4.16.2",
3030
"intersect": "1.0.1",
3131
"lodash": "4.17.4",
3232
"lru-cache": "4.1.1",
33-
"mime": "2.1.0",
33+
"mime": "2.2.0",
3434
"mongodb": "3.0.1",
3535
"multer": "1.3.0",
3636
"parse": "1.11.0",
37-
"pg-promise": "7.3.2",
37+
"pg-promise": "7.4.0",
3838
"redis": "2.8.0",
3939
"request": "2.83.0",
40-
"semver": "5.4.1",
40+
"semver": "5.5.0",
4141
"tv4": "1.3.0",
4242
"uuid": "^3.1.0",
4343
"winston": "2.4.0",
4444
"winston-daily-rotate-file": "1.7.2",
45-
"ws": "3.3.3"
45+
"ws": "4.0.0"
4646
},
4747
"devDependencies": {
4848
"babel-cli": "6.26.0",
@@ -56,17 +56,18 @@
5656
"deep-diff": "0.3.8",
5757
"eslint": "^4.9.0",
5858
"eslint-plugin-flowtype": "^2.39.1",
59+
"flow-bin": "^0.64.0",
5960
"gaze": "1.1.2",
60-
"jasmine": "2.8.0",
61+
"jasmine": "2.9.0",
6162
"jasmine-spec-reporter": "^4.1.0",
6263
"mongodb-runner": "3.6.1",
63-
"nodemon": "1.14.6",
64+
"nodemon": "1.14.11",
6465
"nyc": "^11.0.2",
6566
"request-promise": "4.2.2"
6667
},
6768
"scripts": {
6869
"dev": "npm run build && node bin/dev",
69-
"lint": "eslint --cache ./",
70+
"lint": "flow && eslint --cache ./",
7071
"build": "babel src/ -d lib/ --copy-files",
7172
"pretest": "npm run lint",
7273
"test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 TESTING=1 jasmine",

spec/CloudCode.spec.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,32 @@ describe('beforeFind hooks', () => {
14721472
});
14731473
});
14741474

1475+
it('should handle sorting where', (done) => {
1476+
Parse.Cloud.beforeFind('MyObject', (req) => {
1477+
const query = req.query;
1478+
query.ascending('score');
1479+
return query;
1480+
});
1481+
1482+
const count = 20;
1483+
const objects = [];
1484+
while (objects.length != count) {
1485+
const object = new Parse.Object('MyObject');
1486+
object.set('score', Math.floor(Math.random() * 100));
1487+
objects.push(object);
1488+
}
1489+
Parse.Object.saveAll(objects).then(() => {
1490+
const query = new Parse.Query('MyObject');
1491+
return query.find();
1492+
}).then((objects) => {
1493+
let lastScore = -1;
1494+
objects.forEach((element) => {
1495+
expect(element.get('score') >= lastScore).toBe(true);
1496+
lastScore = element.get('score');
1497+
});
1498+
}).then(done).catch(done.fail);
1499+
});
1500+
14751501
it('should add beforeFind trigger using get API',(done) => {
14761502
const hook = {
14771503
method: function(req) {

spec/MongoStorageAdapter.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

3-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
4-
const MongoClient = require('mongodb').MongoClient;
3+
import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter';
4+
const { MongoClient } = require('mongodb');
55
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
66

77
// These tests are specific to the mongo storage adapter + mongo storage format

spec/ParsePolygon.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const TestObject = Parse.Object.extend('TestObject');
2-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
2+
import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter';
33
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
44
const rp = require('request-promise');
55
const defaultHeaders = {

spec/ParseQuery.Aggregate.spec.js

Lines changed: 147 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ const masterKeyOptions = {
1414
}
1515

1616
const loadTestData = () => {
17-
const data1 = {score: 10, name: 'foo', sender: {group: 'A'}, size: ['S', 'M']};
18-
const data2 = {score: 10, name: 'foo', sender: {group: 'A'}, size: ['M', 'L']};
19-
const data3 = {score: 10, name: 'bar', sender: {group: 'B'}, size: ['S']};
20-
const data4 = {score: 20, name: 'dpl', sender: {group: 'B'}, size: ['S']};
17+
const data1 = {score: 10, name: 'foo', sender: {group: 'A'}, views: 900, size: ['S', 'M']};
18+
const data2 = {score: 10, name: 'foo', sender: {group: 'A'}, views: 800, size: ['M', 'L']};
19+
const data3 = {score: 10, name: 'bar', sender: {group: 'B'}, views: 700, size: ['S']};
20+
const data4 = {score: 20, name: 'dpl', sender: {group: 'B'}, views: 700, size: ['S']};
2121
const obj1 = new TestObject(data1);
2222
const obj2 = new TestObject(data2);
2323
const obj3 = new TestObject(data3);
@@ -96,6 +96,27 @@ describe('Parse.Query Aggregate testing', () => {
9696
}).catch(done.fail);
9797
});
9898

99+
it('group by pointer', (done) => {
100+
const pointer1 = new TestObject();
101+
const pointer2 = new TestObject();
102+
const obj1 = new TestObject({ pointer: pointer1 });
103+
const obj2 = new TestObject({ pointer: pointer2 });
104+
const obj3 = new TestObject({ pointer: pointer1 });
105+
const pipeline = [
106+
{ group: { objectId: '$pointer' } }
107+
];
108+
Parse.Object.saveAll([pointer1, pointer2, obj1, obj2, obj3]).then(() => {
109+
const query = new Parse.Query(TestObject);
110+
return query.aggregate(pipeline);
111+
}).then((results) => {
112+
expect(results.length).toEqual(3);
113+
expect(results.some(result => result.objectId === pointer1.id)).toEqual(true);
114+
expect(results.some(result => result.objectId === pointer2.id)).toEqual(true);
115+
expect(results.some(result => result.objectId === null)).toEqual(true);
116+
done();
117+
});
118+
});
119+
99120
it('group sum query', (done) => {
100121
const options = Object.assign({}, masterKeyOptions, {
101122
body: {
@@ -231,7 +252,7 @@ describe('Parse.Query Aggregate testing', () => {
231252
}).catch(done.fail);
232253
});
233254

234-
it('match query', (done) => {
255+
it('match comparison query', (done) => {
235256
const options = Object.assign({}, masterKeyOptions, {
236257
body: {
237258
match: { score: { $gt: 15 }},
@@ -245,6 +266,127 @@ describe('Parse.Query Aggregate testing', () => {
245266
}).catch(done.fail);
246267
});
247268

269+
it('match multiple comparison query', (done) => {
270+
const options = Object.assign({}, masterKeyOptions, {
271+
body: {
272+
match: { score: { $gt: 5, $lt: 15 }},
273+
}
274+
});
275+
rp.get(Parse.serverURL + '/aggregate/TestObject', options)
276+
.then((resp) => {
277+
expect(resp.results.length).toBe(3);
278+
expect(resp.results[0].score).toBe(10);
279+
expect(resp.results[1].score).toBe(10);
280+
expect(resp.results[2].score).toBe(10);
281+
done();
282+
}).catch(done.fail);
283+
});
284+
285+
it('match complex comparison query', (done) => {
286+
const options = Object.assign({}, masterKeyOptions, {
287+
body: {
288+
match: { score: { $gt: 5, $lt: 15 }, views: { $gt: 850, $lt: 1000 }},
289+
}
290+
});
291+
rp.get(Parse.serverURL + '/aggregate/TestObject', options)
292+
.then((resp) => {
293+
expect(resp.results.length).toBe(1);
294+
expect(resp.results[0].score).toBe(10);
295+
expect(resp.results[0].views).toBe(900);
296+
done();
297+
}).catch(done.fail);
298+
});
299+
300+
it('match comparison and equality query', (done) => {
301+
const options = Object.assign({}, masterKeyOptions, {
302+
body: {
303+
match: { score: { $gt: 5, $lt: 15 }, views: 900},
304+
}
305+
});
306+
rp.get(Parse.serverURL + '/aggregate/TestObject', options)
307+
.then((resp) => {
308+
expect(resp.results.length).toBe(1);
309+
expect(resp.results[0].score).toBe(10);
310+
expect(resp.results[0].views).toBe(900);
311+
done();
312+
}).catch(done.fail);
313+
});
314+
315+
it('match $or query', (done) => {
316+
const options = Object.assign({}, masterKeyOptions, {
317+
body: {
318+
match: { $or: [{ score: { $gt: 15, $lt: 25 } }, { views: { $gt: 750, $lt: 850 } }]},
319+
}
320+
});
321+
rp.get(Parse.serverURL + '/aggregate/TestObject', options)
322+
.then((resp) => {
323+
expect(resp.results.length).toBe(2);
324+
// Match score { $gt: 15, $lt: 25 }
325+
expect(resp.results.some(result => result.score === 20)).toEqual(true);
326+
expect(resp.results.some(result => result.views === 700)).toEqual(true);
327+
328+
// Match view { $gt: 750, $lt: 850 }
329+
expect(resp.results.some(result => result.score === 10)).toEqual(true);
330+
expect(resp.results.some(result => result.views === 800)).toEqual(true);
331+
done();
332+
}).catch(done.fail);
333+
});
334+
335+
it('match objectId query', (done) => {
336+
const obj1 = new TestObject();
337+
const obj2 = new TestObject();
338+
Parse.Object.saveAll([obj1, obj2]).then(() => {
339+
const pipeline = [
340+
{ match: { objectId: obj1.id } }
341+
];
342+
const query = new Parse.Query(TestObject);
343+
return query.aggregate(pipeline);
344+
}).then((results) => {
345+
expect(results.length).toEqual(1);
346+
expect(results[0].objectId).toEqual(obj1.id);
347+
done();
348+
});
349+
});
350+
351+
it('match field query', (done) => {
352+
const obj1 = new TestObject({ name: 'TestObject1'});
353+
const obj2 = new TestObject({ name: 'TestObject2'});
354+
Parse.Object.saveAll([obj1, obj2]).then(() => {
355+
const pipeline = [
356+
{ match: { name: 'TestObject1' } }
357+
];
358+
const query = new Parse.Query(TestObject);
359+
return query.aggregate(pipeline);
360+
}).then((results) => {
361+
expect(results.length).toEqual(1);
362+
expect(results[0].objectId).toEqual(obj1.id);
363+
done();
364+
});
365+
});
366+
367+
it('match pointer query', (done) => {
368+
const pointer1 = new TestObject();
369+
const pointer2 = new TestObject();
370+
const obj1 = new TestObject({ pointer: pointer1 });
371+
const obj2 = new TestObject({ pointer: pointer2 });
372+
const obj3 = new TestObject({ pointer: pointer1 });
373+
374+
Parse.Object.saveAll([pointer1, pointer2, obj1, obj2, obj3]).then(() => {
375+
const pipeline = [
376+
{ match: { pointer: pointer1.id } }
377+
];
378+
const query = new Parse.Query(TestObject);
379+
return query.aggregate(pipeline);
380+
}).then((results) => {
381+
expect(results.length).toEqual(2);
382+
expect(results[0].pointer.objectId).toEqual(pointer1.id);
383+
expect(results[1].pointer.objectId).toEqual(pointer1.id);
384+
expect(results.some(result => result.objectId === obj1.id)).toEqual(true);
385+
expect(results.some(result => result.objectId === obj3.id)).toEqual(true);
386+
done();
387+
});
388+
});
389+
248390
it('project query', (done) => {
249391
const options = Object.assign({}, masterKeyOptions, {
250392
body: {

spec/ParseQuery.FullTextSearch.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

3-
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
3+
import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter';
44
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
5-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
5+
import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter';
66
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
77
const Parse = require('parse/node');
88
const rp = require('request-promise');

spec/ParseServer.spec.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22
/* Tests for ParseServer.js */
33
const express = require('express');
4-
4+
import MongoStorageAdapter from '../src/Adapters/Storage/Mongo/MongoStorageAdapter';
5+
import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter';
56
import ParseServer from '../src/ParseServer';
67

78
describe('Server Url Checks', () => {
@@ -35,8 +36,6 @@ describe('Server Url Checks', () => {
3536
});
3637

3738
it('handleShutdown, close connection', (done) => {
38-
var MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
39-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
4039
const mongoURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
4140
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
4241
let databaseAdapter;

spec/PostgresInitOptions.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const Parse = require('parse/node').Parse;
2-
const PostgresStorageAdapter = require('../src/Adapters/Storage/Postgres/PostgresStorageAdapter');
2+
import PostgresStorageAdapter from '../src/Adapters/Storage/Postgres/PostgresStorageAdapter';
33
const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_test_database';
44
const ParseServer = require("../src/index");
55
const express = require('express');

0 commit comments

Comments
 (0)