Adds liniting into the workflow (#3082)

* initial linting of src

* fix indent to 2 spaces

* Removes unnecessary rules

* ignore spec folder for now

* Spec linting

* Fix spec indent

* nits

* nits

* no no-empty rule
This commit is contained in:
Florent Vilmart
2016-11-24 15:47:41 -05:00
committed by GitHub
parent 6e2fba4ae4
commit 8c2c76dd26
149 changed files with 3478 additions and 3507 deletions

2
.eslintignore Normal file
View File

@@ -0,0 +1,2 @@
lib/*
coverage/*

20
.eslintrc.json Normal file
View File

@@ -0,0 +1,20 @@
{
"root": true,
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true
},
"parser": "babel-eslint",
"plugins": [
"flowtype"
],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"indent": ["error", 2],
"linebreak-style": ["error", "unix"]
}
}

View File

@@ -15,6 +15,7 @@ before_script:
- psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres - psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres
- psql -c 'CREATE EXTENSION postgis;' -U postgres -d parse_server_postgres_adapter_test_database - psql -c 'CREATE EXTENSION postgis;' -U postgres -d parse_server_postgres_adapter_test_database
- psql -c 'CREATE EXTENSION postgis_topology;' -U postgres -d parse_server_postgres_adapter_test_database - psql -c 'CREATE EXTENSION postgis_topology;' -U postgres -d parse_server_postgres_adapter_test_database
- npm run lint
env: env:
global: global:
- COVERAGE_OPTION='./node_modules/.bin/istanbul cover' - COVERAGE_OPTION='./node_modules/.bin/istanbul cover'

View File

@@ -46,6 +46,7 @@
"devDependencies": { "devDependencies": {
"babel-cli": "6.18.0", "babel-cli": "6.18.0",
"babel-core": "6.18.2", "babel-core": "6.18.2",
"babel-eslint": "^7.1.1",
"babel-plugin-syntax-flow": "6.13.0", "babel-plugin-syntax-flow": "6.13.0",
"babel-plugin-transform-flow-strip-types": "6.18.0", "babel-plugin-transform-flow-strip-types": "6.18.0",
"babel-preset-es2015": "6.14.0", "babel-preset-es2015": "6.14.0",
@@ -54,6 +55,8 @@
"bcrypt-nodejs": "0.0.3", "bcrypt-nodejs": "0.0.3",
"cross-env": "3.1.3", "cross-env": "3.1.3",
"deep-diff": "0.3.4", "deep-diff": "0.3.4",
"eslint": "^3.10.2",
"eslint-plugin-flowtype": "^2.25.0",
"gaze": "1.1.1", "gaze": "1.1.1",
"istanbul": "1.0.0-alpha.1", "istanbul": "1.0.0-alpha.1",
"jasmine": "2.5.2", "jasmine": "2.5.2",
@@ -64,6 +67,7 @@
}, },
"scripts": { "scripts": {
"dev": "npm run build && node bin/dev", "dev": "npm run build && node bin/dev",
"lint": "eslint ./",
"build": "babel src/ -d lib/", "build": "babel src/ -d lib/",
"test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 NODE_ENV=test TESTING=1 $COVERAGE_OPTION jasmine", "test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 NODE_ENV=test TESTING=1 $COVERAGE_OPTION jasmine",
"test:win": "npm run pretest && cross-env NODE_ENV=test TESTING=1 node ./node_modules/jasmine/bin/jasmine.js && npm run posttest", "test:win": "npm run pretest && cross-env NODE_ENV=test TESTING=1 node ./node_modules/jasmine/bin/jasmine.js && npm run posttest",

35
spec/.eslintrc.json Normal file
View File

@@ -0,0 +1,35 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true,
"jasmine": true
},
"globals": {
"Parse": true,
"reconfigureServer": true,
"createTestUser": true,
"jfail": true,
"ok": true,
"strictEqual": true,
"TestObject": true,
"Item": true,
"Container": true,
"equal": true,
"notEqual": true,
"it_exclude_dbs": true,
"describe_only_db": true,
"on_db": true,
"defaultConfiguration": true,
"expectSuccess": true,
"range": true,
"expectError": true,
"jequal": true,
"create": true,
"arrayContains": true
},
"rules": {
"no-console": [0],
"indent": ["error", 2]
}
}

View File

@@ -5,7 +5,7 @@ const Config = require("../src/Config");
var loginWithWrongCredentialsShouldFail = function(username, password) { var loginWithWrongCredentialsShouldFail = function(username, password) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Parse.User.logIn(username, password) Parse.User.logIn(username, password)
.then(user => reject('login should have failed')) .then(() => reject('login should have failed'))
.catch(err => { .catch(err => {
if (err.message === 'Invalid username/password.') { if (err.message === 'Invalid username/password.') {
resolve(); resolve();
@@ -20,7 +20,7 @@ var isAccountLockoutError = function(username, password, duration, waitTime) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
Parse.User.logIn(username, password) Parse.User.logIn(username, password)
.then(user => reject('login should have failed')) .then(() => reject('login should have failed'))
.catch(err => { .catch(err => {
if (err.message === 'Your account is locked due to multiple failed login attempts. Please try again after ' + duration + ' minute(s)') { if (err.message === 'Your account is locked due to multiple failed login attempts. Please try again after ' + duration + ' minute(s)') {
resolve(); resolve();
@@ -45,7 +45,7 @@ describe("Account Lockout Policy: ", () => {
user.setPassword('password'); user.setPassword('password');
return user.signUp(null); return user.signUp(null);
}) })
.then(user => { .then(() => {
return loginWithWrongCredentialsShouldFail('username1', 'incorrect password 1'); return loginWithWrongCredentialsShouldFail('username1', 'incorrect password 1');
}) })
.then(() => { .then(() => {
@@ -71,7 +71,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('set duration to an invalid number test failed'); fail('set duration to an invalid number test failed');
done(); done();
}) })
@@ -95,7 +95,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('set threshold to an invalid number test failed'); fail('set threshold to an invalid number test failed');
done(); done();
}) })
@@ -119,7 +119,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('threshold value < 1 is invalid test failed'); fail('threshold value < 1 is invalid test failed');
done(); done();
}) })
@@ -143,7 +143,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('threshold value > 999 is invalid test failed'); fail('threshold value > 999 is invalid test failed');
done(); done();
}) })
@@ -167,7 +167,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('duration value < 1 is invalid test failed'); fail('duration value < 1 is invalid test failed');
done(); done();
}) })
@@ -191,7 +191,7 @@ describe("Account Lockout Policy: ", () => {
publicServerURL: "https://my.public.server.com/1" publicServerURL: "https://my.public.server.com/1"
}) })
.then(() => { .then(() => {
var config = new Config('test'); new Config('test');
fail('duration value > 99999 is invalid test failed'); fail('duration value > 99999 is invalid test failed');
done(); done();
}) })
@@ -230,7 +230,7 @@ describe("Account Lockout Policy: ", () => {
return isAccountLockoutError('username2', 'wrong password', 1, 1); return isAccountLockoutError('username2', 'wrong password', 1, 1);
}) })
.then(() => { .then(() => {
done(); done();
}) })
.catch(err => { .catch(err => {
fail('lock account after failed login attempts test failed: ' + JSON.stringify(err)); fail('lock account after failed login attempts test failed: ' + JSON.stringify(err));
@@ -301,7 +301,7 @@ describe("Account Lockout Policy: ", () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
Parse.User.logIn('username4', 'correct password') Parse.User.logIn('username4', 'correct password')
.then(user => resolve()) .then(() => resolve())
.catch(err => reject(err)); .catch(err => reject(err));
}, 3001); }, 3001);
}); });

View File

@@ -31,7 +31,7 @@ describe("AdaptableController", ()=>{
}); });
it("should fail setting the wrong adapter to the controller", (done) => { it("should fail setting the wrong adapter to the controller", (done) => {
function WrongAdapter() {}; function WrongAdapter() {}
var adapter = new FilesAdapter(); var adapter = new FilesAdapter();
var controller = new FilesController(adapter); var controller = new FilesController(adapter);
var otherAdapter = new WrongAdapter(); var otherAdapter = new WrongAdapter();
@@ -42,7 +42,7 @@ describe("AdaptableController", ()=>{
}); });
it("should fail to instantiate a controller with wrong adapter", (done) => { it("should fail to instantiate a controller with wrong adapter", (done) => {
function WrongAdapter() {}; function WrongAdapter() {}
var adapter = new WrongAdapter(); var adapter = new WrongAdapter();
expect(() => { expect(() => {
new FilesController(adapter); new FilesController(adapter);
@@ -59,10 +59,10 @@ describe("AdaptableController", ()=>{
it("should accept an object adapter", (done) => { it("should accept an object adapter", (done) => {
var adapter = { var adapter = {
createFile: function(config, filename, data) { }, createFile: function() { },
deleteFile: function(config, filename) { }, deleteFile: function() { },
getFileData: function(config, filename) { }, getFileData: function() { },
getFileLocation: function(config, filename) { }, getFileLocation: function() { },
} }
expect(() => { expect(() => {
new FilesController(adapter); new FilesController(adapter);
@@ -71,11 +71,11 @@ describe("AdaptableController", ()=>{
}); });
it("should accept an object adapter", (done) => { it("should accept an object adapter", (done) => {
function AGoodAdapter() {}; function AGoodAdapter() {}
AGoodAdapter.prototype.createFile = function(config, filename, data) { }; AGoodAdapter.prototype.createFile = function() { };
AGoodAdapter.prototype.deleteFile = function(config, filename) { }; AGoodAdapter.prototype.deleteFile = function() { };
AGoodAdapter.prototype.getFileData = function(config, filename) { }; AGoodAdapter.prototype.getFileData = function() { };
AGoodAdapter.prototype.getFileLocation = function(config, filename) { }; AGoodAdapter.prototype.getFileLocation = function() { };
var adapter = new AGoodAdapter(); var adapter = new AGoodAdapter();
expect(() => { expect(() => {

View File

@@ -1,6 +1,6 @@
const analyticsAdapter = { const analyticsAdapter = {
appOpened: function(parameters, req) {}, appOpened: function() {},
trackEvent: function(eventName, parameters, req) {} trackEvent: function() {}
} }
describe('AnalyticsController', () => { describe('AnalyticsController', () => {
@@ -9,7 +9,7 @@ describe('AnalyticsController', () => {
spyOn(analyticsAdapter, 'trackEvent').and.callThrough(); spyOn(analyticsAdapter, 'trackEvent').and.callThrough();
reconfigureServer({ reconfigureServer({
analyticsAdapter analyticsAdapter
}).then(() => { }).then(() => {
return Parse.Analytics.track('MyEvent', { return Parse.Analytics.track('MyEvent', {
key: 'value', key: 'value',
count: '0' count: '0'
@@ -26,7 +26,7 @@ describe('AnalyticsController', () => {
} }
}); });
done(); done();
}, (err) => { }, (err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}) })
@@ -37,7 +37,7 @@ describe('AnalyticsController', () => {
spyOn(analyticsAdapter, 'appOpened').and.callThrough(); spyOn(analyticsAdapter, 'appOpened').and.callThrough();
reconfigureServer({ reconfigureServer({
analyticsAdapter analyticsAdapter
}).then(() => { }).then(() => {
return Parse.Analytics.track('AppOpened', { return Parse.Analytics.track('AppOpened', {
key: 'value', key: 'value',
count: '0' count: '0'
@@ -53,7 +53,7 @@ describe('AnalyticsController', () => {
} }
}); });
done(); done();
}, (err) => { }, (err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}) })

View File

@@ -4,7 +4,6 @@ describe('Auth', () => {
describe('getUserRoles', () => { describe('getUserRoles', () => {
var auth; var auth;
var config; var config;
var cacheController;
var currentRoles = null; var currentRoles = null;
var currentUserId = 'userId'; var currentUserId = 'userId';
@@ -51,8 +50,8 @@ describe('Auth', () => {
expect(roles).toEqual(currentRoles); expect(roles).toEqual(currentRoles);
return auth.getUserRoles() return auth.getUserRoles()
}) })
.then((roles) => auth.getUserRoles()) .then(() => auth.getUserRoles())
.then((roles) => auth.getUserRoles()) .then(() => auth.getUserRoles())
.then((roles) => { .then((roles) => {
// Should only call the cache adapter once. // Should only call the cache adapter once.
expect(config.cacheController.role.get.calls.count()).toEqual(1); expect(config.cacheController.role.get.calls.count()).toEqual(1);
@@ -79,7 +78,7 @@ describe('Auth', () => {
.then(() => done()); .then(() => done());
}); });
it('should properly handle bcrypt upgrade', (done) => { it('should properly handle bcrypt upgrade', (done) => {
var bcryptOriginal = require('bcrypt-nodejs'); var bcryptOriginal = require('bcrypt-nodejs');
var bcryptNew = require('bcryptjs'); var bcryptNew = require('bcryptjs');
bcryptOriginal.hash('my1Long:password', null, null, function(err, res) { bcryptOriginal.hash('my1Long:password', null, null, function(err, res) {

View File

@@ -62,13 +62,13 @@ describe('CacheController', function() {
it('should handle cache rejections', (done) => { it('should handle cache rejections', (done) => {
FakeCacheAdapter.get = () => Promise.reject(); FakeCacheAdapter.get = () => Promise.reject();
var cache = new CacheController(FakeCacheAdapter, FakeAppID); var cache = new CacheController(FakeCacheAdapter, FakeAppID);
cache.get('foo').then(done, () => { cache.get('foo').then(done, () => {
fail('Promise should not be rejected.'); fail('Promise should not be rejected.');
}); });
}); });
}); });

View File

@@ -1,27 +1,27 @@
var ClientSDK = require('../src/ClientSDK'); var ClientSDK = require('../src/ClientSDK');
describe('ClientSDK', () => { describe('ClientSDK', () => {
it('should properly parse the SDK versions', () => { it('should properly parse the SDK versions', () => {
let clientSDKFromVersion = ClientSDK.fromString; let clientSDKFromVersion = ClientSDK.fromString;
expect(clientSDKFromVersion('i1.1.1')).toEqual({ expect(clientSDKFromVersion('i1.1.1')).toEqual({
sdk: 'i', sdk: 'i',
version: '1.1.1' version: '1.1.1'
}); });
expect(clientSDKFromVersion('i1')).toEqual({ expect(clientSDKFromVersion('i1')).toEqual({
sdk: 'i', sdk: 'i',
version: '1' version: '1'
}); });
expect(clientSDKFromVersion('apple-tv1.13.0')).toEqual({ expect(clientSDKFromVersion('apple-tv1.13.0')).toEqual({
sdk: 'apple-tv', sdk: 'apple-tv',
version: '1.13.0' version: '1.13.0'
}); });
expect(clientSDKFromVersion('js1.9.0')).toEqual({ expect(clientSDKFromVersion('js1.9.0')).toEqual({
sdk: 'js', sdk: 'js',
version: '1.9.0' version: '1.9.0'
}); });
}); });
it('should properly sastisfy', () => { it('should properly sastisfy', () => {
expect(ClientSDK.compatible({ expect(ClientSDK.compatible({
js: '>=1.9.0' js: '>=1.9.0'
})("js1.9.0")).toBe(true); })("js1.9.0")).toBe(true);

View File

@@ -1,9 +1,7 @@
"use strict" "use strict"
const Parse = require("parse/node"); const Parse = require("parse/node");
const request = require('request');
const rp = require('request-promise'); const rp = require('request-promise');
const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').InMemoryCacheAdapter; const InMemoryCacheAdapter = require('../src/Adapters/Cache/InMemoryCacheAdapter').InMemoryCacheAdapter;
const triggers = require('../src/triggers');
describe('Cloud Code', () => { describe('Cloud Code', () => {
it('can load absolute cloud code file', done => { it('can load absolute cloud code file', done => {
@@ -62,13 +60,15 @@ describe('Cloud Code', () => {
it('returns an error', (done) => { it('returns an error', (done) => {
Parse.Cloud.define('cloudCodeWithError', (req, res) => { Parse.Cloud.define('cloudCodeWithError', (req, res) => {
/* eslint-disable no-undef */
foo.bar(); foo.bar();
/* eslint-enable no-undef */
res.success('I better throw an error.'); res.success('I better throw an error.');
}); });
Parse.Cloud.run('cloudCodeWithError') Parse.Cloud.run('cloudCodeWithError')
.then( .then(
a => done.fail('should not succeed'), () => done.fail('should not succeed'),
e => { e => {
expect(e).toEqual(new Parse.Error(1, undefined)); expect(e).toEqual(new Parse.Error(1, undefined));
done(); done();
@@ -96,7 +96,7 @@ describe('Cloud Code', () => {
Parse.Cloud.beforeSave('BeforeSaveFailWithPromise', function (req, res) { Parse.Cloud.beforeSave('BeforeSaveFailWithPromise', function (req, res) {
var query = new Parse.Query('Yolo'); var query = new Parse.Query('Yolo');
query.find().then(() => { query.find().then(() => {
res.error('Nope'); res.error('Nope');
}, () => { }, () => {
res.success(); res.success();
}); });
@@ -145,10 +145,10 @@ describe('Cloud Code', () => {
var obj = new Parse.Object('BeforeSaveChanged'); var obj = new Parse.Object('BeforeSaveChanged');
obj.set('foo', 'bing'); obj.set('foo', 'bing');
obj.save().then(() => { obj.save().then(() => {
expect(obj.get('foo')).toEqual('baz'); expect(obj.get('foo')).toEqual('baz');
obj.set('foo', 'bar'); obj.set('foo', 'bar');
return obj.save().then(() => { return obj.save().then(() => {
expect(obj.get('foo')).toEqual('baz'); expect(obj.get('foo')).toEqual('baz');
done(); done();
}) })
@@ -180,34 +180,34 @@ describe('Cloud Code', () => {
it('test afterSave ran on created object and returned a promise', function(done) { it('test afterSave ran on created object and returned a promise', function(done) {
Parse.Cloud.afterSave('AfterSaveTest2', function(req) { Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
let obj = req.object; let obj = req.object;
if(!obj.existed()) if(!obj.existed())
{ {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
obj.set('proof', obj.id); obj.set('proof', obj.id);
obj.save().then(function(){ obj.save().then(function(){
promise.resolve(); promise.resolve();
}); });
}, 1000); }, 1000);
return promise; return promise;
} }
}); });
let obj = new Parse.Object('AfterSaveTest2'); let obj = new Parse.Object('AfterSaveTest2');
obj.save().then(function(){ obj.save().then(function(){
let query = new Parse.Query('AfterSaveTest2'); let query = new Parse.Query('AfterSaveTest2');
query.equalTo('proof', obj.id); query.equalTo('proof', obj.id);
query.find().then(function(results) { query.find().then(function(results) {
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
let savedObject = results[0]; let savedObject = results[0];
expect(savedObject.get('proof')).toEqual(obj.id); expect(savedObject.get('proof')).toEqual(obj.id);
done(); done();
}, },
function(error) { function(error) {
fail(error); fail(error);
done(); done();
}); });
}); });
}); });
@@ -215,124 +215,124 @@ describe('Cloud Code', () => {
// TODO: Fails on CI randomly as racing // TODO: Fails on CI randomly as racing
xit('test afterSave ignoring promise, object not found', function(done) { xit('test afterSave ignoring promise, object not found', function(done) {
Parse.Cloud.afterSave('AfterSaveTest2', function(req) { Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
let obj = req.object; let obj = req.object;
if(!obj.existed()) if(!obj.existed())
{ {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
obj.set('proof', obj.id); obj.set('proof', obj.id);
obj.save().then(function(){ obj.save().then(function(){
promise.resolve(); promise.resolve();
}); });
}, 1000); }, 1000);
return promise; return promise;
} }
}); });
let obj = new Parse.Object('AfterSaveTest2'); let obj = new Parse.Object('AfterSaveTest2');
obj.save().then(function(){ obj.save().then(function(){
done(); done();
}) })
let query = new Parse.Query('AfterSaveTest2'); let query = new Parse.Query('AfterSaveTest2');
query.equalTo('proof', obj.id); query.equalTo('proof', obj.id);
query.find().then(function(results) { query.find().then(function(results) {
expect(results.length).toEqual(0); expect(results.length).toEqual(0);
}, },
function(error) { function(error) {
fail(error); fail(error);
}); });
}); });
it('test afterSave rejecting promise', function(done) { it('test afterSave rejecting promise', function(done) {
Parse.Cloud.afterSave('AfterSaveTest2', function(req) { Parse.Cloud.afterSave('AfterSaveTest2', function() {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
promise.reject("THIS SHOULD BE IGNORED"); promise.reject("THIS SHOULD BE IGNORED");
}, 1000); }, 1000);
return promise; return promise;
}); });
let obj = new Parse.Object('AfterSaveTest2'); let obj = new Parse.Object('AfterSaveTest2');
obj.save().then(function(){ obj.save().then(function(){
done(); done();
}, function(error){ }, function(error){
fail(error); fail(error);
done(); done();
}) })
}); });
it('test afterDelete returning promise, object is deleted when destroy resolves', function(done) { it('test afterDelete returning promise, object is deleted when destroy resolves', function(done) {
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) { Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
let obj = new Parse.Object('AfterDeleteTestProof'); let obj = new Parse.Object('AfterDeleteTestProof');
obj.set('proof', req.object.id); obj.set('proof', req.object.id);
obj.save().then(function(){ obj.save().then(function(){
promise.resolve(); promise.resolve();
}); });
}, 1000); }, 1000);
return promise; return promise;
}); });
let errorHandler = function(error) { let errorHandler = function(error) {
fail(error); fail(error);
done();
}
let obj = new Parse.Object('AfterDeleteTest2');
obj.save().then(function(){
obj.destroy().then(function(){
let query = new Parse.Query('AfterDeleteTestProof');
query.equalTo('proof', obj.id);
query.find().then(function(results) {
expect(results.length).toEqual(1);
let deletedObject = results[0];
expect(deletedObject.get('proof')).toEqual(obj.id);
done(); done();
} }, errorHandler);
}, errorHandler)
let obj = new Parse.Object('AfterDeleteTest2'); }, errorHandler);
obj.save().then(function(){
obj.destroy().then(function(){
let query = new Parse.Query('AfterDeleteTestProof');
query.equalTo('proof', obj.id);
query.find().then(function(results) {
expect(results.length).toEqual(1);
let deletedObject = results[0];
expect(deletedObject.get('proof')).toEqual(obj.id);
done();
}, errorHandler);
}, errorHandler)
}, errorHandler);
}); });
it('test afterDelete ignoring promise, object is not yet deleted', function(done) { it('test afterDelete ignoring promise, object is not yet deleted', function(done) {
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) { Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
let obj = new Parse.Object('AfterDeleteTestProof'); let obj = new Parse.Object('AfterDeleteTestProof');
obj.set('proof', req.object.id); obj.set('proof', req.object.id);
obj.save().then(function(){ obj.save().then(function(){
promise.resolve(); promise.resolve();
}); });
}, 1000); }, 1000);
return promise; return promise;
}); });
let errorHandler = function(error) { let errorHandler = function(error) {
fail(error); fail(error);
done(); done();
} }
let obj = new Parse.Object('AfterDeleteTest2'); let obj = new Parse.Object('AfterDeleteTest2');
obj.save().then(function(){ obj.save().then(function(){
obj.destroy().then(function(){ obj.destroy().then(function(){
done(); done();
}) })
let query = new Parse.Query('AfterDeleteTestProof'); let query = new Parse.Query('AfterDeleteTestProof');
query.equalTo('proof', obj.id); query.equalTo('proof', obj.id);
query.find().then(function(results) { query.find().then(function(results) {
expect(results.length).toEqual(0); expect(results.length).toEqual(0);
}, errorHandler);
}, errorHandler); }, errorHandler);
}, errorHandler);
}); });
it('test beforeSave happens on update', function(done) { it('test beforeSave happens on update', function(done) {
@@ -553,7 +553,7 @@ describe('Cloud Code', () => {
'array': ['a', 'b', 'c'], 'array': ['a', 'b', 'c'],
'arrayOfArray': [['a', 'b', 'c'], ['d', 'e', 'f']] 'arrayOfArray': [['a', 'b', 'c'], ['d', 'e', 'f']]
}; };
Parse.Cloud.run('params', params).then((result) => { Parse.Cloud.run('params', params).then(() => {
done(); done();
}); });
}); });
@@ -583,7 +583,7 @@ describe('Cloud Code', () => {
Parse.Cloud.define('createBeforeSaveChangedObject', function(req, res){ Parse.Cloud.define('createBeforeSaveChangedObject', function(req, res){
var obj = new Parse.Object('BeforeSaveChanged'); var obj = new Parse.Object('BeforeSaveChanged');
obj.save().then(() => { obj.save().then(() => {
res.success(obj); res.success(obj);
}) })
}) })
@@ -707,7 +707,7 @@ describe('Cloud Code', () => {
obj.save({ foo: 'bar' }).then((objAgain) => { obj.save({ foo: 'bar' }).then((objAgain) => {
expect(objAgain.get('foo')).toEqual('baz'); expect(objAgain.get('foo')).toEqual('baz');
done(); done();
}, (e) => { }, () => {
fail('Should not have failed to save.'); fail('Should not have failed to save.');
done(); done();
}); });
@@ -720,8 +720,7 @@ describe('Cloud Code', () => {
response.success(); response.success();
}); });
Parse.Cloud.afterSave('ChangingObject', function(request, response) { Parse.Cloud.afterSave('ChangingObject', function(request) {
let json = request.object.toJSON();
expect(request.object.has("file")).toBe(false); expect(request.object.has("file")).toBe(false);
expect(request.object.has("date")).toBe(false); expect(request.object.has("date")).toBe(false);
expect(request.object.get('file')).toBeUndefined(); expect(request.object.get('file')).toBeUndefined();
@@ -747,9 +746,9 @@ describe('Cloud Code', () => {
return request.params.success === 100; return request.params.success === 100;
}); });
Parse.Cloud.run('functionWithParameterValidation', {"success":100}).then((s) => { Parse.Cloud.run('functionWithParameterValidation', {"success":100}).then(() => {
done(); done();
}, (e) => { }, () => {
fail('Validation should not have failed.'); fail('Validation should not have failed.');
done(); done();
}); });
@@ -883,7 +882,7 @@ describe('Cloud Code', () => {
}); });
}); });
it('beforeSave should not affect fetched pointers', done => { it('beforeSave should not affect fetched pointers', done => {
Parse.Cloud.beforeSave('BeforeSaveUnchanged', (req, res) => { Parse.Cloud.beforeSave('BeforeSaveUnchanged', (req, res) => {
res.success(); res.success();
}); });
@@ -974,7 +973,7 @@ it('beforeSave should not affect fetched pointers', done => {
expect(aBeforeSaveObj.get('before')).toEqual('save'); expect(aBeforeSaveObj.get('before')).toEqual('save');
expect(aBeforeSaveObj.get('remove')).toEqual(undefined); expect(aBeforeSaveObj.get('remove')).toEqual(undefined);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -998,15 +997,15 @@ it('beforeSave should not affect fetched pointers', done => {
let object; let object;
let testObject = new TestObject({key: 'value'}); let testObject = new TestObject({key: 'value'});
testObject.save().then(() => { testObject.save().then(() => {
object = new BeforeSaveObject(); object = new BeforeSaveObject();
return object.save().then(() => { return object.save().then(() => {
object.set({remove:testObject}) object.set({remove:testObject})
return object.save(); return object.save();
}); });
}).then((objectAgain) => { }).then((objectAgain) => {
expect(objectAgain.get('remove')).toBeUndefined(); expect(objectAgain.get('remove')).toBeUndefined();
expect(object.get('remove')).toBeUndefined(); expect(object.get('remove')).toBeUndefined();
done(); done();
}).fail((err) => { }).fail((err) => {
jfail(err); jfail(err);
done(); done();
@@ -1021,7 +1020,7 @@ it('beforeSave should not affect fetched pointers', done => {
var object = req.object; var object = req.object;
object.set('before', 'save'); object.set('before', 'save');
testObj = new TestObject(); testObj = new TestObject();
testObj.save().then(() => { testObj.save().then(() => {
object.relation('testsRelation').add(testObj); object.relation('testsRelation').add(testObj);
res.success(); res.success();
}, res.error); }, res.error);
@@ -1038,10 +1037,10 @@ it('beforeSave should not affect fetched pointers', done => {
}) })
}); });
describe('cloud jobs', () => { describe('cloud jobs', () => {
it('should define a job', (done) => { it('should define a job', (done) => {
expect(() => { expect(() => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
res.success(); res.success();
}); });
}).not.toThrow(); }).not.toThrow();
@@ -1052,17 +1051,17 @@ it('beforeSave should not affect fetched pointers', done => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Master-Key': Parse.masterKey, 'X-Parse-Master-Key': Parse.masterKey,
}, },
}).then((result) => { }).then(() => {
done(); done();
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
}); });
it('should not run without master key', (done) => { it('should not run without master key', (done) => {
expect(() => { expect(() => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
res.success(); res.success();
}); });
}).not.toThrow(); }).not.toThrow();
@@ -1073,18 +1072,18 @@ it('beforeSave should not affect fetched pointers', done => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
}, },
}).then((result) => { }).then(() => {
fail('Expected to be unauthorized'); fail('Expected to be unauthorized');
done(); done();
}, (err) =>  { }, (err) => {
expect(err.statusCode).toBe(403); expect(err.statusCode).toBe(403);
done(); done();
}); });
}); });
it('should run with master key', (done) => { it('should run with master key', (done) => {
expect(() => { expect(() => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
expect(req.functionName).toBeUndefined(); expect(req.functionName).toBeUndefined();
expect(req.jobName).toBe('myJob'); expect(req.jobName).toBe('myJob');
expect(typeof req.jobId).toBe('string'); expect(typeof req.jobId).toBe('string');
@@ -1102,16 +1101,16 @@ it('beforeSave should not affect fetched pointers', done => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Master-Key': Parse.masterKey, 'X-Parse-Master-Key': Parse.masterKey,
}, },
}).then((response) => { }).then(() => {
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
}); });
it('should run with master key basic auth', (done) => { it('should run with master key basic auth', (done) => {
expect(() => { expect(() => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
expect(req.functionName).toBeUndefined(); expect(req.functionName).toBeUndefined();
expect(req.jobName).toBe('myJob'); expect(req.jobName).toBe('myJob');
expect(typeof req.jobId).toBe('string'); expect(typeof req.jobId).toBe('string');
@@ -1125,25 +1124,25 @@ it('beforeSave should not affect fetched pointers', done => {
rp.post({ rp.post({
url: `http://${Parse.applicationId}:${Parse.masterKey}@localhost:8378/1/jobs/myJob`, url: `http://${Parse.applicationId}:${Parse.masterKey}@localhost:8378/1/jobs/myJob`,
}).then((response) => { }).then(() => {
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
}); });
it('should set the message / success on the job', (done) => { it('should set the message / success on the job', (done) => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
res.message('hello'); res.message('hello');
res.message().then(() => { res.message().then(() => {
return getJobStatus(req.jobId); return getJobStatus(req.jobId);
}).then((jobStatus) => { }).then((jobStatus) => {
expect(jobStatus.get('message')).toEqual('hello'); expect(jobStatus.get('message')).toEqual('hello');
expect(jobStatus.get('status')).toEqual('running'); expect(jobStatus.get('status')).toEqual('running');
return res.success().then(() => { return res.success().then(() => {
return getJobStatus(req.jobId); return getJobStatus(req.jobId);
}); });
}).then((jobStatus) => { }).then((jobStatus) => {
expect(jobStatus.get('message')).toEqual('hello'); expect(jobStatus.get('message')).toEqual('hello');
expect(jobStatus.get('status')).toEqual('succeeded'); expect(jobStatus.get('status')).toEqual('succeeded');
done(); done();
@@ -1160,18 +1159,18 @@ it('beforeSave should not affect fetched pointers', done => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Master-Key': Parse.masterKey, 'X-Parse-Master-Key': Parse.masterKey,
}, },
}).then((response) => { }).then(() => {
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
}); });
it('should set the failure on the job', (done) => { it('should set the failure on the job', (done) => {
Parse.Cloud.job('myJob', (req, res) => { Parse.Cloud.job('myJob', (req, res) => {
res.error('Something went wrong').then(() => { res.error('Something went wrong').then(() => {
return getJobStatus(req.jobId); return getJobStatus(req.jobId);
}).then((jobStatus) => { }).then((jobStatus) => {
expect(jobStatus.get('message')).toEqual('Something went wrong'); expect(jobStatus.get('message')).toEqual('Something went wrong');
expect(jobStatus.get('status')).toEqual('failed'); expect(jobStatus.get('status')).toEqual('failed');
done(); done();
@@ -1187,8 +1186,8 @@ it('beforeSave should not affect fetched pointers', done => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-Master-Key': Parse.masterKey, 'X-Parse-Master-Key': Parse.masterKey,
}, },
}).then((response) => { }).then(() => {
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
@@ -1202,8 +1201,8 @@ it('beforeSave should not affect fetched pointers', done => {
}); });
describe('beforeFind hooks', () => { describe('beforeFind hooks', () => {
it('should add beforeFind trigger', (done) => { it('should add beforeFind trigger', (done) => {
Parse.Cloud.beforeFind('MyObject', (req, res) => { Parse.Cloud.beforeFind('MyObject', (req) => {
let q = req.query; let q = req.query;
expect(q instanceof Parse.Query).toBe(true); expect(q instanceof Parse.Query).toBe(true);
let jsonQuery = q.toJSON(); let jsonQuery = q.toJSON();
@@ -1219,13 +1218,13 @@ describe('beforeFind hooks', () => {
query.greaterThan('some', 10); query.greaterThan('some', 10);
query.include('otherKey'); query.include('otherKey');
query.include('otherValue'); query.include('otherValue');
query.find().then(() => { query.find().then(() => {
done(); done();
}); });
}); });
it('should use modify', (done) => { it('should use modify', (done) => {
Parse.Cloud.beforeFind('MyObject', (req) => { Parse.Cloud.beforeFind('MyObject', (req) => {
let q = req.query; let q = req.query;
q.equalTo('forced', true); q.equalTo('forced', true);
}); });
@@ -1235,10 +1234,10 @@ describe('beforeFind hooks', () => {
let obj1 = new Parse.Object('MyObject'); let obj1 = new Parse.Object('MyObject');
obj1.set('forced', true); obj1.set('forced', true);
Parse.Object.saveAll([obj0, obj1]).then(() => { Parse.Object.saveAll([obj0, obj1]).then(() => {
let query = new Parse.Query('MyObject'); let query = new Parse.Query('MyObject');
query.equalTo('forced', false); query.equalTo('forced', false);
query.find().then((results) => { query.find().then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
let firstResult = results[0]; let firstResult = results[0];
expect(firstResult.get('forced')).toBe(true); expect(firstResult.get('forced')).toBe(true);
@@ -1247,8 +1246,8 @@ describe('beforeFind hooks', () => {
}); });
}); });
it('should use the modified the query', (done) => { it('should use the modified the query', (done) => {
Parse.Cloud.beforeFind('MyObject', (req) => { Parse.Cloud.beforeFind('MyObject', (req) => {
let q = req.query; let q = req.query;
let otherQuery = new Parse.Query('MyObject'); let otherQuery = new Parse.Query('MyObject');
otherQuery.equalTo('forced', true); otherQuery.equalTo('forced', true);
@@ -1260,34 +1259,34 @@ describe('beforeFind hooks', () => {
let obj1 = new Parse.Object('MyObject'); let obj1 = new Parse.Object('MyObject');
obj1.set('forced', true); obj1.set('forced', true);
Parse.Object.saveAll([obj0, obj1]).then(() => { Parse.Object.saveAll([obj0, obj1]).then(() => {
let query = new Parse.Query('MyObject'); let query = new Parse.Query('MyObject');
query.equalTo('forced', false); query.equalTo('forced', false);
query.find().then((results) => { query.find().then((results) => {
expect(results.length).toBe(2); expect(results.length).toBe(2);
done(); done();
}); });
}); });
}); });
it('should reject queries', (done) => { it('should reject queries', (done) => {
Parse.Cloud.beforeFind('MyObject', (req) => { Parse.Cloud.beforeFind('MyObject', () => {
return Promise.reject('Do not run that query'); return Promise.reject('Do not run that query');
}); });
let query = new Parse.Query('MyObject'); let query = new Parse.Query('MyObject');
query.find().then(() => { query.find().then(() => {
fail('should not succeed'); fail('should not succeed');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(1); expect(err.code).toBe(1);
expect(err.message).toEqual('Do not run that query'); expect(err.message).toEqual('Do not run that query');
done(); done();
}); });
}); });
it('should handle empty where', (done) => { it('should handle empty where', (done) => {
Parse.Cloud.beforeFind('MyObject', (req) => { Parse.Cloud.beforeFind('MyObject', (req) => {
let otherQuery = new Parse.Query('MyObject'); let otherQuery = new Parse.Query('MyObject');
otherQuery.equalTo('some', true); otherQuery.equalTo('some', true);
return Parse.Query.or(req.query, otherQuery); return Parse.Query.or(req.query, otherQuery);
@@ -1299,9 +1298,9 @@ describe('beforeFind hooks', () => {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
}, },
}).then((result) => { }).then(() => {
done(); done();
}, (err) =>  { }, (err) => {
fail(err); fail(err);
done(); done();
}); });
@@ -1397,19 +1396,19 @@ describe('afterFind hooks', () => {
obj.save().then(function() { obj.save().then(function() {
let query = new Parse.Query('MyObject'); let query = new Parse.Query('MyObject');
query.equalTo('objectId',obj.id); query.equalTo('objectId',obj.id);
query.find().then(function(results) { query.find().then(function() {
fail("AfterFind should handle response failure correctly"); fail("AfterFind should handle response failure correctly");
done(); done();
}, function(error) { }, function() {
done(); done();
}); });
}, function(error) { }, function() {
done(); done();
}); });
}); });
it('should also work with promise',(done) => { it('should also work with promise',(done) => {
Parse.Cloud.afterFind('MyObject', (req, res) => { Parse.Cloud.afterFind('MyObject', (req) => {
let promise = new Parse.Promise(); let promise = new Parse.Promise();
setTimeout(function(){ setTimeout(function(){
for(let i = 0 ; i < req.objects.length ; i++){ for(let i = 0 ; i < req.objects.length ; i++){

View File

@@ -6,215 +6,215 @@ const fs = require('fs');
const loremFile = __dirname + '/support/lorem.txt'; const loremFile = __dirname + '/support/lorem.txt';
describe("Cloud Code Logger", () => { describe("Cloud Code Logger", () => {
let user; let user;
beforeEach(done => { beforeEach(done => {
Parse.User.enableUnsafeCurrentUser(); Parse.User.enableUnsafeCurrentUser();
return reconfigureServer({ return reconfigureServer({
// useful to flip to false for fine tuning :). // useful to flip to false for fine tuning :).
silent: true, silent: true,
}).then(() => { }).then(() => {
return Parse.User.signUp('tester', 'abc') return Parse.User.signUp('tester', 'abc')
.then(loggedInUser => user = loggedInUser) .then(loggedInUser => user = loggedInUser)
.then(() => Parse.User.logIn(user.get('username'), 'abc')) .then(() => Parse.User.logIn(user.get('username'), 'abc'))
.then(() => done()) .then(() => done())
});
}); });
});
// Note that helpers takes care of logout. // Note that helpers takes care of logout.
// see helpers.js:afterEach // see helpers.js:afterEach
it("should expose log to functions", done => { it("should expose log to functions", done => {
var logController = new LoggerController(new WinstonLoggerAdapter()); var logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.define("loggerTest", (req, res) => { Parse.Cloud.define("loggerTest", (req, res) => {
req.log.info('logTest', 'info log', { info: 'some log' }); req.log.info('logTest', 'info log', { info: 'some log' });
req.log.error('logTest', 'error log', { error: 'there was an error' }); req.log.error('logTest', 'error log', { error: 'there was an error' });
res.success({}); res.success({});
});
Parse.Cloud.run('loggerTest').then(() => {
return logController.getLogs({ from: Date.now() - 500, size: 1000 });
}).then((res) => {
expect(res.length).not.toBe(0);
let lastLogs = res.slice(0, 3);
let cloudFunctionMessage = lastLogs[0];
let errorMessage = lastLogs[1];
let infoMessage = lastLogs[2];
expect(cloudFunctionMessage.level).toBe('info');
expect(cloudFunctionMessage.params).toEqual({});
expect(cloudFunctionMessage.message).toMatch(/Ran cloud function loggerTest for user [^ ]* with:\n Input: {}\n Result: {}/);
expect(cloudFunctionMessage.functionName).toEqual('loggerTest');
expect(errorMessage.level).toBe('error');
expect(errorMessage.error).toBe('there was an error');
expect(errorMessage.message).toBe('logTest error log');
expect(infoMessage.level).toBe('info');
expect(infoMessage.info).toBe('some log');
expect(infoMessage.message).toBe('logTest info log');
done();
});
}); });
it('trigger should obfuscate password', done => { Parse.Cloud.run('loggerTest').then(() => {
const logController = new LoggerController(new WinstonLoggerAdapter()); return logController.getLogs({ from: Date.now() - 500, size: 1000 });
}).then((res) => {
expect(res.length).not.toBe(0);
let lastLogs = res.slice(0, 3);
let cloudFunctionMessage = lastLogs[0];
let errorMessage = lastLogs[1];
let infoMessage = lastLogs[2];
expect(cloudFunctionMessage.level).toBe('info');
expect(cloudFunctionMessage.params).toEqual({});
expect(cloudFunctionMessage.message).toMatch(/Ran cloud function loggerTest for user [^ ]* with:\n {2}Input: {}\n {2}Result: {}/);
expect(cloudFunctionMessage.functionName).toEqual('loggerTest');
expect(errorMessage.level).toBe('error');
expect(errorMessage.error).toBe('there was an error');
expect(errorMessage.message).toBe('logTest error log');
expect(infoMessage.level).toBe('info');
expect(infoMessage.info).toBe('some log');
expect(infoMessage.message).toBe('logTest info log');
done();
});
});
Parse.Cloud.beforeSave(Parse.User, (req, res) => { it('trigger should obfuscate password', done => {
res.success(req.object); const logController = new LoggerController(new WinstonLoggerAdapter());
});
Parse.User.signUp('tester123', 'abc') Parse.Cloud.beforeSave(Parse.User, (req, res) => {
res.success(req.object);
});
Parse.User.signUp('tester123', 'abc')
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then((res) => { .then((res) => {
const entry = res[0]; const entry = res[0];
expect(entry.message).not.toMatch(/password":"abc/); expect(entry.message).not.toMatch(/password":"abc/);
expect(entry.message).toMatch(/\*\*\*\*\*\*\*\*/); expect(entry.message).toMatch(/\*\*\*\*\*\*\*\*/);
done(); done();
}) })
.then(null, e => done.fail(e)); .then(null, e => done.fail(e));
});
it("should expose log to trigger", (done) => {
var logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave("MyObject", (req, res) => {
req.log.info('beforeSave MyObject', 'info log', { info: 'some log' });
req.log.error('beforeSave MyObject', 'error log', { error: 'there was an error' });
res.success({});
}); });
it("should expose log to trigger", (done) => { let obj = new Parse.Object('MyObject');
var logController = new LoggerController(new WinstonLoggerAdapter()); obj.save().then(() => {
return logController.getLogs({ from: Date.now() - 500, size: 1000 })
}).then((res) => {
expect(res.length).not.toBe(0);
let lastLogs = res.slice(0, 3);
let cloudTriggerMessage = lastLogs[0];
let errorMessage = lastLogs[1];
let infoMessage = lastLogs[2];
expect(cloudTriggerMessage.level).toBe('info');
expect(cloudTriggerMessage.triggerType).toEqual('beforeSave');
expect(cloudTriggerMessage.message).toMatch(/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {}/);
expect(cloudTriggerMessage.user).toBe(user.id);
expect(errorMessage.level).toBe('error');
expect(errorMessage.error).toBe('there was an error');
expect(errorMessage.message).toBe('beforeSave MyObject error log');
expect(infoMessage.level).toBe('info');
expect(infoMessage.info).toBe('some log');
expect(infoMessage.message).toBe('beforeSave MyObject info log');
done();
});
});
Parse.Cloud.beforeSave("MyObject", (req, res) => { it('should truncate really long lines when asked to', () => {
req.log.info('beforeSave MyObject', 'info log', { info: 'some log' }); const logController = new LoggerController(new WinstonLoggerAdapter());
req.log.error('beforeSave MyObject', 'error log', { error: 'there was an error' }); const longString = fs.readFileSync(loremFile, 'utf8');
res.success({}); const truncatedString = logController.truncateLogMessage(longString);
}); expect(truncatedString.length).toBe(1015); // truncate length + the string '... (truncated)'
});
let obj = new Parse.Object('MyObject'); it('should truncate input and result of long lines', done => {
obj.save().then(() => { const logController = new LoggerController(new WinstonLoggerAdapter());
return logController.getLogs({ from: Date.now() - 500, size: 1000 }) const longString = fs.readFileSync(loremFile, 'utf8');
}).then((res) => { Parse.Cloud.define('aFunction', (req, res) => {
expect(res.length).not.toBe(0); res.success(req.params);
let lastLogs = res.slice(0, 3);
let cloudTriggerMessage = lastLogs[0];
let errorMessage = lastLogs[1];
let infoMessage = lastLogs[2];
expect(cloudTriggerMessage.level).toBe('info');
expect(cloudTriggerMessage.triggerType).toEqual('beforeSave');
expect(cloudTriggerMessage.message).toMatch(/beforeSave triggered for MyObject for user [^ ]*\n Input: {}\n Result: {}/);
expect(cloudTriggerMessage.user).toBe(user.id);
expect(errorMessage.level).toBe('error');
expect(errorMessage.error).toBe('there was an error');
expect(errorMessage.message).toBe('beforeSave MyObject error log');
expect(infoMessage.level).toBe('info');
expect(infoMessage.info).toBe('some log');
expect(infoMessage.message).toBe('beforeSave MyObject info log');
done();
});
}); });
it('should truncate really long lines when asked to', () => { Parse.Cloud.run('aFunction', { longString })
const logController = new LoggerController(new WinstonLoggerAdapter());
const longString = fs.readFileSync(loremFile, 'utf8');
const truncatedString = logController.truncateLogMessage(longString);
expect(truncatedString.length).toBe(1015); // truncate length + the string '... (truncated)'
});
it('should truncate input and result of long lines', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
const longString = fs.readFileSync(loremFile, 'utf8');
Parse.Cloud.define('aFunction', (req, res) => {
res.success(req.params);
});
Parse.Cloud.run('aFunction', { longString })
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then(logs => { .then(logs => {
const log = logs[0]; const log = logs[0];
expect(log.level).toEqual('info'); expect(log.level).toEqual('info');
expect(log.message).toMatch( expect(log.message).toMatch(
/Ran cloud function aFunction for user [^ ]* with:\n Input: {.*?\(truncated\)$/m); /Ran cloud function aFunction for user [^ ]* with:\n {2}Input: {.*?\(truncated\)$/m);
done(); done();
}) })
.then(null, e => done.fail(e)); .then(null, e => done.fail(e));
}); });
it('should log an afterSave', done => { it('should log an afterSave', done => {
const logController = new LoggerController(new WinstonLoggerAdapter()); const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.afterSave("MyObject", (req) => { }); Parse.Cloud.afterSave("MyObject", () => { });
new Parse.Object('MyObject') new Parse.Object('MyObject')
.save() .save()
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then((logs) => { .then((logs) => {
const log = logs[0]; const log = logs[0];
expect(log.triggerType).toEqual('afterSave'); expect(log.triggerType).toEqual('afterSave');
done(); done();
}) })
// catch errors - not that the error is actually useful :( // catch errors - not that the error is actually useful :(
.then(null, e => done.fail(e)); .then(null, e => done.fail(e));
});
it('should log a denied beforeSave', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave("MyObject", (req, res) => {
res.error('uh oh!');
}); });
it('should log a denied beforeSave', done => { new Parse.Object('MyObject')
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave("MyObject", (req, res) => {
res.error('uh oh!');
});
new Parse.Object('MyObject')
.save() .save()
.then( .then(
() => done.fail('this is not supposed to succeed'), () => done.fail('this is not supposed to succeed'),
e => logController.getLogs({ from: Date.now() - 500, size: 1000 }) () => logController.getLogs({ from: Date.now() - 500, size: 1000 })
) )
.then(logs => { .then(logs => {
const log = logs[1]; // 0 is the 'uh oh!' from rejection... const log = logs[1]; // 0 is the 'uh oh!' from rejection...
expect(log.level).toEqual('error'); expect(log.level).toEqual('error');
expect(log.error).toEqual({ code: 141, message: 'uh oh!' }); expect(log.error).toEqual({ code: 141, message: 'uh oh!' });
done() done()
}); });
});
it('should log cloud function success', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.define('aFunction', (req, res) => {
res.success('it worked!');
}); });
it('should log cloud function success', done => { Parse.Cloud.run('aFunction', { foo: 'bar' })
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.define('aFunction', (req, res) => {
res.success('it worked!');
});
Parse.Cloud.run('aFunction', { foo: 'bar' })
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then(logs => { .then(logs => {
const log = logs[0]; const log = logs[0];
expect(log.level).toEqual('info'); expect(log.level).toEqual('info');
expect(log.message).toMatch( expect(log.message).toMatch(
/Ran cloud function aFunction for user [^ ]* with:\n Input: {"foo":"bar"}\n Result: "it worked!/); /Ran cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Result: "it worked!/);
done(); done();
}); });
});
it('should log cloud function failure', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.define('aFunction', (req, res) => {
res.error('it failed!');
}); });
it('should log cloud function failure', done => { Parse.Cloud.run('aFunction', { foo: 'bar' })
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.define('aFunction', (req, res) => {
res.error('it failed!');
});
Parse.Cloud.run('aFunction', { foo: 'bar' })
.then(null, () => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(null, () => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then(logs => { .then(logs => {
const log = logs[1]; const log = logs[1];
expect(log.level).toEqual('error'); expect(log.level).toEqual('error');
expect(log.message).toMatch( expect(log.message).toMatch(
/Failed running cloud function aFunction for user [^ ]* with:\n Input: {"foo":"bar"}\n Error: {"code":141,"message":"it failed!"}/); /Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error: {"code":141,"message":"it failed!"}/);
done(); done();
}); });
});
xit('should log a changed beforeSave indicating a change', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave("MyObject", (req, res) => {
const myObj = req.object;
myObj.set('aChange', true);
res.success(myObj);
}); });
xit('should log a changed beforeSave indicating a change', done => { new Parse.Object('MyObject')
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave("MyObject", (req, res) => {
const myObj = req.object;
myObj.set('aChange', true);
res.success(myObj);
});
new Parse.Object('MyObject')
.save() .save()
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then(logs => { .then(() => {
// expect the log to indicate that it has changed // expect the log to indicate that it has changed
/* /*
Here's what it looks like on parse.com... Here's what it looks like on parse.com...
@@ -222,8 +222,8 @@ describe("Cloud Code Logger", () => {
Input: {"original":{"clientVersion":"1","createdAt":"2016-06-02T05:29:08.694Z","image":{"__type":"File","name":"tfss-xxxxxxxx.png","url":"http://files.parsetfss.com/xxxxxxxx.png"},"lastScanDate":{"__type":"Date","iso":"2016-06-02T05:28:58.135Z"},"localIdentifier":"XXXXX","objectId":"OFHMX7ZUcI","status":... (truncated) Input: {"original":{"clientVersion":"1","createdAt":"2016-06-02T05:29:08.694Z","image":{"__type":"File","name":"tfss-xxxxxxxx.png","url":"http://files.parsetfss.com/xxxxxxxx.png"},"lastScanDate":{"__type":"Date","iso":"2016-06-02T05:28:58.135Z"},"localIdentifier":"XXXXX","objectId":"OFHMX7ZUcI","status":... (truncated)
Result: Update changed to {"object":{"__type":"Pointer","className":"Emoticode","objectId":"ksrq7z3Ehc"},"imageThumb":{"__type":"File","name":"tfss-xxxxxxx.png","url":"http://files.parsetfss.com/xxxxx.png"},"status":"success"} Result: Update changed to {"object":{"__type":"Pointer","className":"Emoticode","objectId":"ksrq7z3Ehc"},"imageThumb":{"__type":"File","name":"tfss-xxxxxxx.png","url":"http://files.parsetfss.com/xxxxx.png"},"status":"success"}
*/ */
done(); done();
}) })
.then(null, e => done.fail(JSON.stringify(e))); .then(null, e => done.fail(JSON.stringify(e)));
}).pend('needs more work.....'); }).pend('needs more work.....');
}); });

View File

@@ -1,6 +1,5 @@
"use strict"; "use strict";
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
const request = require('request'); const request = require('request');
const Config = require('../src/Config'); const Config = require('../src/Config');
@@ -34,8 +33,8 @@ describe("Email Verification Token Expiration: ", () => {
expect(sendEmailOptions).not.toBeUndefined(); expect(sendEmailOptions).not.toBeUndefined();
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done(); done();
@@ -75,21 +74,21 @@ describe("Email Verification Token Expiration: ", () => {
expect(sendEmailOptions).not.toBeUndefined(); expect(sendEmailOptions).not.toBeUndefined();
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
user.fetch() user.fetch()
.then(() => { .then(() => {
expect(user.get('emailVerified')).toEqual(false); expect(user.get('emailVerified')).toEqual(false);
done(); done();
}) })
.catch((err) => { .catch(() => {
jfail(error); jfail(error);
done(); done();
}); });
}); });
}, 1000); }, 1000);
}).catch((err) => { }).catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -119,13 +118,13 @@ describe("Email Verification Token Expiration: ", () => {
return user.signUp(); return user.signUp();
}).then(() => { }).then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=testEmailVerifyTokenValidity'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=testEmailVerifyTokenValidity');
done(); done();
}); });
}).catch((err) => { }).catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -155,20 +154,20 @@ describe("Email Verification Token Expiration: ", () => {
return user.signUp(); return user.signUp();
}).then(() => { }).then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
user.fetch() user.fetch()
.then(() => { .then(() => {
expect(user.get('emailVerified')).toEqual(true); expect(user.get('emailVerified')).toEqual(true);
done(); done();
}) })
.catch((err) => { .catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
}); });
}).catch((err) => { }).catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -198,8 +197,8 @@ describe("Email Verification Token Expiration: ", () => {
return user.signUp(); return user.signUp();
}).then(() => { }).then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
Parse.User.logIn("testEmailVerifyTokenValidity", "expiringToken") Parse.User.logIn("testEmailVerifyTokenValidity", "expiringToken")
.then(user => { .then(user => {
@@ -212,7 +211,7 @@ describe("Email Verification Token Expiration: ", () => {
done(); done();
}); });
}); });
}).catch((err) => { }).catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -252,6 +251,7 @@ describe("Email Verification Token Expiration: ", () => {
expect(user.emailVerified).toEqual(false); expect(user.emailVerified).toEqual(false);
expect(typeof user._email_verify_token).toBe('string'); expect(typeof user._email_verify_token).toBe('string');
expect(typeof user._email_verify_token_expires_at).toBe('object'); expect(typeof user._email_verify_token_expires_at).toBe('object');
expect(sendEmailOptions).toBeDefined();
done(); done();
}) })
.catch(error => { .catch(error => {
@@ -285,11 +285,11 @@ describe("Email Verification Token Expiration: ", () => {
}) })
.then(() => { .then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
let config = new Config('test'); let config = new Config('test');
return config.database.find('_User', {username: 'unsets_email_verify_token_expires_at'}).then((results) => { return config.database.find('_User', {username: 'unsets_email_verify_token_expires_at'}).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
return results[0]; return results[0];
}) })
@@ -355,14 +355,14 @@ describe("Email Verification Token Expiration: ", () => {
}) })
.then(() => { .then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done(); done();
}); });
}) })
.catch((err) => { .catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -405,14 +405,14 @@ describe("Email Verification Token Expiration: ", () => {
}) })
.then(() => { .then(() => {
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done(); done();
}); });
}) })
.catch((err) => { .catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -420,8 +420,6 @@ describe("Email Verification Token Expiration: ", () => {
it('setting the email on the user should set a new email verification token and new expiration date for the token when expire email verify token flag is set', done => { it('setting the email on the user should set a new email verification token and new expiration date for the token when expire email verify token flag is set', done => {
let db;
let user = new Parse.User(); let user = new Parse.User();
let userBeforeEmailReset; let userBeforeEmailReset;
@@ -450,7 +448,7 @@ describe("Email Verification Token Expiration: ", () => {
}) })
.then(() => { .then(() => {
let config = new Config('test'); let config = new Config('test');
return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => { return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => {
return results[0]; return results[0];
}); });
}) })
@@ -460,14 +458,14 @@ describe("Email Verification Token Expiration: ", () => {
// trigger another token generation by setting the email // trigger another token generation by setting the email
user.set('email', 'user@parse.com'); user.set('email', 'user@parse.com');
return new Promise((resolve, reject) => { return new Promise((resolve) => {
// wait for half a sec to get a new expiration time // wait for half a sec to get a new expiration time
setTimeout( () => resolve(user.save()), 500 ); setTimeout( () => resolve(user.save()), 500 );
}); });
}) })
.then(() => { .then(() => {
let config = new Config('test'); let config = new Config('test');
return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => { return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => {
return results[0]; return results[0];
}); });
}) })
@@ -475,9 +473,10 @@ describe("Email Verification Token Expiration: ", () => {
expect(typeof userAfterEmailReset).toBe('object'); expect(typeof userAfterEmailReset).toBe('object');
expect(userBeforeEmailReset._email_verify_token).not.toEqual(userAfterEmailReset._email_verify_token); expect(userBeforeEmailReset._email_verify_token).not.toEqual(userAfterEmailReset._email_verify_token);
expect(userBeforeEmailReset._email_verify_token_expires_at).not.toEqual(userAfterEmailReset.__email_verify_token_expires_at); expect(userBeforeEmailReset._email_verify_token_expires_at).not.toEqual(userAfterEmailReset.__email_verify_token_expires_at);
expect(sendEmailOptions).toBeDefined();
done(); done();
}) })
.catch((err) => { .catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });
@@ -512,6 +511,7 @@ describe("Email Verification Token Expiration: ", () => {
.then(() => { .then(() => {
expect(user.get('emailVerified')).toEqual(false); expect(user.get('emailVerified')).toEqual(false);
expect(typeof user.get('_email_verify_token_expires_at')).toBe('undefined'); expect(typeof user.get('_email_verify_token_expires_at')).toBe('undefined');
expect(sendEmailOptions).toBeDefined();
done(); done();
}) })
.catch(error => { .catch(error => {
@@ -519,7 +519,7 @@ describe("Email Verification Token Expiration: ", () => {
done(); done();
}); });
}).catch((err) => { }).catch((error) => {
jfail(error); jfail(error);
done(); done();
}); });

View File

@@ -27,7 +27,7 @@ describe('Enable single schema cache', () => {
config = fakeRequestForConfig(); config = fakeRequestForConfig();
nobody = auth.nobody(config); nobody = auth.nobody(config);
return rest.find(config, nobody, 'Bar', {type: 1}); return rest.find(config, nobody, 'Bar', {type: 1});
}).then((response) => { }).then(() => {
fail('Should throw error'); fail('Should throw error');
done(); done();
}, (error) => { }, (error) => {

View File

@@ -25,7 +25,7 @@ describe('EventEmitterPubSub', function() {
subscriber.unsubscribe('testChannel'); subscriber.unsubscribe('testChannel');
// Register mock checked for subscriber // Register mock checked for subscriber
var isCalled = false; var isCalled = false;
subscriber.on('message', function(channel, message) { subscriber.on('message', function() {
isCalled = true; isCalled = true;
}); });

View File

@@ -1,9 +1,9 @@
'use strict'; 'use strict';
var httpRequest = require("../src/cloud-code/httpRequest"), var httpRequest = require("../src/cloud-code/httpRequest"),
HTTPResponse = require('../src/cloud-code/HTTPResponse').default, HTTPResponse = require('../src/cloud-code/HTTPResponse').default,
bodyParser = require('body-parser'), bodyParser = require('body-parser'),
express = require("express"); express = require("express");
var port = 13371; var port = 13371;
var httpRequestServer = "http://localhost:"+port; var httpRequestServer = "http://localhost:"+port;
@@ -125,7 +125,7 @@ describe("httpRequest", () => {
it("should fail on 404", (done) => { it("should fail on 404", (done) => {
httpRequest({ httpRequest({
url: httpRequestServer+"/404", url: httpRequestServer+"/404",
}).then(function(httpResponse){ }).then(function(){
fail("should not succeed"); fail("should not succeed");
done(); done();
}, function(httpResponse){ }, function(httpResponse){
@@ -143,7 +143,7 @@ describe("httpRequest", () => {
method: "POST", method: "POST",
url: httpRequestServer+"/echo", url: httpRequestServer+"/echo",
body: { body: {
foo: "bar" foo: "bar"
}, },
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -155,7 +155,7 @@ describe("httpRequest", () => {
expect(httpResponse.status).toBe(200); expect(httpResponse.status).toBe(200);
expect(httpResponse.data).toEqual({foo: "bar"}); expect(httpResponse.data).toEqual({foo: "bar"});
done(); done();
}, function(httpResponse){ }, function(){
fail("should not fail"); fail("should not fail");
done(); done();
}) })
@@ -182,7 +182,7 @@ describe("httpRequest", () => {
done(); done();
}) })
it("should encode a www-form body", (done) => { it("should encode a www-form body", (done) => {
let options = { let options = {
body: {"foo": "bar", "bar": "baz"}, body: {"foo": "bar", "bar": "baz"},
headers: {'cOntent-tYpe': 'application/x-www-form-urlencoded'} headers: {'cOntent-tYpe': 'application/x-www-form-urlencoded'}
@@ -220,7 +220,7 @@ describe("httpRequest", () => {
httpRequest({ httpRequest({
url: httpRequestServer+"/qs", url: httpRequestServer+"/qs",
params: { params: {
foo: "bar" foo: "bar"
} }
}).then(function(httpResponse){ }).then(function(httpResponse){
expect(httpResponse.status).toBe(200); expect(httpResponse.status).toBe(200);
@@ -269,7 +269,7 @@ describe("httpRequest", () => {
it('serialized httpResponse correctly with body object', () => { it('serialized httpResponse correctly with body object', () => {
let httpResponse = new HTTPResponse({}, {foo: "bar"}); let httpResponse = new HTTPResponse({}, {foo: "bar"});
let encodedResponse = Parse._encode(httpResponse); Parse._encode(httpResponse);
let serialized = JSON.stringify(httpResponse); let serialized = JSON.stringify(httpResponse);
let result = JSON.parse(serialized); let result = JSON.parse(serialized);

View File

@@ -15,7 +15,7 @@ describe('InMemoryCache', function() {
function wait(sleep) { function wait(sleep) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve) {
setTimeout(resolve, sleep); setTimeout(resolve, sleep);
}) })
} }

View File

@@ -5,7 +5,7 @@ describe('InMemoryCacheAdapter', function() {
var VALUE = 'world'; var VALUE = 'world';
function wait(sleep) { function wait(sleep) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve) {
setTimeout(resolve, sleep); setTimeout(resolve, sleep);
}) })
} }
@@ -15,8 +15,6 @@ describe('InMemoryCacheAdapter', function() {
ttl: NaN ttl: NaN
}); });
var noop = () => {};
// Verify all methods return promises. // Verify all methods return promises.
Promise.all([ Promise.all([
cache.put(KEY, VALUE), cache.put(KEY, VALUE),

View File

@@ -69,15 +69,15 @@ describe('InstallationsRouter', () => {
.then(() => { .then(() => {
return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest); return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest);
}).then(() => { }).then(() => {
return router.handleFind(request); return router.handleFind(request);
}).then((res) => { }).then((res) => {
var results = res.response.results; var results = res.response.results;
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('query installations with limit = 0', (done) => { it('query installations with limit = 0', (done) => {
@@ -100,21 +100,21 @@ describe('InstallationsRouter', () => {
info: {} info: {}
}; };
var config = new Config('test'); new Config('test');
var router = new InstallationsRouter(); var router = new InstallationsRouter();
rest.create(config, auth.nobody(config), '_Installation', androidDeviceRequest) rest.create(config, auth.nobody(config), '_Installation', androidDeviceRequest)
.then(() => { .then(() => {
return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest); return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest);
}).then(() => { }).then(() => {
return router.handleFind(request); return router.handleFind(request);
}).then((res) => { }).then((res) => {
var response = res.response; var response = res.response;
expect(response.results.length).toEqual(0); expect(response.results.length).toEqual(0);
done(); done();
}).catch((err) => { }).catch((err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}); });
}); });
it('query installations with count = 1', done => { it('query installations with count = 1', done => {
@@ -179,15 +179,15 @@ describe('InstallationsRouter', () => {
.then(() => { .then(() => {
return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest); return rest.create(config, auth.nobody(config), '_Installation', iosDeviceRequest);
}).then(() => { }).then(() => {
return router.handleFind(request); return router.handleFind(request);
}).then((res) => { }).then((res) => {
var response = res.response; var response = res.response;
expect(response.results.length).toEqual(0); expect(response.results.length).toEqual(0);
expect(response.count).toEqual(2); expect(response.count).toEqual(2);
done(); done();
}).catch((err) => { }).catch((err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}); });
}); });
}); });

View File

@@ -22,7 +22,7 @@ describe('Logger', () => {
}); });
it('should have files transports', (done) => { it('should have files transports', (done) => {
reconfigureServer().then(() => { reconfigureServer().then(() => {
let transports = logging.logger.transports; let transports = logging.logger.transports;
let transportKeys = Object.keys(transports); let transportKeys = Object.keys(transports);
expect(transportKeys.length).toBe(3); expect(transportKeys.length).toBe(3);
@@ -33,7 +33,7 @@ describe('Logger', () => {
it('should disable files logs', (done) => { it('should disable files logs', (done) => {
reconfigureServer({ reconfigureServer({
logsFolder: null logsFolder: null
}).then(() => { }).then(() => {
let transports = logging.logger.transports; let transports = logging.logger.transports;
let transportKeys = Object.keys(transports); let transportKeys = Object.keys(transports);
expect(transportKeys.length).toBe(1); expect(transportKeys.length).toBe(1);
@@ -47,8 +47,8 @@ describe('Logger', () => {
logsFolder: null, logsFolder: null,
jsonLogs: true, jsonLogs: true,
silent: false silent: false
}).then(() => { }).then(() => {
let spy = spyOn(process.stdout, 'write'); spyOn(process.stdout, 'write');
logging.logger.info('hi', {key: 'value'}); logging.logger.info('hi', {key: 'value'});
expect(process.stdout.write).toHaveBeenCalled(); expect(process.stdout.write).toHaveBeenCalled();
var firstLog = process.stdout.write.calls.first().args[0]; var firstLog = process.stdout.write.calls.first().args[0];
@@ -56,7 +56,7 @@ describe('Logger', () => {
return reconfigureServer({ return reconfigureServer({
jsonLogs: false jsonLogs: false
}); });
}).then(() => { }).then(() => {
done(); done();
}); });
}); });

View File

@@ -12,7 +12,7 @@ describe('LoggerController', () => {
loggerController.getLogs(query).then(function(res) { loggerController.getLogs(query).then(function(res) {
expect(res.length).not.toBe(0); expect(res.length).not.toBe(0);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -74,7 +74,7 @@ describe('LoggerController', () => {
loggerController.getLogs(query).then(function(res) { loggerController.getLogs(query).then(function(res) {
expect(res.length).toBe(0); expect(res.length).toBe(0);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
fail("should not fail"); fail("should not fail");
done(); done();
@@ -84,7 +84,7 @@ describe('LoggerController', () => {
it('should throw without an adapter', (done) => { it('should throw without an adapter', (done) => {
expect(() => { expect(() => {
var loggerController = new LoggerController(); new LoggerController();
}).toThrow(); }).toThrow();
done(); done();
}); });

View File

@@ -3,121 +3,121 @@ var AppCache = require('../src/cache').AppCache;
describe('middlewares', () => { describe('middlewares', () => {
var fakeReq, fakeRes; var fakeReq, fakeRes;
beforeEach(() => { beforeEach(() => {
fakeReq = { fakeReq = {
originalUrl: 'http://example.com/parse/', originalUrl: 'http://example.com/parse/',
url: 'http://example.com/', url: 'http://example.com/',
body: { body: {
_ApplicationId: 'FakeAppId' _ApplicationId: 'FakeAppId'
}, },
headers: {}, headers: {},
get: (key) => { get: (key) => {
return fakeReq.headers[key.toLowerCase()] return fakeReq.headers[key.toLowerCase()]
} }
};
fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status']);
AppCache.put(fakeReq.body._ApplicationId, {});
});
afterEach(() => {
AppCache.del(fakeReq.body._ApplicationId);
});
it('should use _ContentType if provided', (done) => {
expect(fakeReq.headers['content-type']).toEqual(undefined);
var contentType = 'image/jpeg';
fakeReq.body._ContentType = contentType;
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeReq.headers['content-type']).toEqual(contentType);
expect(fakeReq.body._ContentType).toEqual(undefined);
done()
});
});
it('should give invalid response when keys are configured but no key supplied', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should give invalid response when keys are configured but supplied key is incorrect', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-rest-api-key'] = 'wrongKey';
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should give invalid response when keys are configured but different key is supplied', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-client-key'] = 'clientKey';
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should succeed when any one of the configured keys supplied', (done) => {
AppCache.put(fakeReq.body._ApplicationId, {
clientKey: 'clientKey',
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-rest-api-key'] = 'restAPIKey';
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeRes.status).not.toHaveBeenCalled();
done();
});
});
it('should succeed when no keys are configured and none supplied', (done) => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey'
});
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeRes.status).not.toHaveBeenCalled();
done();
});
});
const BodyParams = {
clientVersion: '_ClientVersion',
installationId: '_InstallationId',
sessionToken: '_SessionToken',
masterKey: '_MasterKey',
javascriptKey: '_JavaScriptKey'
}; };
fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status']);
AppCache.put(fakeReq.body._ApplicationId, {});
});
const BodyKeys = Object.keys(BodyParams); afterEach(() => {
AppCache.del(fakeReq.body._ApplicationId);
});
BodyKeys.forEach((infoKey) => { it('should use _ContentType if provided', (done) => {
const bodyKey = BodyParams[infoKey]; expect(fakeReq.headers['content-type']).toEqual(undefined);
const keyValue = 'Fake' + bodyKey; var contentType = 'image/jpeg';
// javascriptKey is the only one that gets defaulted, fakeReq.body._ContentType = contentType;
const otherKeys = BodyKeys.filter((otherKey) => otherKey !== infoKey && otherKey !== 'javascriptKey'); middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeReq.headers['content-type']).toEqual(contentType);
it(`it should pull ${bodyKey} into req.info`, (done) => { expect(fakeReq.body._ContentType).toEqual(undefined);
fakeReq.body[bodyKey] = keyValue; done()
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeReq.body[bodyKey]).toEqual(undefined);
expect(fakeReq.info[infoKey]).toEqual(keyValue);
otherKeys.forEach((otherKey) => {
expect(fakeReq.info[otherKey]).toEqual(undefined);
});
done();
});
});
}); });
});
it('should give invalid response when keys are configured but no key supplied', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should give invalid response when keys are configured but supplied key is incorrect', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-rest-api-key'] = 'wrongKey';
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should give invalid response when keys are configured but different key is supplied', () => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-client-key'] = 'clientKey';
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
it('should succeed when any one of the configured keys supplied', (done) => {
AppCache.put(fakeReq.body._ApplicationId, {
clientKey: 'clientKey',
masterKey: 'masterKey',
restAPIKey: 'restAPIKey'
});
fakeReq.headers['x-parse-rest-api-key'] = 'restAPIKey';
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeRes.status).not.toHaveBeenCalled();
done();
});
});
it('should succeed when no keys are configured and none supplied', (done) => {
AppCache.put(fakeReq.body._ApplicationId, {
masterKey: 'masterKey'
});
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeRes.status).not.toHaveBeenCalled();
done();
});
});
const BodyParams = {
clientVersion: '_ClientVersion',
installationId: '_InstallationId',
sessionToken: '_SessionToken',
masterKey: '_MasterKey',
javascriptKey: '_JavaScriptKey'
};
const BodyKeys = Object.keys(BodyParams);
BodyKeys.forEach((infoKey) => {
const bodyKey = BodyParams[infoKey];
const keyValue = 'Fake' + bodyKey;
// javascriptKey is the only one that gets defaulted,
const otherKeys = BodyKeys.filter((otherKey) => otherKey !== infoKey && otherKey !== 'javascriptKey');
it(`it should pull ${bodyKey} into req.info`, (done) => {
fakeReq.body[bodyKey] = keyValue;
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
expect(fakeReq.body[bodyKey]).toEqual(undefined);
expect(fakeReq.info[infoKey]).toEqual(keyValue);
otherKeys.forEach((otherKey) => {
expect(fakeReq.info[otherKey]).toEqual(undefined);
});
done();
});
});
});
}); });

View File

@@ -1,21 +1,21 @@
module.exports = options => { module.exports = options => {
if (!options) { if (!options) {
throw "Options were not provided" throw "Options were not provided"
} }
let adapter = { let adapter = {
sendVerificationEmail: () => Promise.resolve(), sendVerificationEmail: () => Promise.resolve(),
sendPasswordResetEmail: () => Promise.resolve(), sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve() sendMail: () => Promise.resolve()
}; };
if (options.sendMail) { if (options.sendMail) {
adapter.sendMail = options.sendMail adapter.sendMail = options.sendMail
} }
if (options.sendPasswordResetEmail) { if (options.sendPasswordResetEmail) {
adapter.sendPasswordResetEmail = options.sendPasswordResetEmail adapter.sendPasswordResetEmail = options.sendPasswordResetEmail
} }
if (options.sendVerificationEmail) { if (options.sendVerificationEmail) {
adapter.sendVerificationEmail = options.sendVerificationEmail; adapter.sendVerificationEmail = options.sendVerificationEmail;
} }
return adapter; return adapter;
} }

View File

@@ -278,7 +278,7 @@ describe('parseObjectToMongoObjectForCreate', () => {
done(); done();
}); });
it('untransforms mongodb number types', (done) => { it('untransforms mongodb number types', (done) => {
var input = { var input = {
long: mongodb.Long.fromNumber(Number.MAX_SAFE_INTEGER), long: mongodb.Long.fromNumber(Number.MAX_SAFE_INTEGER),
double: new mongodb.Double(Number.MAX_VALUE) double: new mongodb.Double(Number.MAX_VALUE)

View File

@@ -128,7 +128,7 @@ describe('OAuth', function() {
var path = "/"; var path = "/";
var oauthClient = new OAuth(options); var oauthClient = new OAuth(options);
oauthClient.post(path, null, body).then(function(data){ oauthClient.post(path, null, body).then(function(){
jequal(false, true); jequal(false, true);
done(); done();
}).catch(function(){ }).catch(function(){
@@ -192,7 +192,7 @@ describe('OAuth', function() {
}; };
}; };
var ExtendedUser = Parse.User.extend({ Parse.User.extend({
extended: function() { extended: function() {
return true; return true;
} }
@@ -206,13 +206,13 @@ describe('OAuth', function() {
}; };
var options = { var options = {
headers: {'X-Parse-Application-Id': 'test', headers: {'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
'X-Parse-Installation-Id': 'yolo', 'X-Parse-Installation-Id': 'yolo',
'Content-Type': 'application/json' }, 'Content-Type': 'application/json' },
url: 'http://localhost:8378/1/users', url: 'http://localhost:8378/1/users',
body: JSON.stringify(jsonBody) body: JSON.stringify(jsonBody)
}; };
return request.post(options, callback); return request.post(options, callback);
} }
@@ -227,15 +227,15 @@ describe('OAuth', function() {
var sessionToken = b.sessionToken; var sessionToken = b.sessionToken;
var q = new Parse.Query("_Session"); var q = new Parse.Query("_Session");
q.equalTo('sessionToken', sessionToken); q.equalTo('sessionToken', sessionToken);
q.first({useMasterKey: true}).then((res) => { q.first({useMasterKey: true}).then((res) => {
if (!res) { if (!res) {
fail('should not fail fetching the session'); fail('should not fail fetching the session');
done(); done();
return; return;
} }
expect(res.get("installationId")).toEqual('yolo'); expect(res.get("installationId")).toEqual('yolo');
done(); done();
}).fail((err) => { }).fail(() => {
fail('should not fail fetching the session'); fail('should not fail fetching the session');
done(); done();
}) })
@@ -305,20 +305,20 @@ describe('OAuth', function() {
"User should be linked to myoauth"); "User should be linked to myoauth");
done(); done();
}, },
error: function(model, error) { error: function() {
ok(false, "linking again should succeed"); ok(false, "linking again should succeed");
done(); done();
} }
}); });
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "unlinking should succeed"); ok(false, "unlinking should succeed");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have worked"); ok(false, "linking should have worked");
done(); done();
} }

View File

@@ -7,7 +7,7 @@ describe('Parse.Push', () => {
var pushAdapter = { var pushAdapter = {
send: function(body, installations) { send: function(body, installations) {
var badge = body.data.badge; var badge = body.data.badge;
let promises = installations.map((installation) => { let promises = installations.map((installation) => {
if (installation.deviceType == "ios") { if (installation.deviceType == "ios") {
expect(installation.badge).toEqual(badge); expect(installation.badge).toEqual(badge);
expect(installation.originalBadge+1).toEqual(installation.badge); expect(installation.originalBadge+1).toEqual(installation.badge);
@@ -47,45 +47,45 @@ describe('Parse.Push', () => {
installations.push(installation); installations.push(installation);
} }
return Parse.Object.saveAll(installations); return Parse.Object.saveAll(installations);
}).catch((err) => { }).catch((err) => {
console.error(err); console.error(err);
}) })
} }
it('should properly send push', (done) => { it('should properly send push', (done) => {
return setup().then(() => { return setup().then(() => {
return Parse.Push.send({ return Parse.Push.send({
where: { where: {
deviceType: 'ios' deviceType: 'ios'
}, },
data: { data: {
badge: 'Increment', badge: 'Increment',
alert: 'Hello world!' alert: 'Hello world!'
} }
}, {useMasterKey: true}) }, {useMasterKey: true})
}) })
.then(() => { .then(() => {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should properly send push with lowercaseIncrement', (done) => { it('should properly send push with lowercaseIncrement', (done) => {
return setup().then(() => { return setup().then(() => {
return Parse.Push.send({ return Parse.Push.send({
where: { where: {
deviceType: 'ios' deviceType: 'ios'
}, },
data: { data: {
badge: 'increment', badge: 'increment',
alert: 'Hello world!' alert: 'Hello world!'
} }
}, {useMasterKey: true}) }, {useMasterKey: true})
}).then(() => { }).then(() => {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -113,7 +113,7 @@ describe('Parse.Push', () => {
expect(body.error).toEqual('unauthorized'); expect(body.error).toEqual('unauthorized');
done(); done();
}); });
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -148,7 +148,7 @@ describe('Parse.Push', () => {
} }
done(); done();
}); });
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -166,12 +166,12 @@ describe('Parse.Push', () => {
alert: 'Hello world!' alert: 'Hello world!'
} }
}, {useMasterKey: true}) }, {useMasterKey: true})
}).then((response) => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
}, (err) => { }, (err) => {
expect(err.code).toEqual(Parse.Error.PUSH_MISCONFIGURED); expect(err.code).toEqual(Parse.Error.PUSH_MISCONFIGURED);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });

View File

@@ -63,7 +63,7 @@ describe('Parse.ACL', () => {
// Get // Get
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.get(object.id, { query.get(object.id, {
success: function(model) { success: function() {
fail('Should not have retrieved the object.'); fail('Should not have retrieved the object.');
done(); done();
}, },
@@ -1139,7 +1139,7 @@ describe('Parse.ACL', () => {
ACL: new Parse.ACL(), ACL: new Parse.ACL(),
foo: "bar" foo: "bar"
}, { }, {
success: function(user) { success: function() {
Parse.User.logOut() Parse.User.logOut()
.then(() => { .then(() => {
Parse.User.logIn("tdurden", "mayhem", { Parse.User.logIn("tdurden", "mayhem", {
@@ -1211,13 +1211,13 @@ describe('Parse.ACL', () => {
} }
}; };
Parse.Cloud.afterSave(Parse.User, req => { Parse.Cloud.afterSave(Parse.User, req => {
if (!req.object.existed()) { if (!req.object.existed()) {
var user = req.object; var user = req.object;
var acl = new Parse.ACL(user); var acl = new Parse.ACL(user);
user.setACL(acl); user.setACL(acl);
user.save(null, {useMasterKey: true}).then(user => { user.save(null, {useMasterKey: true}).then(user => {
new Parse.Query('_User').get(user.objectId).then(user => { new Parse.Query('_User').get(user.objectId).then(() => {
fail('should not have fetched user without public read enabled'); fail('should not have fetched user without public read enabled');
done(); done();
}, error => { }, error => {

View File

@@ -2,18 +2,16 @@
// It would probably be better to refactor them into different files. // It would probably be better to refactor them into different files.
'use strict'; 'use strict';
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
var request = require('request'); var request = require('request');
const rp = require('request-promise'); const rp = require('request-promise');
const Parse = require("parse/node"); const Parse = require("parse/node");
let Config = require('../src/Config'); let Config = require('../src/Config');
const SchemaController = require('../src/Controllers/SchemaController'); const SchemaController = require('../src/Controllers/SchemaController');
var TestUtils = require('../src/TestUtils'); var TestUtils = require('../src/TestUtils');
const deepcopy = require('deepcopy');
const userSchema = SchemaController.convertSchemaToAdapterSchema({ className: '_User', fields: Object.assign({}, SchemaController.defaultColumns._Default, SchemaController.defaultColumns._User) }); const userSchema = SchemaController.convertSchemaToAdapterSchema({ className: '_User', fields: Object.assign({}, SchemaController.defaultColumns._Default, SchemaController.defaultColumns._User) });
describe_only_db('mongo')('miscellaneous', () => { describe_only_db('mongo')('miscellaneous', () => {
it('test rest_create_app', function(done) { it('test rest_create_app', function(done) {
var appId; var appId;
Parse._request('POST', 'rest_create_app').then((res) => { Parse._request('POST', 'rest_create_app').then((res) => {
@@ -86,7 +84,7 @@ describe('miscellaneous', function() {
let numCreated = 0; let numCreated = 0;
let numFailed = 0; let numFailed = 0;
let p1 = createTestUser(); let p1 = createTestUser();
p1.then(user => { p1.then(() => {
numCreated++; numCreated++;
expect(numCreated).toEqual(1); expect(numCreated).toEqual(1);
}) })
@@ -96,7 +94,7 @@ describe('miscellaneous', function() {
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN); expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
}); });
let p2 = createTestUser(); let p2 = createTestUser();
p2.then(user => { p2.then(() => {
numCreated++; numCreated++;
expect(numCreated).toEqual(1); expect(numCreated).toEqual(1);
}) })
@@ -121,7 +119,7 @@ describe('miscellaneous', function() {
user1.setUsername('u1'); user1.setUsername('u1');
user1.setEmail('dupe@dupe.dupe'); user1.setEmail('dupe@dupe.dupe');
let p1 = user1.signUp(); let p1 = user1.signUp();
p1.then(user => { p1.then(() => {
numCreated++; numCreated++;
expect(numCreated).toEqual(1); expect(numCreated).toEqual(1);
}, error => { }, error => {
@@ -135,7 +133,7 @@ describe('miscellaneous', function() {
user2.setUsername('u2'); user2.setUsername('u2');
user2.setEmail('dupe@dupe.dupe'); user2.setEmail('dupe@dupe.dupe');
let p2 = user2.signUp(); let p2 = user2.signUp();
p2.then(user => { p2.then(() => {
numCreated++; numCreated++;
expect(numCreated).toEqual(1); expect(numCreated).toEqual(1);
}, error => { }, error => {
@@ -174,7 +172,7 @@ describe('miscellaneous', function() {
user.setUsername('u'); user.setUsername('u');
return user.signUp() return user.signUp()
}) })
.then(result => { .then(() => {
fail('should not have been able to sign up'); fail('should not have been able to sign up');
done(); done();
}) })
@@ -212,7 +210,7 @@ describe('miscellaneous', function() {
}); });
}); });
it('ensure that if you try to sign up a user with a unique username and email, but duplicates in some other field that has a uniqueness constraint, you get a regular duplicate value error', done => { it('ensure that if you try to sign up a user with a unique username and email, but duplicates in some other field that has a uniqueness constraint, you get a regular duplicate value error', done => {
let config = new Config('test'); let config = new Config('test');
config.database.adapter.addFieldIfNotExists('_User', 'randomField', { type: 'String' }) config.database.adapter.addFieldIfNotExists('_User', 'randomField', { type: 'String' })
.then(() => config.database.adapter.ensureUniqueness('_User', userSchema, ['randomField'])) .then(() => config.database.adapter.ensureUniqueness('_User', userSchema, ['randomField']))
@@ -533,25 +531,25 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}); });
}); });
it('pointer reassign is working properly (#1288)', (done) => { it('pointer reassign is working properly (#1288)', (done) => {
Parse.Cloud.beforeSave('GameScore', (req, res) => { Parse.Cloud.beforeSave('GameScore', (req, res) => {
var obj = req.object; var obj = req.object;
if (obj.get('point')) { if (obj.get('point')) {
return res.success(); return res.success();
} }
var TestObject1 = Parse.Object.extend('TestObject1'); var TestObject1 = Parse.Object.extend('TestObject1');
var newObj = new TestObject1({'key1': 1}); var newObj = new TestObject1({'key1': 1});
return newObj.save().then((newObj) => { return newObj.save().then((newObj) => {
obj.set('point' , newObj); obj.set('point' , newObj);
res.success(); res.success();
}); });
}); });
var pointId; var pointId;
var obj = new Parse.Object('GameScore'); var obj = new Parse.Object('GameScore');
obj.set('foo', 'bar'); obj.set('foo', 'bar');
obj.save().then(() => { obj.save().then(() => {
expect(obj.get('point')).not.toBeUndefined(); expect(obj.get('point')).not.toBeUndefined();
pointId = obj.get('point').id; pointId = obj.get('point').id;
expect(pointId).not.toBeUndefined(); expect(pointId).not.toBeUndefined();
@@ -816,9 +814,9 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}); });
}); });
it('should return the updated fields on PUT', done => { it('should return the updated fields on PUT', done => {
let obj = new Parse.Object('GameScore'); let obj = new Parse.Object('GameScore');
obj.save({a:'hello', c: 1, d: ['1'], e:['1'], f:['1','2']}).then(( ) => { obj.save({a:'hello', c: 1, d: ['1'], e:['1'], f:['1','2']}).then(( ) => {
var headers = { var headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
@@ -842,13 +840,13 @@ it('ensure that if you try to sign up a user with a unique username and email, b
expect(body.a).toBeUndefined(); expect(body.a).toBeUndefined();
expect(body.c).toEqual(3); // 2+1 expect(body.c).toEqual(3); // 2+1
expect(body.d.length).toBe(2); expect(body.d.length).toBe(2);
expect(body.d.indexOf('1') > -1).toBe(true); expect(body.d.indexOf('1') > -1).toBe(true);
expect(body.d.indexOf('2') > -1).toBe(true); expect(body.d.indexOf('2') > -1).toBe(true);
expect(body.e.length).toBe(2); expect(body.e.length).toBe(2);
expect(body.e.indexOf('1') > -1).toBe(true); expect(body.e.indexOf('1') > -1).toBe(true);
expect(body.e.indexOf('2') > -1).toBe(true); expect(body.e.indexOf('2') > -1).toBe(true);
expect(body.f.length).toBe(1); expect(body.f.length).toBe(1);
expect(body.f.indexOf('1') > -1).toBe(true); expect(body.f.indexOf('1') > -1).toBe(true);
// return nothing on other self // return nothing on other self
expect(body.selfThing).toBeUndefined(); expect(body.selfThing).toBeUndefined();
// updatedAt is always set // updatedAt is always set
@@ -858,7 +856,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
} }
done(); done();
}); });
}).fail((err) => { }).fail(() => {
fail('Should not fail'); fail('Should not fail');
done(); done();
}) })
@@ -869,7 +867,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
Parse.Cloud.define('willFail', (req, res) => { Parse.Cloud.define('willFail', (req, res) => {
res.error('noway'); res.error('noway');
}); });
Parse.Cloud.run('willFail').then((s) => { Parse.Cloud.run('willFail').then(() => {
fail('Should not have succeeded.'); fail('Should not have succeeded.');
done(); done();
}, (e) => { }, (e) => {
@@ -884,7 +882,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
Parse.Cloud.define('willFail', (req, res) => { Parse.Cloud.define('willFail', (req, res) => {
res.error(999, 'noway'); res.error(999, 'noway');
}); });
Parse.Cloud.run('willFail').then((s) => { Parse.Cloud.run('willFail').then(() => {
fail('Should not have succeeded.'); fail('Should not have succeeded.');
done(); done();
}, (e) => { }, (e) => {
@@ -899,7 +897,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
Parse.Cloud.define('willFail', (req, res) => { Parse.Cloud.define('willFail', (req, res) => {
res.error('noway'); res.error('noway');
}); });
Parse.Cloud.run('willFail').then((s) => { Parse.Cloud.run('willFail').then(() => {
fail('Should not have succeeded.'); fail('Should not have succeeded.');
done(); done();
}, (e) => { }, (e) => {
@@ -933,7 +931,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
headers: headers, headers: headers,
url: 'http://localhost:8378/1/classes/GameScore', url: 'http://localhost:8378/1/classes/GameScore',
body: JSON.stringify({ a: 'b' }) body: JSON.stringify({ a: 'b' })
}, (error, response, body) => { }, (error) => {
expect(error).toBe(null); expect(error).toBe(null);
expect(triggerTime).toEqual(2); expect(triggerTime).toEqual(2);
done(); done();
@@ -969,7 +967,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
request.del({ request.del({
headers: headers, headers: headers,
url: 'http://localhost:8378/1/classes/GameScore/' + JSON.parse(body).objectId url: 'http://localhost:8378/1/classes/GameScore/' + JSON.parse(body).objectId
}, (error, response, body) => { }, (error) => {
expect(error).toBe(null); expect(error).toBe(null);
expect(triggerTime).toEqual(2); expect(triggerTime).toEqual(2);
done(); done();
@@ -1013,7 +1011,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
return request.params.success === 100; return request.params.success === 100;
}); });
Parse.Cloud.run('functionWithParameterValidationFailure', {"success":500}).then((s) => { Parse.Cloud.run('functionWithParameterValidationFailure', {"success":500}).then(() => {
fail('Validation should not have succeeded'); fail('Validation should not have succeeded');
done(); done();
}, (e) => { }, (e) => {
@@ -1032,7 +1030,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
Parse.Cloud.run('func', {nullParam: null}) Parse.Cloud.run('func', {nullParam: null})
.then(() => { .then(() => {
done() done()
}, e => { }, () => {
fail('cloud code call failed'); fail('cloud code call failed');
done(); done();
}); });
@@ -1049,7 +1047,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
Parse.Cloud.run('dateFunc', {date: date}) Parse.Cloud.run('dateFunc', {date: date})
.then(() => { .then(() => {
done() done()
}, e => { }, () => {
fail('cloud code call failed'); fail('cloud code call failed');
done(); done();
}); });
@@ -1124,7 +1122,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}); });
it('fails on invalid function', done => { it('fails on invalid function', done => {
Parse.Cloud.run('somethingThatDoesDefinitelyNotExist').then((s) => { Parse.Cloud.run('somethingThatDoesDefinitelyNotExist').then(() => {
fail('This should have never suceeded'); fail('This should have never suceeded');
done(); done();
}, (e) => { }, (e) => {
@@ -1178,7 +1176,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
url: 'http://localhost:8378/1/users', url: 'http://localhost:8378/1/users',
body: JSON.stringify(data) body: JSON.stringify(data)
}; };
request.post(requestOptions, (error, response, body) => { request.post(requestOptions, (error) => {
expect(error).toBe(null); expect(error).toBe(null);
requestOptions.url = 'http://localhost:8378/1/login'; requestOptions.url = 'http://localhost:8378/1/login';
request.get(requestOptions, (error, response, body) => { request.get(requestOptions, (error, response, body) => {
@@ -1193,10 +1191,10 @@ it('ensure that if you try to sign up a user with a unique username and email, b
it('gets relation fields', (done) => { it('gets relation fields', (done) => {
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
let relatedObject = new Parse.Object('RelatedObject'); let relatedObject = new Parse.Object('RelatedObject');
Parse.Object.saveAll([object, relatedObject]).then(() => { Parse.Object.saveAll([object, relatedObject]).then(() => {
object.relation('related').add(relatedObject); object.relation('related').add(relatedObject);
return object.save(); return object.save();
}).then(() => { }).then(() => {
let headers = { let headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
@@ -1216,55 +1214,55 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}) })
done(); done();
}); });
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}) })
}); });
it('properly returns incremented values (#1554)', (done) => { it('properly returns incremented values (#1554)', (done) => {
let headers = { let headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest' 'X-Parse-REST-API-Key': 'rest'
}; };
let requestOptions = { let requestOptions = {
headers: headers, headers: headers,
url: 'http://localhost:8378/1/classes/AnObject', url: 'http://localhost:8378/1/classes/AnObject',
json: true json: true
}; };
let object = new Parse.Object('AnObject');; let object = new Parse.Object('AnObject');
function runIncrement(amount) { function runIncrement(amount) {
let options = Object.assign({}, requestOptions, { let options = Object.assign({}, requestOptions, {
body: { body: {
"key": { "key": {
__op: 'Increment', __op: 'Increment',
amount: amount amount: amount
} }
}, },
url: 'http://localhost:8378/1/classes/AnObject/'+object.id url: 'http://localhost:8378/1/classes/AnObject/'+object.id
}) })
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
request.put(options, (err, res, body) => { request.put(options, (err, res, body) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve(body); resolve(body);
} }
}); });
}) })
} }
object.save().then(() => { object.save().then(() => {
return runIncrement(1); return runIncrement(1);
}).then((res) => { }).then((res) => {
expect(res.key).toBe(1); expect(res.key).toBe(1);
return runIncrement(-1); return runIncrement(-1);
}).then((res) => { }).then((res) => {
expect(res.key).toBe(0); expect(res.key).toBe(0);
done(); done();
}) })
}) })
it('ignores _RevocableSession "header" send by JS SDK', (done) => { it('ignores _RevocableSession "header" send by JS SDK', (done) => {
@@ -1308,25 +1306,25 @@ it('ensure that if you try to sign up a user with a unique username and email, b
it('bans interior keys containing . or $', done => { it('bans interior keys containing . or $', done => {
new Parse.Object('Obj').save({innerObj: {'key with a $': 'fails'}}) new Parse.Object('Obj').save({innerObj: {'key with a $': 'fails'}})
.then(() => { .then(() => {
fail('should not succeed') fail('should not succeed')
}, error => { }, error => {
expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY); expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY);
return new Parse.Object('Obj').save({innerObj: {'key with a .': 'fails'}}); return new Parse.Object('Obj').save({innerObj: {'key with a .': 'fails'}});
}) })
.then(() => { .then(() => {
fail('should not succeed') fail('should not succeed')
}, error => { }, error => {
expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY); expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY);
return new Parse.Object('Obj').save({innerObj: {innerInnerObj: {'key with $': 'fails'}}}); return new Parse.Object('Obj').save({innerObj: {innerInnerObj: {'key with $': 'fails'}}});
}) })
.then(() => { .then(() => {
fail('should not succeed') fail('should not succeed')
}, error => { }, error => {
expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY); expect(error.code).toEqual(Parse.Error.INVALID_NESTED_KEY);
return new Parse.Object('Obj').save({innerObj: {innerInnerObj: {'key with .': 'fails'}}}); return new Parse.Object('Obj').save({innerObj: {innerInnerObj: {'key with .': 'fails'}}});
}) })
.then(() => { .then(() => {
fail('should not succeed') fail('should not succeed')
done(); done();
}, error => { }, error => {
@@ -1382,7 +1380,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
geoField: [1,2], geoField: [1,2],
}); });
done(); done();
}).catch((e) => { }).catch((e) => {
jfail(e); jfail(e);
done(); done();
}); });
@@ -1408,7 +1406,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
headers: headers, headers: headers,
url: 'http://localhost:8378/1/purge/TestObject', url: 'http://localhost:8378/1/purge/TestObject',
json: true json: true
}, (err, res, body) => { }, (err) => {
expect(err).toBe(null); expect(err).toBe(null);
let query = new Parse.Query(TestObject); let query = new Parse.Query(TestObject);
return query.count().then((count) => { return query.count().then((count) => {
@@ -1430,7 +1428,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
headers: headers, headers: headers,
uri: 'http://localhost:8378/1/purge/TestObject', uri: 'http://localhost:8378/1/purge/TestObject',
json: true json: true
}).then(body => { }).then(() => {
fail('Should not succeed'); fail('Should not succeed');
}).catch(err => { }).catch(err => {
expect(err.error.error).toEqual('unauthorized: master key is required'); expect(err.error.error).toEqual('unauthorized: master key is required');
@@ -1456,7 +1454,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
let users = role.relation('users'); let users = role.relation('users');
users.add(user); users.add(user);
return role.save({}, { useMasterKey: true }); return role.save({}, { useMasterKey: true });
}).then((x) => { }).then(() => {
let query = new Parse.Query('_Role'); let query = new Parse.Query('_Role');
return query.find({ useMasterKey: true }); return query.find({ useMasterKey: true });
}).then((x) => { }).then((x) => {
@@ -1473,7 +1471,7 @@ it('ensure that if you try to sign up a user with a unique username and email, b
acl.setRoleWriteAccess('TestRole', true); acl.setRoleWriteAccess('TestRole', true);
object.setACL(acl); object.setACL(acl);
return object.save(); return object.save();
}).then((x) => { }).then(() => {
let query = new Parse.Query('TestObject'); let query = new Parse.Query('TestObject');
return query.find({ sessionToken: user.getSessionToken() }); return query.find({ sessionToken: user.getSessionToken() });
}).then((x) => { }).then((x) => {
@@ -1484,10 +1482,10 @@ it('ensure that if you try to sign up a user with a unique username and email, b
uri: 'http://localhost:8378/1/purge/_Role', uri: 'http://localhost:8378/1/purge/_Role',
json: true json: true
}); });
}).then((x) => { }).then(() => {
let query = new Parse.Query('TestObject'); let query = new Parse.Query('TestObject');
return query.get(object.id, { sessionToken: user.getSessionToken() }); return query.get(object.id, { sessionToken: user.getSessionToken() });
}).then((x) => { }).then(() => {
fail('Should not succeed'); fail('Should not succeed');
}, (e) => { }, (e) => {
expect(e.code).toEqual(Parse.Error.OBJECT_NOT_FOUND); expect(e.code).toEqual(Parse.Error.OBJECT_NOT_FOUND);
@@ -1495,23 +1493,23 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}); });
}); });
it('should not update schema beforeSave #2672', (done) => { it('should not update schema beforeSave #2672', (done) => {
Parse.Cloud.beforeSave('MyObject', (request, response) => { Parse.Cloud.beforeSave('MyObject', (request, response) => {
if (request.object.get('secret')) { if (request.object.get('secret')) {
response.error('cannot set secret here'); response.error('cannot set secret here');
return; return;
} }
response.success(); response.success();
}); });
let object = new Parse.Object('MyObject'); let object = new Parse.Object('MyObject');
object.set('key', 'value'); object.set('key', 'value');
object.save().then(() => { object.save().then(() => {
return object.save({'secret': 'should not update schema'}); return object.save({'secret': 'should not update schema'});
}).then(() => { }).then(() => {
fail(); fail();
done(); done();
}, () => { }, () => {
return rp({ return rp({
method: 'GET', method: 'GET',
headers: { headers: {
@@ -1521,11 +1519,11 @@ it('ensure that if you try to sign up a user with a unique username and email, b
uri: 'http://localhost:8378/1/schemas/MyObject', uri: 'http://localhost:8378/1/schemas/MyObject',
json: true json: true
}); });
}).then((res) => { }).then((res) => {
let fields = res.fields; let fields = res.fields;
expect(fields.secret).toBeUndefined(); expect(fields.secret).toBeUndefined();
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -1533,36 +1531,36 @@ it('ensure that if you try to sign up a user with a unique username and email, b
}); });
describe_only_db('mongo')('legacy _acl', () => { describe_only_db('mongo')('legacy _acl', () => {
it('should have _acl when locking down (regression for #2465)', (done) =>  { it('should have _acl when locking down (regression for #2465)', (done) => {
let headers = { let headers = {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest' 'X-Parse-REST-API-Key': 'rest'
} }
rp({ rp({
method: 'POST', method: 'POST',
headers: headers, headers: headers,
uri: 'http://localhost:8378/1/classes/Report', uri: 'http://localhost:8378/1/classes/Report',
body: { body: {
ACL: {}, ACL: {},
name: 'My Report' name: 'My Report'
}, },
json: true json: true
}).then(() => { }).then(() => {
let config = new Config('test'); let config = new Config('test');
let adapter = config.database.adapter; let adapter = config.database.adapter;
return adapter._adaptiveCollection("Report") return adapter._adaptiveCollection("Report")
.then(collection => collection.find({})) .then(collection => collection.find({}))
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
let result = results[0]; let result = results[0];
expect(result.name).toEqual('My Report'); expect(result.name).toEqual('My Report');
expect(result._wperm).toEqual([]); expect(result._wperm).toEqual([]);
expect(result._rperm).toEqual([]); expect(result._rperm).toEqual([]);
expect(result._acl).toEqual({}); expect(result._acl).toEqual({});
done(); done();
}).catch((err) => { }).catch((err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}); });
}); });
}); });

View File

@@ -20,7 +20,7 @@ describe('ParseCloudCodePublisher', function() {
it('can initialize', function() { it('can initialize', function() {
var config = {} var config = {}
var publisher = new ParseCloudCodePublisher(config); new ParseCloudCodePublisher(config);
var ParsePubSub = require('../src/LiveQuery/ParsePubSub').ParsePubSub; var ParsePubSub = require('../src/LiveQuery/ParsePubSub').ParsePubSub;
expect(ParsePubSub.createPublisher).toHaveBeenCalledWith(config); expect(ParsePubSub.createPublisher).toHaveBeenCalledWith(config);

View File

@@ -113,7 +113,7 @@ describe('Parse.File testing', () => {
'X-Parse-Master-Key': 'test' 'X-Parse-Master-Key': 'test'
}, },
url: 'http://localhost:8378/1/files/' + b.name url: 'http://localhost:8378/1/files/' + b.name
}, (error, response, body) => { }, (error, response) => {
expect(error).toBe(null); expect(error).toBe(null);
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
request.get({ request.get({
@@ -122,7 +122,7 @@ describe('Parse.File testing', () => {
'X-Parse-REST-API-Key': 'rest' 'X-Parse-REST-API-Key': 'rest'
}, },
url: b.url url: b.url
}, (error, response, body) => { }, (error, response) => {
expect(error).toBe(null); expect(error).toBe(null);
try { try {
expect(response.statusCode).toEqual(404); expect(response.statusCode).toEqual(404);
@@ -370,7 +370,7 @@ describe('Parse.File testing', () => {
object.save({ object.save({
file: file file: file
}, expectSuccess({ }, expectSuccess({
success: function(obj) { success: function() {
ok(object.toJSON().file.url); ok(object.toJSON().file.url);
done(); done();
} }
@@ -391,7 +391,7 @@ describe('Parse.File testing', () => {
expect(error).toBe(null); expect(error).toBe(null);
var b = JSON.parse(body); var b = JSON.parse(body);
expect(b.name).toMatch(/\.html$/); expect(b.name).toMatch(/\.html$/);
request.get(b.url, (error, response, body) => { request.get(b.url, (error, response) => {
if (!response) { if (!response) {
fail('response should be set'); fail('response should be set');
return done(); return done();
@@ -572,10 +572,10 @@ describe('Parse.File testing', () => {
}); });
}); });
it('return with publicServerURL when provided', done => { it('return with publicServerURL when provided', done => {
reconfigureServer({ reconfigureServer({
publicServerURL: 'https://mydomain/parse' publicServerURL: 'https://mydomain/parse'
}).then(() => { }).then(() => {
var file = { var file = {
__type: 'File', __type: 'File',
name: '123.txt' name: '123.txt'

View File

@@ -76,7 +76,7 @@ describe('Parse.GeoPoint testing', () => {
obj.set('index', i); obj.set('index', i);
objects.push(obj); objects.push(obj);
}); });
Parse.Object.saveAll(objects).then((list) => { Parse.Object.saveAll(objects).then(() => {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
var point = new Parse.GeoPoint(1.0, -1.0); var point = new Parse.GeoPoint(1.0, -1.0);
query.withinRadians('location', point, 3.14); query.withinRadians('location', point, 3.14);
@@ -99,7 +99,7 @@ describe('Parse.GeoPoint testing', () => {
obj.set('index', i); obj.set('index', i);
objects.push(obj); objects.push(obj);
}); });
Parse.Object.saveAll(objects, function(list) { Parse.Object.saveAll(objects, function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
var point = new Parse.GeoPoint(1.0, -1.0); var point = new Parse.GeoPoint(1.0, -1.0);
query.withinRadians('location', point, 3.14 * 0.5); query.withinRadians('location', point, 3.14 * 0.5);
@@ -123,7 +123,7 @@ describe('Parse.GeoPoint testing', () => {
obj.set('index', i); obj.set('index', i);
objects.push(obj); objects.push(obj);
}); });
Parse.Object.saveAll(objects, function(list) { Parse.Object.saveAll(objects, function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
var point = new Parse.GeoPoint(1.0, -1.0); var point = new Parse.GeoPoint(1.0, -1.0);
query.withinRadians('location', point, 3.14 * 0.25); query.withinRadians('location', point, 3.14 * 0.25);
@@ -154,7 +154,7 @@ describe('Parse.GeoPoint testing', () => {
}; };
it('geo max distance in km everywhere', (done) => { it('geo max distance in km everywhere', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
// Honolulu is 4300 km away from SFO on a sphere ;) // Honolulu is 4300 km away from SFO on a sphere ;)
@@ -169,7 +169,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in km california', (done) => { it('geo max distance in km california', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinKilometers('location', sfo, 3700.0); query.withinKilometers('location', sfo, 3700.0);
@@ -185,7 +185,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in km bay area', (done) => { it('geo max distance in km bay area', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinKilometers('location', sfo, 100.0); query.withinKilometers('location', sfo, 100.0);
@@ -200,7 +200,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in km mid peninsula', (done) => { it('geo max distance in km mid peninsula', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinKilometers('location', sfo, 10.0); query.withinKilometers('location', sfo, 10.0);
@@ -214,7 +214,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in miles everywhere', (done) => { it('geo max distance in miles everywhere', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinMiles('location', sfo, 2600.0); query.withinMiles('location', sfo, 2600.0);
@@ -228,7 +228,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in miles california', (done) => { it('geo max distance in miles california', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinMiles('location', sfo, 2200.0); query.withinMiles('location', sfo, 2200.0);
@@ -244,7 +244,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in miles bay area', (done) => { it('geo max distance in miles bay area', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
// 100km is 62 miles... // 100km is 62 miles...
@@ -260,7 +260,7 @@ describe('Parse.GeoPoint testing', () => {
}); });
it('geo max distance in miles mid peninsula', (done) => { it('geo max distance in miles mid peninsula', (done) => {
makeSomeGeoPoints(function(list) { makeSomeGeoPoints(function() {
var sfo = new Parse.GeoPoint(37.6189722, -122.3748889); var sfo = new Parse.GeoPoint(37.6189722, -122.3748889);
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.withinMiles('location', sfo, 10.0); query.withinMiles('location', sfo, 10.0);

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
var request = require('request'); var request = require('request');
var Parse = require('parse/node').Parse;
let Config = require('../src/Config'); let Config = require('../src/Config');
describe('a GlobalConfig', () => { describe('a GlobalConfig', () => {
@@ -18,7 +17,7 @@ describe('a GlobalConfig', () => {
{ fields: { objectId: { type: 'Number' }, params: {type: 'Object'}} }, { fields: { objectId: { type: 'Number' }, params: {type: 'Object'}} },
query, query,
{ params: { companies: ['US', 'DK'] } } { params: { companies: ['US', 'DK'] } }
).then(done, (err) => { ).then(done, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -123,7 +122,7 @@ describe('a GlobalConfig', () => {
expect(body.params).toEqual({}); expect(body.params).toEqual({});
done(); done();
}); });
}).catch((e) => { }).catch((e) => {
jfail(e); jfail(e);
done(); done();
}); });

View File

@@ -15,25 +15,25 @@ app.use(bodyParser.json({ 'type': '*/*' }))
app.listen(12345); app.listen(12345);
describe('Hooks', () => { describe('Hooks', () => {
it("should have no hooks registered", (done) => { it("should have no hooks registered", (done) => {
Parse.Hooks.getFunctions().then((res) => { Parse.Hooks.getFunctions().then((res) => {
expect(res.constructor).toBe(Array.prototype.constructor); expect(res.constructor).toBe(Array.prototype.constructor);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it("should have no triggers registered", (done) => { it("should have no triggers registered", (done) => {
Parse.Hooks.getTriggers().then( (res) => { Parse.Hooks.getTriggers().then( (res) => {
expect(res.constructor).toBe(Array.prototype.constructor); expect(res.constructor).toBe(Array.prototype.constructor);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it("should CRUD a function registration", (done) => { it("should CRUD a function registration", (done) => {
// Create // Create
@@ -55,7 +55,7 @@ describe('Hooks', () => {
// delete // delete
return Parse.Hooks.removeFunction("My-Test-Function") return Parse.Hooks.removeFunction("My-Test-Function")
}) })
.then((res) => { .then(() => {
// Find again! but should be deleted // Find again! but should be deleted
return Parse.Hooks.getFunction("My-Test-Function") return Parse.Hooks.getFunction("My-Test-Function")
.then(res => { .then(res => {
@@ -78,270 +78,270 @@ describe('Hooks', () => {
it("should CRUD a trigger registration", (done) => { it("should CRUD a trigger registration", (done) => {
// Create // Create
Parse.Hooks.createTrigger("MyClass","beforeDelete", "http://someurl").then((res) => { Parse.Hooks.createTrigger("MyClass","beforeDelete", "http://someurl").then((res) => {
expect(res.className).toBe("MyClass"); expect(res.className).toBe("MyClass");
expect(res.triggerName).toBe("beforeDelete"); expect(res.triggerName).toBe("beforeDelete");
expect(res.url).toBe("http://someurl") expect(res.url).toBe("http://someurl")
// Find // Find
return Parse.Hooks.getTrigger("MyClass","beforeDelete"); return Parse.Hooks.getTrigger("MyClass","beforeDelete");
}, (err) => { }, (err) => {
fail(err); fail(err);
done(); done();
}).then((res) => { }).then((res) => {
expect(res).not.toBe(null); expect(res).not.toBe(null);
expect(res).not.toBe(undefined); expect(res).not.toBe(undefined);
expect(res.objectId).toBeUndefined(); expect(res.objectId).toBeUndefined();
expect(res.url).toBe("http://someurl"); expect(res.url).toBe("http://someurl");
// delete // delete
return Parse.Hooks.updateTrigger("MyClass","beforeDelete", "http://anotherurl"); return Parse.Hooks.updateTrigger("MyClass","beforeDelete", "http://anotherurl");
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}).then((res) => { }).then((res) => {
expect(res.className).toBe("MyClass"); expect(res.className).toBe("MyClass");
expect(res.url).toBe("http://anotherurl") expect(res.url).toBe("http://anotherurl")
expect(res.objectId).toBeUndefined(); expect(res.objectId).toBeUndefined();
return Parse.Hooks.removeTrigger("MyClass","beforeDelete"); return Parse.Hooks.removeTrigger("MyClass","beforeDelete");
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}).then((res) => { }).then(() => {
// Find again! but should be deleted // Find again! but should be deleted
return Parse.Hooks.getTrigger("MyClass","beforeDelete"); return Parse.Hooks.getTrigger("MyClass","beforeDelete");
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}).then(function(){ }).then(function(){
fail("should not succeed"); fail("should not succeed");
done(); done();
}, (err) => { }, (err) => {
if (err) { if (err) {
expect(err).not.toBe(null); expect(err).not.toBe(null);
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe("class MyClass does not exist") expect(err.message).toBe("class MyClass does not exist")
} else { } else {
fail('should have errored'); fail('should have errored');
} }
done(); done();
}); });
}); });
it("should fail to register hooks without Master Key", (done) => { it("should fail to register hooks without Master Key", (done) => {
request.post(Parse.serverURL+"/hooks/functions", { request.post(Parse.serverURL+"/hooks/functions", {
headers: { headers: {
"X-Parse-Application-Id": Parse.applicationId, "X-Parse-Application-Id": Parse.applicationId,
"X-Parse-REST-API-Key": Parse.restKey, "X-Parse-REST-API-Key": Parse.restKey,
}, },
body: JSON.stringify({ url: "http://hello.word", functionName: "SomeFunction"}) body: JSON.stringify({ url: "http://hello.word", functionName: "SomeFunction"})
}, (err, res, body) => { }, (err, res, body) => {
body = JSON.parse(body); body = JSON.parse(body);
expect(body.error).toBe("unauthorized"); expect(body.error).toBe("unauthorized");
done(); done();
}) })
}); });
it("should fail trying to create two times the same function", (done) => { it("should fail trying to create two times the same function", (done) => {
Parse.Hooks.createFunction("my_new_function", "http://url.com").then( () => { Parse.Hooks.createFunction("my_new_function", "http://url.com").then( () => {
return Parse.Hooks.createFunction("my_new_function", "http://url.com") return Parse.Hooks.createFunction("my_new_function", "http://url.com")
}, () => { }, () => {
fail("should create a new function"); fail("should create a new function");
}).then( () => { }).then( () => {
fail("should not be able to create the same function"); fail("should not be able to create the same function");
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('function name: my_new_function already exits') expect(err.message).toBe('function name: my_new_function already exits')
} }
return Parse.Hooks.removeFunction("my_new_function"); return Parse.Hooks.removeFunction("my_new_function");
}).then(() => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}) })
}); });
it("should fail trying to create two times the same trigger", (done) => { it("should fail trying to create two times the same trigger", (done) => {
Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com").then( () => { Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com").then( () => {
return Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com") return Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com")
}, () => { }, () => {
fail("should create a new trigger"); fail("should create a new trigger");
}).then( () => { }).then( () => {
fail("should not be able to create the same trigger"); fail("should not be able to create the same trigger");
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('class MyClass already has trigger beforeSave') expect(err.message).toBe('class MyClass already has trigger beforeSave')
} }
return Parse.Hooks.removeTrigger("MyClass", "beforeSave"); return Parse.Hooks.removeTrigger("MyClass", "beforeSave");
}).then(() => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}) })
}); });
it("should fail trying to update a function that don't exist", (done) => { it("should fail trying to update a function that don't exist", (done) => {
Parse.Hooks.updateFunction("A_COOL_FUNCTION", "http://url.com").then( () => { Parse.Hooks.updateFunction("A_COOL_FUNCTION", "http://url.com").then( () => {
fail("Should not succeed") fail("Should not succeed")
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('no function named: A_COOL_FUNCTION is defined'); expect(err.message).toBe('no function named: A_COOL_FUNCTION is defined');
} }
return Parse.Hooks.getFunction("A_COOL_FUNCTION") return Parse.Hooks.getFunction("A_COOL_FUNCTION")
}).then( (res) => { }).then(() => {
fail("the function should not exist"); fail("the function should not exist");
done(); done();
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('no function named: A_COOL_FUNCTION is defined'); expect(err.message).toBe('no function named: A_COOL_FUNCTION is defined');
} }
done(); done();
}); });
}); });
it("should fail trying to update a trigger that don't exist", (done) => { it("should fail trying to update a trigger that don't exist", (done) => {
Parse.Hooks.updateTrigger("AClassName","beforeSave", "http://url.com").then( () => { Parse.Hooks.updateTrigger("AClassName","beforeSave", "http://url.com").then( () => {
fail("Should not succeed") fail("Should not succeed")
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('class AClassName does not exist'); expect(err.message).toBe('class AClassName does not exist');
} }
return Parse.Hooks.getTrigger("AClassName","beforeSave") return Parse.Hooks.getTrigger("AClassName","beforeSave")
}).then( (res) => { }).then(() => {
fail("the function should not exist"); fail("the function should not exist");
done(); done();
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.message).toBe('class AClassName does not exist'); expect(err.message).toBe('class AClassName does not exist');
} }
done(); done();
}); });
}); });
it("should fail trying to create a malformed function", (done) => { it("should fail trying to create a malformed function", (done) => {
Parse.Hooks.createFunction("MyFunction").then( (res) => { Parse.Hooks.createFunction("MyFunction").then( (res) => {
fail(res); fail(res);
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(143); expect(err.code).toBe(143);
expect(err.error).toBe("invalid hook declaration"); expect(err.error).toBe("invalid hook declaration");
} }
done(); done();
}); });
}); });
it("should fail trying to create a malformed function (REST)", (done) => { it("should fail trying to create a malformed function (REST)", (done) => {
request.post(Parse.serverURL+"/hooks/functions", { request.post(Parse.serverURL+"/hooks/functions", {
headers: { headers: {
"X-Parse-Application-Id": Parse.applicationId, "X-Parse-Application-Id": Parse.applicationId,
"X-Parse-Master-Key": Parse.masterKey, "X-Parse-Master-Key": Parse.masterKey,
}, },
body: JSON.stringify({ functionName: "SomeFunction"}) body: JSON.stringify({ functionName: "SomeFunction"})
}, (err, res, body) => { }, (err, res, body) => {
body = JSON.parse(body); body = JSON.parse(body);
expect(body.error).toBe("invalid hook declaration"); expect(body.error).toBe("invalid hook declaration");
expect(body.code).toBe(143); expect(body.code).toBe(143);
done(); done();
}) })
}); });
it("should create hooks and properly preload them", (done) => { it("should create hooks and properly preload them", (done) => {
var promises = []; var promises = [];
for (var i = 0; i<5; i++) { for (var i = 0; i<5; i++) {
promises.push(Parse.Hooks.createTrigger("MyClass"+i, "beforeSave", "http://url.com/beforeSave/"+i)); promises.push(Parse.Hooks.createTrigger("MyClass"+i, "beforeSave", "http://url.com/beforeSave/"+i));
promises.push(Parse.Hooks.createFunction("AFunction"+i, "http://url.com/function"+i)); promises.push(Parse.Hooks.createFunction("AFunction"+i, "http://url.com/function"+i));
} }
Parse.Promise.when(promises).then(function(results){ Parse.Promise.when(promises).then(function(){
for (var i=0; i<5; i++) { for (var i=0; i<5; i++) {
// Delete everything from memory, as the server just started // Delete everything from memory, as the server just started
triggers.removeTrigger("beforeSave", "MyClass"+i, Parse.applicationId); triggers.removeTrigger("beforeSave", "MyClass"+i, Parse.applicationId);
triggers.removeFunction("AFunction"+i, Parse.applicationId); triggers.removeFunction("AFunction"+i, Parse.applicationId);
expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).toBeUndefined(); expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).toBeUndefined();
expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).toBeUndefined(); expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).toBeUndefined();
} }
const hooksController = new HooksController(Parse.applicationId, AppCache.get('test').databaseController); const hooksController = new HooksController(Parse.applicationId, AppCache.get('test').databaseController);
return hooksController.load() return hooksController.load()
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail('Should properly create all hooks'); fail('Should properly create all hooks');
done(); done();
}).then(function() { }).then(function() {
for (var i=0; i<5; i++) { for (var i=0; i<5; i++) {
expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).not.toBeUndefined(); expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).not.toBeUndefined();
expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).not.toBeUndefined(); expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).not.toBeUndefined();
} }
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail('should properly load all hooks'); fail('should properly load all hooks');
done(); done();
}) })
}); });
it("should run the function on the test server", (done) => { it("should run the function on the test server", (done) => {
app.post("/SomeFunction", function(req, res) { app.post("/SomeFunction", function(req, res) {
res.json({success:"OK!"}); res.json({success:"OK!"});
}); });
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunction").then(function(){ Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunction").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION") return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}).then(function(res){ }).then(function(res){
expect(res).toBe("OK!"); expect(res).toBe("OK!");
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail("Should not fail calling a function"); fail("Should not fail calling a function");
done(); done();
}); });
}); });
it("should run the function on the test server", (done) => { it("should run the function on the test server", (done) => {
app.post("/SomeFunctionError", function(req, res) { app.post("/SomeFunctionError", function(req, res) {
res.json({error: {code: 1337, error: "hacking that one!"}}); res.json({error: {code: 1337, error: "hacking that one!"}});
}); });
// The function is deleted as the DB is dropped between calls // The function is deleted as the DB is dropped between calls
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunctionError").then(function(){ Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunctionError").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION") return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}).then(function(res){ }).then(function() {
fail("Should not succeed calling that function"); fail("Should not succeed calling that function");
done(); done();
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
@@ -350,36 +350,36 @@ describe('Hooks', () => {
expect(err.message.error).toEqual("hacking that one!"); expect(err.message.error).toEqual("hacking that one!");
} }
done(); done();
}); });
}); });
it("should provide X-Parse-Webhook-Key when defined", (done) => { it("should provide X-Parse-Webhook-Key when defined", (done) => {
app.post("/ExpectingKey", function(req, res) { app.post("/ExpectingKey", function(req, res) {
if (req.get('X-Parse-Webhook-Key') === 'hook') { if (req.get('X-Parse-Webhook-Key') === 'hook') {
res.json({success: "correct key provided"}); res.json({success: "correct key provided"});
} else { } else {
res.json({error: "incorrect key provided"}); res.json({error: "incorrect key provided"});
} }
}); });
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKey").then(function(){ Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKey").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION") return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}).then(function(res){ }).then(function(res){
expect(res).toBe("correct key provided"); expect(res).toBe("correct key provided");
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail("Should not fail calling a function"); fail("Should not fail calling a function");
done(); done();
}); });
}); });
it("should not pass X-Parse-Webhook-Key if not provided", (done) => { it("should not pass X-Parse-Webhook-Key if not provided", (done) => {
reconfigureServer({ webhookKey: undefined }) reconfigureServer({ webhookKey: undefined })
.then(() => { .then(() => {
app.post("/ExpectingKeyAlso", function(req, res) { app.post("/ExpectingKeyAlso", function(req, res) {
if (req.get('X-Parse-Webhook-Key') === 'hook') { if (req.get('X-Parse-Webhook-Key') === 'hook') {
@@ -395,103 +395,103 @@ describe('Hooks', () => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}).then(function(res){ }).then(function(){
fail("Should not succeed calling that function"); fail("Should not succeed calling that function");
done(); done();
}, (err) => { }, (err) => {
expect(err).not.toBe(undefined); expect(err).not.toBe(undefined);
expect(err).not.toBe(null); expect(err).not.toBe(null);
if (err) { if (err) {
expect(err.code).toBe(141); expect(err.code).toBe(141);
expect(err.message).toEqual("incorrect key provided"); expect(err.message).toEqual("incorrect key provided");
} }
done(); done();
}); });
}); });
}); });
it("should run the beforeSave hook on the test server", (done) => { it("should run the beforeSave hook on the test server", (done) => {
var triggerCount = 0; var triggerCount = 0;
app.post("/BeforeSaveSome", function(req, res) { app.post("/BeforeSaveSome", function(req, res) {
triggerCount++; triggerCount++;
var object = req.body.object; var object = req.body.object;
object.hello = "world"; object.hello = "world";
// Would need parse cloud express to set much more // Would need parse cloud express to set much more
// But this should override the key upon return // But this should override the key upon return
res.json({success: object}); res.json({success: object});
}); });
// The function is delete as the DB is dropped between calls // The function is delete as the DB is dropped between calls
Parse.Hooks.createTrigger("SomeRandomObject", "beforeSave" ,hookServerURL+"/BeforeSaveSome").then(function(){ Parse.Hooks.createTrigger("SomeRandomObject", "beforeSave" ,hookServerURL+"/BeforeSaveSome").then(function(){
const obj = new Parse.Object("SomeRandomObject"); const obj = new Parse.Object("SomeRandomObject");
return obj.save(); return obj.save();
}).then(function(res) { }).then(function(res) {
expect(triggerCount).toBe(1); expect(triggerCount).toBe(1);
return res.fetch(); return res.fetch();
}).then(function(res) { }).then(function(res) {
expect(res.get("hello")).toEqual("world"); expect(res.get("hello")).toEqual("world");
done(); done();
}).fail((err) => { }).fail((err) => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}); });
}); });
it("beforeSave hooks should correctly handle responses containing entire object", (done) => { it("beforeSave hooks should correctly handle responses containing entire object", (done) => {
app.post("/BeforeSaveSome2", function(req, res) { app.post("/BeforeSaveSome2", function(req, res) {
var object = Parse.Object.fromJSON(req.body.object); var object = Parse.Object.fromJSON(req.body.object);
object.set('hello', "world"); object.set('hello', "world");
res.json({success: object}); res.json({success: object});
}); });
Parse.Hooks.createTrigger("SomeRandomObject2", "beforeSave" ,hookServerURL+"/BeforeSaveSome2").then(function(){ Parse.Hooks.createTrigger("SomeRandomObject2", "beforeSave" ,hookServerURL+"/BeforeSaveSome2").then(function(){
const obj = new Parse.Object("SomeRandomObject2"); const obj = new Parse.Object("SomeRandomObject2");
return obj.save(); return obj.save();
}).then(function(res) { }).then(function(res) {
return res.save(); return res.save();
}).then(function(res) { }).then(function(res) {
expect(res.get("hello")).toEqual("world"); expect(res.get("hello")).toEqual("world");
done(); done();
}).fail((err) => { }).fail((err) => {
fail(`Should not fail: ${JSON.stringify(err)}`); fail(`Should not fail: ${JSON.stringify(err)}`);
done(); done();
}); });
}); });
it("should run the afterSave hook on the test server", (done) => { it("should run the afterSave hook on the test server", (done) => {
var triggerCount = 0; var triggerCount = 0;
var newObjectId; var newObjectId;
app.post("/AfterSaveSome", function(req, res) { app.post("/AfterSaveSome", function(req, res) {
triggerCount++; triggerCount++;
var obj = new Parse.Object("AnotherObject"); var obj = new Parse.Object("AnotherObject");
obj.set("foo", "bar"); obj.set("foo", "bar");
obj.save().then(function(obj){ obj.save().then(function(obj){
newObjectId = obj.id; newObjectId = obj.id;
res.json({success: {}}); res.json({success: {}});
}) })
}); });
// The function is delete as the DB is dropped between calls // The function is delete as the DB is dropped between calls
Parse.Hooks.createTrigger("SomeRandomObject", "afterSave" ,hookServerURL+"/AfterSaveSome").then(function(){ Parse.Hooks.createTrigger("SomeRandomObject", "afterSave" ,hookServerURL+"/AfterSaveSome").then(function(){
const obj = new Parse.Object("SomeRandomObject"); const obj = new Parse.Object("SomeRandomObject");
return obj.save(); return obj.save();
}).then(function(res){ }).then(function() {
var promise = new Parse.Promise(); var promise = new Parse.Promise();
// Wait a bit here as it's an after save // Wait a bit here as it's an after save
setTimeout(function(){ setTimeout(function(){
expect(triggerCount).toBe(1); expect(triggerCount).toBe(1);
var q = new Parse.Query("AnotherObject"); var q = new Parse.Query("AnotherObject");
q.get(newObjectId).then(function(r){ q.get(newObjectId).then(function(r){
promise.resolve(r); promise.resolve(r);
}); });
}, 300) }, 300)
return promise; return promise;
}).then(function(res){ }).then(function(res){
expect(res.get("foo")).toEqual("bar"); expect(res.get("foo")).toEqual("bar");
done(); done();
}).fail((err) => { }).fail((err) => {
jfail(err); jfail(err);
fail("Should not fail creating a function"); fail("Should not fail creating a function");
done(); done();
}); });
}); });
}); });

View File

@@ -3,7 +3,6 @@
// Ported from installation_collection_test.go // Ported from installation_collection_test.go
let auth = require('../src/Auth'); let auth = require('../src/Auth');
let cache = require('../src/cache');
let Config = require('../src/Config'); let Config = require('../src/Config');
let Parse = require('parse/node').Parse; let Parse = require('parse/node').Parse;
let rest = require('../src/rest'); let rest = require('../src/rest');
@@ -17,7 +16,7 @@ const installationSchema = { fields: Object.assign({}, defaultColumns._Default,
describe('Installations', () => { describe('Installations', () => {
beforeEach(() => { beforeEach(() => {
config = new Config('test'); config = new Config('test');
database = config.database; database = config.database;
}); });
@@ -133,7 +132,7 @@ describe('Installations', () => {
.then(() => { .then(() => {
let query = new Parse.Query(Parse.Installation); let query = new Parse.Query(Parse.Installation);
return query.find() return query.find()
}).then((results) => { }).then(() => {
fail('Should not succeed!'); fail('Should not succeed!');
done(); done();
}).catch((error) => { }).catch((error) => {
@@ -160,7 +159,7 @@ describe('Installations', () => {
expect(obj.installationId).toEqual(installId); expect(obj.installationId).toEqual(installId);
expect(obj.deviceType).toEqual(device); expect(obj.deviceType).toEqual(device);
done(); done();
}).catch((error) => { }).catch(() => {
fail('Should not fail'); fail('Should not fail');
done(); done();
}); });
@@ -205,7 +204,7 @@ describe('Installations', () => {
'channels': ['foo', 'bar'], 'channels': ['foo', 'bar'],
'custom': 'allowed' 'custom': 'allowed'
}; };
rest.create(config, auth.nobody(config), '_Installation', input) rest.create(config, auth.nobody(config), '_Installation', input)
.then(() => database.adapter.find('_Installation', installationSchema, {}, {})) .then(() => database.adapter.find('_Installation', installationSchema, {}, {}))
.then(results => { .then(results => {
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
@@ -220,7 +219,6 @@ describe('Installations', () => {
it('merging when installationId already exists', (done) => { it('merging when installationId already exists', (done) => {
var installId1 = '12345678-abcd-abcd-abcd-123456789abc'; var installId1 = '12345678-abcd-abcd-abcd-123456789abc';
var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306'; var t = '11433856eed2f1285fb3aa11136718c1198ed5647875096952c66bf8cb976306';
var installId2 = '12345678-abcd-abcd-abcd-123456789abd';
var input = { var input = {
'deviceToken': t, 'deviceToken': t,
'deviceType': 'ios', 'deviceType': 'ios',
@@ -426,7 +424,7 @@ describe('Installations', () => {
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
expect(results[0].deviceToken).toEqual(u); expect(results[0].deviceToken).toEqual(u);
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -880,7 +878,7 @@ describe('Installations', () => {
'deviceType': device 'deviceType': device
}; };
rest.create(config, auth.nobody(config), '_Installation', input) rest.create(config, auth.nobody(config), '_Installation', input)
.then(createResult => { .then(() => {
let headers = { let headers = {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
@@ -936,14 +934,14 @@ describe('Installations', () => {
'installationId': installId, 'installationId': installId,
'deviceType': device 'deviceType': device
}; };
rest.create(config, auth.nobody(config), '_Installation', input).then(() => { rest.create(config, auth.nobody(config), '_Installation', input).then(() => {
let query = new Parse.Query(Parse.Installation); let query = new Parse.Query(Parse.Installation);
query.equalTo('installationId', installId); query.equalTo('installationId', installId);
query.first({useMasterKey: true}).then((installation) => { query.first({useMasterKey: true}).then((installation) => {
return installation.save({ return installation.save({
key: 'value' key: 'value'
}, {useMasterKey: true}); }, {useMasterKey: true});
}).then(() => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err) jfail(err)
@@ -959,7 +957,7 @@ describe('Installations', () => {
'installationId': installId, 'installationId': installId,
'deviceType': device 'deviceType': device
}; };
rest.create(config, auth.nobody(config), '_Installation', input).then(() => { rest.create(config, auth.nobody(config), '_Installation', input).then(() => {
let query = new Parse.Query(Parse.Installation); let query = new Parse.Query(Parse.Installation);
query.equalTo('installationId', installId); query.equalTo('installationId', installId);
query.first({useMasterKey: true}).then((installation) => { query.first({useMasterKey: true}).then((installation) => {
@@ -967,7 +965,7 @@ describe('Installations', () => {
key: 'value', key: 'value',
installationId: '22222222-abcd-abcd-abcd-123456789abc' installationId: '22222222-abcd-abcd-abcd-123456789abc'
}, {useMasterKey: true}); }, {useMasterKey: true});
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
done(); done();
}, (err) => { }, (err) => {

View File

@@ -159,7 +159,7 @@ describe('ParseLiveQueryServer', function() {
var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {});
// Add two mock clients // Add two mock clients
var clientId = 1; var clientId = 1;
var client = addMockClient(parseLiveQueryServer, clientId); addMockClient(parseLiveQueryServer, clientId);
var clientIdAgain = 2; var clientIdAgain = 2;
var clientAgain = addMockClient(parseLiveQueryServer, clientIdAgain); var clientAgain = addMockClient(parseLiveQueryServer, clientIdAgain);
// Add subscription for mock client 1 // Add subscription for mock client 1
@@ -232,7 +232,7 @@ describe('ParseLiveQueryServer', function() {
var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {});
// Add mock client // Add mock client
var clientId = 1; var clientId = 1;
var client = addMockClient(parseLiveQueryServer, clientId); addMockClient(parseLiveQueryServer, clientId);
// Handle unsubscribe command // Handle unsubscribe command
var parseWebSocket = { var parseWebSocket = {
clientId: 1 clientId: 1
@@ -274,7 +274,7 @@ describe('ParseLiveQueryServer', function() {
expect(subscriptions.size).toBe(0); expect(subscriptions.size).toBe(0);
}); });
it('can set connect command message handler for a parseWebSocket', function() { it('can set connect command message handler for a parseWebSocket', function() {
var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {}); var parseLiveQueryServer = new ParseLiveQueryServer(10, 10, {});
// Register mock connect/subscribe/unsubscribe handler for the server // Register mock connect/subscribe/unsubscribe handler for the server
parseLiveQueryServer._handleConnect = jasmine.createSpy('_handleSubscribe'); parseLiveQueryServer._handleConnect = jasmine.createSpy('_handleSubscribe');
@@ -533,7 +533,7 @@ describe('ParseLiveQueryServer', function() {
// In order to mimic a enter, we need original match return false // In order to mimic a enter, we need original match return false
// and the current match return true // and the current match return true
var counter = 0; var counter = 0;
parseLiveQueryServer._matchesSubscription = function(parseObject, subscription){ parseLiveQueryServer._matchesSubscription = function(parseObject){
if (!parseObject) { if (!parseObject) {
return false; return false;
} }
@@ -567,7 +567,7 @@ describe('ParseLiveQueryServer', function() {
var requestId = 2; var requestId = 2;
addMockSubscription(parseLiveQueryServer, clientId, requestId); addMockSubscription(parseLiveQueryServer, clientId, requestId);
// Mock _matchesSubscription to return matching // Mock _matchesSubscription to return matching
parseLiveQueryServer._matchesSubscription = function(parseObject, subscription){ parseLiveQueryServer._matchesSubscription = function(parseObject){
if (!parseObject) { if (!parseObject) {
return false; return false;
} }
@@ -603,7 +603,7 @@ describe('ParseLiveQueryServer', function() {
// In order to mimic a leave, we need original match return true // In order to mimic a leave, we need original match return true
// and the current match return false // and the current match return false
var counter = 0; var counter = 0;
parseLiveQueryServer._matchesSubscription = function(parseObject, subscription){ parseLiveQueryServer._matchesSubscription = function(parseObject){
if (!parseObject) { if (!parseObject) {
return false; return false;
} }
@@ -637,7 +637,7 @@ describe('ParseLiveQueryServer', function() {
var requestId = 2; var requestId = 2;
addMockSubscription(parseLiveQueryServer, clientId, requestId); addMockSubscription(parseLiveQueryServer, clientId, requestId);
// Mock _matchesSubscription to return matching // Mock _matchesSubscription to return matching
parseLiveQueryServer._matchesSubscription = function(parseObject, subscription){ parseLiveQueryServer._matchesSubscription = function(parseObject){
if (!parseObject) { if (!parseObject) {
return false; return false;
} }
@@ -746,7 +746,6 @@ describe('ParseLiveQueryServer', function() {
}; };
var requestId = 0; var requestId = 0;
var isChecked = false;
parseLiveQueryServer._matchesACL(acl, client, requestId).then(function(isMatched) { parseLiveQueryServer._matchesACL(acl, client, requestId).then(function(isMatched) {
expect(isMatched).toBe(false); expect(isMatched).toBe(false);
done(); done();
@@ -916,7 +915,7 @@ describe('ParseLiveQueryServer', function() {
spyOn(Parse, "Query").and.callFake(function(){ spyOn(Parse, "Query").and.callFake(function(){
return { return {
equalTo(relation, value) { equalTo() {
// Nothing to do here // Nothing to do here
}, },
find() { find() {
@@ -952,7 +951,7 @@ describe('ParseLiveQueryServer', function() {
spyOn(Parse, "Query").and.callFake(function(){ spyOn(Parse, "Query").and.callFake(function(){
return { return {
equalTo(relation, value) { equalTo() {
// Nothing to do here // Nothing to do here
}, },
find() { find() {

View File

@@ -14,7 +14,7 @@
describe('Parse.Object testing', () => { describe('Parse.Object testing', () => {
it("create", function(done) { it("create", function(done) {
create({ "test" : "test" }, function(model, response) { create({ "test" : "test" }, function(model) {
ok(model.id, "Should have an objectId set"); ok(model.id, "Should have an objectId set");
equal(model.get("test"), "test", "Should have the right attribute"); equal(model.get("test"), "test", "Should have the right attribute");
done(); done();
@@ -22,11 +22,11 @@ describe('Parse.Object testing', () => {
}); });
it("update", function(done) { it("update", function(done) {
create({ "test" : "test" }, function(model, response) { create({ "test" : "test" }, function(model) {
var t2 = new TestObject({ objectId: model.id }); var t2 = new TestObject({ objectId: model.id });
t2.set("test", "changed"); t2.set("test", "changed");
t2.save(null, { t2.save(null, {
success: function(model, response) { success: function(model) {
equal(model.get("test"), "changed", "Update should have succeeded"); equal(model.get("test"), "changed", "Update should have succeeded");
done(); done();
} }
@@ -72,10 +72,10 @@ describe('Parse.Object testing', () => {
}); });
it("get", function(done) { it("get", function(done) {
create({ "test" : "test" }, function(model, response) { create({ "test" : "test" }, function(model) {
var t2 = new TestObject({ objectId: model.id }); var t2 = new TestObject({ objectId: model.id });
t2.fetch({ t2.fetch({
success: function(model2, response) { success: function(model2) {
equal(model2.get("test"), "test", "Update should have succeeded"); equal(model2.get("test"), "test", "Update should have succeeded");
ok(model2.id); ok(model2.id);
equal(model2.id, model.id, "Ids should match"); equal(model2.id, model.id, "Ids should match");
@@ -269,20 +269,19 @@ describe('Parse.Object testing', () => {
}); });
it_exclude_dbs(['postgres'])("can set null", function(done) { it_exclude_dbs(['postgres'])("can set null", function(done) {
var errored = false;
var obj = new Parse.Object("TestObject"); var obj = new Parse.Object("TestObject");
obj.set("foo", null); obj.set("foo", null);
obj.save(null, { obj.save(null, {
success: function(obj) { success: function(obj) {
on_db('mongo', () => { on_db('mongo', () => {
equal(obj.get("foo"), null); equal(obj.get("foo"), null);
}); });
on_db('postgres', () => { on_db('postgres', () => {
fail('should not succeed'); fail('should not succeed');
}); });
done(); done();
}, },
error: function(obj, error) { error: function() {
fail('should not fail'); fail('should not fail');
done(); done();
} }
@@ -323,11 +322,11 @@ describe('Parse.Object testing', () => {
it("invalid class name", function(done) { it("invalid class name", function(done) {
var item = new Parse.Object("Foo^bar"); var item = new Parse.Object("Foo^bar");
item.save(null, { item.save(null, {
success: function(item) { success: function() {
ok(false, "The name should have been invalid."); ok(false, "The name should have been invalid.");
done(); done();
}, },
error: function(item, error) { error: function() {
// Because the class name is invalid, the router will not be able to route // Because the class name is invalid, the router will not be able to route
// it, so it will actually return a -1 error code. // it, so it will actually return a -1 error code.
// equal(error.code, Parse.Error.INVALID_CLASS_NAME); // equal(error.code, Parse.Error.INVALID_CLASS_NAME);
@@ -346,7 +345,6 @@ describe('Parse.Object testing', () => {
it("invalid __type", function(done) { it("invalid __type", function(done) {
var item = new Parse.Object("Item"); var item = new Parse.Object("Item");
var types = ['Pointer', 'File', 'Date', 'GeoPoint', 'Bytes']; var types = ['Pointer', 'File', 'Date', 'GeoPoint', 'Bytes'];
var Error = Parse.Error;
var tests = types.map(type => { var tests = types.map(type => {
var test = new Parse.Object("Item"); var test = new Parse.Object("Item");
test.set('foo', { test.set('foo', {
@@ -368,7 +366,7 @@ describe('Parse.Object testing', () => {
"foo": { "foo": {
__type: "IvalidName" __type: "IvalidName"
} }
}).then(fail, err => next(0)); }).then(fail, () => next(0));
}); });
it("simple field deletion", function(done) { it("simple field deletion", function(done) {
@@ -609,7 +607,7 @@ describe('Parse.Object testing', () => {
on_db('mongo', () => { on_db('mongo', () => {
jfail(error); jfail(error);
}); });
on_db('postgres', () => { on_db('postgres', () => {
expect(error.message).toEqual("Postgres does not support AddUnique operator."); expect(error.message).toEqual("Postgres does not support AddUnique operator.");
}); });
done(); done();
@@ -688,7 +686,7 @@ describe('Parse.Object testing', () => {
done(); done();
}, },
error: function(object, error) { error: function() {
ok(false, "This should have saved."); ok(false, "This should have saved.");
done(); done();
} }
@@ -1079,7 +1077,7 @@ describe('Parse.Object testing', () => {
parent.set('children', [child1, child2]); parent.set('children', [child1, child2]);
parent.save(null, { parent.save(null, {
success: function(parent) { success: function() {
var query = new Parse.Query(Child); var query = new Parse.Query(Child);
query.ascending('name'); query.ascending('name');
query.find({ query.find({
@@ -1199,8 +1197,7 @@ describe('Parse.Object testing', () => {
}); });
it("toJSON saved object", function(done) { it("toJSON saved object", function(done) {
var _ = Parse._; create({ "foo" : "bar" }, function(model) {
create({ "foo" : "bar" }, function(model, response) {
var objJSON = model.toJSON(); var objJSON = model.toJSON();
ok(objJSON.foo, "expected json to contain key 'foo'"); ok(objJSON.foo, "expected json to contain key 'foo'");
ok(objJSON.objectId, "expected json to contain key 'objectId'"); ok(objJSON.objectId, "expected json to contain key 'objectId'");
@@ -1274,7 +1271,7 @@ describe('Parse.Object testing', () => {
return bryan.save({ return bryan.save({
meal: "tomatoes" meal: "tomatoes"
}); });
}, function(error) { }, function() {
ok(false, "Save should have succeeded."); ok(false, "Save should have succeeded.");
}).then(function() { }).then(function() {
ok(false, "Save should have failed."); ok(false, "Save should have failed.");
@@ -1474,7 +1471,7 @@ describe('Parse.Object testing', () => {
}); });
done(); done();
}, },
error: function(error) { error: function() {
ok(false, "Failed to fetchAll"); ok(false, "Failed to fetchAll");
done(); done();
} }
@@ -1507,8 +1504,6 @@ describe('Parse.Object testing', () => {
it("fetchAll error on deleted object", function(done) { it("fetchAll error on deleted object", function(done) {
var numItems = 11; var numItems = 11;
var container = new Container();
var subContainer = new Container();
var items = []; var items = [];
for (var i = 0; i < numItems; i++) { for (var i = 0; i < numItems; i++) {
var item = new Item(); var item = new Item();
@@ -1639,7 +1634,7 @@ describe('Parse.Object testing', () => {
done(); done();
}, },
error: function(error) { error: function() {
ok(false, "Failed to fetchAll"); ok(false, "Failed to fetchAll");
done(); done();
} }
@@ -1763,7 +1758,7 @@ describe('Parse.Object testing', () => {
var obj2 = new TestObject(); var obj2 = new TestObject();
obj2.increment('astring'); obj2.increment('astring');
return obj2.save(); return obj2.save();
}).then((obj2) => { }).then(() => {
fail('Should not have saved.'); fail('Should not have saved.');
done(); done();
}, (error) => { }, (error) => {
@@ -1850,7 +1845,7 @@ describe('Parse.Object testing', () => {
object.save().then( res => { object.save().then( res => {
ok(res); ok(res);
return res.fetch(); return res.fetch();
}).then( res => { }).then( res => {
const foo = res.get("foo"); const foo = res.get("foo");
expect(foo["_bar"]).toEqual("_"); expect(foo["_bar"]).toEqual("_");
expect(foo["baz_bar"]).toEqual(1); expect(foo["baz_bar"]).toEqual(1);
@@ -1869,7 +1864,7 @@ describe('Parse.Object testing', () => {
let obj1 = new Parse.Object("AnObject"); let obj1 = new Parse.Object("AnObject");
let obj2 = new Parse.Object("AnObject"); let obj2 = new Parse.Object("AnObject");
Parse.Object.saveAll([obj1, obj2]).then(() => { Parse.Object.saveAll([obj1, obj2]).then(() => {
obj1.set("obj", obj2); obj1.set("obj", obj2);
// Save the pointer, delete the pointee // Save the pointer, delete the pointee
return obj1.save().then(() => { return obj2.destroy() }); return obj1.save().then(() => { return obj2.destroy() });
@@ -1884,7 +1879,7 @@ describe('Parse.Object testing', () => {
} }
let query = new Parse.Query("AnObject"); let query = new Parse.Query("AnObject");
return query.find(); return query.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(1); expect(res.length).toBe(1);
if (res[0]) { if (res[0]) {
expect(res[0].get("obj")).not.toBe(undefined); expect(res[0].get("obj")).not.toBe(undefined);
@@ -1904,7 +1899,7 @@ describe('Parse.Object testing', () => {
let obj1 = new Parse.Object("AnObject"); let obj1 = new Parse.Object("AnObject");
let obj2 = new Parse.Object("AnObject"); let obj2 = new Parse.Object("AnObject");
let obj3 = new Parse.Object("AnObject"); let obj3 = new Parse.Object("AnObject");
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
obj1.set("obj", obj2); obj1.set("obj", obj2);
obj2.set("obj", obj3); obj2.set("obj", obj3);
// Save the pointer, delete the pointee // Save the pointer, delete the pointee
@@ -1934,7 +1929,7 @@ describe('Parse.Object testing', () => {
"key": obj3 "key": obj3
}) })
Parse.Object.saveAll([obj1, obj2]).then(() => { Parse.Object.saveAll([obj1, obj2]).then(() => {
obj1.set("objects", [null, null, obj2]); obj1.set("objects", [null, null, obj2]);
return obj1.save(); return obj1.save();
}).then(() => { }).then(() => {
@@ -1963,7 +1958,7 @@ describe('Parse.Object testing', () => {
"score": 1234 "score": 1234
}); });
score.save().then(() => { score.save().then(() => {
player.set("gameScore", score); player.set("gameScore", score);
player.set("other", "value"); player.set("other", "value");
return player.save(); return player.save();

View File

@@ -19,7 +19,7 @@ describe('ParsePubSub', function() {
}); });
it('can create redis publisher', function() { it('can create redis publisher', function() {
var publisher = ParsePubSub.createPublisher({ ParsePubSub.createPublisher({
redisURL: 'redisURL' redisURL: 'redisURL'
}); });
@@ -30,7 +30,7 @@ describe('ParsePubSub', function() {
}); });
it('can create event emitter publisher', function() { it('can create event emitter publisher', function() {
var publisher = ParsePubSub.createPublisher({}); ParsePubSub.createPublisher({});
var RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; var RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub;
var EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; var EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub;
@@ -39,7 +39,7 @@ describe('ParsePubSub', function() {
}); });
it('can create redis subscriber', function() { it('can create redis subscriber', function() {
var subscriber = ParsePubSub.createSubscriber({ ParsePubSub.createSubscriber({
redisURL: 'redisURL' redisURL: 'redisURL'
}); });
@@ -50,7 +50,7 @@ describe('ParsePubSub', function() {
}); });
it('can create event emitter subscriber', function() { it('can create event emitter subscriber', function() {
var subscriptionInfos = ParsePubSub.createSubscriber({}); ParsePubSub.createSubscriber({});
var RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub; var RedisPubSub = require('../src/Adapters/PubSub/RedisPubSub').RedisPubSub;
var EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub; var EventEmitterPubSub = require('../src/Adapters/PubSub/EventEmitterPubSub').EventEmitterPubSub;

View File

@@ -145,7 +145,7 @@ describe('Parse.Query testing', () => {
}); });
}).then(function(){ }).then(function(){
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -221,7 +221,7 @@ describe('Parse.Query testing', () => {
done(); done();
}, },
}); });
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -243,7 +243,7 @@ describe('Parse.Query testing', () => {
done(); done();
} }
}); });
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -282,7 +282,7 @@ describe('Parse.Query testing', () => {
var objectsList = []; var objectsList = [];
objectsList.push(new DateSet({ objectsList.push(new DateSet({
"dates" : makeDates(["2013-02-01", "2013-02-02", "2013-02-03", "dates" : makeDates(["2013-02-01", "2013-02-02", "2013-02-03",
"2013-02-04"]) "2013-02-04"])
})); }));
objectsList.push(new DateSet({ objectsList.push(new DateSet({
"dates" : makeDates(["2013-02-01", "2013-02-03", "2013-02-04"]) "dates" : makeDates(["2013-02-01", "2013-02-03", "2013-02-04"])
@@ -353,15 +353,15 @@ describe('Parse.Query testing', () => {
}; };
Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.equalTo('number', 3); query.equalTo('number', 3);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 1); equal(results.length, 1);
done(); done();
} }
}); });
}); });
}); });
it("equalTo undefined", function(done) { it("equalTo undefined", function(done) {
@@ -370,15 +370,15 @@ describe('Parse.Query testing', () => {
}; };
Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.equalTo('number', undefined); query.equalTo('number', undefined);
query.find(expectSuccess({ query.find(expectSuccess({
success: function(results) { success: function(results) {
equal(results.length, 0); equal(results.length, 0);
done(); done();
} }
})); }));
}); });
}); });
it("lessThan queries", function(done) { it("lessThan queries", function(done) {
@@ -387,15 +387,15 @@ describe('Parse.Query testing', () => {
}; };
Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), Parse.Object.saveAll([0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.lessThan('number', 7); query.lessThan('number', 7);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 7); equal(results.length, 7);
done(); done();
} }
}); });
}); });
}); });
it("lessThanOrEqualTo queries", function(done) { it("lessThanOrEqualTo queries", function(done) {
@@ -459,16 +459,16 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.lessThanOrEqualTo('number', 7); query.lessThanOrEqualTo('number', 7);
query.greaterThanOrEqualTo('number', 7); query.greaterThanOrEqualTo('number', 7);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 1); equal(results.length, 1);
done(); done();
} }
});
}); });
});
}); });
it("lessThan greaterThan queries", function(done) { it("lessThan greaterThan queries", function(done) {
@@ -478,16 +478,16 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.lessThan('number', 9); query.lessThan('number', 9);
query.greaterThan('number', 3); query.greaterThan('number', 3);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 5); equal(results.length, 5);
done(); done();
} }
});
}); });
});
}); });
it("notEqualTo queries", function(done) { it("notEqualTo queries", function(done) {
@@ -497,15 +497,15 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.notEqualTo('number', 5); query.notEqualTo('number', 5);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 9); equal(results.length, 9);
done(); done();
} }
});
}); });
});
}); });
it("containedIn queries", function(done) { it("containedIn queries", function(done) {
@@ -515,15 +515,15 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.containedIn('number', [3,5,7,9,11]); query.containedIn('number', [3,5,7,9,11]);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 4); equal(results.length, 4);
done(); done();
} }
});
}); });
});
}); });
it("notContainedIn queries", function(done) { it("notContainedIn queries", function(done) {
@@ -533,15 +533,15 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.notContainedIn('number', [3,5,7,9,11]); query.notContainedIn('number', [3,5,7,9,11]);
query.find({ query.find({
success: function(results) { success: function(results) {
equal(results.length, 6); equal(results.length, 6);
done(); done();
} }
});
}); });
});
}); });
@@ -554,8 +554,8 @@ describe('Parse.Query testing', () => {
function(list) { function(list) {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.containedIn('objectId', query.containedIn('objectId',
[list[2].id, list[3].id, list[0].id, [list[2].id, list[3].id, list[0].id,
"NONSENSE"]); "NONSENSE"]);
query.ascending('number'); query.ascending('number');
query.find({ query.find({
success: function(results) { success: function(results) {
@@ -602,15 +602,15 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.equalTo('number', 17); query.equalTo('number', 17);
query.find(expectSuccess({ query.find(expectSuccess({
success: function(results) { success: function(results) {
equal(results.length, 0); equal(results.length, 0);
done(); done();
} }
})); }));
}); });
}); });
it("find with error", function(done) { it("find with error", function(done) {
@@ -651,10 +651,9 @@ describe('Parse.Query testing', () => {
it("get error", function(done) { it("get error", function(done) {
Parse.Object.saveAll([new TestObject({foo: 'bar'})], function(items) { Parse.Object.saveAll([new TestObject({foo: 'bar'})], function(items) {
ok(items[0]); ok(items[0]);
var objectId = items[0].id;
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.get("InvalidObjectID", { query.get("InvalidObjectID", {
success: function(result) { success: function() {
ok(false, "The get should have failed."); ok(false, "The get should have failed.");
done(); done();
}, },
@@ -694,16 +693,16 @@ describe('Parse.Query testing', () => {
it("first with two results", function(done) { it("first with two results", function(done) {
Parse.Object.saveAll([new TestObject({foo: 'bar'}), Parse.Object.saveAll([new TestObject({foo: 'bar'}),
new TestObject({foo: 'bar'})], function() { new TestObject({foo: 'bar'})], function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.equalTo('foo', 'bar'); query.equalTo('foo', 'bar');
query.first({ query.first({
success: function(result) { success: function(result) {
equal(result.get('foo'), 'bar'); equal(result.get('foo'), 'bar');
done(); done();
} }
}); });
}); });
}); });
it("first with error", function(done) { it("first with error", function(done) {
@@ -783,22 +782,22 @@ describe('Parse.Query testing', () => {
Parse.Object.saveAll( Parse.Object.saveAll(
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(makeBoxedNumber),
function() { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.greaterThan("number", 1); query.greaterThan("number", 1);
query.count({ query.count({
success: function(count) { success: function(count) {
equal(count, 8); equal(count, 8);
done(); done();
} }
});
}); });
});
}); });
it("order by ascending number", function(done) { it("order by ascending number", function(done) {
var makeBoxedNumber = function(i) { var makeBoxedNumber = function(i) {
return new BoxedNumber({ number: i }); return new BoxedNumber({ number: i });
}; };
Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber), function(list) { Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber), function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.ascending("number"); query.ascending("number");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -817,7 +816,7 @@ describe('Parse.Query testing', () => {
var makeBoxedNumber = function(i) { var makeBoxedNumber = function(i) {
return new BoxedNumber({ number: i }); return new BoxedNumber({ number: i });
}; };
Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber)).then( function(list) { Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber)).then( function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("number"); query.descending("number");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -839,7 +838,7 @@ describe('Parse.Query testing', () => {
}; };
Parse.Object.saveAll( Parse.Object.saveAll(
[3, 1, 3, 2].map(makeBoxedNumber)).then( [3, 1, 3, 2].map(makeBoxedNumber)).then(
function(list) { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.ascending("number").addDescending("string"); query.ascending("number").addDescending("string");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -867,11 +866,11 @@ describe('Parse.Query testing', () => {
let objects = [3, 1, 3, 2].map(makeBoxedNumber); let objects = [3, 1, 3, 2].map(makeBoxedNumber);
Parse.Object.saveAll(objects) Parse.Object.saveAll(objects)
.then((list) => { .then(() => {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("number").addAscending("string"); query.descending("number").addAscending("string");
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
equal(results.length, 4); equal(results.length, 4);
equal(results[0].get("number"), 3); equal(results[0].get("number"), 3);
equal(results[0].get("string"), "a"); equal(results[0].get("string"), "a");
@@ -882,7 +881,7 @@ describe('Parse.Query testing', () => {
equal(results[3].get("number"), 1); equal(results[3].get("number"), 1);
equal(results[3].get("string"), "b"); equal(results[3].get("string"), "b");
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -894,7 +893,7 @@ describe('Parse.Query testing', () => {
return new BoxedNumber({ number: num, string: strings[i] }); return new BoxedNumber({ number: num, string: strings[i] });
}; };
Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then( Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then(
function(list) { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("number,string"); query.descending("number,string");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -920,7 +919,7 @@ describe('Parse.Query testing', () => {
return new BoxedNumber({ number: num, string: strings[i] }); return new BoxedNumber({ number: num, string: strings[i] });
}; };
Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then( Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then(
function(list) { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("number, string"); query.descending("number, string");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -937,10 +936,10 @@ describe('Parse.Query testing', () => {
done(); done();
} }
})); }));
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it("order by descending number and string, with array arg", function(done) { it("order by descending number and string, with array arg", function(done) {
@@ -949,7 +948,7 @@ describe('Parse.Query testing', () => {
return new BoxedNumber({ number: num, string: strings[i] }); return new BoxedNumber({ number: num, string: strings[i] });
}; };
Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then( Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then(
function(list) { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending(["number", "string"]); query.descending(["number", "string"]);
query.find(expectSuccess({ query.find(expectSuccess({
@@ -975,7 +974,7 @@ describe('Parse.Query testing', () => {
return new BoxedNumber({ number: num, string: strings[i] }); return new BoxedNumber({ number: num, string: strings[i] });
}; };
Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then( Parse.Object.saveAll([3, 1, 3, 2].map(makeBoxedNumber)).then(
function(list) { function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("number", "string"); query.descending("number", "string");
query.find(expectSuccess({ query.find(expectSuccess({
@@ -999,7 +998,7 @@ describe('Parse.Query testing', () => {
var makeBoxedNumber = function(i) { var makeBoxedNumber = function(i) {
return new BoxedNumber({ number: i }); return new BoxedNumber({ number: i });
}; };
Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber), function(list) { Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber), function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.ascending("_password"); query.ascending("_password");
query.find(expectError(Parse.Error.INVALID_KEY_NAME, done)); query.find(expectError(Parse.Error.INVALID_KEY_NAME, done));
@@ -1070,7 +1069,7 @@ describe('Parse.Query testing', () => {
}).then(function() { }).then(function() {
numbers[1].set("number", 4); numbers[1].set("number", 4);
numbers[1].save(null, { numbers[1].save(null, {
success: function(model) { success: function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.ascending("_updated_at"); query.ascending("_updated_at");
query.find({ query.find({
@@ -1097,7 +1096,7 @@ describe('Parse.Query testing', () => {
}).then(function() { }).then(function() {
numbers[1].set("number", 4); numbers[1].set("number", 4);
numbers[1].save(null, { numbers[1].save(null, {
success: function(model) { success: function() {
var query = new Parse.Query(BoxedNumber); var query = new Parse.Query(BoxedNumber);
query.descending("_updated_at"); query.descending("_updated_at");
query.find({ query.find({
@@ -1220,7 +1219,7 @@ describe('Parse.Query testing', () => {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.matches("myString", "FootBall", "i"); query.matches("myString", "FootBall", "i");
query.find({ query.find({
success: function(results) { success: function() {
done(); done();
} }
}); });
@@ -1277,50 +1276,50 @@ describe('Parse.Query testing', () => {
it("contains", function(done) { it("contains", function(done) {
Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}), Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}),
new TestObject({myString: "start" + someAscii}), new TestObject({myString: "start" + someAscii}),
new TestObject({myString: someAscii + "end"}), new TestObject({myString: someAscii + "end"}),
new TestObject({myString: someAscii})], function() { new TestObject({myString: someAscii})], function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.contains("myString", someAscii); query.contains("myString", someAscii);
query.find({ query.find({
success: function(results, foo) { success: function(results) {
equal(results.length, 4); equal(results.length, 4);
done(); done();
} }
}); });
}); });
}); });
it("startsWith", function(done) { it("startsWith", function(done) {
Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}), Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}),
new TestObject({myString: "start" + someAscii}), new TestObject({myString: "start" + someAscii}),
new TestObject({myString: someAscii + "end"}), new TestObject({myString: someAscii + "end"}),
new TestObject({myString: someAscii})], function() { new TestObject({myString: someAscii})], function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.startsWith("myString", someAscii); query.startsWith("myString", someAscii);
query.find({ query.find({
success: function(results, foo) { success: function(results) {
equal(results.length, 2); equal(results.length, 2);
done(); done();
} }
}); });
}); });
}); });
it("endsWith", function(done) { it("endsWith", function(done) {
Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}), Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}),
new TestObject({myString: "start" + someAscii}), new TestObject({myString: "start" + someAscii}),
new TestObject({myString: someAscii + "end"}), new TestObject({myString: someAscii + "end"}),
new TestObject({myString: someAscii})], function() { new TestObject({myString: someAscii})], function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.endsWith("myString", someAscii); query.endsWith("myString", someAscii);
query.find({ query.find({
success: function(results, foo) { success: function(results) {
equal(results.length, 2); equal(results.length, 2);
done(); done();
} }
}); });
}); });
}); });
it("exists", function(done) { it("exists", function(done) {
@@ -1342,7 +1341,7 @@ describe('Parse.Query testing', () => {
equal(results.length, 5); equal(results.length, 5);
for (var result of results) { for (var result of results) {
ok(result.get("x")); ok(result.get("x"));
}; }
done(); done();
} }
}); });
@@ -1359,7 +1358,7 @@ describe('Parse.Query testing', () => {
item.set('y', i + 1); item.set('y', i + 1);
} }
objects.push(item); objects.push(item);
}; }
Parse.Object.saveAll(objects, function() { Parse.Object.saveAll(objects, function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.doesNotExist("x"); query.doesNotExist("x");
@@ -1388,7 +1387,7 @@ describe('Parse.Query testing', () => {
container.set('y', i); container.set('y', i);
} }
objects.push(container); objects.push(container);
}; }
Parse.Object.saveAll(objects).then(function() { Parse.Object.saveAll(objects).then(function() {
var query = new Parse.Query(Container); var query = new Parse.Query(Container);
query.exists("x"); query.exists("x");
@@ -1397,7 +1396,7 @@ describe('Parse.Query testing', () => {
equal(results.length, 5); equal(results.length, 5);
for (var result of results) { for (var result of results) {
ok(result.get("x")); ok(result.get("x"));
}; }
done(); done();
} }
}); });
@@ -1426,7 +1425,7 @@ describe('Parse.Query testing', () => {
equal(results.length, 4); equal(results.length, 4);
for (var result of results) { for (var result of results) {
ok(result.get("y")); ok(result.get("y"));
}; }
done(); done();
} }
}); });
@@ -1579,7 +1578,7 @@ describe('Parse.Query testing', () => {
let object = new Parse.Object("AContainer"); let object = new Parse.Object("AContainer");
object.set('objects', objects); object.set('objects', objects);
return object.save(); return object.save();
}).then(() => { }).then(() => {
let query = new Parse.Query('AContainer'); let query = new Parse.Query('AContainer');
query.include('objects'); query.include('objects');
return query.find() return query.find()
@@ -1593,7 +1592,7 @@ describe('Parse.Query testing', () => {
}); });
expect(total).toBe(0); expect(total).toBe(0);
done() done()
}, () => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}) })
@@ -1618,7 +1617,7 @@ describe('Parse.Query testing', () => {
let object = new Parse.Object("AContainer"); let object = new Parse.Object("AContainer");
object.set('objects', objects); object.set('objects', objects);
return object.save(); return object.save();
}).then(() => { }).then(() => {
let query = new Parse.Query('AContainer'); let query = new Parse.Query('AContainer');
query.include('objects'); query.include('objects');
return query.find() return query.find()
@@ -1632,7 +1631,7 @@ describe('Parse.Query testing', () => {
}); });
expect(total).toBe(0); expect(total).toBe(0);
done() done()
}, (err) => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}) })
@@ -1662,7 +1661,7 @@ describe('Parse.Query testing', () => {
} }
object.set('objects', objects); object.set('objects', objects);
return object.save(); return object.save();
}).then(() => { }).then(() => {
let query = new Parse.Query('AContainer'); let query = new Parse.Query('AContainer');
query.include('objects'); query.include('objects');
return query.find() return query.find()
@@ -1676,37 +1675,37 @@ describe('Parse.Query testing', () => {
}); });
expect(total).toBe(0); expect(total).toBe(0);
done() done()
}, (err) => { }, (err) => {
jfail(err); jfail(err);
fail('should not fail'); fail('should not fail');
done(); done();
}) })
}); });
it('properly fetches nested pointers', (done) =>  { it('properly fetches nested pointers', (done) => {
let color = new Parse.Object('Color'); let color = new Parse.Object('Color');
color.set('hex','#133733'); color.set('hex','#133733');
let circle = new Parse.Object('Circle'); let circle = new Parse.Object('Circle');
circle.set('radius', 1337); circle.set('radius', 1337);
Parse.Object.saveAll([color, circle]).then(() => { Parse.Object.saveAll([color, circle]).then(() => {
circle.set('color', color); circle.set('color', color);
let badCircle = new Parse.Object('Circle'); let badCircle = new Parse.Object('Circle');
badCircle.id = 'badId'; badCircle.id = 'badId';
let complexFigure = new Parse.Object('ComplexFigure'); let complexFigure = new Parse.Object('ComplexFigure');
complexFigure.set('consistsOf', [circle, badCircle]); complexFigure.set('consistsOf', [circle, badCircle]);
return complexFigure.save(); return complexFigure.save();
}).then(() => { }).then(() => {
let q = new Parse.Query('ComplexFigure'); let q = new Parse.Query('ComplexFigure');
q.include('consistsOf.color'); q.include('consistsOf.color');
return q.find() return q.find()
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
let figure = results[0]; let figure = results[0];
expect(figure.get('consistsOf').length).toBe(1); expect(figure.get('consistsOf').length).toBe(1);
expect(figure.get('consistsOf')[0].get('color').get('hex')).toBe('#133733'); expect(figure.get('consistsOf')[0].get('color').get('hex')).toBe('#133733');
done(); done();
}, (err) => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}) })
@@ -1897,7 +1896,7 @@ describe('Parse.Query testing', () => {
obj.set("length", 5); obj.set("length", 5);
equal(obj.get("length"), 5); equal(obj.get("length"), 5);
obj.save(null, { obj.save(null, {
success: function(obj) { success: function() {
var query = new Parse.Query(TestObject); var query = new Parse.Query(TestObject);
query.find({ query.find({
success: function(results) { success: function(results) {
@@ -2072,7 +2071,7 @@ describe('Parse.Query testing', () => {
equal(seen.length, COUNT); equal(seen.length, COUNT);
for (var i = 0; i < COUNT; i++) { for (var i = 0; i < COUNT; i++) {
equal(seen[i], 1, "Should have seen object number " + i); equal(seen[i], 1, "Should have seen object number " + i);
}; }
done(); done();
}, },
error: function(error) { error: function(error) {
@@ -2115,7 +2114,7 @@ describe('Parse.Query testing', () => {
equal(seen.length, COUNT); equal(seen.length, COUNT);
for (var i = 0; i < COUNT; i++) { for (var i = 0; i < COUNT; i++) {
equal(seen[i], 1, "Should have seen object number " + i); equal(seen[i], 1, "Should have seen object number " + i);
}; }
done(); done();
}); });
}); });
@@ -2143,7 +2142,7 @@ describe('Parse.Query testing', () => {
}).then(function() { }).then(function() {
ok(false, "This should have failed."); ok(false, "This should have failed.");
done(); done();
}, function(error) { }, function() {
done(); done();
}); });
}); });
@@ -2171,7 +2170,7 @@ describe('Parse.Query testing', () => {
}).then(function() { }).then(function() {
ok(false, "This should have failed."); ok(false, "This should have failed.");
done(); done();
}, function(error) { }, function() {
done(); done();
}); });
}); });
@@ -2201,7 +2200,7 @@ describe('Parse.Query testing', () => {
}).then(function() { }).then(function() {
ok(false, "This should have failed."); ok(false, "This should have failed.");
done(); done();
}, function(error) { }, function() {
done(); done();
}); });
}); });
@@ -2336,7 +2335,6 @@ describe('Parse.Query testing', () => {
}); });
it('query within dictionary', (done) => { it('query within dictionary', (done) => {
var objs = [];
var promises = []; var promises = [];
for (var i = 0; i < 2; i++) { for (var i = 0; i < 2; i++) {
var proc = (iter) => { var proc = (iter) => {
@@ -2361,24 +2359,24 @@ describe('Parse.Query testing', () => {
it('supports include on the wrong key type (#2262)', function(done) { it('supports include on the wrong key type (#2262)', function(done) {
let childObject = new Parse.Object('TestChildObject'); let childObject = new Parse.Object('TestChildObject');
childObject.set('hello', 'world'); childObject.set('hello', 'world');
childObject.save().then(() => { childObject.save().then(() => {
let obj = new Parse.Object('TestObject'); let obj = new Parse.Object('TestObject');
obj.set('foo', 'bar'); obj.set('foo', 'bar');
obj.set('child', childObject); obj.set('child', childObject);
return obj.save(); return obj.save();
}).then(() => { }).then(() => {
let q = new Parse.Query('TestObject'); let q = new Parse.Query('TestObject');
q.include('child'); q.include('child');
q.include('child.parent'); q.include('child.parent');
q.include('createdAt'); q.include('createdAt');
q.include('createdAt.createdAt'); q.include('createdAt.createdAt');
return q.find(); return q.find();
}).then((objs) => { }).then((objs) => {
expect(objs.length).toBe(1); expect(objs.length).toBe(1);
expect(objs[0].get('child').get('hello')).toEqual('world'); expect(objs[0].get('child').get('hello')).toEqual('world');
expect(objs[0].createdAt instanceof Date).toBe(true); expect(objs[0].createdAt instanceof Date).toBe(true);
done(); done();
}, (err) => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}); });
@@ -2424,7 +2422,7 @@ describe('Parse.Query testing', () => {
query.matchesKeyInQuery("A1", "A2", auxQuery); query.matchesKeyInQuery("A1", "A2", auxQuery);
query.include("A3"); query.include("A3");
query.include("A2"); query.include("A2");
query.find().then((result) => { query.find().then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
@@ -2437,7 +2435,7 @@ describe('Parse.Query testing', () => {
var user = new Parse.User(); var user = new Parse.User();
user.set("username", "foo"); user.set("username", "foo");
user.set("password", "bar"); user.set("password", "bar");
return user.save().then( (user) => { return user.save().then( (user) => {
var objIdQuery = new Parse.Query("_User").equalTo("objectId", user.id); var objIdQuery = new Parse.Query("_User").equalTo("objectId", user.id);
var blockedUserQuery = user.relation("blockedUsers").query(); var blockedUserQuery = user.relation("blockedUsers").query();
@@ -2460,7 +2458,7 @@ describe('Parse.Query testing', () => {
var query = new Parse.Query("_User"); var query = new Parse.Query("_User");
query.doesNotMatchQuery("objectId", orQuery); query.doesNotMatchQuery("objectId", orQuery);
return query.find(); return query.find();
}).then((res) => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
@@ -2477,13 +2475,13 @@ describe('Parse.Query testing', () => {
objects.push(object); objects.push(object);
} }
Parse.Object.saveAll(objects).then((objects) => { Parse.Object.saveAll(objects).then((objects) => {
var container = new Parse.Object('Container'); var container = new Parse.Object('Container');
var pointers = objects.map((obj) => { var pointers = objects.map((obj) => {
return { return {
__type: 'Pointer', __type: 'Pointer',
className: 'ContainedObject', className: 'ContainedObject',
objectId: obj.id objectId: obj.id
} }
}) })
container.set('objects', pointers); container.set('objects', pointers);
@@ -2496,12 +2494,12 @@ describe('Parse.Query testing', () => {
let query = new Parse.Query('Container'); let query = new Parse.Query('Container');
query.matchesQuery('objects', inQuery); query.matchesQuery('objects', inQuery);
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
if (results) { if (results) {
expect(results.length).toBe(2); expect(results.length).toBe(2);
} }
done(); done();
}).fail((err) => { }).fail((err) => {
jfail(err); jfail(err);
fail('should not fail'); fail('should not fail');
done(); done();
@@ -2520,7 +2518,7 @@ describe('Parse.Query testing', () => {
q1.doesNotExist('nonExistantKey1'); q1.doesNotExist('nonExistantKey1');
let q2 = anObject.relation('relation').query(); let q2 = anObject.relation('relation').query();
q2.doesNotExist('nonExistantKey2'); q2.doesNotExist('nonExistantKey2');
let orQuery = Parse.Query.or(q1, q2).find().then(results => { Parse.Query.or(q1, q2).find().then(results => {
expect(results.length).toEqual(1); expect(results.length).toEqual(1);
if (results.length == 1) { if (results.length == 1) {
expect(results[0].objectId).toEqual(q1.objectId); expect(results[0].objectId).toEqual(q1.objectId);
@@ -2592,7 +2590,7 @@ describe('Parse.Query testing', () => {
var BarBaz = new Parse.Object('Barbaz'); var BarBaz = new Parse.Object('Barbaz');
BarBaz.set('key', 'value'); BarBaz.set('key', 'value');
BarBaz.set('otherKey', 'value'); BarBaz.set('otherKey', 'value');
BarBaz.save().then(() => { BarBaz.save().then(() => {
Foobar.set('foo', 'bar'); Foobar.set('foo', 'bar');
Foobar.set('fizz', 'buzz'); Foobar.set('fizz', 'buzz');
Foobar.set('barBaz', BarBaz); Foobar.set('barBaz', BarBaz);
@@ -2624,12 +2622,12 @@ describe('Parse.Query testing', () => {
Bazoo.set('some', 'thing'); Bazoo.set('some', 'thing');
Bazoo.set('otherSome', 'value'); Bazoo.set('otherSome', 'value');
Bazoo.save().then(() => { Bazoo.save().then(() => {
BarBaz.set('key', 'value'); BarBaz.set('key', 'value');
BarBaz.set('otherKey', 'value'); BarBaz.set('otherKey', 'value');
BarBaz.set('bazoo', Bazoo); BarBaz.set('bazoo', Bazoo);
return BarBaz.save(); return BarBaz.save();
}).then(() => { }).then(() => {
Foobar.set('foo', 'bar'); Foobar.set('foo', 'bar');
Foobar.set('fizz', 'buzz'); Foobar.set('fizz', 'buzz');
Foobar.set('barBaz', BarBaz); Foobar.set('barBaz', BarBaz);
@@ -2673,10 +2671,10 @@ describe('Parse.Query testing', () => {
q2.equalTo('x', 2); q2.equalTo('x', 2);
let or01 = Parse.Query.or(q0,q1); let or01 = Parse.Query.or(q0,q1);
return Parse.Query.or(or01, q2).find(); return Parse.Query.or(or01, q2).find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(3); expect(results.length).toBe(3);
done(); done();
}).catch((error) => { }).catch((error) => {
fail('should not fail'); fail('should not fail');
jfail(error); jfail(error);
done(); done();

View File

@@ -46,10 +46,10 @@ describe('Parse.Relation testing', () => {
var childObjects = []; var childObjects = [];
for (var i = 0; i < 10; i++) { for (var i = 0; i < 10; i++) {
childObjects.push(new ChildObject({x:i})); childObjects.push(new ChildObject({x:i}));
}; }
Parse.Object.saveAll(childObjects, expectSuccess({ Parse.Object.saveAll(childObjects, expectSuccess({
success: function(list) { success: function() {
var ParentObject = Parse.Object.extend("ParentObject"); var ParentObject = Parse.Object.extend("ParentObject");
var parent = new ParentObject(); var parent = new ParentObject();
parent.set("x", 4); parent.set("x", 4);
@@ -84,7 +84,7 @@ describe('Parse.Relation testing', () => {
} }
Parse.Object.saveAll(childObjects, { Parse.Object.saveAll(childObjects, {
success: function(list) { success: function() {
var ParentObject = Parse.Object.extend("ParentObject"); var ParentObject = Parse.Object.extend("ParentObject");
var parent = new ParentObject(); var parent = new ParentObject();
parent.set("x", 4); parent.set("x", 4);
@@ -106,7 +106,7 @@ describe('Parse.Relation testing', () => {
"The relation should not be dirty"); "The relation should not be dirty");
done(); done();
}, },
error: function(list) { error: function() {
ok(false, "This shouldn't have failed"); ok(false, "This shouldn't have failed");
done(); done();
} }
@@ -131,7 +131,7 @@ describe('Parse.Relation testing', () => {
var parent; var parent;
var relation; var relation;
Parse.Object.saveAll(childObjects).then(function(list) { Parse.Object.saveAll(childObjects).then(function() {
var ParentObject = Parse.Object.extend('ParentObject'); var ParentObject = Parse.Object.extend('ParentObject');
parent = new ParentObject(); parent = new ParentObject();
parent.set('x', 4); parent.set('x', 4);
@@ -304,34 +304,34 @@ describe('Parse.Relation testing', () => {
} }
Parse.Object.saveAll(childObjects).then(() => { Parse.Object.saveAll(childObjects).then(() => {
var ParentObject = Parse.Object.extend("ParentObject"); var ParentObject = Parse.Object.extend("ParentObject");
var parent = new ParentObject(); var parent = new ParentObject();
parent.set("x", 4); parent.set("x", 4);
var relation = parent.relation("toChilds"); var relation = parent.relation("toChilds");
relation.add(childObjects[0]); relation.add(childObjects[0]);
relation.add(childObjects[1]); relation.add(childObjects[1]);
relation.add(childObjects[2]); relation.add(childObjects[2]);
var parent2 = new ParentObject(); var parent2 = new ParentObject();
parent2.set("x", 3); parent2.set("x", 3);
parent2.set("toChild", childObjects[2]); parent2.set("toChild", childObjects[2]);
var parents = []; var parents = [];
parents.push(parent); parents.push(parent);
parents.push(parent2); parents.push(parent2);
parents.push(new ParentObject()); parents.push(new ParentObject());
return Parse.Object.saveAll(parents).then(() => { return Parse.Object.saveAll(parents).then(() => {
var query = new Parse.Query(ParentObject); var query = new Parse.Query(ParentObject);
query.equalTo("objectId", parent.id); query.equalTo("objectId", parent.id);
query.equalTo("toChilds", childObjects[2]); query.equalTo("toChilds", childObjects[2]);
return query.find().then((list) => { return query.find().then((list) => {
equal(list.length, 1, "There should be 1 result"); equal(list.length, 1, "There should be 1 result");
done(); done();
});
}); });
}).catch(err => { });
}).catch(err => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -345,35 +345,35 @@ describe('Parse.Relation testing', () => {
} }
Parse.Object.saveAll(childObjects).then(() => { Parse.Object.saveAll(childObjects).then(() => {
var ParentObject = Parse.Object.extend("ParentObject"); var ParentObject = Parse.Object.extend("ParentObject");
var parent = new ParentObject(); var parent = new ParentObject();
parent.set("x", 4); parent.set("x", 4);
var relation = parent.relation("toChilds"); var relation = parent.relation("toChilds");
relation.add(childObjects[0]); relation.add(childObjects[0]);
relation.add(childObjects[1]); relation.add(childObjects[1]);
relation.add(childObjects[2]); relation.add(childObjects[2]);
var parent2 = new ParentObject(); var parent2 = new ParentObject();
parent2.set("x", 3); parent2.set("x", 3);
parent2.relation("toChilds").add(childObjects[2]); parent2.relation("toChilds").add(childObjects[2]);
var parents = []; var parents = [];
parents.push(parent); parents.push(parent);
parents.push(parent2); parents.push(parent2);
parents.push(new ParentObject()); parents.push(new ParentObject());
return Parse.Object.saveAll(parents).then(() => { return Parse.Object.saveAll(parents).then(() => {
var query = new Parse.Query(ParentObject); var query = new Parse.Query(ParentObject);
query.equalTo("objectId", parent2.id); query.equalTo("objectId", parent2.id);
// childObjects[2] is in 2 relations // childObjects[2] is in 2 relations
// before the fix, that woul yield 2 results // before the fix, that woul yield 2 results
query.equalTo("toChilds", childObjects[2]); query.equalTo("toChilds", childObjects[2]);
return query.find().then((list) => { return query.find().then((list) => {
equal(list.length, 1, "There should be 1 result"); equal(list.length, 1, "There should be 1 result");
done(); done();
});
}); });
});
}); });
}); });
@@ -385,39 +385,39 @@ describe('Parse.Relation testing', () => {
} }
Parse.Object.saveAll(childObjects).then(() => { Parse.Object.saveAll(childObjects).then(() => {
var ParentObject = Parse.Object.extend("ParentObject"); var ParentObject = Parse.Object.extend("ParentObject");
var parent = new ParentObject(); var parent = new ParentObject();
parent.set("x", 4); parent.set("x", 4);
var relation = parent.relation("toChilds"); var relation = parent.relation("toChilds");
relation.add(childObjects[0]); relation.add(childObjects[0]);
relation.add(childObjects[1]); relation.add(childObjects[1]);
relation.add(childObjects[2]); relation.add(childObjects[2]);
var parent2 = new ParentObject(); var parent2 = new ParentObject();
parent2.set("x", 3); parent2.set("x", 3);
parent2.set("toChild", childObjects[2]); parent2.set("toChild", childObjects[2]);
var parents = []; var parents = [];
parents.push(parent); parents.push(parent);
parents.push(parent2); parents.push(parent2);
parents.push(new ParentObject()); parents.push(new ParentObject());
return Parse.Object.saveAll(parents).then(() => { return Parse.Object.saveAll(parents).then(() => {
var query1 = new Parse.Query(ParentObject); var query1 = new Parse.Query(ParentObject);
query1.containedIn("toChilds", [childObjects[2]]); query1.containedIn("toChilds", [childObjects[2]]);
var query2 = new Parse.Query(ParentObject); var query2 = new Parse.Query(ParentObject);
query2.equalTo("toChild", childObjects[2]); query2.equalTo("toChild", childObjects[2]);
var query = Parse.Query.or(query1, query2); var query = Parse.Query.or(query1, query2);
return query.find().then((list) => { return query.find().then((list) => {
var objectIds = list.map(function(item){ var objectIds = list.map(function(item){
return item.id; return item.id;
});
expect(objectIds.indexOf(parent.id)).not.toBe(-1);
expect(objectIds.indexOf(parent2.id)).not.toBe(-1);
equal(list.length, 2, "There should be 2 results");
done();
}); });
expect(objectIds.indexOf(parent.id)).not.toBe(-1);
expect(objectIds.indexOf(parent2.id)).not.toBe(-1);
equal(list.length, 2, "There should be 2 results");
done();
}); });
});
}); });
}); });
@@ -552,11 +552,11 @@ describe('Parse.Relation testing', () => {
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(5); expect(results.length).toBe(5);
results.forEach((result) => { results.forEach((result) => {
expect(result.get('key').get('even')).toBe(true); expect(result.get('key').get('even')).toBe(true);
}); });
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
// Query on the relation of another owner // Query on the relation of another owner
let object = new Parse.Object('AnotherOwner'); let object = new Parse.Object('AnotherOwner');
object.id = anotherOwner.id; object.id = anotherOwner.id;
@@ -571,7 +571,7 @@ describe('Parse.Relation testing', () => {
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(5); expect(results.length).toBe(5);
results.forEach((result) => { results.forEach((result) => {
expect(result.get('key').get('even')).toBe(false); expect(result.get('key').get('even')).toBe(false);
}); });
done(); done();
@@ -592,11 +592,9 @@ describe('Parse.Relation testing', () => {
new PersonObject({ name: "Billy", hometown: "Detroit" }), new PersonObject({ name: "Billy", hometown: "Detroit" }),
]; ];
let owner = new OwnerObject({name: 'Joe'}); let owner = new OwnerObject({name: 'Joe'});
let ownerId;
let allObjects = [owner].concat(restaurants).concat(persons); let allObjects = [owner].concat(restaurants).concat(persons);
expect(allObjects.length).toEqual(6); expect(allObjects.length).toEqual(6);
Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() { Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() {
ownerId = owner.id;
owner.relation('restaurants').add(restaurants); owner.relation('restaurants').add(restaurants);
return owner.save() return owner.save()
}).then(() => { }).then(() => {
@@ -632,11 +630,9 @@ describe('Parse.Relation testing', () => {
new PersonObject({ name: "Billy", hometown: "Detroit" }), new PersonObject({ name: "Billy", hometown: "Detroit" }),
]; ];
let owner = new OwnerObject({name: 'Joe'}); let owner = new OwnerObject({name: 'Joe'});
let ownerId;
let allObjects = [owner].concat(restaurants).concat(persons); let allObjects = [owner].concat(restaurants).concat(persons);
expect(allObjects.length).toEqual(6); expect(allObjects.length).toEqual(6);
Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() { Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() {
ownerId = owner.id;
owner.relation('restaurants').add(restaurants); owner.relation('restaurants').add(restaurants);
return owner.save() return owner.save()
}).then(() => { }).then(() => {
@@ -705,7 +701,7 @@ describe('Parse.Relation testing', () => {
fail('Should have found admin user, found nothing instead'); fail('Should have found admin user, found nothing instead');
done(); done();
} }
}, error => { }, () => {
fail('User not admin'); fail('User not admin');
done(); done();
}) })

View File

@@ -22,7 +22,7 @@ describe('Parse Role testing', () => {
var users = role.relation('users'); var users = role.relation('users');
users.add(user); users.add(user);
return role.save({}, { useMasterKey: true }); return role.save({}, { useMasterKey: true });
}).then((x) => { }).then(() => {
var query = new Parse.Query('_Role'); var query = new Parse.Query('_Role');
return query.find({ useMasterKey: true }); return query.find({ useMasterKey: true });
}).then((x) => { }).then((x) => {
@@ -42,7 +42,7 @@ describe('Parse Role testing', () => {
acl.setRoleWriteAccess('Foos', true); acl.setRoleWriteAccess('Foos', true);
obj.setACL(acl); obj.setACL(acl);
return obj.save(); return obj.save();
}).then((x) => { }).then(() => {
var query = new Parse.Query('TestObject'); var query = new Parse.Query('TestObject');
return query.find({ sessionToken: user.getSessionToken() }); return query.find({ sessionToken: user.getSessionToken() });
}).then((x) => { }).then((x) => {
@@ -55,7 +55,7 @@ describe('Parse Role testing', () => {
x.set('foo', 'baz'); x.set('foo', 'baz');
// This should fail: // This should fail:
return x.save({},{sessionToken: ""}); return x.save({},{sessionToken: ""});
}).then((x) => { }).then(() => {
fail('Should not have been able to save.'); fail('Should not have been able to save.');
}, (e) => { }, (e) => {
expect(e.code).toEqual(Parse.Error.OBJECT_NOT_FOUND); expect(e.code).toEqual(Parse.Error.OBJECT_NOT_FOUND);
@@ -135,7 +135,7 @@ describe('Parse Role testing', () => {
// 1 call for the 2nd layer // 1 call for the 2nd layer
expect(getAllRolesSpy.calls.count()).toEqual(2); expect(getAllRolesSpy.calls.count()).toEqual(2);
done() done()
}).catch( (err) => { }).catch( () => {
fail("should succeed"); fail("should succeed");
done(); done();
}); });
@@ -145,45 +145,45 @@ describe('Parse Role testing', () => {
it("should recursively load roles", (done) => { it("should recursively load roles", (done) => {
var rolesNames = ["FooRole", "BarRole", "BazRole"]; var rolesNames = ["FooRole", "BarRole", "BazRole"];
var roleIds = {}; var roleIds = {};
createTestUser().then( (user) => { createTestUser().then( (user) => {
// Put the user on the 1st role // Put the user on the 1st role
return createRole(rolesNames[0], null, user).then( (aRole) => { return createRole(rolesNames[0], null, user).then( (aRole) => {
roleIds[aRole.get("name")] = aRole.id; roleIds[aRole.get("name")] = aRole.id;
// set the 1st role as a sibling of the second // set the 1st role as a sibling of the second
// user will should have 2 role now // user will should have 2 role now
return createRole(rolesNames[1], aRole, null); return createRole(rolesNames[1], aRole, null);
}).then( (anotherRole) => { }).then( (anotherRole) => {
roleIds[anotherRole.get("name")] = anotherRole.id; roleIds[anotherRole.get("name")] = anotherRole.id;
// set this role as a sibling of the last // set this role as a sibling of the last
// the user should now have 3 roles // the user should now have 3 roles
return createRole(rolesNames[2], anotherRole, null); return createRole(rolesNames[2], anotherRole, null);
}).then( (lastRole) => { }).then( (lastRole) => {
roleIds[lastRole.get("name")] = lastRole.id; roleIds[lastRole.get("name")] = lastRole.id;
var auth = new Auth({ config: new Config("test"), isMaster: true, user: user }); var auth = new Auth({ config: new Config("test"), isMaster: true, user: user });
return auth._loadRoles(); return auth._loadRoles();
}) })
}).then( (roles) => { }).then( (roles) => {
expect(roles.length).toEqual(3); expect(roles.length).toEqual(3);
rolesNames.forEach( (name) => { rolesNames.forEach( (name) => {
expect(roles.indexOf('role:'+name)).not.toBe(-1); expect(roles.indexOf('role:'+name)).not.toBe(-1);
}); });
done(); done();
}, function(err){ }, function(){
fail("should succeed") fail("should succeed")
done(); done();
}); });
}); });
it("_Role object should not save without name.", (done) => { it("_Role object should not save without name.", (done) => {
var role = new Parse.Role(); var role = new Parse.Role();
role.save(null,{useMasterKey:true}) role.save(null,{useMasterKey:true})
.then((r) => { .then(() => {
fail("_Role object should not save without name."); fail("_Role object should not save without name.");
}, (error) => { }, (error) => {
expect(error.code).toEqual(111); expect(error.code).toEqual(111);
role.set('name','testRole'); role.set('name','testRole');
role.save(null,{useMasterKey:true}) role.save(null,{useMasterKey:true})
.then((r2)=>{ .then(()=>{
fail("_Role object should not save without ACL."); fail("_Role object should not save without ACL.");
}, (error2) =>{ }, (error2) =>{
expect(error2.code).toEqual(111); expect(error2.code).toEqual(111);
@@ -192,23 +192,23 @@ describe('Parse Role testing', () => {
}); });
}); });
it("Should properly resolve roles", (done) => { it("Should properly resolve roles", (done) => {
let admin = new Parse.Role("Admin", new Parse.ACL()); let admin = new Parse.Role("Admin", new Parse.ACL());
let moderator = new Parse.Role("Moderator", new Parse.ACL()); let moderator = new Parse.Role("Moderator", new Parse.ACL());
let superModerator = new Parse.Role("SuperModerator", new Parse.ACL()); let superModerator = new Parse.Role("SuperModerator", new Parse.ACL());
let contentManager = new Parse.Role('ContentManager', new Parse.ACL()); let contentManager = new Parse.Role('ContentManager', new Parse.ACL());
let superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL()); let superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL());
Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}).then(() => { Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}).then(() => {
contentManager.getRoles().add([moderator, superContentManager]); contentManager.getRoles().add([moderator, superContentManager]);
moderator.getRoles().add([admin, superModerator]); moderator.getRoles().add([admin, superModerator]);
superContentManager.getRoles().add(superModerator); superContentManager.getRoles().add(superModerator);
return Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}); return Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true});
}).then(() => { }).then(() => {
var auth = new Auth({ config: new Config("test"), isMaster: true }); var auth = new Auth({ config: new Config("test"), isMaster: true });
// For each role, fetch their sibling, what they inherit // For each role, fetch their sibling, what they inherit
// return with result and roleId for later comparison // return with result and roleId for later comparison
let promises = [admin, moderator, contentManager, superModerator].map((role) => { let promises = [admin, moderator, contentManager, superModerator].map((role) => {
return auth._getAllRolesNamesForRoleIds([role.id]).then((result) => { return auth._getAllRolesNamesForRoleIds([role.id]).then((result) => {
return Parse.Promise.as({ return Parse.Promise.as({
id: role.id, id: role.id,
name: role.get('name'), name: role.get('name'),
@@ -239,7 +239,7 @@ describe('Parse Role testing', () => {
} }
}); });
done(); done();
}).fail((err) => { }).fail(() => {
done(); done();
}) })
@@ -250,16 +250,16 @@ describe('Parse Role testing', () => {
roleACL.setPublicReadAccess(true); roleACL.setPublicReadAccess(true);
var role = new Parse.Role('subscribers', roleACL); var role = new Parse.Role('subscribers', roleACL);
role.save({}, {useMasterKey : true}) role.save({}, {useMasterKey : true})
.then((x)=>{ .then(()=>{
var query = role.relation('users').query(); var query = role.relation('users').query();
query.find({useMasterKey : true}) query.find({useMasterKey : true})
.then((users)=>{ .then(()=>{
done(); done();
}, (e)=>{ }, ()=>{
fail('should not have errors'); fail('should not have errors');
done(); done();
}); });
}, (e) => { }, () => {
fail('should not have errored'); fail('should not have errored');
}); });
}); });
@@ -278,10 +278,10 @@ describe('Parse Role testing', () => {
user = x; user = x;
user2 = new Parse.User(); user2 = new Parse.User();
return user2.save({ username: 'user2', password: 'omgbbq' }); return user2.save({ username: 'user2', password: 'omgbbq' });
}).then((x) => { }).then(() => {
user3 = new Parse.User(); user3 = new Parse.User();
return user3.save({ username: 'user3', password: 'omgbbq' }); return user3.save({ username: 'user3', password: 'omgbbq' });
}).then((x) => { }).then(() => {
role = new Parse.Role('Admin', prACL); role = new Parse.Role('Admin', prACL);
role.getUsers().add(user); role.getUsers().add(user);
return role.save({}, { useMasterKey: true }); return role.save({}, { useMasterKey: true });
@@ -327,7 +327,7 @@ describe('Parse Role testing', () => {
obj2 = new Parse.Object('TestObjectRoles'); obj2 = new Parse.Object('TestObjectRoles');
obj2.set('ACL', adminACL); obj2.set('ACL', adminACL);
return obj2.save(null, { useMasterKey: true }); return obj2.save(null, { useMasterKey: true });
}, (e) => { }, () => {
fail('Admin user should have been able to save.'); fail('Admin user should have been able to save.');
done(); done();
}).then(() => { }).then(() => {

View File

@@ -2,34 +2,34 @@ const ParseServerRESTController = require('../src/ParseServerRESTController').Pa
const ParseServer = require('../src/ParseServer').default; const ParseServer = require('../src/ParseServer').default;
let RESTController; let RESTController;
describe('ParseServerRESTController', () => { describe('ParseServerRESTController', () => {
beforeEach(() => { beforeEach(() => {
RESTController = ParseServerRESTController(Parse.applicationId, ParseServer.promiseRouter({appId: Parse.applicationId})); RESTController = ParseServerRESTController(Parse.applicationId, ParseServer.promiseRouter({appId: Parse.applicationId}));
}) })
it('should handle a get request', (done) => { it('should handle a get request', (done) => {
RESTController.request("GET", "/classes/MyObject").then((res) => { RESTController.request("GET", "/classes/MyObject").then((res) => {
expect(res.results.length).toBe(0); expect(res.results.length).toBe(0);
done(); done();
}, (err) => { }, (err) => {
console.log(err); console.log(err);
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should handle a get request with full serverURL mount path', (done) => { it('should handle a get request with full serverURL mount path', (done) => {
RESTController.request("GET", "/1/classes/MyObject").then((res) => { RESTController.request("GET", "/1/classes/MyObject").then((res) => {
expect(res.results.length).toBe(0); expect(res.results.length).toBe(0);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should handle a POST batch', (done) => { it('should handle a POST batch', (done) => {
RESTController.request("POST", "batch", { RESTController.request("POST", "batch", {
requests: [ requests: [
{ {
@@ -46,72 +46,71 @@ describe('ParseServerRESTController', () => {
path: '/classes/MyObject' path: '/classes/MyObject'
} }
] ]
}).then((res) => { }).then((res) => {
expect(res.length).toBe(3); expect(res.length).toBe(3);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should handle a POST request', (done) => { it('should handle a POST request', (done) => {
RESTController.request("POST", "/classes/MyObject", {"key": "value"}).then((res) => { RESTController.request("POST", "/classes/MyObject", {"key": "value"}).then(() => {
return RESTController.request("GET", "/classes/MyObject"); return RESTController.request("GET", "/classes/MyObject");
}).then((res) => { }).then((res) => {
expect(res.results.length).toBe(1); expect(res.results.length).toBe(1);
expect(res.results[0].key).toEqual("value"); expect(res.results[0].key).toEqual("value");
done(); done();
}).fail((err) => { }).fail((err) => {
console.log(err); console.log(err);
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('ensures sessionTokens are properly handled', (done) => { it('ensures sessionTokens are properly handled', (done) => {
let userId; let userId;
Parse.User.signUp('user', 'pass').then((user) => { Parse.User.signUp('user', 'pass').then((user) => {
userId = user.id; userId = user.id;
let sessionToken = user.getSessionToken(); let sessionToken = user.getSessionToken();
return RESTController.request("GET", "/users/me", undefined, {sessionToken}); return RESTController.request("GET", "/users/me", undefined, {sessionToken});
}).then((res) => { }).then((res) => {
// Result is in JSON format // Result is in JSON format
expect(res.objectId).toEqual(userId); expect(res.objectId).toEqual(userId);
done(); done();
}).fail((err) => { }).fail((err) => {
console.log(err); console.log(err);
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('ensures masterKey is properly handled', (done) => { it('ensures masterKey is properly handled', (done) => {
let userId; let userId;
Parse.User.signUp('user', 'pass').then((user) => { Parse.User.signUp('user', 'pass').then((user) => {
userId = user.id; userId = user.id;
let sessionToken = user.getSessionToken(); return Parse.User.logOut().then(() => {
return Parse.User.logOut().then(() => {
return RESTController.request("GET", "/classes/_User", undefined, {useMasterKey: true}); return RESTController.request("GET", "/classes/_User", undefined, {useMasterKey: true});
}); });
}).then((res) => { }).then((res) => {
expect(res.results.length).toBe(1); expect(res.results.length).toBe(1);
expect(res.results[0].objectId).toEqual(userId); expect(res.results[0].objectId).toEqual(userId);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('ensures no session token is created on creating users', (done) => { it('ensures no session token is created on creating users', (done) => {
RESTController.request("POST", "/classes/_User", {username: "hello", password: "world"}).then(() => { RESTController.request("POST", "/classes/_User", {username: "hello", password: "world"}).then(() => {
let query = new Parse.Query('_Session'); let query = new Parse.Query('_Session');
return query.find({useMasterKey: true}); return query.find({useMasterKey: true});
}).then(sessions => { }).then(sessions => {
expect(sessions.length).toBe(0); expect(sessions.length).toBe(0);
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });

View File

@@ -53,7 +53,7 @@ describe('Parse.User testing', () => {
it("user login wrong username", (done) => { it("user login wrong username", (done) => {
Parse.User.signUp("asdf", "zxcv", null, { Parse.User.signUp("asdf", "zxcv", null, {
success: function(user) { success: function() {
Parse.User.logIn("non_existent_user", "asdf3", Parse.User.logIn("non_existent_user", "asdf3",
expectError(Parse.Error.OBJECT_NOT_FOUND, done)); expectError(Parse.Error.OBJECT_NOT_FOUND, done));
}, },
@@ -67,7 +67,7 @@ describe('Parse.User testing', () => {
it("user login wrong password", (done) => { it("user login wrong password", (done) => {
Parse.User.signUp("asdf", "zxcv", null, { Parse.User.signUp("asdf", "zxcv", null, {
success: function(user) { success: function() {
Parse.User.logIn("asdf", "asdfWrong", Parse.User.logIn("asdf", "asdfWrong",
expectError(Parse.Error.OBJECT_NOT_FOUND, done)); expectError(Parse.Error.OBJECT_NOT_FOUND, done));
} }
@@ -128,7 +128,7 @@ describe('Parse.User testing', () => {
it("user login", (done) => { it("user login", (done) => {
Parse.User.signUp("asdf", "zxcv", null, { Parse.User.signUp("asdf", "zxcv", null, {
success: function(user) { success: function() {
Parse.User.logIn("asdf", "zxcv", { Parse.User.logIn("asdf", "zxcv", {
success: function(user) { success: function(user) {
equal(user.get("username"), "asdf"); equal(user.get("username"), "asdf");
@@ -148,7 +148,7 @@ describe('Parse.User testing', () => {
user.setUsername('asdf'); user.setUsername('asdf');
user.setPassword('zxcv'); user.setPassword('zxcv');
user.setACL(ACL); user.setACL(ACL);
user.signUp().then((user) => { user.signUp().then(() => {
return Parse.User.logIn("asdf", "zxcv"); return Parse.User.logIn("asdf", "zxcv");
}).then((user) => { }).then((user) => {
equal(user.get("username"), "asdf"); equal(user.get("username"), "asdf");
@@ -168,7 +168,7 @@ describe('Parse.User testing', () => {
newACL.setWriteAccess(user.id, false); newACL.setWriteAccess(user.id, false);
user.setACL(newACL); user.setACL(newACL);
return user.save(); return user.save();
}).then((user) => { }).then(() => {
return Parse.User.logIn("asdf", "zxcv"); return Parse.User.logIn("asdf", "zxcv");
}).then((user) => { }).then((user) => {
equal(user.get("username"), "asdf"); equal(user.get("username"), "asdf");
@@ -183,7 +183,7 @@ describe('Parse.User testing', () => {
expect(perms[user.id].write).toBe(true); expect(perms[user.id].write).toBe(true);
expect(perms['*']).toBeUndefined(); expect(perms['*']).toBeUndefined();
done(); done();
}).catch((err) => { }).catch(() => {
fail("Should not fail"); fail("Should not fail");
done(); done();
}) })
@@ -200,7 +200,7 @@ describe('Parse.User testing', () => {
ok(fileAgain.name()); ok(fileAgain.name());
ok(fileAgain.url()); ok(fileAgain.url());
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -374,7 +374,7 @@ describe('Parse.User testing', () => {
object.save({ object.save({
user: userNotAuthedNotChanged user: userNotAuthedNotChanged
}, { }, {
success: function(object) { success: function() {
var item1 = new TestObject(); var item1 = new TestObject();
item1.save({ item1.save({
number: 0 number: 0
@@ -571,7 +571,7 @@ describe('Parse.User testing', () => {
}); });
// Save all the messages. // Save all the messages.
Parse.Object.saveAll(messageList, function(messages) { Parse.Object.saveAll(messageList, function() {
// Assemble an "in" list. // Assemble an "in" list.
var inList = [users[0], users[3], users[3]]; // Intentional dupe var inList = [users[0], users[3], users[3]]; // Intentional dupe
@@ -756,7 +756,7 @@ describe('Parse.User testing', () => {
return Parse.User.logOut(); return Parse.User.logOut();
}).then(() => { }).then(() => {
return Parse.User.logIn("alice", "password"); return Parse.User.logIn("alice", "password");
}).then((user) => { }).then(() => {
// Force the current user to read from disk // Force the current user to read from disk
delete Parse.User._currentUser; delete Parse.User._currentUser;
delete Parse.User._currentUserMatchesDisk; delete Parse.User._currentUserMatchesDisk;
@@ -772,7 +772,6 @@ describe('Parse.User testing', () => {
}); });
it("saving user after browser refresh", (done) => { it("saving user after browser refresh", (done) => {
var _ = Parse._;
var id; var id;
Parse.User.signUp("alice", "password", null).then(function(alice) { Parse.User.signUp("alice", "password", null).then(function(alice) {
@@ -920,12 +919,11 @@ describe('Parse.User testing', () => {
}); });
it("user on disk gets updated after save", (done) => { it("user on disk gets updated after save", (done) => {
var SuperUser = Parse.User.extend({ Parse.User.extend({
isSuper: function() { isSuper: function() {
return true; return true;
} }
}); });
Parse.User.signUp("bob", "welcome", null, { Parse.User.signUp("bob", "welcome", null, {
success: function(user) { success: function(user) {
// Modify the user and save. // Modify the user and save.
@@ -1061,7 +1059,7 @@ describe('Parse.User testing', () => {
}; };
}; };
var ExtendedUser = Parse.User.extend({ Parse.User.extend({
extended: function() { extended: function() {
return true; return true;
} }
@@ -1122,17 +1120,17 @@ describe('Parse.User testing', () => {
it("log in with provider and update token", (done) => { it("log in with provider and update token", (done) => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
var secondProvider = getMockFacebookProviderWithIdToken('8675309', 'jenny_valid_token'); var secondProvider = getMockFacebookProviderWithIdToken('8675309', 'jenny_valid_token');
var errorHandler = function(err) { var errorHandler = function() {
fail('should not fail'); fail('should not fail');
done(); done();
} }
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: (model) => { success: () => {
Parse.User._registerAuthenticationProvider(secondProvider); Parse.User._registerAuthenticationProvider(secondProvider);
return Parse.User.logOut().then(() => { return Parse.User.logOut().then(() => {
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: (model) => { success: () => {
expect(secondProvider.synchronizedAuthToken).toEqual('jenny_valid_token'); expect(secondProvider.synchronizedAuthToken).toEqual('jenny_valid_token');
// Make sure we can login with the new token again // Make sure we can login with the new token again
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
@@ -1243,7 +1241,7 @@ describe('Parse.User testing', () => {
provider.shouldError = true; provider.shouldError = true;
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function() {
ok(false, "logIn should not have succeeded"); ok(false, "logIn should not have succeeded");
}, },
error: function(model, error) { error: function(model, error) {
@@ -1258,7 +1256,7 @@ describe('Parse.User testing', () => {
provider.shouldCancel = true; provider.shouldCancel = true;
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function() {
ok(false, "logIn should not have succeeded"); ok(false, "logIn should not have succeeded");
}, },
error: function(model, error) { error: function(model, error) {
@@ -1272,7 +1270,7 @@ describe('Parse.User testing', () => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function() {
Parse.User.logOut(); Parse.User.logOut();
Parse.Cloud.beforeSave(Parse.User, function(req, res) { Parse.Cloud.beforeSave(Parse.User, function(req, res) {
@@ -1280,7 +1278,7 @@ describe('Parse.User testing', () => {
}); });
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(innerModel) { success: function() {
done(); done();
}, },
error: function(model, error) { error: function(model, error) {
@@ -1299,7 +1297,7 @@ describe('Parse.User testing', () => {
user.set("username", "testLinkWithProvider"); user.set("username", "testLinkWithProvider");
user.set("password", "mypass"); user.set("password", "mypass");
user.signUp(null, { user.signUp(null, {
success: function(model) { success: function() {
user._linkWith("facebook", { user._linkWith("facebook", {
success: function(model) { success: function(model) {
ok(model instanceof Parse.User, "Model should be a Parse.User"); ok(model instanceof Parse.User, "Model should be a Parse.User");
@@ -1310,13 +1308,13 @@ describe('Parse.User testing', () => {
ok(model._isLinked("facebook"), "User should be linked"); ok(model._isLinked("facebook"), "User should be linked");
done(); done();
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have succeeded"); ok(false, "linking should have succeeded");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "signup should not have failed"); ok(false, "signup should not have failed");
done(); done();
} }
@@ -1332,7 +1330,7 @@ describe('Parse.User testing', () => {
user.set("username", "testLinkWithProviderToAlreadyLinkedUser"); user.set("username", "testLinkWithProviderToAlreadyLinkedUser");
user.set("password", "mypass"); user.set("password", "mypass");
user.signUp(null, { user.signUp(null, {
success: function(model) { success: function() {
user._linkWith("facebook", { user._linkWith("facebook", {
success: function(model) { success: function(model) {
ok(model instanceof Parse.User, "Model should be a Parse.User"); ok(model instanceof Parse.User, "Model should be a Parse.User");
@@ -1345,9 +1343,9 @@ describe('Parse.User testing', () => {
user2.set("username", "testLinkWithProviderToAlreadyLinkedUser2"); user2.set("username", "testLinkWithProviderToAlreadyLinkedUser2");
user2.set("password", "mypass"); user2.set("password", "mypass");
user2.signUp(null, { user2.signUp(null, {
success: function(model) { success: function() {
user2._linkWith('facebook', { user2._linkWith('facebook', {
success: (err) => { success: (err) => {
jfail(err); jfail(err);
done(); done();
}, },
@@ -1358,19 +1356,19 @@ describe('Parse.User testing', () => {
}, },
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have failed"); ok(false, "linking should have failed");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have succeeded"); ok(false, "linking should have succeeded");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "signup should not have failed"); ok(false, "signup should not have failed");
done(); done();
} }
@@ -1385,9 +1383,9 @@ describe('Parse.User testing', () => {
user.set("username", "testLinkWithProvider"); user.set("username", "testLinkWithProvider");
user.set("password", "mypass"); user.set("password", "mypass");
user.signUp(null, { user.signUp(null, {
success: function(model) { success: function() {
user._linkWith("facebook", { user._linkWith("facebook", {
success: function(model) { success: function() {
ok(false, "linking should fail"); ok(false, "linking should fail");
done(); done();
}, },
@@ -1399,7 +1397,7 @@ describe('Parse.User testing', () => {
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "signup should not have failed"); ok(false, "signup should not have failed");
done(); done();
} }
@@ -1414,9 +1412,9 @@ describe('Parse.User testing', () => {
user.set("username", "testLinkWithProvider"); user.set("username", "testLinkWithProvider");
user.set("password", "mypass"); user.set("password", "mypass");
user.signUp(null, { user.signUp(null, {
success: function(model) { success: function() {
user._linkWith("facebook", { user._linkWith("facebook", {
success: function(model) { success: function() {
ok(false, "linking should fail"); ok(false, "linking should fail");
done(); done();
}, },
@@ -1428,7 +1426,7 @@ describe('Parse.User testing', () => {
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "signup should not have failed"); ok(false, "signup should not have failed");
done(); done();
} }
@@ -1458,13 +1456,13 @@ describe('Parse.User testing', () => {
"Expiration should be cleared."); "Expiration should be cleared.");
done(); done();
}, },
error: function(model, error) { error: function() {
ok(false, "unlinking should succeed"); ok(false, "unlinking should succeed");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have worked"); ok(false, "linking should have worked");
done(); done();
} }
@@ -1504,19 +1502,19 @@ describe('Parse.User testing', () => {
"User should be linked to facebook"); "User should be linked to facebook");
done(); done();
}, },
error: function(model, error) { error: function() {
ok(false, "linking again should succeed"); ok(false, "linking again should succeed");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "unlinking should succeed"); ok(false, "unlinking should succeed");
done(); done();
} }
}); });
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have worked"); ok(false, "linking should have worked");
done(); done();
} }
@@ -1552,7 +1550,7 @@ describe('Parse.User testing', () => {
} }
}) })
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have worked"); ok(false, "linking should have worked");
done(); done();
} }
@@ -1575,14 +1573,14 @@ describe('Parse.User testing', () => {
Parse.User._registerAuthenticationProvider(mockProvider); Parse.User._registerAuthenticationProvider(mockProvider);
let objectId = model.id; let objectId = model.id;
model._linkWith("myoauth", { model._linkWith("myoauth", {
success: function(model) { success: function() {
Parse.User._registerAuthenticationProvider(secondProvider); Parse.User._registerAuthenticationProvider(secondProvider);
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
return Parse.User._logInWith("facebook", { return Parse.User._logInWith("facebook", {
success: () => { success: () => {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
return Parse.User._logInWith("myoauth", { return Parse.User._logInWith("myoauth", {
success: (user) => { success: (user) => {
expect(user.id).toBe(objectId); expect(user.id).toBe(objectId);
done(); done();
} }
@@ -1639,30 +1637,30 @@ describe('Parse.User testing', () => {
} }
}) })
}, },
error: function(model, error) { error: function() {
ok(false, "linking should have worked"); ok(false, "linking should have worked");
done(); done();
} }
}); });
}); });
it('should fail linking with existing', (done) => { it('should fail linking with existing', (done) => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function() {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
let user = new Parse.User(); let user = new Parse.User();
user.setUsername('user'); user.setUsername('user');
user.setPassword('password'); user.setPassword('password');
return user.signUp().then(() => { return user.signUp().then(() => {
// try to link here // try to link here
user._linkWith('facebook', { user._linkWith('facebook', {
success: () => { success: () => {
fail('should not succeed'); fail('should not succeed');
done(); done();
}, },
error: (err) => { error: () => {
done(); done();
} }
}); });
@@ -1672,20 +1670,20 @@ describe('Parse.User testing', () => {
}); });
}); });
it('should fail linking with existing', (done) => { it('should fail linking with existing', (done) => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function(model) {
let userId = model.id; let userId = model.id;
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
request.post({ request.post({
url:Parse.serverURL+'/classes/_User', url:Parse.serverURL+'/classes/_User',
headers: { headers: {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest' 'X-Parse-REST-API-Key': 'rest'
}, },
json: {authData: {facebook: provider.authData}} json: {authData: {facebook: provider.authData}}
}, (err,res, body) => { }, (err,res, body) => {
// make sure the location header is properly set // make sure the location header is properly set
expect(userId).not.toBeUndefined(); expect(userId).not.toBeUndefined();
@@ -1698,7 +1696,7 @@ describe('Parse.User testing', () => {
}); });
}); });
it('should properly error when password is missing', (done) => { it('should properly error when password is missing', (done) => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
@@ -1709,7 +1707,7 @@ describe('Parse.User testing', () => {
return Parse.User.logOut(); return Parse.User.logOut();
}).then(() => { }).then(() => {
return Parse.User.logIn('myUser', 'password'); return Parse.User.logIn('myUser', 'password');
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
done(); done();
}, (err) => { }, (err) => {
@@ -1721,9 +1719,9 @@ describe('Parse.User testing', () => {
}); });
}); });
it('should have authData in beforeSave and afterSave', (done) => { it('should have authData in beforeSave and afterSave', (done) => {
Parse.Cloud.beforeSave('_User', (request, response) => { Parse.Cloud.beforeSave('_User', (request, response) => {
let authData = request.object.get('authData'); let authData = request.object.get('authData');
expect(authData).not.toBeUndefined(); expect(authData).not.toBeUndefined();
if (authData) { if (authData) {
@@ -1735,7 +1733,7 @@ describe('Parse.User testing', () => {
response.success(); response.success();
}); });
Parse.Cloud.afterSave('_User', (request, response) => { Parse.Cloud.afterSave('_User', (request, response) => {
let authData = request.object.get('authData'); let authData = request.object.get('authData');
expect(authData).not.toBeUndefined(); expect(authData).not.toBeUndefined();
if (authData) { if (authData) {
@@ -1750,7 +1748,7 @@ describe('Parse.User testing', () => {
var provider = getMockFacebookProvider(); var provider = getMockFacebookProvider();
Parse.User._registerAuthenticationProvider(provider); Parse.User._registerAuthenticationProvider(provider);
Parse.User._logInWith("facebook", { Parse.User._logInWith("facebook", {
success: function(model) { success: function() {
done(); done();
} }
}); });
@@ -1777,7 +1775,7 @@ describe('Parse.User testing', () => {
user.set("password", "onetwothreefour"); user.set("password", "onetwothreefour");
ok(!user.authenticated()); ok(!user.authenticated());
user.signUp(null, expectSuccess({ user.signUp(null, expectSuccess({
success: function(result) { success: function() {
ok(user.authenticated()); ok(user.authenticated());
done(); done();
} }
@@ -1932,13 +1930,13 @@ describe('Parse.User testing', () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
var currentSessionToken = ""; var currentSessionToken = "";
Parse.Promise.as().then(function() { Parse.Promise.as().then(function() {
return user.signUp(); return user.signUp();
}).then(function(){ }).then(function(){
currentSessionToken = user.getSessionToken(); currentSessionToken = user.getSessionToken();
return user.fetch(); return user.fetch();
}).then(function(u){ }).then(function(u){
expect(currentSessionToken).toEqual(u.getSessionToken()); expect(currentSessionToken).toEqual(u.getSessionToken());
done(); done();
}, function(error) { }, function(error) {
ok(false, error); ok(false, error);
done(); done();
@@ -1973,7 +1971,7 @@ describe('Parse.User testing', () => {
}).then(() => { }).then(() => {
fail('Should not have been able to sign up.'); fail('Should not have been able to sign up.');
done(); done();
}, (error) => { }, () => {
done(); done();
}); });
}); });
@@ -1994,7 +1992,7 @@ describe('Parse.User testing', () => {
}).then(() => { }).then(() => {
fail('Should not have been able to sign up.'); fail('Should not have been able to sign up.');
done(); done();
}, (error) => { }, () => {
done(); done();
}); });
}); });
@@ -2066,7 +2064,7 @@ describe('Parse.User testing', () => {
it('user get session from token on login', (done) => { it('user get session from token on login', (done) => {
Parse.Promise.as().then(() => { Parse.Promise.as().then(() => {
return Parse.User.signUp("finn", "human", { foo: "bar" }); return Parse.User.signUp("finn", "human", { foo: "bar" });
}).then((user) => { }).then(() => {
return Parse.User.logOut().then(() => { return Parse.User.logOut().then(() => {
return Parse.User.logIn("finn", "human"); return Parse.User.logIn("finn", "human");
}) })
@@ -2114,7 +2112,7 @@ describe('Parse.User testing', () => {
body: JSON.stringify({ foo: 'bar' }) body: JSON.stringify({ foo: 'bar' })
}, (error, response, body) => { }, (error, response, body) => {
expect(error).toBe(null); expect(error).toBe(null);
var b = JSON.parse(body); JSON.parse(body);
done(); done();
}); });
}); });
@@ -2181,7 +2179,7 @@ describe('Parse.User testing', () => {
'X-Parse-REST-API-Key': 'rest' 'X-Parse-REST-API-Key': 'rest'
}, },
url: 'http://localhost:8378/1/sessions/' + objId url: 'http://localhost:8378/1/sessions/' + objId
}, (error, response, body) => { }, (error) => {
expect(error).toBe(null); expect(error).toBe(null);
request.get({ request.get({
headers: { headers: {
@@ -2207,7 +2205,7 @@ describe('Parse.User testing', () => {
.then((pass) => { .then((pass) => {
expect(pass).toBe(true); expect(pass).toBe(true);
done(); done();
}, (e) => { }, () => {
fail('Password format did not match.'); fail('Password format did not match.');
done(); done();
}); });
@@ -2226,7 +2224,7 @@ describe('Parse.User testing', () => {
return newUser.save(); return newUser.save();
}).then(function() { }).then(function() {
return Parse.User.become(sessionToken); return Parse.User.become(sessionToken);
}).then(function(newUser) { }).then(function() {
fail('Session should have been invalidated'); fail('Session should have been invalidated');
done(); done();
}, function(err) { }, function(err) {
@@ -2251,7 +2249,7 @@ describe('Parse.User testing', () => {
}).then(function(newUser) { }).then(function(newUser) {
equal(newUser.get('foo'), 2); equal(newUser.get('foo'), 2);
done(); done();
}, function(e) { }, function() {
fail('The session should still be valid'); fail('The session should still be valid');
done(); done();
}); });
@@ -2281,9 +2279,9 @@ describe('Parse.User testing', () => {
it('support user/password signup with empty authData block', (done) => { it('support user/password signup with empty authData block', (done) => {
// The android SDK can send an empty authData object along with username and password. // The android SDK can send an empty authData object along with username and password.
Parse.User.signUp('artof', 'thedeal', { authData: {} }).then((user) => { Parse.User.signUp('artof', 'thedeal', { authData: {} }).then(() => {
done(); done();
}, (error) => { }, () => {
fail('Signup should have succeeded.'); fail('Signup should have succeeded.');
done(); done();
}); });
@@ -2291,7 +2289,7 @@ describe('Parse.User testing', () => {
it("session expiresAt correct format", (done) => { it("session expiresAt correct format", (done) => {
Parse.User.signUp("asdf", "zxcv", null, { Parse.User.signUp("asdf", "zxcv", null, {
success: function(user) { success: function() {
request.get({ request.get({
url: 'http://localhost:8378/1/classes/_Session', url: 'http://localhost:8378/1/classes/_Session',
json: true, json: true,
@@ -2309,7 +2307,7 @@ describe('Parse.User testing', () => {
it("invalid session tokens are rejected", (done) => { it("invalid session tokens are rejected", (done) => {
Parse.User.signUp("asdf", "zxcv", null, { Parse.User.signUp("asdf", "zxcv", null, {
success: function(user) { success: function() {
request.get({ request.get({
url: 'http://localhost:8378/1/classes/AClass', url: 'http://localhost:8378/1/classes/AClass',
json: true, json: true,
@@ -2333,8 +2331,8 @@ describe('Parse.User testing', () => {
username: 'user', username: 'user',
_hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie', _hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie',
_auth_data_facebook: null _auth_data_facebook: null
}, {}).then(() => { }, {}).then(() => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
request.get({ request.get({
url: 'http://localhost:8378/1/login?username=user&password=test', url: 'http://localhost:8378/1/login?username=user&password=test',
headers: { headers: {
@@ -2355,7 +2353,7 @@ describe('Parse.User testing', () => {
expect(user.username).toEqual('user'); expect(user.username).toEqual('user');
expect(authData).toBeUndefined(); expect(authData).toBeUndefined();
done(); done();
}).catch((err) => { }).catch(() => {
fail('this should not fail'); fail('this should not fail');
done(); done();
}) })
@@ -2367,7 +2365,7 @@ describe('Parse.User testing', () => {
username: 'user', username: 'user',
_hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie', _hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie',
_auth_data_facebook: null _auth_data_facebook: null
}, {}).then(() => { }, {}).then(() => {
return new Parse.Query(Parse.User) return new Parse.Query(Parse.User)
.equalTo('username', 'user') .equalTo('username', 'user')
.first({useMasterKey: true}); .first({useMasterKey: true});
@@ -2376,7 +2374,7 @@ describe('Parse.User testing', () => {
expect(user.get('username')).toEqual('user'); expect(user.get('username')).toEqual('user');
expect(authData).toBeUndefined(); expect(authData).toBeUndefined();
done(); done();
}).catch((err) => { }).catch(() => {
fail('this should not fail'); fail('this should not fail');
done(); done();
}) })
@@ -2484,12 +2482,12 @@ describe('Parse.User testing', () => {
}) })
// Simulate anonymous user save // Simulate anonymous user save
return rp.post({ return rp.post({
url: 'http://localhost:8378/1/classes/_User', url: 'http://localhost:8378/1/classes/_User',
headers: { headers: {
'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest', 'X-Parse-REST-API-Key': 'rest',
}, },
json: {authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} json: {authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}}
}).then((user) => { }).then((user) => {
return rp.put({ return rp.put({
url: 'http://localhost:8378/1/classes/_User/' + user.objectId, url: 'http://localhost:8378/1/classes/_User/' + user.objectId,
@@ -2554,6 +2552,8 @@ describe('Parse.User testing', () => {
fail('no request should succeed: ' + JSON.stringify(res)); fail('no request should succeed: ' + JSON.stringify(res));
done(); done();
}).catch((err) => { }).catch((err) => {
expect(emailCalled).toBeTruthy();
expect(emailOptions).toBeDefined();
expect(err.statusCode).toBe(400); expect(err.statusCode).toBe(400);
expect(err.message).toMatch('{"code":125,"error":"you must provide a valid email string"}'); expect(err.message).toMatch('{"code":125,"error":"you must provide a valid email string"}');
done(); done();
@@ -2563,7 +2563,7 @@ describe('Parse.User testing', () => {
}); });
it('should aftersave with full object', (done) => { it('should aftersave with full object', (done) => {
var hit = 0; var hit = 0;
Parse.Cloud.afterSave('_User', (req, res) => { Parse.Cloud.afterSave('_User', (req, res) => {
hit++; hit++;
@@ -2577,6 +2577,7 @@ describe('Parse.User testing', () => {
user.set('hello', 'world'); user.set('hello', 'world');
return user.save(); return user.save();
}).then(() => { }).then(() => {
expect(hit).toBe(2);
done(); done();
}); });
}); });
@@ -2596,7 +2597,7 @@ describe('Parse.User testing', () => {
return Parse.Cloud.run('testUpdatedUser'); return Parse.Cloud.run('testUpdatedUser');
}).then(() => { }).then(() => {
done(); done();
}, (e) => { }, () => {
fail('Should not have failed.'); fail('Should not have failed.');
done(); done();
}); });
@@ -2606,7 +2607,7 @@ describe('Parse.User testing', () => {
it('should fail to become user with expired token', (done) => { it('should fail to become user with expired token', (done) => {
let token; let token;
Parse.User.signUp("auser", "somepass", null) Parse.User.signUp("auser", "somepass", null)
.then(user => rp({ .then(() => rp({
method: 'GET', method: 'GET',
url: 'http://localhost:8378/1/classes/_Session', url: 'http://localhost:8378/1/classes/_Session',
json: true, json: true,
@@ -2643,26 +2644,26 @@ describe('Parse.User testing', () => {
}) })
}); });
it('should not create extraneous session tokens', (done) => { it('should not create extraneous session tokens', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
config.database.loadSchema().then((s) => { config.database.loadSchema().then((s) => {
// Lock down the _User class for creation // Lock down the _User class for creation
return s.addClassIfNotExists('_User', {}, {create: {}}) return s.addClassIfNotExists('_User', {}, {create: {}})
}).then((res) => { }).then(() => {
let user = new Parse.User(); let user = new Parse.User();
return user.save({'username': 'user', 'password': 'pass'}); return user.save({'username': 'user', 'password': 'pass'});
}).then(() => { }).then(() => {
fail('should not be able to save the user'); fail('should not be able to save the user');
}, (err) => { }, () => {
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
let q = new Parse.Query('_Session'); let q = new Parse.Query('_Session');
return q.find({useMasterKey: true}) return q.find({useMasterKey: true})
}).then((res) => { }).then((res) => {
// We should have no session created // We should have no session created
expect(res.length).toBe(0); expect(res.length).toBe(0);
done(); done();
}, (err) => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}); });
@@ -2721,15 +2722,15 @@ describe('Parse.User testing', () => {
user.set('password', 'password'); user.set('password', 'password');
return user.save() return user.save()
}) })
.then(() => { .then(() => {
// Session token should have been recycled // Session token should have been recycled
expect(body.sessionToken).not.toEqual(user.getSessionToken()); expect(body.sessionToken).not.toEqual(user.getSessionToken());
}) })
.then(() => obj.fetch()) .then(() => obj.fetch())
.then((res) => { .then(() => {
done(); done();
}) })
.catch(error => { .catch(() => {
fail('should not fail') fail('should not fail')
done(); done();
}); });
@@ -2773,12 +2774,12 @@ describe('Parse.User testing', () => {
username: 'hello', username: 'hello',
password: 'world' password: 'world'
}) })
user.signUp().then(() => { user.signUp().then(() => {
return Parse.User.current().relation('relation').query().find(); return Parse.User.current().relation('relation').query().find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(0); expect(res.length).toBe(0);
done(); done();
}).catch((err) => { }).catch((err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}); });

View File

@@ -1,7 +1,6 @@
"use strict"; "use strict";
const requestp = require('request-promise'); const requestp = require('request-promise');
const Config = require('../src/Config');
describe("Password Policy: ", () => { describe("Password Policy: ", () => {
@@ -28,8 +27,8 @@ describe("Password Policy: ", () => {
user.setPassword("original"); user.setPassword("original");
user.set('email', 'user@parse.com'); user.set('email', 'user@parse.com');
return user.signUp(); return user.signUp();
}).then(user => { }).then(() => {
Parse.User.requestPasswordReset('user@parse.com').catch((err) => { Parse.User.requestPasswordReset("user@parse.com").catch((err) => {
jfail(err); jfail(err);
fail("Reset password request should not fail"); fail("Reset password request should not fail");
done(); done();
@@ -81,7 +80,7 @@ describe("Password Policy: ", () => {
user.setPassword("original"); user.setPassword("original");
user.set('email', 'user@parse.com'); user.set('email', 'user@parse.com');
return user.signUp(); return user.signUp();
}).then(user => { }).then(() => {
Parse.User.requestPasswordReset('user@parse.com').catch((err) => { Parse.User.requestPasswordReset('user@parse.com').catch((err) => {
jfail(err); jfail(err);
fail("Reset password request should not fail"); fail("Reset password request should not fail");
@@ -212,7 +211,7 @@ describe("Password Policy: ", () => {
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then(() => { user.signUp().then(() => {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
Parse.User.logIn("user1", "1digit").then(function (user) { Parse.User.logIn("user1", "1digit").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -237,7 +236,7 @@ describe("Password Policy: ", () => {
reconfigureServer({ reconfigureServer({
appName: 'passwordPolicy', appName: 'passwordPolicy',
passwordPolicy: { passwordPolicy: {
validatorCallback: password => false // just fail validatorCallback: () => false // just fail
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
@@ -259,7 +258,7 @@ describe("Password Policy: ", () => {
reconfigureServer({ reconfigureServer({
appName: 'passwordPolicy', appName: 'passwordPolicy',
passwordPolicy: { passwordPolicy: {
validatorCallback: password => true // never fail validatorCallback: () => true // never fail
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
@@ -268,7 +267,7 @@ describe("Password Policy: ", () => {
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then(() => { user.signUp().then(() => {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
Parse.User.logIn("user1", "oneUpper").then(function (user) { Parse.User.logIn("user1", "oneUpper").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -294,7 +293,7 @@ describe("Password Policy: ", () => {
appName: 'passwordPolicy', appName: 'passwordPolicy',
passwordPolicy: { passwordPolicy: {
validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter
validatorCallback: value => true validatorCallback: () => true
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
@@ -317,7 +316,7 @@ describe("Password Policy: ", () => {
appName: 'passwordPolicy', appName: 'passwordPolicy',
passwordPolicy: { passwordPolicy: {
validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter validatorPattern: /[A-Z]+/, // password should contain at least one UPPER case letter
validatorCallback: value => false validatorCallback: () => false
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
@@ -340,7 +339,7 @@ describe("Password Policy: ", () => {
appName: 'passwordPolicy', appName: 'passwordPolicy',
passwordPolicy: { passwordPolicy: {
validatorPattern: /[A-Z]+/, // password should contain at least one digit validatorPattern: /[A-Z]+/, // password should contain at least one digit
validatorCallback: value => true validatorCallback: () => true
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
@@ -349,7 +348,7 @@ describe("Password Policy: ", () => {
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then(() => { user.signUp().then(() => {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
Parse.User.logIn("user1", "oneUpper").then(function (user) { Parse.User.logIn("user1", "oneUpper").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -403,7 +402,7 @@ describe("Password Policy: ", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1');
Parse.User.logIn("user1", "has2init").then(function (user) { Parse.User.logIn("user1", "has2init").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -484,7 +483,7 @@ describe("Password Policy: ", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual(`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy`); expect(response.body).toEqual(`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy`);
Parse.User.logIn("user1", "has 1 digit").then(function (user) { Parse.User.logIn("user1", "has 1 digit").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -584,7 +583,7 @@ describe("Password Policy: ", () => {
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then(() => { user.signUp().then(() => {
done(); done();
}).catch((error) => { }).catch(() => {
fail('Should have succeeded as password does not contain username.'); fail('Should have succeeded as password does not contain username.');
done(); done();
}); });
@@ -605,7 +604,7 @@ describe("Password Policy: ", () => {
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then(() => { user.signUp().then(() => {
done(); done();
}).catch((error) => { }).catch(() => {
fail('Should have succeeded as policy allows username in password.'); fail('Should have succeeded as policy allows username in password.');
done(); done();
}); });
@@ -646,7 +645,7 @@ describe("Password Policy: ", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual(`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy`); expect(response.body).toEqual(`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy`);
Parse.User.logIn("user1", "r@nd0m").then(function (user) { Parse.User.logIn("user1", "r@nd0m").then(function () {
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
@@ -728,7 +727,7 @@ describe("Password Policy: ", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1');
Parse.User.logIn("user1", "uuser11").then(function (user) { Parse.User.logIn("user1", "uuser11").then(function () {
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);
@@ -819,8 +818,8 @@ describe("Password Policy: ", () => {
user.setUsername("user1"); user.setUsername("user1");
user.setPassword("user1"); user.setPassword("user1");
user.set('email', 'user1@parse.com'); user.set('email', 'user1@parse.com');
user.signUp().then((u) => { user.signUp().then(() => {
Parse.User.logIn("user1", "user1").then((user) => { Parse.User.logIn("user1", "user1").then(() => {
done(); done();
}).catch((error) => { }).catch((error) => {
jfail(error); jfail(error);
@@ -885,7 +884,7 @@ describe("Password Policy: ", () => {
}, },
publicServerURL: "http://localhost:8378/1" publicServerURL: "http://localhost:8378/1"
}).then(() => { }).then(() => {
Parse.User.logIn("user1", "user1").then((u) => { Parse.User.logIn("user1", "user1").then(() => {
Parse.User.logOut().then(() => { Parse.User.logOut().then(() => {
// wait for a bit more than the validity duration set // wait for a bit more than the validity duration set
setTimeout(() => { setTimeout(() => {
@@ -957,7 +956,7 @@ describe("Password Policy: ", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=user1');
Parse.User.logIn("user1", "uuser11").then(function (user) { Parse.User.logIn("user1", "uuser11").then(function () {
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);

View File

@@ -1,15 +1,13 @@
'use strict'; 'use strict';
var Schema = require('../src/Controllers/SchemaController');
var Config = require('../src/Config'); var Config = require('../src/Config');
describe('Pointer Permissions', () => { describe('Pointer Permissions', () => {
beforeEach(() => { beforeEach(() => {
new Config(Parse.applicationId).database.schemaCache.clear(); new Config(Parse.applicationId).database.schemaCache.clear();
}); });
it('should work with find', (done) => { it('should work with find', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User(); let user = new Parse.User();
let user2 = new Parse.User(); let user2 = new Parse.User();
@@ -28,27 +26,27 @@ describe('Pointer Permissions', () => {
obj.set('owner', user); obj.set('owner', user);
obj2.set('owner', user2); obj2.set('owner', user2);
return Parse.Object.saveAll([obj, obj2]); return Parse.Object.saveAll([obj, obj2]);
}).then(() => { }).then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
return schema.updateClass('AnObject', {}, {readUserFields: ['owner']}) return schema.updateClass('AnObject', {}, {readUserFields: ['owner']})
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user1', 'password'); return Parse.User.logIn('user1', 'password');
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find(); return q.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(1); expect(res.length).toBe(1);
expect(res[0].id).toBe(obj.id); expect(res[0].id).toBe(obj.id);
done(); done();
}).catch(error => { }).catch(error => {
fail(JSON.stringify(error)); fail(JSON.stringify(error));
done(); done();
}); });
}); });
it('should work with write', (done) => { it('should work with write', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User(); let user = new Parse.User();
let user2 = new Parse.User(); let user2 = new Parse.User();
@@ -69,16 +67,16 @@ describe('Pointer Permissions', () => {
obj2.set('owner', user2); obj2.set('owner', user2);
obj2.set('reader', user); obj2.set('reader', user);
return Parse.Object.saveAll([obj, obj2]); return Parse.Object.saveAll([obj, obj2]);
}).then(() => { }).then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
return schema.updateClass('AnObject', {}, {writeUserFields: ['owner'], readUserFields: ['reader', 'owner']}); return schema.updateClass('AnObject', {}, {writeUserFields: ['owner'], readUserFields: ['reader', 'owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user1', 'password'); return Parse.User.logIn('user1', 'password');
}).then(() => { }).then(() => {
obj2.set('hello', 'world'); obj2.set('hello', 'world');
return obj2.save(); return obj2.save();
}).then((res) => { }).then(() => {
fail('User should not be able to update obj2'); fail('User should not be able to update obj2');
}, (err) => { }, (err) => {
// User 1 should not be able to update obj2 // User 1 should not be able to update obj2
@@ -87,19 +85,19 @@ describe('Pointer Permissions', () => {
}).then(()=> { }).then(()=> {
obj.set('hello', 'world'); obj.set('hello', 'world');
return obj.save(); return obj.save();
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}, (err) => { }, () => {
fail('User should be able to update'); fail('User should be able to update');
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find(); return q.find();
}, (err) => { }, () => {
fail('should login with user 2'); fail('should login with user 2');
}).then((res) => { }).then((res) => {
expect(res.length).toBe(2); expect(res.length).toBe(2);
res.forEach((result) => { res.forEach((result) => {
if (result.id == obj.id) { if (result.id == obj.id) {
expect(result.get('hello')).toBe('world'); expect(result.get('hello')).toBe('world');
} else { } else {
@@ -107,7 +105,7 @@ describe('Pointer Permissions', () => {
} }
}) })
done(); done();
}, (err) =>  { }, () => {
fail("failed"); fail("failed");
done(); done();
}) })
@@ -129,32 +127,32 @@ describe('Pointer Permissions', () => {
let obj2 = new Parse.Object('AnObject'); let obj2 = new Parse.Object('AnObject');
user.signUp().then(() => { user.signUp().then(() => {
return user2.signUp() return user2.signUp()
}).then(() => { }).then(() => {
Parse.User.logOut(); Parse.User.logOut();
}).then(() => { }).then(() => {
obj.set('owner', user); obj.set('owner', user);
return Parse.Object.saveAll([obj, obj2]); return Parse.Object.saveAll([obj, obj2]);
}).then(() => { }).then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
return schema.updateClass('AnObject', {}, {find: {}, get:{}, readUserFields: ['owner']}) return schema.updateClass('AnObject', {}, {find: {}, get:{}, readUserFields: ['owner']})
}); });
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find(); return q.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(0); expect(res.length).toBe(0);
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find(); return q.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(0); expect(res.length).toBe(0);
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.get(obj.id); return q.get(obj.id);
}).then(() => { }).then(() => {
fail('User 2 should not get the obj1 object'); fail('User 2 should not get the obj1 object');
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
expect(err.message).toBe('Object not found.'); expect(err.message).toBe('Object not found.');
return Promise.resolve(); return Promise.resolve();
@@ -163,17 +161,17 @@ describe('Pointer Permissions', () => {
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find(); return q.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(1); expect(res.length).toBe(1);
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
fail('should not fail'); fail('should not fail');
done(); done();
}) })
}); });
it('should not allow creating objects', (done) => { it('should not allow creating objects', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User(); let user = new Parse.User();
user.set({ user.set({
@@ -181,25 +179,25 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
user.save().then(() => { user.save().then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
return schema.addClassIfNotExists('AnObject', {owner: {type:'Pointer', targetClass: '_User'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']}); return schema.addClassIfNotExists('AnObject', {owner: {type:'Pointer', targetClass: '_User'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user1', 'password'); return Parse.User.logIn('user1', 'password');
}).then(() => { }).then(() => {
obj.set('owner', user); obj.set('owner', user);
return obj.save(); return obj.save();
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(119); expect(err.code).toBe(119);
done(); done();
}) })
}); });
it('should handle multiple writeUserFields', done => { it('should handle multiple writeUserFields', done => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User(); let user = new Parse.User();
let user2 = new Parse.User(); let user2 = new Parse.User();
@@ -218,10 +216,10 @@ describe('Pointer Permissions', () => {
obj.set('otherOwner', user2); obj.set('otherOwner', user2);
return obj.save(); return obj.save();
}) })
.then(() => config.database.loadSchema()) .then(() => config.database.loadSchema())
.then(schema => schema.updateClass('AnObject', {}, {find: {"*": true},writeUserFields: ['owner', 'otherOwner']})) .then(schema => schema.updateClass('AnObject', {}, {find: {"*": true},writeUserFields: ['owner', 'otherOwner']}))
.then(() => Parse.User.logIn('user1', 'password')) .then(() => Parse.User.logIn('user1', 'password'))
.then(() => obj.save({hello: 'fromUser1'})) .then(() => obj.save({hello: 'fromUser1'}))
.then(() => Parse.User.logIn('user2', 'password')) .then(() => Parse.User.logIn('user2', 'password'))
.then(() => obj.save({hello: 'fromUser2'})) .then(() => obj.save({hello: 'fromUser2'}))
.then(() => Parse.User.logOut()) .then(() => Parse.User.logOut())
@@ -229,59 +227,59 @@ describe('Pointer Permissions', () => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.first(); return q.first();
}) })
.then(result => { .then(result => {
expect(result.get('hello')).toBe('fromUser2'); expect(result.get('hello')).toBe('fromUser2');
done(); done();
}).catch(err => { }).catch(() => {
fail('should not fail'); fail('should not fail');
done(); done();
}) })
}); });
it('should prevent creating pointer permission on missing field', (done) => { it('should prevent creating pointer permission on missing field', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
return schema.addClassIfNotExists('AnObject', {}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']}); return schema.addClassIfNotExists('AnObject', {}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
}).catch((err) => { }).catch((err) => {
expect(err.code).toBe(107); expect(err.code).toBe(107);
expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields"); expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields");
done(); done();
}) })
}); });
it('should prevent creating pointer permission on bad field', (done) => { it('should prevent creating pointer permission on bad field', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
return schema.addClassIfNotExists('AnObject', {owner: {type: 'String'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']}); return schema.addClassIfNotExists('AnObject', {owner: {type: 'String'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
}).catch((err) => { }).catch((err) => {
expect(err.code).toBe(107); expect(err.code).toBe(107);
expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields"); expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields");
done(); done();
}) })
}); });
it('should prevent creating pointer permission on bad field', (done) => { it('should prevent creating pointer permission on bad field', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
object.set('owner', 'value'); object.set('owner', 'value');
object.save().then(() => { object.save().then(() => {
return config.database.loadSchema(); return config.database.loadSchema();
}).then((schema) => { }).then((schema) => {
return schema.updateClass('AnObject', {}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
}).then(() => { }).then(() => {
fail('should not succeed'); fail('should not succeed');
}).catch((err) => { }).catch((err) => {
expect(err.code).toBe(107); expect(err.code).toBe(107);
expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields"); expect(err.message).toBe("'owner' is not a valid column for class level pointer permissions writeUserFields");
done(); done();
}) })
}); });
it('tests CLP / Pointer Perms / ACL write (PP Locked)', (done) => { it('tests CLP / Pointer Perms / ACL write (PP Locked)', (done) => {
/* /*
tests: tests:
CLP: update closed ({}) CLP: update closed ({})
@@ -314,21 +312,21 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user1', 'password'); return Parse.User.logIn('user1', 'password');
}).then(() => { }).then(() => {
// user1 has ACL read/write but should be blocked by PP // user1 has ACL read/write but should be blocked by PP
return obj.save({key: 'value'}); return obj.save({key: 'value'});
}).then(() => { }).then(() => {
fail('Should not succeed saving'); fail('Should not succeed saving');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
done(); done();
}); });
}); });
it('tests CLP / Pointer Perms / ACL write (ACL Locked)', (done) => { it('tests CLP / Pointer Perms / ACL write (ACL Locked)', (done) => {
/* /*
tests: tests:
CLP: update closed ({}) CLP: update closed ({})
@@ -347,7 +345,7 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => { Parse.Object.saveAll([user, user2]).then(() => {
let ACL = new Parse.ACL(); let ACL = new Parse.ACL();
ACL.setReadAccess(user, true); ACL.setReadAccess(user, true);
ACL.setWriteAccess(user, true); ACL.setWriteAccess(user, true);
@@ -359,21 +357,21 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}).then(() => { }).then(() => {
// user1 has ACL read/write but should be blocked by ACL // user1 has ACL read/write but should be blocked by ACL
return obj.save({key: 'value'}); return obj.save({key: 'value'});
}).then(() => { }).then(() => {
fail('Should not succeed saving'); fail('Should not succeed saving');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
done(); done();
}); });
}); });
it('tests CLP / Pointer Perms / ACL write (ACL/PP OK)', (done) => { it('tests CLP / Pointer Perms / ACL write (ACL/PP OK)', (done) => {
/* /*
tests: tests:
CLP: update closed ({}) CLP: update closed ({})
@@ -392,7 +390,7 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => { Parse.Object.saveAll([user, user2]).then(() => {
let ACL = new Parse.ACL(); let ACL = new Parse.ACL();
ACL.setWriteAccess(user, true); ACL.setWriteAccess(user, true);
ACL.setWriteAccess(user2, true); ACL.setWriteAccess(user2, true);
@@ -404,21 +402,21 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}).then(() => { }).then(() => {
// user1 has ACL read/write but should be blocked by ACL // user1 has ACL read/write but should be blocked by ACL
return obj.save({key: 'value'}); return obj.save({key: 'value'});
}).then((objAgain) => { }).then((objAgain) => {
expect(objAgain.get('key')).toBe('value'); expect(objAgain.get('key')).toBe('value');
done(); done();
}, (err) => { }, () => {
fail('Should not fail saving'); fail('Should not fail saving');
done(); done();
}); });
}); });
it('tests CLP / Pointer Perms / ACL read (PP locked)', (done) => { it('tests CLP / Pointer Perms / ACL read (PP locked)', (done) => {
/* /*
tests: tests:
CLP: find/get open ({}) CLP: find/get open ({})
@@ -439,7 +437,7 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => { Parse.Object.saveAll([user, user2]).then(() => {
let ACL = new Parse.ACL(); let ACL = new Parse.ACL();
ACL.setReadAccess(user, true); ACL.setReadAccess(user, true);
ACL.setWriteAccess(user, true); ACL.setWriteAccess(user, true);
@@ -451,21 +449,21 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {find: {}, get: {}, readUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {find: {}, get: {}, readUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user1', 'password'); return Parse.User.logIn('user1', 'password');
}).then(() => { }).then(() => {
// user1 has ACL read/write but should be block // user1 has ACL read/write but should be block
return obj.fetch(); return obj.fetch();
}).then(() => { }).then(() => {
fail('Should not succeed saving'); fail('Should not succeed saving');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
done(); done();
}); });
}); });
it('tests CLP / Pointer Perms / ACL read (PP/ACL OK)', (done) => { it('tests CLP / Pointer Perms / ACL read (PP/ACL OK)', (done) => {
/* /*
tests: tests:
CLP: find/get open ({"*": true}) CLP: find/get open ({"*": true})
@@ -484,7 +482,7 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => { Parse.Object.saveAll([user, user2]).then(() => {
let ACL = new Parse.ACL(); let ACL = new Parse.ACL();
ACL.setReadAccess(user, true); ACL.setReadAccess(user, true);
ACL.setWriteAccess(user, true); ACL.setWriteAccess(user, true);
@@ -498,21 +496,21 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {find: {"*": true}, get: {"*": true}, readUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {find: {"*": true}, get: {"*": true}, readUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}).then(() => { }).then(() => {
// user1 has ACL read/write but should be block // user1 has ACL read/write but should be block
return obj.fetch(); return obj.fetch();
}).then((objAgain) => { }).then((objAgain) => {
expect(objAgain.id).toBe(obj.id); expect(objAgain.id).toBe(obj.id);
done(); done();
}, (err) => { }, () => {
fail('Should not fail fetching'); fail('Should not fail fetching');
done(); done();
}); });
}); });
it('tests CLP / Pointer Perms / ACL read (ACL locked)', (done) => { it('tests CLP / Pointer Perms / ACL read (ACL locked)', (done) => {
/* /*
tests: tests:
CLP: find/get open ({"*": true}) CLP: find/get open ({"*": true})
@@ -531,7 +529,7 @@ describe('Pointer Permissions', () => {
password: 'password' password: 'password'
}); });
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
Parse.Object.saveAll([user, user2]).then(() => { Parse.Object.saveAll([user, user2]).then(() => {
let ACL = new Parse.ACL(); let ACL = new Parse.ACL();
ACL.setReadAccess(user, true); ACL.setReadAccess(user, true);
ACL.setWriteAccess(user, true); ACL.setWriteAccess(user, true);
@@ -543,15 +541,15 @@ describe('Pointer Permissions', () => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {}, {find: {"*": true}, get: {"*": true}, readUserFields: ['owner']}); return schema.updateClass('AnObject', {}, {find: {"*": true}, get: {"*": true}, readUserFields: ['owner']});
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'password'); return Parse.User.logIn('user2', 'password');
}).then(() => { }).then(() => {
// user2 has ACL read/write but should be block by ACL // user2 has ACL read/write but should be block by ACL
return obj.fetch(); return obj.fetch();
}).then(() => { }).then(() => {
fail('Should not succeed saving'); fail('Should not succeed saving');
done(); done();
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
done(); done();
}); });
@@ -559,10 +557,9 @@ describe('Pointer Permissions', () => {
it('should let master key find objects', (done) => { it('should let master key find objects', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User();
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']}); return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']});
@@ -575,13 +572,13 @@ describe('Pointer Permissions', () => {
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
let q = new Parse.Query('AnObject'); let q = new Parse.Query('AnObject');
return q.find({useMasterKey: true}); return q.find({useMasterKey: true});
}).then((objects) => { }).then((objects) => {
expect(objects.length).toBe(1); expect(objects.length).toBe(1);
done(); done();
}, (err) => { }, () => {
fail('master key should find the object'); fail('master key should find the object');
done(); done();
}) })
@@ -589,10 +586,9 @@ describe('Pointer Permissions', () => {
it('should let master key get objects', (done) => { it('should let master key get objects', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User();
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']}); return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']});
@@ -612,7 +608,7 @@ describe('Pointer Permissions', () => {
expect(objectAgain).not.toBeUndefined(); expect(objectAgain).not.toBeUndefined();
expect(objectAgain.id).toBe(object.id); expect(objectAgain.id).toBe(object.id);
done(); done();
}, (err) => { }, () => {
fail('master key should find the object'); fail('master key should find the object');
done(); done();
}) })
@@ -621,10 +617,9 @@ describe('Pointer Permissions', () => {
it('should let master key update objects', (done) => { it('should let master key update objects', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User();
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {update: {}, writeUserFields: ['owner']}); return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {update: {}, writeUserFields: ['owner']});
@@ -636,12 +631,12 @@ describe('Pointer Permissions', () => {
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
return object.save({'hello': 'baz'}, {useMasterKey: true}); return object.save({'hello': 'baz'}, {useMasterKey: true});
}).then((objectAgain) => { }).then((objectAgain) => {
expect(objectAgain.get('hello')).toBe('baz'); expect(objectAgain.get('hello')).toBe('baz');
done(); done();
}, (err) => { }, () => {
fail('master key should save the object'); fail('master key should save the object');
done(); done();
}) })
@@ -649,10 +644,9 @@ describe('Pointer Permissions', () => {
it('should let master key delete objects', (done) => { it('should let master key delete objects', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
let user = new Parse.User();
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
return config.database.loadSchema().then((schema) => { return config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: ['owner']}); return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: ['owner']});
@@ -664,35 +658,35 @@ describe('Pointer Permissions', () => {
}, (err) => { }, (err) => {
expect(err.code).toBe(101); expect(err.code).toBe(101);
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
return object.destroy({useMasterKey: true}); return object.destroy({useMasterKey: true});
}).then((objectAgain) => { }).then(() => {
done(); done();
}, (err) => { }, () => {
fail('master key should destroy the object'); fail('master key should destroy the object');
done(); done();
}) })
}); });
it('should fail with invalid pointer perms', () => { it('should fail with invalid pointer perms', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: 'owner'}); return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: 'owner'});
}).catch((err) => { }).catch((err) => {
expect(err.code).toBe(Parse.Error.INVALID_JSON); expect(err.code).toBe(Parse.Error.INVALID_JSON);
done(); done();
}); });
}); });
it('should fail with invalid pointer perms', () => { it('should fail with invalid pointer perms', (done) => {
let config = new Config(Parse.applicationId); let config = new Config(Parse.applicationId);
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
// Lock the update, and let only owner write // Lock the update, and let only owner write
return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: ['owner', 'invalid']}); return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: ['owner', 'invalid']});
}).catch((err) => { }).catch((err) => {
expect(err.code).toBe(Parse.Error.INVALID_JSON); expect(err.code).toBe(Parse.Error.INVALID_JSON);
done(); done();
}); });
}) })
}); });

View File

@@ -1,14 +1,14 @@
var PromiseRouter = require("../src/PromiseRouter").default; var PromiseRouter = require("../src/PromiseRouter").default;
describe("PromiseRouter", () => { describe("PromiseRouter", () => {
it("should properly handle rejects", (done) => { it("should properly handle rejects", (done) => {
var router = new PromiseRouter(); var router = new PromiseRouter();
router.route("GET", "/dummy", (req)=> { router.route("GET", "/dummy", ()=> {
return Promise.reject({ return Promise.reject({
error: "an error", error: "an error",
code: -1 code: -1
}) })
}, (req) => { }, () => {
fail("this should not be called"); fail("this should not be called");
}); });

View File

@@ -3,7 +3,7 @@ var request = require('request');
describe("public API", () => { describe("public API", () => {
it("should get invalid_link.html", (done) => { it("should get invalid_link.html", (done) => {
request('http://localhost:8378/1/apps/invalid_link.html', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/invalid_link.html', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(200); expect(httpResponse.statusCode).toBe(200);
done(); done();
}); });
@@ -15,7 +15,7 @@ describe("public API", () => {
publicServerURL: 'http://localhost:8378/1', publicServerURL: 'http://localhost:8378/1',
}) })
.then(() => { .then(() => {
request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(200); expect(httpResponse.statusCode).toBe(200);
done(); done();
}); });
@@ -23,14 +23,14 @@ describe("public API", () => {
}); });
it("should get verify_email_success.html", (done) => { it("should get verify_email_success.html", (done) => {
request('http://localhost:8378/1/apps/verify_email_success.html', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/verify_email_success.html', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(200); expect(httpResponse.statusCode).toBe(200);
done(); done();
}); });
}); });
it("should get password_reset_success.html", (done) => { it("should get password_reset_success.html", (done) => {
request('http://localhost:8378/1/apps/password_reset_success.html', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/password_reset_success.html', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(200); expect(httpResponse.statusCode).toBe(200);
done(); done();
}); });
@@ -38,26 +38,26 @@ describe("public API", () => {
}); });
describe("public API without publicServerURL", () => { describe("public API without publicServerURL", () => {
beforeEach(done => { beforeEach(done => {
reconfigureServer({ appName: 'unused' }) reconfigureServer({ appName: 'unused' })
.then(done, fail); .then(done, fail);
}); });
it("should get 404 on verify_email", (done) => { it("should get 404 on verify_email", (done) => {
request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(404); expect(httpResponse.statusCode).toBe(404);
done(); done();
}); });
}); });
it("should get 404 choose_password", (done) => { it("should get 404 choose_password", (done) => {
request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(404); expect(httpResponse.statusCode).toBe(404);
done(); done();
}); });
}); });
it("should get 404 on request_password_reset", (done) => { it("should get 404 on request_password_reset", (done) => {
request('http://localhost:8378/1/apps/test/request_password_reset', (err, httpResponse, body) => { request('http://localhost:8378/1/apps/test/request_password_reset', (err, httpResponse) => {
expect(httpResponse.statusCode).toBe(404); expect(httpResponse.statusCode).toBe(404);
done(); done();
}); });

View File

@@ -21,14 +21,14 @@ function createProduct() {
describe("test validate_receipt endpoint", () => { describe("test validate_receipt endpoint", () => {
beforeEach( done => { beforeEach( done => {
createProduct().then(done).fail(function(err){ createProduct().then(done).fail(function(){
done(); done();
}); });
}) })
it("should bypass appstore validation", (done) => { it("should bypass appstore validation", (done) => {
request.post({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'}, 'X-Parse-REST-API-Key': 'rest'},
@@ -45,7 +45,7 @@ describe("test validate_receipt endpoint", () => {
}, function(err, res, body){ }, function(err, res, body){
if (typeof body != "object") { if (typeof body != "object") {
fail("Body is not an object"); fail("Body is not an object");
done(); done();
} else { } else {
expect(body.__type).toEqual("File"); expect(body.__type).toEqual("File");
const url = body.url; const url = body.url;
@@ -60,7 +60,7 @@ describe("test validate_receipt endpoint", () => {
}); });
it("should fail for missing receipt", (done) => { it("should fail for missing receipt", (done) => {
request.post({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'}, 'X-Parse-REST-API-Key': 'rest'},
@@ -73,7 +73,7 @@ describe("test validate_receipt endpoint", () => {
}, function(err, res, body){ }, function(err, res, body){
if (typeof body != "object") { if (typeof body != "object") {
fail("Body is not an object"); fail("Body is not an object");
done(); done();
} else { } else {
expect(body.code).toEqual(Parse.Error.INVALID_JSON); expect(body.code).toEqual(Parse.Error.INVALID_JSON);
done(); done();
@@ -82,7 +82,7 @@ describe("test validate_receipt endpoint", () => {
}); });
it("should fail for missing product identifier", (done) => { it("should fail for missing product identifier", (done) => {
request.post({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'}, 'X-Parse-REST-API-Key': 'rest'},
@@ -98,7 +98,7 @@ describe("test validate_receipt endpoint", () => {
}, function(err, res, body){ }, function(err, res, body){
if (typeof body != "object") { if (typeof body != "object") {
fail("Body is not an object"); fail("Body is not an object");
done(); done();
} else { } else {
expect(body.code).toEqual(Parse.Error.INVALID_JSON); expect(body.code).toEqual(Parse.Error.INVALID_JSON);
done(); done();
@@ -108,7 +108,7 @@ describe("test validate_receipt endpoint", () => {
it("should bypass appstore validation and not find product", (done) => { it("should bypass appstore validation and not find product", (done) => {
request.post({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'}, 'X-Parse-REST-API-Key': 'rest'},
@@ -135,7 +135,7 @@ describe("test validate_receipt endpoint", () => {
}); });
it("should fail at appstore validation", done => { it("should fail at appstore validation", done => {
request.post({ request.post({
headers: { headers: {
'X-Parse-Application-Id': 'test', 'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'}, 'X-Parse-REST-API-Key': 'rest'},
@@ -160,49 +160,49 @@ describe("test validate_receipt endpoint", () => {
}); });
it("should not create a _Product", (done) => { it("should not create a _Product", (done) => {
var product = new Parse.Object("_Product"); var product = new Parse.Object("_Product");
product.save().then(function(){ product.save().then(function(){
fail("Should not be able to save"); fail("Should not be able to save");
done(); done();
}, function(err){ }, function(err){
expect(err.code).toEqual(Parse.Error.INCORRECT_TYPE); expect(err.code).toEqual(Parse.Error.INCORRECT_TYPE);
done(); done();
}) })
}); });
it("should be able to update a _Product", (done) => { it("should be able to update a _Product", (done) => {
var query = new Parse.Query("_Product"); var query = new Parse.Query("_Product");
query.first().then(function(product) { query.first().then(function(product) {
if (!product) { if (!product) {
return Promise.reject(new Error('Product should be found')); return Promise.reject(new Error('Product should be found'));
} }
product.set("title", "a new title"); product.set("title", "a new title");
return product.save(); return product.save();
}).then(function(productAgain){ }).then(function(productAgain){
expect(productAgain.get('downloadName')).toEqual(productAgain.get('download').name()); expect(productAgain.get('downloadName')).toEqual(productAgain.get('download').name());
expect(productAgain.get("title")).toEqual("a new title"); expect(productAgain.get("title")).toEqual("a new title");
done(); done();
}).fail(function(err){ }).fail(function(err){
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}); });
}); });
it("should not be able to remove a require key in a _Product", (done) => { it("should not be able to remove a require key in a _Product", (done) => {
var query = new Parse.Query("_Product"); var query = new Parse.Query("_Product");
query.first().then(function(product){ query.first().then(function(product){
if (!product) { if (!product) {
return Promise.reject(new Error('Product should be found')); return Promise.reject(new Error('Product should be found'));
} }
product.unset("title"); product.unset("title");
return product.save(); return product.save();
}).then(function(productAgain){ }).then(function(){
fail("Should not succeed"); fail("Should not succeed");
done(); done();
}).fail(function(err){ }).fail(function(err){
expect(err.code).toEqual(Parse.Error.INCORRECT_TYPE); expect(err.code).toEqual(Parse.Error.INCORRECT_TYPE);
expect(err.message).toEqual("title is required."); expect(err.message).toEqual("title is required.");
done(); done();
}); });
}); });
}); });

View File

@@ -5,7 +5,7 @@ var Config = require('../src/Config');
const successfulTransmissions = function(body, installations) { const successfulTransmissions = function(body, installations) {
let promises = installations.map((device) => { let promises = installations.map((device) => {
return Promise.resolve({ return Promise.resolve({
transmitted: true, transmitted: true,
device: device, device: device,
@@ -17,7 +17,7 @@ const successfulTransmissions = function(body, installations) {
const successfulIOS = function(body, installations) { const successfulIOS = function(body, installations) {
let promises = installations.map((device) => { let promises = installations.map((device) => {
return Promise.resolve({ return Promise.resolve({
transmitted: device.deviceType == "ios", transmitted: device.deviceType == "ios",
device: device, device: device,
@@ -98,8 +98,8 @@ describe('PushController', () => {
// Make mock request // Make mock request
var timeStr = '2015-03-19T22:05:08Z'; var timeStr = '2015-03-19T22:05:08Z';
var body = { var body = {
'expiration_time': timeStr 'expiration_time': timeStr
} }
var time = PushController.getExpirationTime(body); var time = PushController.getExpirationTime(body);
expect(time).toEqual(new Date(timeStr).valueOf()); expect(time).toEqual(new Date(timeStr).valueOf());
@@ -132,114 +132,70 @@ describe('PushController', () => {
it('properly increment badges', (done) => { it('properly increment badges', (done) => {
var payload = {data:{ var payload = {data:{
alert: "Hello World!", alert: "Hello World!",
badge: "Increment", badge: "Increment",
}} }}
var installations = []; var installations = [];
while(installations.length != 10) { while(installations.length != 10) {
var installation = new Parse.Object("_Installation"); let installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length); installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length) installation.set("deviceToken","device_token_"+installations.length)
installation.set("badge", installations.length); installation.set("badge", installations.length);
installation.set("originalBadge", installations.length); installation.set("originalBadge", installations.length);
installation.set("deviceType", "ios"); installation.set("deviceType", "ios");
installations.push(installation); installations.push(installation);
}
while(installations.length != 15) {
var installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length)
installation.set("deviceType", "android");
installations.push(installation);
}
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
installations.forEach((installation) => {
if (installation.deviceType == "ios") {
expect(installation.badge).toEqual(badge);
expect(installation.originalBadge+1).toEqual(installation.badge);
} else {
expect(installation.badge).toBeUndefined();
}
})
return successfulTransmissions(body, installations);
},
getValidPushTypes: function() {
return ["ios", "android"];
} }
}
var config = new Config(Parse.applicationId); while(installations.length != 15) {
var auth = { let installation = new Parse.Object("_Installation");
isMaster: true installation.set("installationId", "installation_"+installations.length);
} installation.set("deviceToken","device_token_"+installations.length)
installation.set("deviceType", "android");
installations.push(installation);
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push); var pushAdapter = {
Parse.Object.saveAll(installations).then((installations) => { send: function(body, installations) {
return pushController.sendPush(payload, {}, config, auth); var badge = body.data.badge;
}).then((result) => { installations.forEach((installation) => {
done(); if (installation.deviceType == "ios") {
}, (err) => { expect(installation.badge).toEqual(badge);
jfail(err); expect(installation.originalBadge+1).toEqual(installation.badge);
done(); } else {
}); expect(installation.badge).toBeUndefined();
}
})
return successfulTransmissions(body, installations);
},
getValidPushTypes: function() {
return ["ios", "android"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
Parse.Object.saveAll(installations).then(() => {
return pushController.sendPush(payload, {}, config, auth);
}).then(() => {
done();
}, (err) => {
jfail(err);
done();
});
}); });
it('properly set badges to 1', (done) => { it('properly set badges to 1', (done) => {
var payload = {data: { var payload = {data: {
alert: "Hello World!", alert: "Hello World!",
badge: 1, badge: 1,
}} }}
var installations = [];
while(installations.length != 10) {
var installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length)
installation.set("badge", installations.length);
installation.set("originalBadge", installations.length);
installation.set("deviceType", "ios");
installations.push(installation);
}
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
installations.forEach((installation) => {
expect(installation.badge).toEqual(badge);
expect(1).toEqual(installation.badge);
})
return successfulTransmissions(body, installations);
},
getValidPushTypes: function() {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
Parse.Object.saveAll(installations).then((installations) => {
return pushController.sendPush(payload, {}, config, auth);
}).then((result) => {
done();
}, (err) => {
fail("should not fail");
done();
});
});
it('properly creates _PushStatus', (done) => {
var installations = []; var installations = [];
while(installations.length != 10) { while(installations.length != 10) {
var installation = new Parse.Object("_Installation"); var installation = new Parse.Object("_Installation");
@@ -251,188 +207,232 @@ describe('PushController', () => {
installations.push(installation); installations.push(installation);
} }
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
installations.forEach((installation) => {
expect(installation.badge).toEqual(badge);
expect(1).toEqual(installation.badge);
})
return successfulTransmissions(body, installations);
},
getValidPushTypes: function() {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
Parse.Object.saveAll(installations).then(() => {
return pushController.sendPush(payload, {}, config, auth);
}).then(() => {
done();
}, () => {
fail("should not fail");
done();
});
});
it('properly creates _PushStatus', (done) => {
var installations = [];
while(installations.length != 10) {
let installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length)
installation.set("badge", installations.length);
installation.set("originalBadge", installations.length);
installation.set("deviceType", "ios");
installations.push(installation);
}
while(installations.length != 15) { while(installations.length != 15) {
var installation = new Parse.Object("_Installation"); let installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length); installation.set("installationId", "installation_"+installations.length);
installation.set("deviceToken","device_token_"+installations.length) installation.set("deviceToken","device_token_"+installations.length)
installation.set("deviceType", "android"); installation.set("deviceType", "android");
installations.push(installation); installations.push(installation);
} }
var payload = {data: {
alert: "Hello World!",
badge: 1,
}}
var pushAdapter = {
send: function(body, installations) {
return successfulIOS(body, installations);
},
getValidPushTypes: function() {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
Parse.Object.saveAll(installations).then(() => {
return pushController.sendPush(payload, {}, config, auth);
}).then((result) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000);
});
}).then(() => {
let query = new Parse.Query('_PushStatus');
return query.find({useMasterKey: true});
}).then((results) => {
expect(results.length).toBe(1);
let result = results[0];
expect(result.createdAt instanceof Date).toBe(true);
expect(result.updatedAt instanceof Date).toBe(true);
expect(result.id.length).toBe(10);
expect(result.get('source')).toEqual('rest');
expect(result.get('query')).toEqual(JSON.stringify({}));
expect(typeof result.get('payload')).toEqual("string");
expect(JSON.parse(result.get('payload'))).toEqual(payload.data);
expect(result.get('status')).toEqual('succeeded');
expect(result.get('numSent')).toEqual(10);
expect(result.get('sentPerType')).toEqual({
'ios': 10 // 10 ios
});
expect(result.get('numFailed')).toEqual(5);
expect(result.get('failedPerType')).toEqual({
'android': 5 // android
});
// Try to get it without masterKey
let query = new Parse.Query('_PushStatus');
return query.find();
}).then((results) => {
expect(results.length).toBe(0);
done();
});
});
it('should properly report failures in _PushStatus', (done) => {
var pushAdapter = {
send: function(body, installations) {
return installations.map((installation) => {
return Promise.resolve({
deviceType: installation.deviceType
})
})
},
getValidPushTypes: function() {
return ["ios"];
}
}
let where = { 'channels': {
'$ins': ['Giants', 'Mets']
}};
var payload = {data: {
alert: "Hello World!",
badge: 1,
}}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
pushController.sendPush(payload, where, config, auth).then(() => {
fail('should not succeed');
done();
}).catch(() => {
let query = new Parse.Query('_PushStatus');
query.find({useMasterKey: true}).then((results) => {
expect(results.length).toBe(1);
let pushStatus = results[0];
expect(pushStatus.get('status')).toBe('failed');
done();
});
})
});
it('should support full RESTQuery for increment', (done) => {
var payload = {data: { var payload = {data: {
alert: "Hello World!", alert: "Hello World!",
badge: 'Increment', badge: 1,
}} }}
var pushAdapter = { var pushAdapter = {
send: function(body, installations) { send: function(body, installations) {
return successfulTransmissions(body, installations); return successfulIOS(body, installations);
}, },
getValidPushTypes: function() { getValidPushTypes: function() {
return ["ios"]; return ["ios"];
}
} }
}
var config = new Config(Parse.applicationId); var config = new Config(Parse.applicationId);
var auth = { var auth = {
isMaster: true isMaster: true
} }
let where = { var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
'deviceToken': { Parse.Object.saveAll(installations).then(() => {
'$inQuery': { return pushController.sendPush(payload, {}, config, auth);
'where': { }).then(() => {
'deviceType': 'ios' return new Promise((resolve) => {
}, setTimeout(() => {
className: '_Installation' resolve();
} }, 1000);
} });
} }).then(() => {
let query = new Parse.Query('_PushStatus');
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push); return query.find({useMasterKey: true});
pushController.sendPush(payload, where, config, auth).then((result) => { }).then((results) => {
expect(results.length).toBe(1);
let result = results[0];
expect(result.createdAt instanceof Date).toBe(true);
expect(result.updatedAt instanceof Date).toBe(true);
expect(result.id.length).toBe(10);
expect(result.get('source')).toEqual('rest');
expect(result.get('query')).toEqual(JSON.stringify({}));
expect(typeof result.get('payload')).toEqual("string");
expect(JSON.parse(result.get('payload'))).toEqual(payload.data);
expect(result.get('status')).toEqual('succeeded');
expect(result.get('numSent')).toEqual(10);
expect(result.get('sentPerType')).toEqual({
'ios': 10 // 10 ios
});
expect(result.get('numFailed')).toEqual(5);
expect(result.get('failedPerType')).toEqual({
'android': 5 // android
});
// Try to get it without masterKey
let query = new Parse.Query('_PushStatus');
return query.find();
}).then((results) => {
expect(results.length).toBe(0);
done(); done();
}).catch((err) => { });
});
it('should properly report failures in _PushStatus', (done) => {
var pushAdapter = {
send: function(body, installations) {
return installations.map((installation) => {
return Promise.resolve({
deviceType: installation.deviceType
})
})
},
getValidPushTypes: function() {
return ["ios"];
}
}
let where = { 'channels': {
'$ins': ['Giants', 'Mets']
}};
var payload = {data: {
alert: "Hello World!",
badge: 1,
}}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
pushController.sendPush(payload, where, config, auth).then(() => {
fail('should not succeed');
done();
}).catch(() => {
let query = new Parse.Query('_PushStatus');
query.find({useMasterKey: true}).then((results) => {
expect(results.length).toBe(1);
let pushStatus = results[0];
expect(pushStatus.get('status')).toBe('failed');
done();
});
})
});
it('should support full RESTQuery for increment', (done) => {
var payload = {data: {
alert: "Hello World!",
badge: 'Increment',
}}
var pushAdapter = {
send: function(body, installations) {
return successfulTransmissions(body, installations);
},
getValidPushTypes: function() {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
let where = {
'deviceToken': {
'$inQuery': {
'where': {
'deviceType': 'ios'
},
className: '_Installation'
}
}
}
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
pushController.sendPush(payload, where, config, auth).then(() => {
done();
}).catch((err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should support object type for alert', (done) => { it('should support object type for alert', (done) => {
var payload = {data: { var payload = {data: {
alert: { alert: {
'loc-key': 'hello_world', 'loc-key': 'hello_world',
}, },
}} }}
var pushAdapter = { var pushAdapter = {
send: function(body, installations) { send: function(body, installations) {
return successfulTransmissions(body, installations); return successfulTransmissions(body, installations);
}, },
getValidPushTypes: function() { getValidPushTypes: function() {
return ["ios"]; return ["ios"];
}
} }
}
var config = new Config(Parse.applicationId); var config = new Config(Parse.applicationId);
var auth = { var auth = {
isMaster: true isMaster: true
} }
let where = { let where = {
'deviceToken': { 'deviceToken': {
'$inQuery': { '$inQuery': {
'where': { 'where': {
'deviceType': 'ios' 'deviceType': 'ios'
}, },
className: '_Installation' className: '_Installation'
} }
} }
} }
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push); var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
pushController.sendPush(payload, where, config, auth).then((result) => { pushController.sendPush(payload, where, config, auth).then(() => {
done(); done();
}).catch((err) => { }).catch(() => {
fail('should not fail'); fail('should not fail');
done(); done();
}); });

View File

@@ -10,14 +10,14 @@ describe('RedisPubSub', function() {
}); });
it('can create publisher', function() { it('can create publisher', function() {
var publisher = RedisPubSub.createPublisher({redisURL: 'redisAddress'}); RedisPubSub.createPublisher({redisURL: 'redisAddress'});
var redis = require('redis'); var redis = require('redis');
expect(redis.createClient).toHaveBeenCalledWith('redisAddress', { no_ready_check: true }); expect(redis.createClient).toHaveBeenCalledWith('redisAddress', { no_ready_check: true });
}); });
it('can create subscriber', function() { it('can create subscriber', function() {
var subscriber = RedisPubSub.createSubscriber({redisURL: 'redisAddress'}); RedisPubSub.createSubscriber({redisURL: 'redisAddress'});
var redis = require('redis'); var redis = require('redis');
expect(redis.createClient).toHaveBeenCalledWith('redisAddress', { no_ready_check: true }); expect(redis.createClient).toHaveBeenCalledWith('redisAddress', { no_ready_check: true });

View File

@@ -1,7 +1,6 @@
"use strict"; "use strict";
// These tests check the "create" / "update" functionality of the REST API. // These tests check the "create" / "update" functionality of the REST API.
var auth = require('../src/Auth'); var auth = require('../src/Auth');
var cache = require('../src/cache');
var Config = require('../src/Config'); var Config = require('../src/Config');
var Parse = require('parse/node').Parse; var Parse = require('parse/node').Parse;
var rest = require('../src/rest'); var rest = require('../src/rest');
@@ -12,7 +11,7 @@ let database = config.database;
describe('rest create', () => { describe('rest create', () => {
beforeEach(() => { beforeEach(() => {
config = new Config('test'); config = new Config('test');
}); });
@@ -93,7 +92,7 @@ describe('rest create', () => {
expect(err.message).toEqual('This user is not allowed to access ' + expect(err.message).toEqual('This user is not allowed to access ' +
'non-existent class: ClientClassCreation'); 'non-existent class: ClientClassCreation');
done(); done();
}); });
}); });
it('handles create on existent class when disabled client class creation', (done) => { it('handles create on existent class when disabled client class creation', (done) => {
@@ -106,7 +105,7 @@ describe('rest create', () => {
}) })
.then(() => { .then(() => {
done(); done();
}, err => { }, () => {
fail('Should not throw error') fail('Should not throw error')
}); });
}); });
@@ -186,7 +185,6 @@ describe('rest create', () => {
username: 'hello', username: 'hello',
password: 'world' password: 'world'
} }
var username1;
var objectId; var objectId;
rest.create(config, auth.nobody(config), '_User', data1) rest.create(config, auth.nobody(config), '_User', data1)
.then((r) => { .then((r) => {
@@ -197,24 +195,24 @@ describe('rest create', () => {
return auth.getAuthForSessionToken({config, sessionToken: r.response.sessionToken }) return auth.getAuthForSessionToken({config, sessionToken: r.response.sessionToken })
}).then((sessionAuth) => { }).then((sessionAuth) => {
return rest.update(config, sessionAuth, '_User', objectId, updatedData); return rest.update(config, sessionAuth, '_User', objectId, updatedData);
}).then((r) => { }).then(() => {
return Parse.User.logOut().then(() => { return Parse.User.logOut().then(() => {
return Parse.User.logIn('hello', 'world'); return Parse.User.logIn('hello', 'world');
}) })
}).then((r) => { }).then((r) => {
expect(r.id).toEqual(objectId); expect(r.id).toEqual(objectId);
expect(r.get('username')).toEqual('hello'); expect(r.get('username')).toEqual('hello');
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}) })
}); });
it('handles no anonymous users config', (done) => { it('handles no anonymous users config', (done) => {
var NoAnnonConfig = Object.assign({}, config); var NoAnnonConfig = Object.assign({}, config);
NoAnnonConfig.authDataManager.setEnableAnonymousUsers(false); NoAnnonConfig.authDataManager.setEnableAnonymousUsers(false);
var data1 = { var data1 = {
authData: { authData: {
anonymous: { anonymous: {
id: '00000000-0000-0000-0000-000000000001' id: '00000000-0000-0000-0000-000000000001'
@@ -262,7 +260,7 @@ describe('rest create', () => {
var output = response.results[0]; var output = response.results[0];
expect(output.user.objectId).toEqual(newUserSignedUpByFacebookObjectId); expect(output.user.objectId).toEqual(newUserSignedUpByFacebookObjectId);
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -359,7 +357,7 @@ describe('rest create', () => {
foo: 'bar', foo: 'bar',
}; };
var sessionLength = 3600, // 1 Hour ahead var sessionLength = 3600, // 1 Hour ahead
now = new Date(); // For reference later now = new Date(); // For reference later
config.sessionLength = sessionLength; config.sessionLength = sessionLength;
rest.create(config, auth.nobody(config), '_User', user) rest.create(config, auth.nobody(config), '_User', user)
@@ -385,7 +383,7 @@ describe('rest create', () => {
expect(actual.getMinutes()).toEqual(expected.getMinutes()); expect(actual.getMinutes()).toEqual(expected.getMinutes());
done(); done();
}).catch(err => { }).catch(err => {
jfail(err); jfail(err);
done(); done();
}); });
@@ -415,7 +413,7 @@ describe('rest create', () => {
expect(session.expiresAt).toBeUndefined(); expect(session.expiresAt).toBeUndefined();
done(); done();
}).catch(err => { }).catch(err => {
console.error(err); console.error(err);
fail(err); fail(err);
done(); done();

View File

@@ -1,12 +1,10 @@
'use strict' 'use strict'
// These tests check the "find" functionality of the REST API. // These tests check the "find" functionality of the REST API.
var auth = require('../src/Auth'); var auth = require('../src/Auth');
var cache = require('../src/cache');
var Config = require('../src/Config'); var Config = require('../src/Config');
var rest = require('../src/rest'); var rest = require('../src/rest');
var querystring = require('querystring'); var querystring = require('querystring');
var request = require('request');
var rp = require('request-promise'); var rp = require('request-promise');
var config; var config;
@@ -15,7 +13,7 @@ var nobody = auth.nobody(config);
describe('rest query', () => { describe('rest query', () => {
beforeEach(() => { beforeEach(() => {
config = new Config('test'); config = new Config('test');
database = config.database; database = config.database;
}); });
@@ -145,7 +143,7 @@ describe('rest query', () => {
expect(err.message).toEqual('This user is not allowed to access ' + expect(err.message).toEqual('This user is not allowed to access ' +
'non-existent class: ClientClassCreation'); 'non-existent class: ClientClassCreation');
done(); done();
}); });
}); });
it('query existent class when disabled client class creation', (done) => { it('query existent class when disabled client class creation', (done) => {
@@ -159,7 +157,7 @@ describe('rest query', () => {
.then((result) => { .then((result) => {
expect(result.results.length).toEqual(0); expect(result.results.length).toEqual(0);
done(); done();
}, err => { }, () => {
fail('Should not throw error') fail('Should not throw error')
}); });
}); });
@@ -179,8 +177,8 @@ describe('rest query', () => {
headers: headers, headers: headers,
url: 'http://localhost:8378/1/classes/TestParameterEncode?' url: 'http://localhost:8378/1/classes/TestParameterEncode?'
+ querystring.stringify({ + querystring.stringify({
where: '{"foo":{"$ne": "baz"}}', where: '{"foo":{"$ne": "baz"}}',
limit: 1 limit: 1
}).replace('=', '%3D'), }).replace('=', '%3D'),
}).then(fail, (response) => { }).then(fail, (response) => {
let error = response.error; let error = response.error;
@@ -192,7 +190,7 @@ describe('rest query', () => {
headers: headers, headers: headers,
url: 'http://localhost:8378/1/classes/TestParameterEncode?' url: 'http://localhost:8378/1/classes/TestParameterEncode?'
+ querystring.stringify({ + querystring.stringify({
limit: 1 limit: 1
}).replace('=', '%3D'), }).replace('=', '%3D'),
}).then(fail, (response) => { }).then(fail, (response) => {
let error = response.error; let error = response.error;
@@ -200,7 +198,7 @@ describe('rest query', () => {
expect(b.code).toEqual(Parse.Error.INVALID_QUERY); expect(b.code).toEqual(Parse.Error.INVALID_QUERY);
}); });
return Promise.all([p0, p1]); return Promise.all([p0, p1]);
}).then(done).catch((err) => { }).then(done).catch((err) => {
jfail(err); jfail(err);
fail('should not fail'); fail('should not fail');
done(); done();
@@ -239,14 +237,14 @@ describe('rest query', () => {
it('makes sure null pointers are handed correctly #2189', done => { it('makes sure null pointers are handed correctly #2189', done => {
let object = new Parse.Object('AnObject'); let object = new Parse.Object('AnObject');
let anotherObject = new Parse.Object('AnotherObject'); let anotherObject = new Parse.Object('AnotherObject');
anotherObject.save().then(() => { anotherObject.save().then(() => {
object.set('values', [null, null, anotherObject]); object.set('values', [null, null, anotherObject]);
return object.save(); return object.save();
}).then(() => { }).then(() => {
let query = new Parse.Query('AnObject'); let query = new Parse.Query('AnObject');
query.include('values'); query.include('values');
return query.first(); return query.first();
}).then((result) => { }).then((result) => {
let values = result.get('values'); let values = result.get('values');
expect(values.length).toBe(3); expect(values.length).toBe(3);
let anotherObjectFound = false; let anotherObjectFound = false;
@@ -261,7 +259,7 @@ describe('rest query', () => {
expect(nullCounts).toBe(2); expect(nullCounts).toBe(2);
expect(anotherObjectFound).toBeTruthy(); expect(anotherObjectFound).toBeTruthy();
done(); done();
}, (err) => { }, (err) => {
console.error(err); console.error(err);
fail(err); fail(err);
done(); done();

View File

@@ -16,60 +16,60 @@ function createUser() {
describe_only_db('mongo')('revocable sessions', () => { describe_only_db('mongo')('revocable sessions', () => {
beforeEach((done) => { beforeEach((done) => {
// Create 1 user with the legacy // Create 1 user with the legacy
createUser().then(done); createUser().then(done);
}); });
it('should upgrade legacy session token', done => { it('should upgrade legacy session token', done => {
let user = Parse.Object.fromJSON({ let user = Parse.Object.fromJSON({
className: '_User', className: '_User',
objectId: '1234567890', objectId: '1234567890',
sessionToken: sessionToken sessionToken: sessionToken
}); });
user._upgradeToRevocableSession().then((res) => { user._upgradeToRevocableSession().then((res) => {
expect(res.getSessionToken().indexOf('r:')).toBe(0); expect(res.getSessionToken().indexOf('r:')).toBe(0);
const config = new Config(Parse.applicationId); const config = new Config(Parse.applicationId);
// use direct access to the DB to make sure we're not // use direct access to the DB to make sure we're not
// getting the session token stripped // getting the session token stripped
return config.database.loadSchema().then(schemaController => { return config.database.loadSchema().then(schemaController => {
return schemaController.getOneSchema('_User', true) return schemaController.getOneSchema('_User', true)
}).then((schema) => { }).then((schema) => {
return config.database.adapter.find('_User', schema, {objectId: '1234567890'}, {}) return config.database.adapter.find('_User', schema, {objectId: '1234567890'}, {})
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
expect(results[0].sessionToken).toBeUndefined(); expect(results[0].sessionToken).toBeUndefined();
}); });
}).then(() => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should be able to become with revocable session token', done => { it('should be able to become with revocable session token', done => {
let user = Parse.Object.fromJSON({ let user = Parse.Object.fromJSON({
className: '_User', className: '_User',
objectId: '1234567890', objectId: '1234567890',
sessionToken: sessionToken sessionToken: sessionToken
}); });
user._upgradeToRevocableSession().then((res) => { user._upgradeToRevocableSession().then((res) => {
expect(res.getSessionToken().indexOf('r:')).toBe(0); expect(res.getSessionToken().indexOf('r:')).toBe(0);
return Parse.User.logOut().then(() => { return Parse.User.logOut().then(() => {
return Parse.User.become(res.getSessionToken()) return Parse.User.become(res.getSessionToken())
}).then((user) => { }).then((user) => {
expect(user.id).toEqual('1234567890'); expect(user.id).toEqual('1234567890');
}); });
}).then(() => { }).then(() => {
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('should not upgrade bad legacy session token', done => { it('should not upgrade bad legacy session token', done => {
rp.post({ rp.post({
url: Parse.serverURL+'/upgradeToRevocableSession', url: Parse.serverURL+'/upgradeToRevocableSession',
headers: { headers: {
@@ -78,19 +78,19 @@ describe_only_db('mongo')('revocable sessions', () => {
'X-Parse-Session-Token': 'badSessionToken' 'X-Parse-Session-Token': 'badSessionToken'
}, },
json: true json: true
}).then((res) => { }).then(() => {
fail('should not be able to upgrade a bad token'); fail('should not be able to upgrade a bad token');
}, (response) => { }, (response) => {
expect(response.statusCode).toBe(400); expect(response.statusCode).toBe(400);
expect(response.error).not.toBeUndefined(); expect(response.error).not.toBeUndefined();
expect(response.error.code).toBe(Parse.Error.INVALID_SESSION_TOKEN); expect(response.error.code).toBe(Parse.Error.INVALID_SESSION_TOKEN);
expect(response.error.error).toEqual('invalid legacy session token'); expect(response.error.error).toEqual('invalid legacy session token');
}).then(() => { }).then(() => {
done(); done();
}); });
}); });
it('should not crash without session token #2720', done => { it('should not crash without session token #2720', done => {
rp.post({ rp.post({
url: Parse.serverURL+'/upgradeToRevocableSession', url: Parse.serverURL+'/upgradeToRevocableSession',
headers: { headers: {
@@ -98,14 +98,14 @@ describe_only_db('mongo')('revocable sessions', () => {
'X-Parse-Rest-API-Key': 'rest' 'X-Parse-Rest-API-Key': 'rest'
}, },
json: true json: true
}).then((res) => { }).then(() => {
fail('should not be able to upgrade a bad token'); fail('should not be able to upgrade a bad token');
}, (response) => { }, (response) => {
expect(response.statusCode).toBe(404); expect(response.statusCode).toBe(404);
expect(response.error).not.toBeUndefined(); expect(response.error).not.toBeUndefined();
expect(response.error.code).toBe(Parse.Error.OBJECT_NOT_FOUND); expect(response.error.code).toBe(Parse.Error.OBJECT_NOT_FOUND);
expect(response.error.error).toEqual('invalid session'); expect(response.error.error).toEqual('invalid session');
}).then(() => { }).then(() => {
done(); done();
}); });
}); });

View File

@@ -20,14 +20,14 @@ var hasAllPODobject = () => {
}; };
describe('SchemaController', () => { describe('SchemaController', () => {
beforeEach(() => { beforeEach(() => {
config = new Config('test'); config = new Config('test');
}); });
it('can validate one object', (done) => { it('can validate one object', (done) => {
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
return schema.validateObject('TestObject', {a: 1, b: 'yo', c: false}); return schema.validateObject('TestObject', {a: 1, b: 'yo', c: false});
}).then((schema) => { }).then(() => {
done(); done();
}, (error) => { }, (error) => {
jfail(error); jfail(error);
@@ -38,7 +38,7 @@ describe('SchemaController', () => {
it('can validate one object with dot notation', (done) => { it('can validate one object with dot notation', (done) => {
config.database.loadSchema().then((schema) => { config.database.loadSchema().then((schema) => {
return schema.validateObject('TestObjectWithSubDoc', {x: false, y: 'YY', z: 1, 'aObject.k1': 'newValue'}); return schema.validateObject('TestObjectWithSubDoc', {x: false, y: 'YY', z: 1, 'aObject.k1': 'newValue'});
}).then((schema) => { }).then(() => {
done(); done();
}, (error) => { }, (error) => {
jfail(error); jfail(error);
@@ -51,7 +51,7 @@ describe('SchemaController', () => {
return schema.validateObject('Foo', {x: true, y: 'yyy', z: 0}); return schema.validateObject('Foo', {x: true, y: 'yyy', z: 0});
}).then((schema) => { }).then((schema) => {
return schema.validateObject('Foo', {x: false, y: 'YY', z: 1}); return schema.validateObject('Foo', {x: false, y: 'YY', z: 1});
}).then((schema) => { }).then(() => {
done(); done();
}); });
}); });
@@ -61,7 +61,7 @@ describe('SchemaController', () => {
return schema.validateObject('Stuff', {aRelation: {__type:'Relation',className:'Stuff'}}); return schema.validateObject('Stuff', {aRelation: {__type:'Relation',className:'Stuff'}});
}).then((schema) => { }).then((schema) => {
return schema.validateObject('Stuff', {aRelation: {__type:'Pointer',className:'Stuff'}}) return schema.validateObject('Stuff', {aRelation: {__type:'Pointer',className:'Stuff'}})
.then((schema) => { .then(() => {
fail('expected invalidity'); fail('expected invalidity');
done(); done();
}, done); }, done);
@@ -103,13 +103,13 @@ describe('SchemaController', () => {
return schema.setPermissions('Stuff', { return schema.setPermissions('Stuff', {
'find': {} 'find': {}
}); });
}).then((schema) => { }).then(() => {
var query = new Parse.Query('Stuff'); var query = new Parse.Query('Stuff');
return query.find(); return query.find();
}).then((results) => { }).then(() => {
fail('Class permissions should have rejected this query.'); fail('Class permissions should have rejected this query.');
done(); done();
}, (e) => { }, () => {
done(); done();
}); });
}); });
@@ -128,12 +128,12 @@ describe('SchemaController', () => {
return schema.setPermissions('Stuff', { return schema.setPermissions('Stuff', {
'find': find 'find': find
}); });
}).then((schema) => { }).then(() => {
var query = new Parse.Query('Stuff'); var query = new Parse.Query('Stuff');
return query.find(); return query.find();
}).then((results) => { }).then(() => {
done(); done();
}, (e) => { }, () => {
fail('Class permissions should have allowed this query.'); fail('Class permissions should have allowed this query.');
done(); done();
}); });
@@ -155,7 +155,7 @@ describe('SchemaController', () => {
'find': find, 'find': find,
'get': get 'get': get
}); });
}).then((schema) => { }).then(() => {
obj = new Parse.Object('Stuff'); obj = new Parse.Object('Stuff');
obj.set('foo', 'bar'); obj.set('foo', 'bar');
return obj.save(); return obj.save();
@@ -163,14 +163,14 @@ describe('SchemaController', () => {
obj = o; obj = o;
var query = new Parse.Query('Stuff'); var query = new Parse.Query('Stuff');
return query.find(); return query.find();
}).then((results) => { }).then(() => {
fail('Class permissions should have rejected this query.'); fail('Class permissions should have rejected this query.');
done(); done();
}, (e) => { }, () => {
var query = new Parse.Query('Stuff'); var query = new Parse.Query('Stuff');
return query.get(obj.id).then((o) => { return query.get(obj.id).then(() => {
done(); done();
}, (e) => { }, () => {
fail('Class permissions should have allowed this get query'); fail('Class permissions should have allowed this get query');
done(); done();
}); });
@@ -427,7 +427,6 @@ describe('SchemaController', () => {
ACL: { type: 'ACL' }, ACL: { type: 'ACL' },
aString: { type: 'String' }, aString: { type: 'String' },
aNumber: { type: 'Number' }, aNumber: { type: 'Number' },
aString: { type: 'String' },
aBool: { type: 'Boolean' }, aBool: { type: 'Boolean' },
aDate: { type: 'Date' }, aDate: { type: 'Date' },
aObject: { type: 'Object' }, aObject: { type: 'Object' },
@@ -591,7 +590,7 @@ describe('SchemaController', () => {
jfail(error); jfail(error);
}); });
}) })
.catch(error => fail('Couldn\'t load schema')); .catch(() => fail('Couldn\'t load schema'));
}); });
it('refuses to delete fields from invalid class names', done => { it('refuses to delete fields from invalid class names', done => {
@@ -703,10 +702,10 @@ describe('SchemaController', () => {
}) })
.then(() => config.database.collectionExists('_Join:relationField:NewClass')) .then(() => config.database.collectionExists('_Join:relationField:NewClass'))
.then(exist => { .then(exist => {
on_db('postgres', () => { on_db('postgres', () => {
// We create the table when creating the column // We create the table when creating the column
expect(exist).toEqual(true); expect(exist).toEqual(true);
}, () => { }, () => {
expect(exist).toEqual(false); expect(exist).toEqual(false);
}); });
@@ -730,7 +729,7 @@ describe('SchemaController', () => {
Parse.Object.disableSingleInstance(); Parse.Object.disableSingleInstance();
var obj1 = hasAllPODobject(); var obj1 = hasAllPODobject();
var obj2 = hasAllPODobject(); var obj2 = hasAllPODobject();
var p = Parse.Object.saveAll([obj1, obj2]) Parse.Object.saveAll([obj1, obj2])
.then(() => config.database.loadSchema()) .then(() => config.database.loadSchema())
.then(schema => schema.deleteField('aString', 'HasAllPOD', config.database)) .then(schema => schema.deleteField('aString', 'HasAllPOD', config.database))
.then(() => new Parse.Query('HasAllPOD').get(obj1.id)) .then(() => new Parse.Query('HasAllPOD').get(obj1.id))
@@ -824,58 +823,58 @@ describe('SchemaController', () => {
done(); done();
}); });
it('yields a proper schema mismatch error (#2661)', done => { it('yields a proper schema mismatch error (#2661)', done => {
let anObject = new Parse.Object('AnObject'); let anObject = new Parse.Object('AnObject');
let anotherObject = new Parse.Object('AnotherObject'); let anotherObject = new Parse.Object('AnotherObject');
let someObject = new Parse.Object('SomeObject'); let someObject = new Parse.Object('SomeObject');
Parse.Object.saveAll([anObject, anotherObject, someObject]).then(() => { Parse.Object.saveAll([anObject, anotherObject, someObject]).then(() => {
anObject.set('pointer', anotherObject); anObject.set('pointer', anotherObject);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
anObject.set('pointer', someObject); anObject.set('pointer', someObject);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
fail('shoud not save correctly'); fail('shoud not save correctly');
done(); done();
}, (err) => { }, (err) => {
expect(err instanceof Parse.Error).toBeTruthy(); expect(err instanceof Parse.Error).toBeTruthy();
expect(err.message).toEqual('schema mismatch for AnObject.pointer; expected Pointer<AnotherObject> but got Pointer<SomeObject>') expect(err.message).toEqual('schema mismatch for AnObject.pointer; expected Pointer<AnotherObject> but got Pointer<SomeObject>')
done(); done();
}); });
}); });
it('yields a proper schema mismatch error bis (#2661)', done => { it('yields a proper schema mismatch error bis (#2661)', done => {
let anObject = new Parse.Object('AnObject'); let anObject = new Parse.Object('AnObject');
let someObject = new Parse.Object('SomeObject'); let someObject = new Parse.Object('SomeObject');
Parse.Object.saveAll([anObject, someObject]).then(() => { Parse.Object.saveAll([anObject, someObject]).then(() => {
anObject.set('number', 1); anObject.set('number', 1);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
anObject.set('number', someObject); anObject.set('number', someObject);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
fail('shoud not save correctly'); fail('shoud not save correctly');
done(); done();
}, (err) => { }, (err) => {
expect(err instanceof Parse.Error).toBeTruthy(); expect(err instanceof Parse.Error).toBeTruthy();
expect(err.message).toEqual('schema mismatch for AnObject.number; expected Number but got Pointer<SomeObject>') expect(err.message).toEqual('schema mismatch for AnObject.number; expected Number but got Pointer<SomeObject>')
done(); done();
}); });
}); });
it('yields a proper schema mismatch error ter (#2661)', done => { it('yields a proper schema mismatch error ter (#2661)', done => {
let anObject = new Parse.Object('AnObject'); let anObject = new Parse.Object('AnObject');
let someObject = new Parse.Object('SomeObject'); let someObject = new Parse.Object('SomeObject');
Parse.Object.saveAll([anObject, someObject]).then(() => { Parse.Object.saveAll([anObject, someObject]).then(() => {
anObject.set('pointer', someObject); anObject.set('pointer', someObject);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
anObject.set('pointer', 1); anObject.set('pointer', 1);
return anObject.save(); return anObject.save();
}).then(() => { }).then(() => {
fail('shoud not save correctly'); fail('shoud not save correctly');
done(); done();
}, (err) => { }, (err) => {
expect(err instanceof Parse.Error).toBeTruthy(); expect(err instanceof Parse.Error).toBeTruthy();
expect(err.message).toEqual('schema mismatch for AnObject.pointer; expected Pointer<SomeObject> but got Number') expect(err.message).toEqual('schema mismatch for AnObject.pointer; expected Pointer<SomeObject> but got Number')
done(); done();

View File

@@ -17,7 +17,7 @@ describe('SessionTokenCache', function() {
it('can get undefined userId', function(done) { it('can get undefined userId', function(done) {
var sessionTokenCache = new SessionTokenCache(); var sessionTokenCache = new SessionTokenCache();
sessionTokenCache.getUserId(undefined).then((userIdFromCache) => { sessionTokenCache.getUserId(undefined).then(() => {
}, (error) => { }, (error) => {
expect(error).not.toBeNull(); expect(error).not.toBeNull();
done(); done();

View File

@@ -1,7 +1,7 @@
let twitter = require('../src/authDataManager/twitter'); let twitter = require('../src/authDataManager/twitter');
describe('Twitter Auth', () => { describe('Twitter Auth', () => {
it('should use the proper configuration', () => { it('should use the proper configuration', () => {
// Multiple options, consumer_key found // Multiple options, consumer_key found
expect(twitter.handleMultipleConfigurations({ expect(twitter.handleMultipleConfigurations({
consumer_key: 'hello', consumer_key: 'hello',

View File

@@ -1,6 +1,5 @@
'use strict'; 'use strict';
var request = require('request');
const Parse = require("parse/node"); const Parse = require("parse/node");
let Config = require('../src/Config'); let Config = require('../src/Config');

View File

@@ -55,7 +55,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
done(); done();
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -89,7 +89,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
done(); done();
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -132,7 +132,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
}, 200); }, 200);
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -179,7 +179,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
}, 200); }, 200);
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -220,8 +220,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.fetch() user.fetch()
.then((user) => { .then((user) => {
return user.save(); return user.save();
}).then((user) => { }).then(() => {
return Parse.User.requestPasswordReset("testSendSimpleAdapter@parse.com").catch((err) => { return Parse.User.requestPasswordReset("testSendSimpleAdapter@parse.com").catch(() => {
fail('Should not fail requesting a password'); fail('Should not fail requesting a password');
done(); done();
}) })
@@ -230,7 +230,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
done(); done();
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -256,8 +256,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.logIn("zxcv", "asdf")) .then(() => Parse.User.logIn("zxcv", "asdf"))
.then(result => { .then(() => {
fail('login should have failed'); fail('login should have failed');
done(); done();
}, error => { }, error => {
@@ -296,8 +296,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
}).then(() => { }).then(() => {
expect(sendEmailOptions).not.toBeUndefined(); expect(sendEmailOptions).not.toBeUndefined();
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user');
user.fetch() user.fetch()
@@ -309,7 +309,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
expect(typeof user).toBe('object'); expect(typeof user).toBe('object');
expect(user.get('emailVerified')).toBe(true); expect(user.get('emailVerified')).toBe(true);
done(); done();
}, error => { }, () => {
fail('login should have succeeded'); fail('login should have succeeded');
done(); done();
}); });
@@ -343,12 +343,12 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.logIn("zxcv", "asdf")) .then(() => Parse.User.logIn("zxcv", "asdf"))
.then(user => { .then(user => {
expect(typeof user).toBe('object'); expect(typeof user).toBe('object');
expect(user.get('emailVerified')).toBe(false); expect(user.get('emailVerified')).toBe(false);
done(); done();
}, error => { }, () => {
fail('login should have succeeded'); fail('login should have succeeded');
done(); done();
}); });
@@ -375,7 +375,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com")) .then(() => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => { .then(result => {
console.log(result); console.log(result);
fail('sending password reset email should not have succeeded'); fail('sending password reset email should not have succeeded');
@@ -406,7 +406,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com")) .then(() => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => { .then(result => {
console.log(result); console.log(result);
fail('sending password reset email should not have succeeded'); fail('sending password reset email should not have succeeded');
@@ -434,7 +434,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com")) .then(() => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => { .then(result => {
console.log(result); console.log(result);
fail('sending password reset email should not have succeeded'); fail('sending password reset email should not have succeeded');
@@ -466,8 +466,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setUsername("zxcv"); user.setUsername("zxcv");
user.set("email", "testInvalidConfig@parse.com"); user.set("email", "testInvalidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testInvalidConfig@parse.com")) .then(() => Parse.User.requestPasswordReset("testInvalidConfig@parse.com"))
.then(result => { .then(() => {
done(); done();
}, error => { }, error => {
done(error); done(error);
@@ -504,8 +504,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.setPassword("asdf"); user.setPassword("asdf");
user.setUsername("testValidConfig@parse.com"); user.setUsername("testValidConfig@parse.com");
user.signUp(null) user.signUp(null)
.then(user => Parse.User.requestPasswordReset("testValidConfig@parse.com")) .then(() => Parse.User.requestPasswordReset("testValidConfig@parse.com"))
.then(result => { .then(() => {
expect(adapter.sendMail).toHaveBeenCalled(); expect(adapter.sendMail).toHaveBeenCalled();
done(); done();
}, error => { }, error => {
@@ -544,7 +544,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
done(); done();
}); });
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -579,7 +579,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
expect(emailSent).toBe(true); expect(emailSent).toBe(true);
done(); done();
}, },
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -611,8 +611,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
}).then(() => { }).then(() => {
expect(sendEmailOptions).not.toBeUndefined(); expect(sendEmailOptions).not.toBeUndefined();
request.get(sendEmailOptions.link, { request.get(sendEmailOptions.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user');
user.fetch() user.fetch()
@@ -645,7 +645,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
.then(() => { .then(() => {
request.get('http://localhost:8378/1/apps/test/verify_email', { request.get('http://localhost:8378/1/apps/test/verify_email', {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done() done()
@@ -667,7 +667,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
.then(() => { .then(() => {
request.get('http://localhost:8378/1/apps/test/verify_email?token=asdfasdf&username=sadfasga', { request.get('http://localhost:8378/1/apps/test/verify_email?token=asdfasdf&username=sadfasga', {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done(); done();
@@ -678,10 +678,10 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
it('does not update email verified if you use an invalid token', done => { it('does not update email verified if you use an invalid token', done => {
var user = new Parse.User(); var user = new Parse.User();
var emailAdapter = { var emailAdapter = {
sendVerificationEmail: options => { sendVerificationEmail: () => {
request.get('http://localhost:8378/1/apps/test/verify_email?token=invalid&username=zxcv', { request.get('http://localhost:8378/1/apps/test/verify_email?token=invalid&username=zxcv', {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
user.fetch() user.fetch()
@@ -706,7 +706,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
user.set('email', 'user@parse.com'); user.set('email', 'user@parse.com');
user.signUp(null, { user.signUp(null, {
success: () => {}, success: () => {},
error: function(userAgain, error) { error: function() {
fail('Failed to save user'); fail('Failed to save user');
done(); done();
} }
@@ -721,9 +721,9 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
sendPasswordResetEmail: options => { sendPasswordResetEmail: options => {
request.get(options.link, { request.get(options.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
if (error) { if (error) {
jfail(err); jfail(error);
fail("Failed to get the reset link"); fail("Failed to get the reset link");
return; return;
} }
@@ -771,7 +771,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
.then(() => { .then(() => {
request.get('http://localhost:8378/1/apps/test/request_password_reset?token=asdfasdf&username=sadfasga', { request.get('http://localhost:8378/1/apps/test/request_password_reset?token=asdfasdf&username=sadfasga', {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
done(); done();
@@ -786,7 +786,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
sendPasswordResetEmail: options => { sendPasswordResetEmail: options => {
request.get(options.link, { request.get(options.link, {
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
if (error) { if (error) {
jfail(error); jfail(error);
fail("Failed to get the reset link"); fail("Failed to get the reset link");
@@ -806,10 +806,10 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
url: "http://localhost:8378/1/apps/test/request_password_reset" , url: "http://localhost:8378/1/apps/test/request_password_reset" ,
body: `new_password=hello&token=${token}&username=zxcv`, body: `new_password=hello&token=${token}&username=zxcv`,
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
}, },
followRedirect: false, followRedirect: false,
}, (error, response, body) => { }, (error, response) => {
if (error) { if (error) {
jfail(error); jfail(error);
fail("Failed to POST request password reset"); fail("Failed to POST request password reset");
@@ -818,7 +818,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
expect(response.statusCode).toEqual(302); expect(response.statusCode).toEqual(302);
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=zxcv'); expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=zxcv');
Parse.User.logIn("zxcv", "hello").then(function(user){ Parse.User.logIn("zxcv", "hello").then(function(){
let config = new Config('test'); let config = new Config('test');
config.database.adapter.find('_User', { fields: {} }, { 'username': 'zxcv' }, { limit: 1 }) config.database.adapter.find('_User', { fields: {} }, { 'username': 'zxcv' }, { limit: 1 })
.then(results => { .then(results => {

View File

@@ -1,37 +1,36 @@
'use strict'; 'use strict';
var WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; var WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter;
var Parse = require('parse/node').Parse;
var request = require('request'); var request = require('request');
describe('info logs', () => { describe('info logs', () => {
it("Verify INFO logs", (done) => { it("Verify INFO logs", (done) => {
var winstonLoggerAdapter = new WinstonLoggerAdapter(); var winstonLoggerAdapter = new WinstonLoggerAdapter();
winstonLoggerAdapter.log('info', 'testing info logs', () => { winstonLoggerAdapter.log('info', 'testing info logs', () => {
winstonLoggerAdapter.query({
from: new Date(Date.now() - 500),
size: 100,
level: 'info'
}, (results) => {
if (results.length == 0) {
fail('The adapter should return non-empty results');
} else {
expect(results[0].message).toEqual('testing info logs');
}
// Check the error log
// Regression #2639
winstonLoggerAdapter.query({ winstonLoggerAdapter.query({
from: new Date(Date.now() - 500), from: new Date(Date.now() - 500),
size: 100, size: 100,
level: 'info' level: 'error'
}, (results) => { }, (results) => {
if (results.length == 0) { expect(results.length).toEqual(0);
fail('The adapter should return non-empty results'); done();
} else {
expect(results[0].message).toEqual('testing info logs');
}
// Check the error log
// Regression #2639
winstonLoggerAdapter.query({
from: new Date(Date.now() - 500),
size: 100,
level: 'error'
}, (results) => {
expect(results.length).toEqual(0);
done();
});
}); });
}); });
}); });
});
}); });
describe('error logs', () => { describe('error logs', () => {
@@ -79,7 +78,7 @@ describe('verbose logs', () => {
request.get({ request.get({
headers: headers, headers: headers,
url: 'http://localhost:8378/1/login?username=test&password=moon-y' url: 'http://localhost:8378/1/login?username=test&password=moon-y'
}, (error, response, body) => { }, () => {
let winstonLoggerAdapter = new WinstonLoggerAdapter(); let winstonLoggerAdapter = new WinstonLoggerAdapter();
return winstonLoggerAdapter.query({ return winstonLoggerAdapter.query({
from: new Date(Date.now() - 500), from: new Date(Date.now() - 500),
@@ -92,7 +91,7 @@ describe('verbose logs', () => {
done(); done();
}); });
}); });
}).catch((err) => { }).catch((err) => {
fail(JSON.stringify(err)); fail(JSON.stringify(err));
done(); done();
}) })

View File

@@ -25,7 +25,6 @@ if (global._babelPolyfill) {
var cache = require('../src/cache').default; var cache = require('../src/cache').default;
var express = require('express'); var express = require('express');
var facebook = require('../src/authDataManager/facebook');
var ParseServer = require('../src/index').ParseServer; var ParseServer = require('../src/index').ParseServer;
var path = require('path'); var path = require('path');
var TestUtils = require('../src/TestUtils'); var TestUtils = require('../src/TestUtils');
@@ -40,8 +39,8 @@ const postgresURI = 'postgres://localhost:5432/parse_server_postgres_adapter_tes
let databaseAdapter; let databaseAdapter;
// need to bind for mocking mocha // need to bind for mocking mocha
let startDB = () => {}; let startDB = () => {};
let stopDB = () => {}; let stopDB = () => {};
if (process.env.PARSE_SERVER_TEST_DB === 'postgres') { if (process.env.PARSE_SERVER_TEST_DB === 'postgres') {
databaseAdapter = new PostgresStorageAdapter({ databaseAdapter = new PostgresStorageAdapter({
@@ -53,7 +52,7 @@ if (process.env.PARSE_SERVER_TEST_DB === 'postgres') {
timeout: () => {}, timeout: () => {},
slow: () => {} slow: () => {}
}); });
stopDB = require('mongodb-runner/mocha/after');; stopDB = require('mongodb-runner/mocha/after');
databaseAdapter = new MongoStorageAdapter({ databaseAdapter = new MongoStorageAdapter({
uri: mongoURI, uri: mongoURI,
collectionPrefix: 'test_', collectionPrefix: 'test_',
@@ -64,9 +63,9 @@ var port = 8378;
let filesAdapter; let filesAdapter;
on_db('mongo', () => { on_db('mongo', () => {
filesAdapter = new GridStoreAdapter(mongoURI); filesAdapter = new GridStoreAdapter(mongoURI);
}, () => { }, () => {
filesAdapter = new FSAdapter(); filesAdapter = new FSAdapter();
}); });
@@ -121,7 +120,7 @@ let openConnections = {};
var app = express(); var app = express();
var api = new ParseServer(defaultConfiguration); var api = new ParseServer(defaultConfiguration);
app.use('/1', api); app.use('/1', api);
app.use('/1', (req, res) => { app.use('/1', () => {
fail('should not call next'); fail('should not call next');
}); });
var server = app.listen(port); var server = app.listen(port);
@@ -143,7 +142,7 @@ const reconfigureServer = changedConfiguration => {
api = new ParseServer(newConfiguration); api = new ParseServer(newConfiguration);
api.use(require('./testing-routes').router); api.use(require('./testing-routes').router);
app.use('/1', api); app.use('/1', api);
app.use('/1', (req, res) => { app.use('/1', () => {
fail('should not call next'); fail('should not call next');
}); });
server = app.listen(port); server = app.listen(port);
@@ -195,7 +194,7 @@ beforeEach(done => {
Parse.initialize('test', 'test', 'test'); Parse.initialize('test', 'test', 'test');
Parse.serverURL = 'http://localhost:' + port + '/1'; Parse.serverURL = 'http://localhost:' + port + '/1';
done(); done();
}, error => { }, () => {
Parse.initialize('test', 'test', 'test'); Parse.initialize('test', 'test', 'test');
Parse.serverURL = 'http://localhost:' + port + '/1'; Parse.serverURL = 'http://localhost:' + port + '/1';
// fail(JSON.stringify(error)); // fail(JSON.stringify(error));
@@ -284,7 +283,7 @@ function notEqual(a, b, message) {
function expectSuccess(params, done) { function expectSuccess(params, done) {
return { return {
success: params.success, success: params.success,
error: function(e) { error: function() {
fail('failure happened in expectSuccess'); fail('failure happened in expectSuccess');
done ? done() : null; done ? done() : null;
}, },
@@ -417,7 +416,7 @@ global.describe_only_db = db => {
} else if (!process.env.PARSE_SERVER_TEST_DB && db == 'mongo') { } else if (!process.env.PARSE_SERVER_TEST_DB && db == 'mongo') {
return describe; return describe;
} else { } else {
return () => {}; return () => {};
} }
} }

View File

@@ -9,7 +9,7 @@ var express = require('express');
const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter'); const MongoStorageAdapter = require('../src/Adapters/Storage/Mongo/MongoStorageAdapter');
describe('server', () => { describe('server', () => {
it('requires a master key and app id', done => { it('requires a master key and app id', done => {
reconfigureServer({ appId: undefined }) reconfigureServer({ appId: undefined })
.catch(error => { .catch(error => {
expect(error).toEqual('You must provide an appId!'); expect(error).toEqual('You must provide an appId!');
@@ -32,7 +32,7 @@ describe('server', () => {
headers: { headers: {
'Authorization': 'Basic ' + new Buffer('test:' + 'test').toString('base64') 'Authorization': 'Basic ' + new Buffer('test:' + 'test').toString('base64')
} }
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
done(); done();
}); });
@@ -46,7 +46,7 @@ describe('server', () => {
headers: { headers: {
'Authorization': 'Basic ' + new Buffer('test:javascript-key=' + 'test').toString('base64') 'Authorization': 'Basic ' + new Buffer('test:javascript-key=' + 'test').toString('base64')
} }
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
done(); done();
}); });
@@ -167,20 +167,20 @@ describe('server', () => {
it('can respond 200 on path health', done => { it('can respond 200 on path health', done => {
request.get({ request.get({
url: 'http://localhost:8378/1/health', url: 'http://localhost:8378/1/health',
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toBe(200); expect(response.statusCode).toBe(200);
done(); done();
}); });
}); });
it('can create a parse-server v1', done => { it('can create a parse-server v1', done => {
var parseServer = new ParseServer.default(Object.assign({}, var parseServer = new ParseServer.default(Object.assign({},
defaultConfiguration, { defaultConfiguration, {
appId: "aTestApp", appId: "aTestApp",
masterKey: "aTestMasterKey", masterKey: "aTestMasterKey",
serverURL: "http://localhost:12666/parse", serverURL: "http://localhost:12666/parse",
__indexBuildCompletionCallbackForTests: promise => { __indexBuildCompletionCallbackForTests: promise => {
promise promise
.then(() => { .then(() => {
expect(Parse.applicationId).toEqual("aTestApp"); expect(Parse.applicationId).toEqual("aTestApp");
var app = express(); var app = express();
@@ -189,31 +189,31 @@ describe('server', () => {
var server = app.listen(12666); var server = app.listen(12666);
var obj = new Parse.Object("AnObject"); var obj = new Parse.Object("AnObject");
var objId; var objId;
obj.save().then((obj) => { obj.save().then((obj) => {
objId = obj.id; objId = obj.id;
var q = new Parse.Query("AnObject"); var q = new Parse.Query("AnObject");
return q.first(); return q.first();
}).then((obj) => { }).then((obj) => {
expect(obj.id).toEqual(objId); expect(obj.id).toEqual(objId);
server.close(done); server.close(done);
}).fail((err) => { }).fail(() => {
server.close(done); server.close(done);
}) })
}); });
}}) }})
); );
}); });
it('can create a parse-server v2', done => { it('can create a parse-server v2', done => {
let objId; let objId;
let server let server
let parseServer = ParseServer.ParseServer(Object.assign({}, let parseServer = ParseServer.ParseServer(Object.assign({},
defaultConfiguration, { defaultConfiguration, {
appId: "anOtherTestApp", appId: "anOtherTestApp",
masterKey: "anOtherTestMasterKey", masterKey: "anOtherTestMasterKey",
serverURL: "http://localhost:12667/parse", serverURL: "http://localhost:12667/parse",
__indexBuildCompletionCallbackForTests: promise => { __indexBuildCompletionCallbackForTests: promise => {
promise promise
.then(() => { .then(() => {
expect(Parse.applicationId).toEqual("anOtherTestApp"); expect(Parse.applicationId).toEqual("anOtherTestApp");
let app = express(); let app = express();
@@ -223,12 +223,12 @@ describe('server', () => {
let obj = new Parse.Object("AnObject"); let obj = new Parse.Object("AnObject");
return obj.save() return obj.save()
}) })
.then(obj => { .then(obj => {
objId = obj.id; objId = obj.id;
let q = new Parse.Query("AnObject"); let q = new Parse.Query("AnObject");
return q.first(); return q.first();
}) })
.then(obj => { .then(obj => {
expect(obj.id).toEqual(objId); expect(obj.id).toEqual(objId);
server.close(done); server.close(done);
}) })
@@ -240,11 +240,11 @@ describe('server', () => {
done(); done();
} }
}); });
}} }}
)); ));
}); });
it('has createLiveQueryServer', done => { it('has createLiveQueryServer', done => {
// original implementation through the factory // original implementation through the factory
expect(typeof ParseServer.ParseServer.createLiveQueryServer).toEqual('function'); expect(typeof ParseServer.ParseServer.createLiveQueryServer).toEqual('function');
// For import calls // For import calls
@@ -261,7 +261,7 @@ describe('server', () => {
done(); done();
}); });
it('properly gives publicServerURL when set', done => { it('properly gives publicServerURL when set', done => {
reconfigureServer({ publicServerURL: 'https://myserver.com/1' }) reconfigureServer({ publicServerURL: 'https://myserver.com/1' })
.then(() => { .then(() => {
var config = new Config('test', 'http://localhost:8378/1'); var config = new Config('test', 'http://localhost:8378/1');
@@ -270,7 +270,7 @@ describe('server', () => {
}); });
}); });
it('properly removes trailing slash in mount', done => { it('properly removes trailing slash in mount', done => {
reconfigureServer({}) reconfigureServer({})
.then(() => { .then(() => {
var config = new Config('test', 'http://localhost:8378/1/'); var config = new Config('test', 'http://localhost:8378/1/');
@@ -279,7 +279,7 @@ describe('server', () => {
}); });
}); });
it('should throw when getting invalid mount', done => { it('should throw when getting invalid mount', done => {
reconfigureServer({ publicServerURL: 'blabla:/some' }) reconfigureServer({ publicServerURL: 'blabla:/some' })
.catch(error => { .catch(error => {
expect(error).toEqual('publicServerURL should be a valid HTTPS URL starting with https://') expect(error).toEqual('publicServerURL should be a valid HTTPS URL starting with https://')

View File

@@ -5,30 +5,30 @@ import {
} from '../src/cli/utils/parsers'; } from '../src/cli/utils/parsers';
describe('parsers', () => { describe('parsers', () => {
it('parses correctly with numberParser', () => { it('parses correctly with numberParser', () => {
const parser = numberParser('key'); const parser = numberParser('key');
expect(parser(2)).toEqual(2); expect(parser(2)).toEqual(2);
expect(parser('2')).toEqual(2); expect(parser('2')).toEqual(2);
expect(() => {parser('string')}).toThrow(); expect(() => {parser('string')}).toThrow();
}); });
it('parses correctly with numberOrBoolParser', () => { it('parses correctly with numberOrBoolParser', () => {
const parser = numberOrBoolParser('key'); const parser = numberOrBoolParser('key');
expect(parser(true)).toEqual(true); expect(parser(true)).toEqual(true);
expect(parser(false)).toEqual(false); expect(parser(false)).toEqual(false);
expect(parser('true')).toEqual(true); expect(parser('true')).toEqual(true);
expect(parser('false')).toEqual(false); expect(parser('false')).toEqual(false);
expect(parser(1)).toEqual(1); expect(parser(1)).toEqual(1);
expect(parser('1')).toEqual(1); expect(parser('1')).toEqual(1);
}); });
it('parses correctly with booleanParser', () => { it('parses correctly with booleanParser', () => {
const parser = booleanParser; const parser = booleanParser;
expect(parser(true)).toEqual(true); expect(parser(true)).toEqual(true);
expect(parser(false)).toEqual(false); expect(parser(false)).toEqual(false);
expect(parser('true')).toEqual(true); expect(parser('true')).toEqual(true);
expect(parser('false')).toEqual(false); expect(parser('false')).toEqual(false);
expect(parser(1)).toEqual(true); expect(parser(1)).toEqual(true);
expect(parser(2)).toEqual(false); expect(parser(2)).toEqual(false);
}); });
}); });

View File

@@ -118,8 +118,8 @@ var masterKeyHeaders = {
describe('schemas', () => { describe('schemas', () => {
beforeEach(() => { beforeEach(() => {
config.database.schemaCache.clear(); config.database.schemaCache.clear();
}); });
it('requires the master key to get all schemas', (done) => { it('requires the master key to get all schemas', (done) => {
@@ -298,7 +298,7 @@ describe('schemas', () => {
body: { body: {
className: 'A', className: 'A',
}, },
}, (error, response, body) => { }, (error) => {
expect(error).toEqual(null); expect(error).toEqual(null);
request.post({ request.post({
url: 'http://localhost:8378/1/schemas', url: 'http://localhost:8378/1/schemas',
@@ -350,7 +350,7 @@ describe('schemas', () => {
it('responds with all fields when getting incomplete schema', done => { it('responds with all fields when getting incomplete schema', done => {
config.database.loadSchema() config.database.loadSchema()
.then(schemaController => schemaController.addClassIfNotExists('_Installation', {}, defaultClassLevelPermissions)) .then(schemaController => schemaController.addClassIfNotExists('_Installation', {}, defaultClassLevelPermissions))
.then(() => { .then(() => {
request.get({ request.get({
url: 'http://localhost:8378/1/schemas/_Installation', url: 'http://localhost:8378/1/schemas/_Installation',
headers: masterKeyHeaders, headers: masterKeyHeaders,
@@ -417,7 +417,7 @@ describe('schemas', () => {
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
body: {}, body: {},
}, (error, response, body) => { }, () => {
request.put({ request.put({
url: 'http://localhost:8378/1/schemas/NewClass', url: 'http://localhost:8378/1/schemas/NewClass',
headers: noAuthHeaders, headers: noAuthHeaders,
@@ -452,7 +452,7 @@ describe('schemas', () => {
json: true, json: true,
body: { body: {
fields: { fields: {
newField: {type: 'String'} newField: {type: 'String'}
} }
} }
}, (error, response, body) => { }, (error, response, body) => {
@@ -607,7 +607,7 @@ describe('schemas', () => {
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
body: {}, body: {},
}, (error, response, body) => { }, () => {
request.put({ request.put({
url: 'http://localhost:8378/1/schemas/NewClass', url: 'http://localhost:8378/1/schemas/NewClass',
headers: masterKeyHeaders, headers: masterKeyHeaders,
@@ -656,7 +656,7 @@ describe('schemas', () => {
url: 'http://localhost:8378/1/schemas/_User', url: 'http://localhost:8378/1/schemas/_User',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true json: true
}, (error, response, body) => { }, () => {
request.put({ request.put({
url: 'http://localhost:8378/1/schemas/_User', url: 'http://localhost:8378/1/schemas/_User',
headers: masterKeyHeaders, headers: masterKeyHeaders,
@@ -781,7 +781,7 @@ describe('schemas', () => {
url: 'http://localhost:8378/1/schemas/HasAllPOD', url: 'http://localhost:8378/1/schemas/HasAllPOD',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.body).toEqual(plainOldDataSchema); expect(response.body).toEqual(plainOldDataSchema);
done(); done();
}); });
@@ -860,7 +860,7 @@ describe('schemas', () => {
url: 'http://localhost:8378/1/schemas/MyOtherClass', url: 'http://localhost:8378/1/schemas/MyOtherClass',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
expect(response.body).toEqual({}); expect(response.body).toEqual({});
config.database.collectionExists('_Join:aRelation:MyOtherClass').then(exists => { config.database.collectionExists('_Join:aRelation:MyOtherClass').then(exists => {
@@ -903,14 +903,14 @@ describe('schemas', () => {
body: { body: {
className: 'NewClassForDelete' className: 'NewClassForDelete'
} }
}, (error, response, body) => { }, (error, response) => {
expect(error).toEqual(null); expect(error).toEqual(null);
expect(response.body.className).toEqual('NewClassForDelete'); expect(response.body.className).toEqual('NewClassForDelete');
request.del({ request.del({
url: 'http://localhost:8378/1/schemas/NewClassForDelete', url: 'http://localhost:8378/1/schemas/NewClassForDelete',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
expect(response.body).toEqual({}); expect(response.body).toEqual({});
config.database.loadSchema().then(schema => { config.database.loadSchema().then(schema => {
@@ -931,27 +931,27 @@ describe('schemas', () => {
body: { body: {
className: 'NewClassForDelete' className: 'NewClassForDelete'
} }
}, (error, response, body) => { }, (error, response) => {
expect(error).toEqual(null); expect(error).toEqual(null);
expect(response.body.className).toEqual('NewClassForDelete'); expect(response.body.className).toEqual('NewClassForDelete');
request.post({ request.post({
url: 'http://localhost:8378/1/classes/NewClassForDelete', url: 'http://localhost:8378/1/classes/NewClassForDelete',
headers: restKeyHeaders, headers: restKeyHeaders,
json: true json: true
}, (error, response, body) => { }, (error, response) => {
expect(error).toEqual(null); expect(error).toEqual(null);
expect(typeof response.body.objectId).toEqual('string'); expect(typeof response.body.objectId).toEqual('string');
request.del({ request.del({
url: 'http://localhost:8378/1/classes/NewClassForDelete/' + response.body.objectId, url: 'http://localhost:8378/1/classes/NewClassForDelete/' + response.body.objectId,
headers: restKeyHeaders, headers: restKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error) => {
expect(error).toEqual(null); expect(error).toEqual(null);
request.del({ request.del({
url: 'http://localhost:8378/1/schemas/NewClassForDelete', url: 'http://localhost:8378/1/schemas/NewClassForDelete',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
expect(response.body).toEqual({}); expect(response.body).toEqual({});
config.database.loadSchema().then(schema => { config.database.loadSchema().then(schema => {
@@ -981,13 +981,13 @@ describe('schemas', () => {
} }
} }
} }
}, (error, response, body) => { }, (error) => {
expect(error).toEqual(null); expect(error).toEqual(null);
request.get({ request.get({
url: 'http://localhost:8378/1/schemas/AClass', url: 'http://localhost:8378/1/schemas/AClass',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
expect(response.body.classLevelPermissions).toEqual({ expect(response.body.classLevelPermissions).toEqual({
find: { find: {
@@ -1054,11 +1054,11 @@ describe('schemas', () => {
} }
} }
} }
}, (error, response, body) => { }, (error) => {
expect(error).toEqual(null); expect(error).toEqual(null);
let object = new Parse.Object('AClass'); let object = new Parse.Object('AClass');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
fail('should not be able to add a field'); fail('should not be able to add a field');
done(); done();
}, (err) => { }, (err) => {
@@ -1083,13 +1083,13 @@ describe('schemas', () => {
} }
} }
} }
}, (error, response, body) => { }, (error) => {
expect(error).toEqual(null); expect(error).toEqual(null);
let object = new Parse.Object('AClass'); let object = new Parse.Object('AClass');
object.set('hello', 'world'); object.set('hello', 'world');
return object.save().then(() => { return object.save().then(() => {
done(); done();
}, (err) => { }, () => {
fail('should be able to add a field'); fail('should be able to add a field');
done(); done();
}) })
@@ -1109,7 +1109,7 @@ describe('schemas', () => {
} }
} }
}, (error, response, body) => { }, (error, response, body) => {
expect(body.error).toEqual("'1234567890A' is not a valid key for class level permissions"); expect(body.error).toEqual("'1234567890A' is not a valid key for class level permissions");
done(); done();
}) })
}); });
@@ -1217,7 +1217,7 @@ describe('schemas', () => {
} }
} }
}, (error, response, body) => { }, (error, response, body) => {
expect(body.error).toEqual("'' is not a valid value for class level permissions find:*:"); expect(body.error).toEqual("'' is not a valid value for class level permissions find:*:");
done(); done();
}) })
}); });
@@ -1229,22 +1229,22 @@ describe('schemas', () => {
op = request.put; op = request.put;
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
op({ op({
url: 'http://localhost:8378/1/schemas/'+className, url: 'http://localhost:8378/1/schemas/'+className,
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
body: { body: {
classLevelPermissions: permissions classLevelPermissions: permissions
} }
}, (error, response, body) => { }, (error, response, body) => {
if (error) { if (error) {
return reject(error); return reject(error);
} }
if (body.error) { if (body.error) {
return reject(body); return reject(body);
} }
return resolve(body); return resolve(body);
}) })
}); });
} }
@@ -1263,33 +1263,33 @@ describe('schemas', () => {
'find': { 'find': {
'role:admin': true 'role:admin': true
} }
}).then(() => { }).then(() => {
return Parse.Object.saveAll([user, admin, role], {useMasterKey: true}); return Parse.Object.saveAll([user, admin, role], {useMasterKey: true});
}).then(()=> { }).then(()=> {
role.relation('users').add(admin); role.relation('users').add(admin);
return role.save(null, {useMasterKey: true}); return role.save(null, {useMasterKey: true});
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user').then(() => { return Parse.User.logIn('user', 'user').then(() => {
let obj = new Parse.Object('AClass'); let obj = new Parse.Object('AClass');
return obj.save(null, {useMasterKey: true}); return obj.save(null, {useMasterKey: true});
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((err) => { return query.find().then(() => {
fail('Use should hot be able to find!') fail('Use should hot be able to find!')
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}) })
}).then(() => { }).then(() => {
return Parse.User.logIn('admin', 'admin'); return Parse.User.logIn('admin', 'admin');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
done(); done();
}).catch( (err) => { }).catch( (err) => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -1310,21 +1310,21 @@ describe('schemas', () => {
'find': { 'find': {
'role:admin': true 'role:admin': true
} }
}).then(() => { }).then(() => {
return Parse.Object.saveAll([user, admin, role], {useMasterKey: true}); return Parse.Object.saveAll([user, admin, role], {useMasterKey: true});
}).then(()=> { }).then(()=> {
role.relation('users').add(admin); role.relation('users').add(admin);
return role.save(null, {useMasterKey: true}); return role.save(null, {useMasterKey: true});
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user').then(() => { return Parse.User.logIn('user', 'user').then(() => {
let obj = new Parse.Object('AClass'); let obj = new Parse.Object('AClass');
return obj.save(null, {useMasterKey: true}); return obj.save(null, {useMasterKey: true});
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((err) => { return query.find().then(() => {
fail('User should not be able to find!') fail('User should not be able to find!')
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}) })
@@ -1340,19 +1340,19 @@ describe('schemas', () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((result) => { return query.find().then((result) => {
expect(result.length).toBe(1); expect(result.length).toBe(1);
}, (err) => { }, () => {
fail('User should be able to find!') fail('User should be able to find!')
done(); done();
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('admin', 'admin'); return Parse.User.logIn('admin', 'admin');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
done(); done();
}).catch( (err) => { }).catch( (err) => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -1373,21 +1373,21 @@ describe('schemas', () => {
'find': { 'find': {
'role:admin': true 'role:admin': true
} }
}).then(() => { }).then(() => {
return Parse.Object.saveAll([user, admin, role], {useMasterKey: true}); return Parse.Object.saveAll([user, admin, role], {useMasterKey: true});
}).then(()=> { }).then(()=> {
role.relation('users').add(admin); role.relation('users').add(admin);
return role.save(null, {useMasterKey: true}); return role.save(null, {useMasterKey: true});
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user').then(() => { return Parse.User.logIn('user', 'user').then(() => {
let obj = new Parse.Object('AClass'); let obj = new Parse.Object('AClass');
return obj.save(null, {useMasterKey: true}); return obj.save(null, {useMasterKey: true});
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((err) => { return query.find().then(() => {
fail('User should not be able to find!') fail('User should not be able to find!')
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}) })
@@ -1398,13 +1398,13 @@ describe('schemas', () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((result) => { return query.find().then((result) => {
expect(result.length).toBe(1); expect(result.length).toBe(1);
}, (err) => { }, () => {
fail('User should be able to find!') fail('User should be able to find!')
done(); done();
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('admin', 'admin'); return Parse.User.logIn('admin', 'admin');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
@@ -1431,21 +1431,21 @@ describe('schemas', () => {
'find': { 'find': {
'role:admin': true 'role:admin': true
} }
}).then(() => { }).then(() => {
return Parse.Object.saveAll([user, admin, role], {useMasterKey: true}); return Parse.Object.saveAll([user, admin, role], {useMasterKey: true});
}).then(()=> { }).then(()=> {
role.relation('users').add(admin); role.relation('users').add(admin);
return role.save(null, {useMasterKey: true}); return role.save(null, {useMasterKey: true});
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user').then(() => { return Parse.User.logIn('user', 'user').then(() => {
let obj = new Parse.Object('AClass'); let obj = new Parse.Object('AClass');
return obj.save(null, {useMasterKey: true}); return obj.save(null, {useMasterKey: true});
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((err) => { return query.find().then(() => {
fail('User should not be able to find!') fail('User should not be able to find!')
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}) })
@@ -1455,28 +1455,28 @@ describe('schemas', () => {
'found': { 'found': {
'role:admin': true 'role:admin': true
} }
}, true).then(() => { }, true).then(() => {
fail("Should not be able to save a borked CLP"); fail("Should not be able to save a borked CLP");
}, () => { }, () => {
return Promise.resolve(); return Promise.resolve();
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((result) => { return query.find().then(() => {
fail('User should not be able to find!') fail('User should not be able to find!')
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}); });
}).then(() => { }).then(() => {
return Parse.User.logIn('admin', 'admin'); return Parse.User.logIn('admin', 'admin');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(1); expect(results.length).toBe(1);
done(); done();
}).catch( (err) => { }).catch( (err) => {
jfail(err); jfail(err);
done(); done();
}) })
@@ -1496,11 +1496,11 @@ describe('schemas', () => {
let role = new Parse.Role('admin', new Parse.ACL()); let role = new Parse.Role('admin', new Parse.ACL());
Promise.resolve().then(() => { Promise.resolve().then(() => {
return Parse.Object.saveAll([user, user2, admin, role], {useMasterKey: true}); return Parse.Object.saveAll([user, user2, admin, role], {useMasterKey: true});
}).then(()=> { }).then(()=> {
role.relation('users').add(admin); role.relation('users').add(admin);
return role.save(null, {useMasterKey: true}).then(() => { return role.save(null, {useMasterKey: true}).then(() => {
let perm = { let perm = {
find: {} find: {}
}; };
@@ -1508,8 +1508,8 @@ describe('schemas', () => {
perm['find'][user.id] = true; perm['find'][user.id] = true;
return setPermissionsOnClass('AClass', perm); return setPermissionsOnClass('AClass', perm);
}) })
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user').then(() => { return Parse.User.logIn('user', 'user').then(() => {
let obj = new Parse.Object('AClass'); let obj = new Parse.Object('AClass');
return obj.save(); return obj.save();
}) })
@@ -1517,38 +1517,38 @@ describe('schemas', () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find().then((res) => { return query.find().then((res) => {
expect(res.length).toEqual(1); expect(res.length).toEqual(1);
}, (err) => { }, () => {
fail('User should be able to find!') fail('User should be able to find!')
return Promise.resolve(); return Promise.resolve();
}) })
}).then(() => { }).then(() => {
return Parse.User.logIn('admin', 'admin'); return Parse.User.logIn('admin', 'admin');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then(() => {
fail("should not be able to read!"); fail("should not be able to read!");
return Promise.resolve(); return Promise.resolve();
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action create on class AClass.'); expect(err.message).toEqual('Permission denied for action create on class AClass.');
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
return Parse.User.logIn('user2', 'user2'); return Parse.User.logIn('user2', 'user2');
}).then( () => { }).then( () => {
let query = new Parse.Query('AClass'); let query = new Parse.Query('AClass');
return query.find(); return query.find();
}).then((results) => { }).then(() => {
fail("should not be able to read!"); fail("should not be able to read!");
return Promise.resolve(); return Promise.resolve();
}, (err) => { }, (err) => {
expect(err.message).toEqual('Permission denied for action find on class AClass.'); expect(err.message).toEqual('Permission denied for action find on class AClass.');
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
done(); done();
}); });
}); });
it('can query with include and CLP (issue #2005)', (done) => { it('can query with include and CLP (issue #2005)', (done) => {
setPermissionsOnClass('AnotherObject', { setPermissionsOnClass('AnotherObject', {
get: {"*": true}, get: {"*": true},
find: {}, find: {},
@@ -1556,43 +1556,43 @@ describe('schemas', () => {
update: {'*': true}, update: {'*': true},
delete: {'*': true}, delete: {'*': true},
addField:{'*': true} addField:{'*': true}
}).then(() => { }).then(() => {
let obj = new Parse.Object('AnObject'); let obj = new Parse.Object('AnObject');
let anotherObject = new Parse.Object('AnotherObject'); let anotherObject = new Parse.Object('AnotherObject');
return obj.save({ return obj.save({
anotherObject anotherObject
}) })
}).then(() => { }).then(() => {
let query = new Parse.Query('AnObject'); let query = new Parse.Query('AnObject');
query.include('anotherObject'); query.include('anotherObject');
return query.find(); return query.find();
}).then((res) => { }).then((res) => {
expect(res.length).toBe(1); expect(res.length).toBe(1);
expect(res[0].get('anotherObject')).not.toBeUndefined(); expect(res[0].get('anotherObject')).not.toBeUndefined();
done(); done();
}).catch((err) => { }).catch((err) => {
jfail(err); jfail(err);
done(); done();
}) })
}); });
it('can add field as master (issue #1257)', (done) => { it('can add field as master (issue #1257)', (done) => {
setPermissionsOnClass('AClass', { setPermissionsOnClass('AClass', {
'addField': {} 'addField': {}
}).then(() => { }).then(() => {
var obj = new Parse.Object('AClass'); var obj = new Parse.Object('AClass');
obj.set('key', 'value'); obj.set('key', 'value');
return obj.save(null, {useMasterKey: true}) return obj.save(null, {useMasterKey: true})
}).then((obj) => { }).then((obj) => {
expect(obj.get('key')).toEqual('value'); expect(obj.get('key')).toEqual('value');
done(); done();
}, (err) => { }, () => {
fail('should not fail'); fail('should not fail');
done(); done();
}); });
}); });
it('can login when addFields is false (issue #1355)', (done) => { it('can login when addFields is false (issue #1355)', (done) => {
setPermissionsOnClass('_User', { setPermissionsOnClass('_User', {
'create': {'*': true}, 'create': {'*': true},
'addField': {} 'addField': {}
@@ -1616,7 +1616,7 @@ describe('schemas', () => {
url: 'http://localhost:8378/1/schemas/MyClass', url: 'http://localhost:8378/1/schemas/MyClass',
headers: masterKeyHeaders, headers: masterKeyHeaders,
json: true, json: true,
}, (error, response, body) => { }, (error, response) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
expect(response.body).toEqual({}); expect(response.body).toEqual({});
done(); done();
@@ -1641,56 +1641,56 @@ describe('schemas', () => {
'update': {'role:admin': true}, 'update': {'role:admin': true},
'delete': {'role:admin': true} 'delete': {'role:admin': true}
}) })
}).then(() => { }).then(() => {
return obj.save(); return obj.save();
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'user') return Parse.User.logIn('user', 'user')
}).then(() => { }).then(() => {
return obj.destroy(); return obj.destroy();
}).then((result) => { }).then(() => {
let query = new Parse.Query('AnObject'); let query = new Parse.Query('AnObject');
return query.find(); return query.find();
}).then((results) => { }).then((results) => {
expect(results.length).toBe(0); expect(results.length).toBe(0);
done(); done();
}).catch((err) => { }).catch((err) => {
fail('should not fail'); fail('should not fail');
jfail(err); jfail(err);
done(); done();
}); });
}); });
it('regression test for #2246', done => { it('regression test for #2246', done => {
let profile = new Parse.Object('UserProfile'); let profile = new Parse.Object('UserProfile');
let user = new Parse.User(); let user = new Parse.User();
function initialize() { function initialize() {
return user.save({ return user.save({
username: 'user', username: 'user',
password: 'password' password: 'password'
}).then(() => { }).then(() => {
return profile.save({user}).then(() => { return profile.save({user}).then(() => {
return user.save({ return user.save({
userProfile: profile userProfile: profile
}, {useMasterKey: true}); }, {useMasterKey: true});
}); });
}); });
} }
initialize().then(() => { initialize().then(() => {
return setPermissionsOnClass('UserProfile', { return setPermissionsOnClass('UserProfile', {
'readUserFields': ['user'], 'readUserFields': ['user'],
'writeUserFields': ['user'] 'writeUserFields': ['user']
}, true); }, true);
}).then(() => { }).then(() => {
return Parse.User.logIn('user', 'password') return Parse.User.logIn('user', 'password')
}).then(() => { }).then(() => {
let query = new Parse.Query('_User'); let query = new Parse.Query('_User');
query.include('userProfile'); query.include('userProfile');
return query.get(user.id); return query.get(user.id);
}).then((user) => { }).then((user) => {
expect(user.get('userProfile')).not.toBeUndefined(); expect(user.get('userProfile')).not.toBeUndefined();
done(); done();
}, (err) => { }, (err) => {
jfail(err); jfail(err);
done(); done();
}); });

View File

@@ -1,6 +1,5 @@
// This class handles the Account Lockout Policy settings. // This class handles the Account Lockout Policy settings.
import Parse from 'parse/node';
import Config from './Config';
export class AccountLockout { export class AccountLockout {
constructor(user, config) { constructor(user, config) {
@@ -13,7 +12,7 @@ export class AccountLockout {
*/ */
_setFailedLoginCount(value) { _setFailedLoginCount(value) {
let query = { let query = {
username: this._user.username, username: this._user.username
}; };
const updateFields = { const updateFields = {
@@ -76,7 +75,7 @@ export class AccountLockout {
*/ */
_incrementFailedLoginCount() { _incrementFailedLoginCount() {
const query = { const query = {
username: this._user.username, username: this._user.username
}; };
const updateFields = {_failed_login_count: {__op: 'Increment', amount: 1}}; const updateFields = {_failed_login_count: {__op: 'Increment', amount: 1}};
@@ -93,7 +92,7 @@ export class AccountLockout {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = { const query = {
username: this._user.username, username: this._user.username,
_failed_login_count: { $gte: this._config.accountLockout.threshold }, _failed_login_count: { $gte: this._config.accountLockout.threshold }
}; };
const now = new Date(); const now = new Date();

View File

@@ -1,3 +1,4 @@
/*eslint no-unused-vars: "off"*/
export class AnalyticsAdapter { export class AnalyticsAdapter {
/* /*

View File

@@ -1,3 +1,4 @@
/*eslint no-unused-vars: "off"*/
export class CacheAdapter { export class CacheAdapter {
/** /**
* Get a value in the cache * Get a value in the cache

View File

@@ -7,7 +7,7 @@ export class InMemoryCacheAdapter {
} }
get(key) { get(key) {
return new Promise((resolve, reject) => { return new Promise((resolve) => {
let record = this.cache.get(key); let record = this.cache.get(key);
if (record == null) { if (record == null) {
return resolve(null); return resolve(null);

View File

@@ -1,19 +1,18 @@
export class NullCacheAdapter { export class NullCacheAdapter {
constructor(ctx) { constructor() {}
}
get(key) { get() {
return new Promise((resolve, _) => { return new Promise((resolve) => {
return resolve(null); return resolve(null);
}) })
} }
put(key, value, ttl) { put() {
return Promise.resolve(); return Promise.resolve();
} }
del(key) { del() {
return Promise.resolve(); return Promise.resolve();
} }

View File

@@ -3,7 +3,7 @@ import logger from '../../logger';
const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds in milliseconds const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds in milliseconds
function debug() { function debug() {
logger.debug.apply(logger, ['RedisCacheAdapter', ...arguments]); logger.debug.apply(logger, ['RedisCacheAdapter', ...arguments]);
} }
@@ -16,8 +16,8 @@ export class RedisCacheAdapter {
get(key) { get(key) {
debug('get', key); debug('get', key);
this.p = this.p.then(() => { this.p = this.p.then(() => {
return new Promise((resolve, _) => { return new Promise((resolve) => {
this.client.get(key, function(err, res) { this.client.get(key, function(err, res) {
debug('-> get', key, res); debug('-> get', key, res);
if(!res) { if(!res) {
@@ -39,14 +39,14 @@ export class RedisCacheAdapter {
if (ttl < 0 || isNaN(ttl)) { if (ttl < 0 || isNaN(ttl)) {
ttl = DEFAULT_REDIS_TTL; ttl = DEFAULT_REDIS_TTL;
} }
this.p = this.p.then(() => { this.p = this.p.then(() => {
return new Promise((resolve, _) => { return new Promise((resolve) => {
if (ttl === Infinity) { if (ttl === Infinity) {
this.client.set(key, value, function(err, res) { this.client.set(key, value, function() {
resolve(); resolve();
}); });
} else { } else {
this.client.psetex(key, ttl, value, function(err, res) { this.client.psetex(key, ttl, value, function() {
resolve(); resolve();
}); });
} }
@@ -57,9 +57,9 @@ export class RedisCacheAdapter {
del(key) { del(key) {
debug('del', key); debug('del', key);
this.p = this.p.then(() => { this.p = this.p.then(() => {
return new Promise((resolve, _) => { return new Promise((resolve) => {
this.client.del(key, function(err, res) { this.client.del(key, function() {
resolve(); resolve();
}); });
}); });
@@ -69,9 +69,9 @@ export class RedisCacheAdapter {
clear() { clear() {
debug('clear'); debug('clear');
this.p = this.p.then(() => { this.p = this.p.then(() => {
return new Promise((resolve, _) => { return new Promise((resolve) => {
this.client.flushall(function(err, res) { this.client.flushall(function() {
resolve(); resolve();
}); });
}); });

View File

@@ -1,4 +1,4 @@
/*eslint no-unused-vars: "off"*/
/* /*
Mail Adapter prototype Mail Adapter prototype
A MailAdapter should implement at least sendMail() A MailAdapter should implement at least sendMail()

View File

@@ -1,3 +1,4 @@
/*eslint no-unused-vars: "off"*/
// Files Adapter // Files Adapter
// //
// Allows you to change the file storage mechanism. // Allows you to change the file storage mechanism.

View File

@@ -28,7 +28,7 @@ export class GridStoreAdapter extends FilesAdapter {
// For a given config object, filename, and data, store a file // For a given config object, filename, and data, store a file
// Returns a promise // Returns a promise
createFile(filename: string, data, contentType) { createFile(filename: string, data) {
return this._connect().then(database => { return this._connect().then(database => {
let gridStore = new GridStore(database, filename, 'w'); let gridStore = new GridStore(database, filename, 'w');
return gridStore.open(); return gridStore.open();

View File

@@ -1,3 +1,4 @@
/*eslint no-unused-vars: "off"*/
// Logger Adapter // Logger Adapter
// //
// Allows you to change the logger mechanism // Allows you to change the logger mechanism

View File

@@ -37,7 +37,7 @@ function updateTransports(options) {
}, options)); }, options));
} }
// Mount the additional transports // Mount the additional transports
additionalTransports.forEach((transport) => { additionalTransports.forEach((transport) => {
transports[transport.name] = transport; transports[transport.name] = transport;
}); });
logger.configure({ logger.configure({
@@ -65,7 +65,7 @@ export function configureLogger({
} }
try { try {
fs.mkdirSync(logsFolder); fs.mkdirSync(logsFolder);
} catch (exception) {} } catch (e) { /* */ }
} }
options.dirname = logsFolder; options.dirname = logsFolder;
options.level = logLevel; options.level = logLevel;
@@ -90,7 +90,7 @@ export function removeTransport(transport) {
logger.configure({ logger.configure({
transports: _.values(transports) transports: _.values(transports)
}); });
_.remove(additionalTransports, (transport) => { _.remove(additionalTransports, (transport) => {
return transport.name === transportName; return transport.name === transportName;
}); });
} }

View File

@@ -3,11 +3,6 @@ import { logger, addTransport, configureLogger } from './WinstonLogger';
const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
// returns Date object rounded to nearest day
let _getNearestDay = (date) => {
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}
export class WinstonLoggerAdapter extends LoggerAdapter { export class WinstonLoggerAdapter extends LoggerAdapter {
constructor(options) { constructor(options) {
super(); super();
@@ -38,18 +33,16 @@ export class WinstonLoggerAdapter extends LoggerAdapter {
let limit = options.size || 10; let limit = options.size || 10;
let order = options.order || 'desc'; let order = options.order || 'desc';
let level = options.level || 'info'; let level = options.level || 'info';
let roundedUntil = _getNearestDay(until);
let roundedFrom = _getNearestDay(from);
var options = { const queryOptions = {
from, from,
until, until,
limit, limit,
order order
}; };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
logger.query(options, (err, res) => { logger.query(queryOptions, (err, res) => {
if (err) { if (err) {
callback(err); callback(err);
return reject(err); return reject(err);

View File

@@ -1,3 +1,4 @@
/*eslint no-unused-vars: "off"*/
// Push Adapter // Push Adapter
// //
// Allows you to change the push notification mechanism. // Allows you to change the push notification mechanism.

View File

@@ -84,7 +84,7 @@ export default class MongoCollection {
_ensureSparseUniqueIndexInBackground(indexRequest) { _ensureSparseUniqueIndexInBackground(indexRequest) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._mongoCollection.ensureIndex(indexRequest, { unique: true, background: true, sparse: true }, (error, indexName) => { this._mongoCollection.ensureIndex(indexRequest, { unique: true, background: true, sparse: true }, (error) => {
if (error) { if (error) {
reject(error); reject(error);
} else { } else {

View File

@@ -1,4 +1,5 @@
import MongoCollection from './MongoCollection'; import MongoCollection from './MongoCollection';
import Parse from 'parse/node';
function mongoFieldToParseSchemaField(type) { function mongoFieldToParseSchemaField(type) {
if (type[0] === '*') { if (type[0] === '*') {
@@ -14,16 +15,16 @@ function mongoFieldToParseSchemaField(type) {
}; };
} }
switch (type) { switch (type) {
case 'number': return {type: 'Number'}; case 'number': return {type: 'Number'};
case 'string': return {type: 'String'}; case 'string': return {type: 'String'};
case 'boolean': return {type: 'Boolean'}; case 'boolean': return {type: 'Boolean'};
case 'date': return {type: 'Date'}; case 'date': return {type: 'Date'};
case 'map': case 'map':
case 'object': return {type: 'Object'}; case 'object': return {type: 'Object'};
case 'array': return {type: 'Array'}; case 'array': return {type: 'Array'};
case 'geopoint': return {type: 'GeoPoint'}; case 'geopoint': return {type: 'GeoPoint'};
case 'file': return {type: 'File'}; case 'file': return {type: 'File'};
case 'bytes': return {type: 'Bytes'}; case 'bytes': return {type: 'Bytes'};
} }
} }
@@ -87,16 +88,16 @@ function _mongoSchemaQueryFromNameQuery(name: string, query) {
// Does no validation. That is expected to be done in Parse Server. // Does no validation. That is expected to be done in Parse Server.
function parseFieldTypeToMongoFieldType({ type, targetClass }) { function parseFieldTypeToMongoFieldType({ type, targetClass }) {
switch (type) { switch (type) {
case 'Pointer': return `*${targetClass}`; case 'Pointer': return `*${targetClass}`;
case 'Relation': return `relation<${targetClass}>`; case 'Relation': return `relation<${targetClass}>`;
case 'Number': return 'number'; case 'Number': return 'number';
case 'String': return 'string'; case 'String': return 'string';
case 'Boolean': return 'boolean'; case 'Boolean': return 'boolean';
case 'Date': return 'date'; case 'Date': return 'date';
case 'Object': return 'object'; case 'Object': return 'object';
case 'Array': return 'array'; case 'Array': return 'array';
case 'GeoPoint': return 'geopoint'; case 'GeoPoint': return 'geopoint';
case 'File': return 'file'; case 'File': return 'file';
} }
} }

View File

@@ -11,7 +11,9 @@ import {
transformWhere, transformWhere,
transformUpdate, transformUpdate,
} from './MongoTransform'; } from './MongoTransform';
import Parse from 'parse/node';
import _ from 'lodash'; import _ from 'lodash';
import defaults from '../../../defaults';
let mongodb = require('mongodb'); let mongodb = require('mongodb');
let MongoClient = mongodb.MongoClient; let MongoClient = mongodb.MongoClient;
@@ -63,7 +65,7 @@ const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPe
} }
if (typeof classLevelPermissions !== 'undefined') { if (typeof classLevelPermissions !== 'undefined') {
mongoObject._metadata = mongoObject._metadata || {}; mongoObject._metadata = mongoObject._metadata || {};
if (!classLevelPermissions) { if (!classLevelPermissions) {
delete mongoObject._metadata.class_permissions; delete mongoObject._metadata.class_permissions;
} else { } else {
@@ -111,14 +113,14 @@ export class MongoStorageAdapter {
delete this.connectionPromise; delete this.connectionPromise;
return; return;
} }
database.on('error', (error) => { database.on('error', () => {
delete this.connectionPromise; delete this.connectionPromise;
}); });
database.on('close', (error) => { database.on('close', () => {
delete this.connectionPromise; delete this.connectionPromise;
}); });
this.database = database; this.database = database;
}).catch((err) => { }).catch((err) => {
delete this.connectionPromise; delete this.connectionPromise;
return Promise.reject(err); return Promise.reject(err);
}); });
@@ -288,7 +290,7 @@ export class MongoStorageAdapter {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
} }
return Promise.resolve(); return Promise.resolve();
}, error => { }, () => {
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error'); throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database adapter error');
}); });
} }
@@ -327,7 +329,7 @@ export class MongoStorageAdapter {
schema = convertParseSchemaToMongoSchema(schema); schema = convertParseSchemaToMongoSchema(schema);
let mongoWhere = transformWhere(className, query, schema); let mongoWhere = transformWhere(className, query, schema);
let mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema)); let mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
let mongoKeys = _.reduce(keys, (memo, key) => { let mongoKeys = _.reduce(keys, (memo, key) => {
memo[transformKey(className, key, schema)] = 1; memo[transformKey(className, key, schema)] = 1;
return memo; return memo;
}, {}); }, {});

View File

@@ -6,10 +6,10 @@ var Parse = require('parse/node').Parse;
const transformKey = (className, fieldName, schema) => { const transformKey = (className, fieldName, schema) => {
// Check if the schema is known since it's a built-in field. // Check if the schema is known since it's a built-in field.
switch(fieldName) { switch(fieldName) {
case 'objectId': return '_id'; case 'objectId': return '_id';
case 'createdAt': return '_created_at'; case 'createdAt': return '_created_at';
case 'updatedAt': return '_updated_at'; case 'updatedAt': return '_updated_at';
case 'sessionToken': return '_session_token'; case 'sessionToken': return '_session_token';
} }
if (schema.fields[fieldName] && schema.fields[fieldName].__type == 'Pointer') { if (schema.fields[fieldName] && schema.fields[fieldName].__type == 'Pointer') {
@@ -197,7 +197,7 @@ function transformQueryKeyValue(className, key, value, schema) {
return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; return {key: '$or', value: value.map(subQuery => transformWhere(className, subQuery, schema))};
case '$and': case '$and':
return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema))}; return {key: '$and', value: value.map(subQuery => transformWhere(className, subQuery, schema))};
default: default: {
// Other auth data // Other auth data
const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/); const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/);
if (authDataMatch) { if (authDataMatch) {
@@ -206,6 +206,7 @@ function transformQueryKeyValue(className, key, value, schema) {
return {key: `_auth_data_${provider}.id`, value}; return {key: `_auth_data_${provider}.id`, value};
} }
} }
}
const expectedTypeIsArray = const expectedTypeIsArray =
schema && schema &&
@@ -530,8 +531,8 @@ function transformConstraint(constraint, inArray) {
break; break;
case '$in': case '$in':
case '$nin': case '$nin': {
var arr = constraint[key]; let arr = constraint[key];
if (!(arr instanceof Array)) { if (!(arr instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
} }
@@ -543,16 +544,16 @@ function transformConstraint(constraint, inArray) {
return result; return result;
}); });
break; break;
}
case '$all': case '$all': {
var arr = constraint[key]; let arr = constraint[key];
if (!(arr instanceof Array)) { if (!(arr instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, throw new Parse.Error(Parse.Error.INVALID_JSON,
'bad ' + key + ' value'); 'bad ' + key + ' value');
} }
answer[key] = arr.map(transformInteriorAtom); answer[key] = arr.map(transformInteriorAtom);
break; break;
}
case '$regex': case '$regex':
var s = constraint[key]; var s = constraint[key];
if (typeof s !== 'string') { if (typeof s !== 'string') {
@@ -736,7 +737,7 @@ const mongoObjectToParseObject = (className, mongoObject, schema) => {
case 'symbol': case 'symbol':
case 'function': case 'function':
throw 'bad value in mongoObjectToParseObject'; throw 'bad value in mongoObjectToParseObject';
case 'object': case 'object': {
if (mongoObject === null) { if (mongoObject === null) {
return null; return null;
} }
@@ -868,6 +869,7 @@ const mongoObjectToParseObject = (className, mongoObject, schema) => {
}); });
return { ...restObject, ...relationFields }; return { ...restObject, ...relationFields };
}
default: default:
throw 'unknown js type'; throw 'unknown js type';
} }

View File

@@ -1,4 +1,5 @@
import { createClient } from './PostgresClient'; import { createClient } from './PostgresClient';
import Parse from 'parse/node';
const PostgresRelationDoesNotExistError = '42P01'; const PostgresRelationDoesNotExistError = '42P01';
const PostgresDuplicateRelationError = '42P07'; const PostgresDuplicateRelationError = '42P07';
@@ -16,21 +17,21 @@ const debug = function(){
const parseTypeToPostgresType = type => { const parseTypeToPostgresType = type => {
switch (type.type) { switch (type.type) {
case 'String': return 'text'; case 'String': return 'text';
case 'Date': return 'timestamp with time zone'; case 'Date': return 'timestamp with time zone';
case 'Object': return 'jsonb'; case 'Object': return 'jsonb';
case 'File': return 'text'; case 'File': return 'text';
case 'Boolean': return 'boolean'; case 'Boolean': return 'boolean';
case 'Pointer': return 'char(10)'; case 'Pointer': return 'char(10)';
case 'Number': return 'double precision'; case 'Number': return 'double precision';
case 'GeoPoint': return 'point'; case 'GeoPoint': return 'point';
case 'Array': case 'Array':
if (type.contents && type.contents.type === 'String') { if (type.contents && type.contents.type === 'String') {
return 'text[]'; return 'text[]';
} else { } else {
return 'jsonb'; return 'jsonb';
} }
default: throw `no type for ${JSON.stringify(type)} yet`; default: throw `no type for ${JSON.stringify(type)} yet`;
} }
}; };
@@ -41,7 +42,7 @@ const ParseToPosgresComparator = {
'$lte': '<=' '$lte': '<='
} }
const toPostgresValue = value => { const toPostgresValue = value => {
if (typeof value === 'object') { if (typeof value === 'object') {
if (value.__type === 'Date') { if (value.__type === 'Date') {
return value.iso; return value.iso;
@@ -53,7 +54,7 @@ const toPostgresValue = value => {
return value; return value;
} }
const transformValue = value => { const transformValue = value => {
if (value.__type === 'Pointer') { if (value.__type === 'Pointer') {
return value.objectId; return value.objectId;
} }
@@ -79,7 +80,7 @@ const defaultCLPS = Object.freeze({
addField: {'*': true}, addField: {'*': true},
}); });
const toParseSchema = (schema) => { const toParseSchema = (schema) => {
if (schema.className === '_User') { if (schema.className === '_User') {
delete schema.fields._hashed_password; delete schema.fields._hashed_password;
} }
@@ -98,7 +99,7 @@ const toParseSchema = (schema) => {
}; };
} }
const toPostgresSchema = (schema) => { const toPostgresSchema = (schema) => {
if (!schema) { if (!schema) {
return schema; return schema;
} }
@@ -111,8 +112,8 @@ const toPostgresSchema = (schema) => {
return schema; return schema;
} }
const handleDotFields = (object) => { const handleDotFields = (object) => {
Object.keys(object).forEach(fieldName => { Object.keys(object).forEach(fieldName => {
if (fieldName.indexOf('.') > -1) { if (fieldName.indexOf('.') > -1) {
let components = fieldName.split('.'); let components = fieldName.split('.');
let first = components.shift(); let first = components.shift();
@@ -123,7 +124,9 @@ const handleDotFields = (object) => {
if (value && value.__op === 'Delete') { if (value && value.__op === 'Delete') {
value = undefined; value = undefined;
} }
while(next = components.shift()) { /* eslint-disable no-cond-assign */
while(next = components.shift()) {
/* eslint-enable no-cond-assign */
currentObj[next] = currentObj[next] || {}; currentObj[next] = currentObj[next] || {};
if (components.length === 0) { if (components.length === 0) {
currentObj[next] = value; currentObj[next] = value;
@@ -151,7 +154,7 @@ const validateKeys = (object) => {
} }
// Returns the list of join tables on a schema // Returns the list of join tables on a schema
const joinTablesForSchema = (schema) => { const joinTablesForSchema = (schema) => {
let list = []; let list = [];
if (schema) { if (schema) {
Object.keys(schema.fields).forEach((field) => { Object.keys(schema.fields).forEach((field) => {
@@ -185,11 +188,11 @@ const buildWhereClause = ({ schema, query, index }) => {
} }
if (fieldName.indexOf('.') >= 0) { if (fieldName.indexOf('.') >= 0) {
let components = fieldName.split('.').map((cmpt, index) => { let components = fieldName.split('.').map((cmpt, index) => {
if (index === 0) { if (index === 0) {
return `"${cmpt}"`; return `"${cmpt}"`;
} }
return `'${cmpt}'`;  return `'${cmpt}'`;
}); });
let name = components.slice(0, components.length-1).join('->'); let name = components.slice(0, components.length-1).join('->');
name+='->>'+components[components.length-1]; name+='->>'+components[components.length-1];
@@ -209,7 +212,7 @@ const buildWhereClause = ({ schema, query, index }) => {
} else if (fieldName === '$or' || fieldName === '$and') { } else if (fieldName === '$or' || fieldName === '$and') {
let clauses = []; let clauses = [];
let clauseValues = []; let clauseValues = [];
fieldValue.forEach((subQuery, idx) =>  { fieldValue.forEach((subQuery) => {
let clause = buildWhereClause({ schema, query: subQuery, index }); let clause = buildWhereClause({ schema, query: subQuery, index });
if (clause.pattern.length > 0) { if (clause.pattern.length > 0) {
clauses.push(clause.pattern); clauses.push(clause.pattern);
@@ -268,7 +271,7 @@ const buildWhereClause = ({ schema, query, index }) => {
} }
index = index + 1 + inPatterns.length; index = index + 1 + inPatterns.length;
} else if (isInOrNin) { } else if (isInOrNin) {
var createConstraint = (baseArray, notIn) => { var createConstraint = (baseArray, notIn) => {
if (baseArray.length > 0) { if (baseArray.length > 0) {
let not = notIn ? ' NOT ' : ''; let not = notIn ? ' NOT ' : '';
if (isArrayField) { if (isArrayField) {
@@ -375,7 +378,7 @@ const buildWhereClause = ({ schema, query, index }) => {
index += 2; index += 2;
} }
Object.keys(ParseToPosgresComparator).forEach(cmp => { Object.keys(ParseToPosgresComparator).forEach(cmp => {
if (fieldValue[cmp]) { if (fieldValue[cmp]) {
let pgComparator = ParseToPosgresComparator[cmp]; let pgComparator = ParseToPosgresComparator[cmp];
patterns.push(`$${index}:name ${pgComparator} $${index + 1}`); patterns.push(`$${index}:name ${pgComparator} $${index + 1}`);
@@ -416,10 +419,10 @@ export class PostgresStorageAdapter {
throw error; throw error;
} }
}); });
}; }
classExists(name) { classExists(name) {
return this._client.one(`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)`, [name]).then((res) => { return this._client.one(`SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1)`, [name]).then((res) => {
return res.exists; return res.exists;
}); });
} }
@@ -433,15 +436,15 @@ export class PostgresStorageAdapter {
createClass(className, schema) { createClass(className, schema) {
return this._client.tx(t => { return this._client.tx(t => {
const q1 = this.createTable(className, schema, t); const q1 = this.createTable(className, schema, t);
const q2 = t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema }); const q2 = t.none('INSERT INTO "_SCHEMA" ("className", "schema", "isParseClass") VALUES ($<className>, $<schema>, true)', { className, schema });
return t.batch([q1, q2]); return t.batch([q1, q2]);
}) })
.then(() => { .then(() => {
return toParseSchema(schema) return toParseSchema(schema)
}) })
.catch((err) => { .catch((err) => {
if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) { if (Array.isArray(err.data) && err.data.length > 1 && err.data[0].result.code === PostgresTransactionAbortedError) {
err = err.data[1].result; err = err.data[1].result;
} }
@@ -500,9 +503,9 @@ export class PostgresStorageAdapter {
} else { } else {
throw error; throw error;
} }
}).then(() => { }).then(() => {
// Create the relation tables // Create the relation tables
return Promise.all(relations.map((fieldName) => { return Promise.all(relations.map((fieldName) => {
return conn.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`}); return conn.none('CREATE TABLE IF NOT EXISTS $<joinTable:name> ("relatedId" varChar(120), "owningId" varChar(120), PRIMARY KEY("relatedId", "owningId") )', {joinTable: `_Join:${fieldName}:${className}`});
})); }));
}); });
@@ -551,11 +554,11 @@ export class PostgresStorageAdapter {
// Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.) // Drops a collection. Resolves with true if it was a Parse Schema (eg. _User, Custom, etc.)
// and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible. // and resolves with false if it wasn't (eg. a join table). Rejects if deletion was impossible.
deleteClass(className) { deleteClass(className) {
return Promise.resolve().then(() => { return Promise.resolve().then(() => {
let operations = [[`DROP TABLE IF EXISTS $1:name`, [className]], let operations = [[`DROP TABLE IF EXISTS $1:name`, [className]],
[`DELETE FROM "_SCHEMA" WHERE "className"=$1`, [className]]]; [`DELETE FROM "_SCHEMA" WHERE "className"=$1`, [className]]];
return this._client.tx(t=>t.batch(operations.map(statement=>t.none(statement[0], statement[1])))); return this._client.tx(t=>t.batch(operations.map(statement=>t.none(statement[0], statement[1]))));
}).then(() => { }).then(() => {
// resolves with false when _Join table // resolves with false when _Join table
return className.indexOf('_Join:') != 0; return className.indexOf('_Join:') != 0;
}); });
@@ -567,7 +570,7 @@ export class PostgresStorageAdapter {
debug('deleteAllClasses'); debug('deleteAllClasses');
return this._client.any('SELECT * FROM "_SCHEMA"') return this._client.any('SELECT * FROM "_SCHEMA"')
.then(results => { .then(results => {
let joins = results.reduce((list, schema) => { let joins = results.reduce((list, schema) => {
return list.concat(joinTablesForSchema(schema.schema)); return list.concat(joinTablesForSchema(schema.schema));
}, []); }, []);
const classes = ['_SCHEMA','_PushStatus','_JobStatus','_Hooks','_GlobalConfig', ...results.map(result => result.className), ...joins]; const classes = ['_SCHEMA','_PushStatus','_JobStatus','_Hooks','_GlobalConfig', ...results.map(result => result.className), ...joins];
@@ -579,7 +582,7 @@ export class PostgresStorageAdapter {
} else { } else {
throw error; throw error;
} }
}).then(() => { }).then(() => {
debug(`deleteAllClasses done in ${new Date().getTime() - now}`); debug(`deleteAllClasses done in ${new Date().getTime() - now}`);
}); });
} }
@@ -600,8 +603,8 @@ export class PostgresStorageAdapter {
deleteFields(className, schema, fieldNames) { deleteFields(className, schema, fieldNames) {
debug('deleteFields', className, fieldNames); debug('deleteFields', className, fieldNames);
return Promise.resolve() return Promise.resolve()
.then(() => { .then(() => {
fieldNames = fieldNames.reduce((list, fieldName) => { fieldNames = fieldNames.reduce((list, fieldName) => {
let field = schema.fields[fieldName] let field = schema.fields[fieldName]
if (field.type !== 'Relation') { if (field.type !== 'Relation') {
list.push(fieldName); list.push(fieldName);
@@ -611,11 +614,11 @@ export class PostgresStorageAdapter {
}, []); }, []);
let values = [className, ...fieldNames]; let values = [className, ...fieldNames];
let columns = fieldNames.map((name, idx) => { let columns = fieldNames.map((name, idx) => {
return `$${idx+2}:name`; return `$${idx+2}:name`;
}).join(','); }).join(',');
let doBatch = (t) => { let doBatch = (t) => {
let batch = [ let batch = [
t.none('UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>', {schema, className}) t.none('UPDATE "_SCHEMA" SET "schema"=$<schema> WHERE "className"=$<className>', {schema, className})
]; ];
@@ -624,7 +627,7 @@ export class PostgresStorageAdapter {
} }
return batch; return batch;
} }
return this._client.tx((t) => { return this._client.tx((t) => {
return t.batch(doBatch(t)); return t.batch(doBatch(t));
}); });
}); });
@@ -658,7 +661,6 @@ export class PostgresStorageAdapter {
createObject(className, schema, object) { createObject(className, schema, object) {
debug('createObject', className, object); debug('createObject', className, object);
let columnsArray = []; let columnsArray = [];
let newFieldsArray = [];
let valuesArray = []; let valuesArray = [];
schema = toPostgresSchema(schema); schema = toPostgresSchema(schema);
let geoPoints = {}; let geoPoints = {};
@@ -705,39 +707,39 @@ export class PostgresStorageAdapter {
return; return;
} }
switch (schema.fields[fieldName].type) { switch (schema.fields[fieldName].type) {
case 'Date': case 'Date':
if (object[fieldName]) { if (object[fieldName]) {
valuesArray.push(object[fieldName].iso); valuesArray.push(object[fieldName].iso);
} else { } else {
valuesArray.push(null); valuesArray.push(null);
} }
break; break;
case 'Pointer': case 'Pointer':
valuesArray.push(object[fieldName].objectId); valuesArray.push(object[fieldName].objectId);
break; break;
case 'Array': case 'Array':
if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) { if (['_rperm', '_wperm'].indexOf(fieldName) >= 0) {
valuesArray.push(object[fieldName]);
} else {
valuesArray.push(JSON.stringify(object[fieldName]));
}
break;
case 'Object':
case 'String':
case 'Number':
case 'Boolean':
valuesArray.push(object[fieldName]); valuesArray.push(object[fieldName]);
break; } else {
case 'File': valuesArray.push(JSON.stringify(object[fieldName]));
valuesArray.push(object[fieldName].name); }
break; break;
case 'GeoPoint': case 'Object':
case 'String':
case 'Number':
case 'Boolean':
valuesArray.push(object[fieldName]);
break;
case 'File':
valuesArray.push(object[fieldName].name);
break;
case 'GeoPoint':
// pop the point and process later // pop the point and process later
geoPoints[fieldName] = object[fieldName]; geoPoints[fieldName] = object[fieldName];
columnsArray.pop(); columnsArray.pop();
break; break;
default: default:
throw `Type ${schema.fields[fieldName].type} not supported yet`; throw `Type ${schema.fields[fieldName].type} not supported yet`;
} }
}); });
@@ -752,7 +754,7 @@ export class PostgresStorageAdapter {
} }
return `$${index + 2 + columnsArray.length}${termination}`; return `$${index + 2 + columnsArray.length}${termination}`;
}); });
let geoPointsInjects = Object.keys(geoPoints).map((key, idx) => { let geoPointsInjects = Object.keys(geoPoints).map((key) => {
let value = geoPoints[key]; let value = geoPoints[key];
valuesArray.push(value.longitude, value.latitude); valuesArray.push(value.longitude, value.latitude);
let l = valuesArray.length + columnsArray.length; let l = valuesArray.length + columnsArray.length;
@@ -802,13 +804,12 @@ export class PostgresStorageAdapter {
// Return value not currently well specified. // Return value not currently well specified.
findOneAndUpdate(className, schema, query, update) { findOneAndUpdate(className, schema, query, update) {
debug('findOneAndUpdate', className, query, update); debug('findOneAndUpdate', className, query, update);
return this.updateObjectsByQuery(className, schema, query, update).then((val) => val[0]); return this.updateObjectsByQuery(className, schema, query, update).then((val) => val[0]);
} }
// Apply the update to all objects that match the given Parse Query. // Apply the update to all objects that match the given Parse Query.
updateObjectsByQuery(className, schema, query, update) { updateObjectsByQuery(className, schema, query, update) {
debug('updateObjectsByQuery', className, query, update); debug('updateObjectsByQuery', className, query, update);
let conditionPatterns = [];
let updatePatterns = []; let updatePatterns = [];
let values = [className] let values = [className]
let index = 2; let index = 2;
@@ -838,8 +839,8 @@ export class PostgresStorageAdapter {
} else if (fieldName == 'authData') { } else if (fieldName == 'authData') {
// This recursively sets the json_object // This recursively sets the json_object
// Only 1 level deep // Only 1 level deep
let generate = (jsonb, key, value) => { let generate = (jsonb, key, value) => {
return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`;  return `json_object_set_key(COALESCE(${jsonb}, '{}'::jsonb), ${key}, ${value})::jsonb`;
} }
let lastKey = `$${index}:name`; let lastKey = `$${index}:name`;
let fieldNameIndex = index; let fieldNameIndex = index;
@@ -930,10 +931,10 @@ export class PostgresStorageAdapter {
return p + ` - '$${index + 1 + i}:value'`; return p + ` - '$${index + 1 + i}:value'`;
}, ''); }, '');
updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${deletePatterns} || $${index + 1 + keysToDelete.length}::jsonb )`); updatePatterns.push(`$${index}:name = ( COALESCE($${index}:name, '{}'::jsonb) ${deletePatterns} || $${index + 1 + keysToDelete.length}::jsonb )`);
values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue)); values.push(fieldName, ...keysToDelete, JSON.stringify(fieldValue));
index += 2 + keysToDelete.length; index += 2 + keysToDelete.length;
} else if (Array.isArray(fieldValue) } else if (Array.isArray(fieldValue)
&& schema.fields[fieldName] && schema.fields[fieldName]
&& schema.fields[fieldName].type === 'Array') { && schema.fields[fieldName].type === 'Array') {
@@ -970,7 +971,7 @@ export class PostgresStorageAdapter {
upsertOneObject(className, schema, query, update) { upsertOneObject(className, schema, query, update) {
debug('upsertOneObject', {className, query, update}); debug('upsertOneObject', {className, query, update});
let createValue = Object.assign({}, query, update); let createValue = Object.assign({}, query, update);
return this.createObject(className, schema, createValue).catch((err) => { return this.createObject(className, schema, createValue).catch((err) => {
// ignore duplicate value errors as it's upsert // ignore duplicate value errors as it's upsert
if (err.code === Parse.Error.DUPLICATE_VALUE) { if (err.code === Parse.Error.DUPLICATE_VALUE) {
return this.findOneAndUpdate(className, schema, query, update); return this.findOneAndUpdate(className, schema, query, update);
@@ -999,26 +1000,26 @@ export class PostgresStorageAdapter {
let sortPattern = ''; let sortPattern = '';
if (sort) { if (sort) {
let sorting = Object.keys(sort).map((key) => { let sorting = Object.keys(sort).map((key) => {
// Using $idx pattern gives: non-integer constant in ORDER BY // Using $idx pattern gives: non-integer constant in ORDER BY
if (sort[key] === 1) { if (sort[key] === 1) {
return `"${key}" ASC`; return `"${key}" ASC`;
} }
return `"${key}" DESC`; return `"${key}" DESC`;
}).join(','); }).join(',');
sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : ''; sortPattern = sort !== undefined && Object.keys(sort).length > 0 ? `ORDER BY ${sorting}` : '';
} }
if (where.sorts && Object.keys(where.sorts).length > 0) { if (where.sorts && Object.keys(where.sorts).length > 0) {
sortPattern = `ORDER BY ${where.sorts.join(',')}`; sortPattern = `ORDER BY ${where.sorts.join(',')}`;
} }
let columns = '*'; let columns = '*';
if (keys) { if (keys) {
// Exclude empty keys // Exclude empty keys
keys = keys.filter((key) => { keys = keys.filter((key) => {
return key.length > 0; return key.length > 0;
}); });
columns = keys.map((key, index) => { columns = keys.map((key, index) => {
return `$${index+values.length+1}:name`; return `$${index+values.length+1}:name`;
}).join(','); }).join(',');
values = values.concat(keys); values = values.concat(keys);
@@ -1027,7 +1028,7 @@ export class PostgresStorageAdapter {
const qs = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern}`; const qs = `SELECT ${columns} FROM $1:name ${wherePattern} ${sortPattern} ${limitPattern} ${skipPattern}`;
debug(qs, values); debug(qs, values);
return this._client.any(qs, values) return this._client.any(qs, values)
.catch((err) => { .catch((err) => {
// Query on non existing table, don't crash // Query on non existing table, don't crash
if (err.code === PostgresRelationDoesNotExistError) { if (err.code === PostgresRelationDoesNotExistError) {
return []; return [];
@@ -1127,7 +1128,7 @@ export class PostgresStorageAdapter {
const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : ''; const wherePattern = where.pattern.length > 0 ? `WHERE ${where.pattern}` : '';
const qs = `SELECT count(*) FROM $1:name ${wherePattern}`; const qs = `SELECT count(*) FROM $1:name ${wherePattern}`;
return this._client.one(qs, values, a => +a.count).catch((err) => { return this._client.one(qs, values, a => +a.count).catch((err) => {
if (err.code === PostgresRelationDoesNotExistError) { if (err.code === PostgresRelationDoesNotExistError) {
return 0; return 0;
} }
@@ -1138,7 +1139,7 @@ export class PostgresStorageAdapter {
performInitialization({ VolatileClassesSchemas }) { performInitialization({ VolatileClassesSchemas }) {
let now = new Date().getTime(); let now = new Date().getTime();
debug('performInitialization'); debug('performInitialization');
let promises = VolatileClassesSchemas.map((schema) => { let promises = VolatileClassesSchemas.map((schema) => {
return this.createTable(schema.className, schema).catch((err) =>{ return this.createTable(schema.className, schema).catch((err) =>{
if (err.code === PostgresDuplicateRelationError || err.code === Parse.Error.INVALID_CLASS_NAME) { if (err.code === PostgresDuplicateRelationError || err.code === Parse.Error.INVALID_CLASS_NAME) {
return Promise.resolve(); return Promise.resolve();
@@ -1146,36 +1147,34 @@ export class PostgresStorageAdapter {
throw err; throw err;
}); });
}); });
/* eslint-disable no-console */
promises = promises.concat([ promises = promises.concat([
this._client.any(json_object_set_key).catch((err) => { this._client.any(json_object_set_key).catch((err) => {
console.error(err); console.error(err);
}), }),
this._client.any(array_add).catch((err) => { this._client.any(array_add).catch((err) => {
console.error(err); console.error(err);
}), }),
this._client.any(array_add_unique).catch((err) => { this._client.any(array_add_unique).catch((err) => {
console.error(err); console.error(err);
}), }),
this._client.any(array_remove).catch((err) => { this._client.any(array_remove).catch((err) => {
console.error(err); console.error(err);
}), }),
this._client.any(array_contains_all).catch((err) => { this._client.any(array_contains_all).catch((err) => {
console.error(err); console.error(err);
}), }),
this._client.any(array_contains).catch((err) => { this._client.any(array_contains).catch((err) => {
console.error(err); console.error(err);
}) })
]); ]);
return Promise.all(promises).then(() => { /* eslint-enable no-console */
return Promise.all(promises).then(() => {
debug(`initialzationDone in ${new Date().getTime() - now}`); debug(`initialzationDone in ${new Date().getTime() - now}`);
}, (err) => {}); }, () => {});
} }
} }
function notImplemented() {
return Promise.reject(new Error('Not implemented yet.'));
}
function removeWhiteSpace(regex) { function removeWhiteSpace(regex) {
if (!regex.endsWith('\n')){ if (!regex.endsWith('\n')){
regex += '\n'; regex += '\n';

View File

@@ -1,4 +1,3 @@
var deepcopy = require('deepcopy');
var Parse = require('parse/node').Parse; var Parse = require('parse/node').Parse;
var RestQuery = require('./RestQuery'); var RestQuery = require('./RestQuery');
@@ -80,13 +79,13 @@ var getAuthForSessionToken = function({ config, sessionToken, installationId } =
var getAuthForLegacySessionToken = function({config, sessionToken, installationId } = {}) { var getAuthForLegacySessionToken = function({config, sessionToken, installationId } = {}) {
var restOptions = { var restOptions = {
limit: 1 limit: 1
}; };
var query = new RestQuery(config, master(config), '_User', { sessionToken: sessionToken}, restOptions); var query = new RestQuery(config, master(config), '_User', { sessionToken: sessionToken}, restOptions);
return query.execute().then((response) => { return query.execute().then((response) => {
var results = response.results; var results = response.results;
if (results.length !== 1) { if (results.length !== 1) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid legacy session token'); throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid legacy session token');
} }
let obj = results[0]; let obj = results[0];
obj.className = '_User'; obj.className = '_User';
@@ -163,7 +162,7 @@ Auth.prototype._loadRoles = function() {
// Given a list of roleIds, find all the parent roles, returns a promise with all names // Given a list of roleIds, find all the parent roles, returns a promise with all names
Auth.prototype._getAllRolesNamesForRoleIds = function(roleIDs, names = [], queriedRoles = {}) { Auth.prototype._getAllRolesNamesForRoleIds = function(roleIDs, names = [], queriedRoles = {}) {
let ins = roleIDs.filter((roleID) => { let ins = roleIDs.filter((roleID) => {
return queriedRoles[roleID] !== true; return queriedRoles[roleID] !== true;
}).map((roleID) => { }).map((roleID) => {
// mark as queried // mark as queried
@@ -194,7 +193,7 @@ Auth.prototype._getAllRolesNamesForRoleIds = function(roleIDs, names = [], queri
return Promise.resolve(names); return Promise.resolve(names);
} }
// Map the results with all Ids and names // Map the results with all Ids and names
let resultMap = results.reduce((memo, role) => { let resultMap = results.reduce((memo, role) => {
memo.names.push(role.name); memo.names.push(role.name);
memo.ids.push(role.objectId); memo.ids.push(role.objectId);
return memo; return memo;

View File

@@ -50,15 +50,15 @@ export class AdaptableController {
// Makes sure the prototype matches // Makes sure the prototype matches
let mismatches = Object.getOwnPropertyNames(Type.prototype).reduce( (obj, key) => { let mismatches = Object.getOwnPropertyNames(Type.prototype).reduce( (obj, key) => {
const adapterType = typeof adapter[key]; const adapterType = typeof adapter[key];
const expectedType = typeof Type.prototype[key]; const expectedType = typeof Type.prototype[key];
if (adapterType !== expectedType) { if (adapterType !== expectedType) {
obj[key] = { obj[key] = {
expected: expectedType, expected: expectedType,
actual: adapterType actual: adapterType
} }
} }
return obj; return obj;
}, {}); }, {});
if (Object.keys(mismatches).length > 0) { if (Object.keys(mismatches).length > 0) {

View File

@@ -7,7 +7,7 @@ export class AnalyticsController extends AdaptableController {
return this.adapter.appOpened(req.body, req); return this.adapter.appOpened(req.body, req);
}).then((response) => { }).then((response) => {
return { response: response || {} }; return { response: response || {} };
}).catch((err) => { }).catch(() => {
return { response: {} }; return { response: {} };
}); });
} }
@@ -17,7 +17,7 @@ export class AnalyticsController extends AdaptableController {
return this.adapter.trackEvent(req.params.eventName, req.body, req); return this.adapter.trackEvent(req.params.eventName, req.body, req);
}).then((response) => { }).then((response) => {
return { response: response || {} }; return { response: response || {} };
}).catch((err) => { }).catch(() => {
return { response: {} }; return { response: {} };
}); });
} }

View File

@@ -3,7 +3,6 @@
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import _ from 'lodash'; import _ from 'lodash';
import mongdb from 'mongodb';
import intersect from 'intersect'; import intersect from 'intersect';
import deepcopy from 'deepcopy'; import deepcopy from 'deepcopy';
import logger from '../logger'; import logger from '../logger';
@@ -45,7 +44,7 @@ const transformObjectACL = ({ ACL, ...result }) => {
const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count']; const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count'];
const isSpecialQueryKey = key => { const isSpecialQueryKey = key => {
return specialQuerykeys.indexOf(key) >= 0; return specialQuerykeys.indexOf(key) >= 0;
} }
@@ -148,7 +147,7 @@ DatabaseController.prototype.validateObject = function(className, object, query,
return Promise.resolve(); return Promise.resolve();
} }
return this.canAddField(schema, className, object, aclGroup); return this.canAddField(schema, className, object, aclGroup);
}).then(() => { }).then(() => {
return schema.validateObject(className, object, query); return schema.validateObject(className, object, query);
}); });
}; };
@@ -193,7 +192,7 @@ const filterSensitiveData = (isMaster, aclGroup, className, object) => {
// write permissions. // write permissions.
const specialKeysForUpdate = ['_hashed_password', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count', '_perishable_token_expires_at', '_password_changed_at']; const specialKeysForUpdate = ['_hashed_password', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count', '_perishable_token_expires_at', '_password_changed_at'];
const isSpecialUpdateKey = key => { const isSpecialUpdateKey = key => {
return specialKeysForUpdate.indexOf(key) >= 0; return specialKeysForUpdate.indexOf(key) >= 0;
} }
@@ -208,7 +207,6 @@ DatabaseController.prototype.update = function(className, query, update, {
var isMaster = acl === undefined; var isMaster = acl === undefined;
var aclGroup = acl || []; var aclGroup = acl || [];
var mongoUpdate;
return this.loadSchema() return this.loadSchema()
.then(schemaController => { .then(schemaController => {
return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'update')) return (isMaster ? Promise.resolve() : schemaController.validatePermission(className, aclGroup, 'update'))
@@ -280,7 +278,7 @@ function sanitizeDatabaseResult(originalObject, result) {
let keyUpdate = originalObject[key]; let keyUpdate = originalObject[key];
// determine if that was an op // determine if that was an op
if (keyUpdate && typeof keyUpdate === 'object' && keyUpdate.__op if (keyUpdate && typeof keyUpdate === 'object' && keyUpdate.__op
&& ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1) { && ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1) {
// only valid ops that produce an actionable result // only valid ops that produce an actionable result
response[key] = result[key]; response[key] = result[key];
} }
@@ -302,7 +300,7 @@ DatabaseController.prototype.handleRelationUpdates = function(className, objectI
return; return;
} }
if (op.__op == 'AddRelation') { if (op.__op == 'AddRelation') {
for (var object of op.objects) { for (let object of op.objects) {
pending.push(this.addRelation(key, className, pending.push(this.addRelation(key, className,
objectId, objectId,
object.objectId)); object.objectId));
@@ -311,7 +309,7 @@ DatabaseController.prototype.handleRelationUpdates = function(className, objectI
} }
if (op.__op == 'RemoveRelation') { if (op.__op == 'RemoveRelation') {
for (var object of op.objects) { for (let object of op.objects) {
pending.push(this.removeRelation(key, className, pending.push(this.removeRelation(key, className,
objectId, objectId,
object.objectId)); object.objectId));
@@ -326,10 +324,10 @@ DatabaseController.prototype.handleRelationUpdates = function(className, objectI
} }
}; };
for (var key in update) { for (let key in update) {
process(update[key], key); process(update[key], key);
} }
for (var key of deleteMe) { for (let key of deleteMe) {
delete update[key]; delete update[key];
} }
return Promise.all(pending); return Promise.all(pending);
@@ -415,35 +413,35 @@ const flattenUpdateOperatorsForCreate = object => {
for (let key in object) { for (let key in object) {
if (object[key] && object[key].__op) { if (object[key] && object[key].__op) {
switch (object[key].__op) { switch (object[key].__op) {
case 'Increment': case 'Increment':
if (typeof object[key].amount !== 'number') { if (typeof object[key].amount !== 'number') {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
} }
object[key] = object[key].amount; object[key] = object[key].amount;
break; break;
case 'Add': case 'Add':
if (!(object[key].objects instanceof Array)) { if (!(object[key].objects instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
} }
object[key] = object[key].objects; object[key] = object[key].objects;
break; break;
case 'AddUnique': case 'AddUnique':
if (!(object[key].objects instanceof Array)) { if (!(object[key].objects instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
} }
object[key] = object[key].objects; object[key] = object[key].objects;
break; break;
case 'Remove': case 'Remove':
if (!(object[key].objects instanceof Array)) { if (!(object[key].objects instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
} }
object[key] = [] object[key] = []
break; break;
case 'Delete': case 'Delete':
delete object[key]; delete object[key];
break; break;
default: default:
throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, `The ${object[key].__op} operator is not supported yet.`); throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, `The ${object[key].__op} operator is not supported yet.`);
} }
} }
} }
@@ -451,7 +449,7 @@ const flattenUpdateOperatorsForCreate = object => {
const transformAuthData = (className, object, schema) => { const transformAuthData = (className, object, schema) => {
if (object.authData && className === '_User') { if (object.authData && className === '_User') {
Object.keys(object.authData).forEach(provider => { Object.keys(object.authData).forEach(provider => {
const providerData = object.authData[provider]; const providerData = object.authData[provider];
const fieldName = `_auth_data_${provider}`; const fieldName = `_auth_data_${provider}`;
if (providerData == null) { if (providerData == null) {
@@ -504,7 +502,7 @@ DatabaseController.prototype.canAddField = function(schema, className, object, a
} }
let fields = Object.keys(object); let fields = Object.keys(object);
let schemaFields = Object.keys(classSchema); let schemaFields = Object.keys(classSchema);
let newKeys = fields.filter((field) => { let newKeys = fields.filter((field) => {
return schemaFields.indexOf(field) < 0; return schemaFields.indexOf(field) < 0;
}) })
if (newKeys.length > 0) { if (newKeys.length > 0) {
@@ -523,20 +521,6 @@ DatabaseController.prototype.deleteEverything = function() {
]); ]);
}; };
// Finds the keys in a query. Returns a Set. REST format only
function keysForQuery(query) {
var sublist = query['$and'] || query['$or'];
if (sublist) {
let answer = sublist.reduce((memo, subquery) => {
return memo.concat(keysForQuery(subquery));
}, []);
return new Set(answer);
}
return new Set(Object.keys(query));
}
// Returns a promise for a list of related ids given an owning id. // Returns a promise for a list of related ids given an owning id.
// className here is the owning className. // className here is the owning className.
DatabaseController.prototype.relatedIds = function(className, key, owningId) { DatabaseController.prototype.relatedIds = function(className, key, owningId) {
@@ -561,10 +545,10 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
if (query['$or']) { if (query['$or']) {
let ors = query['$or']; let ors = query['$or'];
return Promise.all(ors.map((aQuery, index) => { return Promise.all(ors.map((aQuery, index) => {
return this.reduceInRelation(className, aQuery, schema).then((aQuery) => { return this.reduceInRelation(className, aQuery, schema).then((aQuery) => {
query['$or'][index] = aQuery; query['$or'][index] = aQuery;
}); });
})).then(() => { })).then(() => {
return Promise.resolve(query); return Promise.resolve(query);
}); });
} }
@@ -575,7 +559,6 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
if (!t || t.type !== 'Relation') { if (!t || t.type !== 'Relation') {
return Promise.resolve(query); return Promise.resolve(query);
} }
let relatedClassName = t.targetClass;
// Build the list of queries // Build the list of queries
let queries = Object.keys(query[key]).map((constraintKey) => { let queries = Object.keys(query[key]).map((constraintKey) => {
let relatedIds; let relatedIds;
@@ -625,7 +608,7 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
return Promise.resolve(); return Promise.resolve();
}) })
return Promise.all(promises).then(() => { return Promise.all(promises).then(() => {
return Promise.resolve(query); return Promise.resolve(query);
}) })
}; };
@@ -839,7 +822,7 @@ DatabaseController.prototype.deleteSchema = function(className) {
}) })
.then(schema => { .then(schema => {
return this.collectionExists(className) return this.collectionExists(className)
.then(exist => this.adapter.count(className, { fields: {} })) .then(() => this.adapter.count(className, { fields: {} }))
.then(count => { .then(count => {
if (count > 0) { if (count > 0) {
throw new Parse.Error(255, `Class ${className} is not empty, contains ${count} objects, cannot drop schema.`); throw new Parse.Error(255, `Class ${className} is not empty, contains ${count} objects, cannot drop schema.`);
@@ -866,10 +849,10 @@ DatabaseController.prototype.addPointerPermissions = function(schema, className,
let perms = schema.perms[className]; let perms = schema.perms[className];
let field = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; let field = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields';
let userACL = aclGroup.filter((acl) => { let userACL = aclGroup.filter((acl) => {
return acl.indexOf('role:') != 0 && acl != '*'; return acl.indexOf('role:') != 0 && acl != '*';
}); });
// the ACL should have exactly 1 user // the ACL should have exactly 1 user
if (perms && perms[field] && perms[field].length > 0) { if (perms && perms[field] && perms[field].length > 0) {
// No user set return undefined // No user set return undefined
// If the length is > 1, that means we didn't dedup users correctly // If the length is > 1, that means we didn't dedup users correctly
if (userACL.length != 1) { if (userACL.length != 1) {
@@ -877,20 +860,19 @@ DatabaseController.prototype.addPointerPermissions = function(schema, className,
} }
let userId = userACL[0]; let userId = userACL[0];
let userPointer = { let userPointer = {
"__type": "Pointer", "__type": "Pointer",
"className": "_User", "className": "_User",
"objectId": userId "objectId": userId
}; };
let constraints = {};
let permFields = perms[field]; let permFields = perms[field];
let ors = permFields.map((key) => { let ors = permFields.map((key) => {
let q = { let q = {
[key]: userPointer [key]: userPointer
}; };
return {'$and': [q, query]}; return {'$and': [q, query]};
}); });
if (ors.length > 1) { if (ors.length > 1) {
return {'$or': ors}; return {'$or': ors};
} }
return ors[0]; return ors[0];

View File

@@ -1,5 +1,4 @@
// FilesController.js // FilesController.js
import { Parse } from 'parse/node';
import { randomHexString } from '../cryptoUtils'; import { randomHexString } from '../cryptoUtils';
import AdaptableController from './AdaptableController'; import AdaptableController from './AdaptableController';
import { FilesAdapter } from '../Adapters/Files/FilesAdapter'; import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
@@ -85,7 +84,7 @@ export class FilesController extends AdaptableController {
getFileStream(config, filename) { getFileStream(config, filename) {
return this.adapter.getFileStream(filename); return this.adapter.getFileStream(filename);
} }
} }
export default FilesController; export default FilesController;

View File

@@ -51,8 +51,7 @@ export class HooksController {
return this._removeHooks({ className: className, triggerName: triggerName }); return this._removeHooks({ className: className, triggerName: triggerName });
} }
_getHooks(query = {}, limit) { _getHooks(query = {}) {
let options = limit ? { limit: limit } : undefined;
return this.database.find(DefaultHooksCollectionName, query).then((results) => { return this.database.find(DefaultHooksCollectionName, query).then((results) => {
return results.map((result) => { return results.map((result) => {
delete result.objectId; delete result.objectId;
@@ -113,7 +112,7 @@ export class HooksController {
} }
return this.addHook(hook); return this.addHook(hook);
}; }
createHook(aHook) { createHook(aHook) {
if (aHook.functionName) { if (aHook.functionName) {
@@ -134,7 +133,7 @@ export class HooksController {
} }
throw new Parse.Error(143, "invalid hook declaration"); throw new Parse.Error(143, "invalid hook declaration");
}; }
updateHook(aHook) { updateHook(aHook) {
if (aHook.functionName) { if (aHook.functionName) {
@@ -153,7 +152,7 @@ export class HooksController {
}); });
} }
throw new Parse.Error(143, "invalid hook declaration"); throw new Parse.Error(143, "invalid hook declaration");
}; }
} }
function wrapToHTTPRequest(hook, key) { function wrapToHTTPRequest(hook, key) {
@@ -170,7 +169,7 @@ function wrapToHTTPRequest(hook, key) {
jsonBody.original = req.original.toJSON(); jsonBody.original = req.original.toJSON();
jsonBody.original.className = req.original.className; jsonBody.original.className = req.original.className;
} }
let jsonRequest = { let jsonRequest: any = {
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },

View File

@@ -5,7 +5,6 @@ export class LiveQueryController {
liveQueryPublisher: any; liveQueryPublisher: any;
constructor(config: any) { constructor(config: any) {
let classNames;
// If config is empty, we just assume no classs needs to be registered as LiveQuery // If config is empty, we just assume no classs needs to be registered as LiveQuery
if (!config || !config.classNames) { if (!config || !config.classNames) {
this.classNames = new Set(); this.classNames = new Set();

View File

@@ -1,5 +1,4 @@
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import AdaptableController from './AdaptableController'; import AdaptableController from './AdaptableController';
import { LoggerAdapter } from '../Adapters/Logger/LoggerAdapter'; import { LoggerAdapter } from '../Adapters/Logger/LoggerAdapter';
import url from 'url'; import url from 'url';

View File

@@ -1,5 +1,4 @@
import { Parse } from 'parse/node'; import { Parse } from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import rest from '../rest'; import rest from '../rest';
import AdaptableController from './AdaptableController'; import AdaptableController from './AdaptableController';
import { PushAdapter } from '../Adapters/Push/PushAdapter'; import { PushAdapter } from '../Adapters/Push/PushAdapter';
@@ -9,7 +8,6 @@ import RestWrite from '../RestWrite';
import { master } from '../Auth'; import { master } from '../Auth';
import { pushStatusHandler } from '../StatusHandler'; import { pushStatusHandler } from '../StatusHandler';
const FEATURE_NAME = 'push';
const UNSUPPORTED_BADGE_KEY = "unsupported"; const UNSUPPORTED_BADGE_KEY = "unsupported";
export class PushController extends AdaptableController { export class PushController extends AdaptableController {
@@ -24,7 +22,7 @@ export class PushController extends AdaptableController {
var deviceTypes = []; var deviceTypes = [];
if (typeof deviceTypeField === 'string') { if (typeof deviceTypeField === 'string') {
deviceTypes.push(deviceTypeField); deviceTypes.push(deviceTypeField);
} else if (typeof deviceTypeField['$in'] === 'array') { } else if (Array.isArray(deviceTypeField['$in'])) {
deviceTypes.concat(deviceTypeField['$in']); deviceTypes.concat(deviceTypeField['$in']);
} }
for (var i = 0; i < deviceTypes.length; i++) { for (var i = 0; i < deviceTypes.length; i++) {
@@ -98,13 +96,13 @@ export class PushController extends AdaptableController {
}).then((results) => { }).then((results) => {
return pushStatus.complete(results); return pushStatus.complete(results);
}).catch((err) => { }).catch((err) => {
return pushStatus.fail(err).then(() => { return pushStatus.fail(err).then(() => {
throw err; throw err;
}); });
}); });
} }
sendToAdapter(body, installations, pushStatus, config) { sendToAdapter(body, installations, pushStatus) {
if (body.data && body.data.badge && typeof body.data.badge == 'string' && body.data.badge.toLowerCase() == "increment") { if (body.data && body.data.badge && typeof body.data.badge == 'string' && body.data.badge.toLowerCase() == "increment") {
// Collect the badges to reduce the # of calls // Collect the badges to reduce the # of calls
let badgeInstallationsMap = installations.reduce((map, installation) => { let badgeInstallationsMap = installations.reduce((map, installation) => {

View File

@@ -21,7 +21,7 @@ export default class SchemaCache {
} }
put(key, value) { put(key, value) {
return this.cache.get(this.prefix+ALL_KEYS).then((allKeys) => { return this.cache.get(this.prefix+ALL_KEYS).then((allKeys) => {
allKeys = allKeys || {}; allKeys = allKeys || {};
allKeys[key] = true; allKeys[key] = true;
return Promise.all([this.cache.put(this.prefix+ALL_KEYS, allKeys, this.ttl), this.cache.put(key, value, this.ttl)]); return Promise.all([this.cache.put(this.prefix+ALL_KEYS, allKeys, this.ttl), this.cache.put(key, value, this.ttl)]);
@@ -72,8 +72,7 @@ export default class SchemaCache {
clear() { clear() {
// That clears all caches... // That clears all caches...
let promise = Promise.resolve(); return this.cache.get(this.prefix+ALL_KEYS).then((allKeys) => {
return this.cache.get(this.prefix+ALL_KEYS).then((allKeys) => {
if (!allKeys) { if (!allKeys) {
return; return;
} }

View File

@@ -15,7 +15,6 @@
// TODO: hide all schema logic inside the database adapter. // TODO: hide all schema logic inside the database adapter.
const Parse = require('parse/node').Parse; const Parse = require('parse/node').Parse;
import _ from 'lodash';
const defaultColumns = Object.freeze({ const defaultColumns = Object.freeze({
// Contain the default columns for every parse object type (except _Join collection) // Contain the default columns for every parse object type (except _Join collection)
@@ -152,7 +151,7 @@ function validateCLP(perms, fields) {
} else { } else {
perms[operation].forEach((key) => { perms[operation].forEach((key) => {
if (!fields[key] || fields[key].type != 'Pointer' || fields[key].targetClass != '_User') { if (!fields[key] || fields[key].type != 'Pointer' || fields[key].targetClass != '_User') {
throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid column for class level pointer permissions ${operation}`); throw new Parse.Error(Parse.Error.INVALID_JSON, `'${key}' is not a valid column for class level pointer permissions ${operation}`);
} }
}); });
} }
@@ -222,19 +221,19 @@ const fieldTypeIsInvalid = ({ type, targetClass }) => {
if (!targetClass) { if (!targetClass) {
return new Parse.Error(135, `type ${type} needs a class name`); return new Parse.Error(135, `type ${type} needs a class name`);
} else if (typeof targetClass !== 'string') { } else if (typeof targetClass !== 'string') {
return invalidJsonError; return invalidJsonError;
} else if (!classNameIsValid(targetClass)) { } else if (!classNameIsValid(targetClass)) {
return new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(targetClass)); return new Parse.Error(Parse.Error.INVALID_CLASS_NAME, invalidClassNameMessage(targetClass));
} else { } else {
return undefined; return undefined;
} }
} }
if (typeof type !== 'string') { if (typeof type !== 'string') {
return invalidJsonError; return invalidJsonError;
} }
if (validNonRelationOrPointerTypes.indexOf(type) < 0) { if (validNonRelationOrPointerTypes.indexOf(type) < 0) {
return new Parse.Error(Parse.Error.INCORRECT_TYPE, `invalid field type: ${type}`); return new Parse.Error(Parse.Error.INCORRECT_TYPE, `invalid field type: ${type}`);
} }
return undefined; return undefined;
} }
@@ -280,14 +279,14 @@ const injectDefaultSchema = ({className, fields, classLevelPermissions}) => ({
const _HooksSchema = {className: "_Hooks", fields: defaultColumns._Hooks}; const _HooksSchema = {className: "_Hooks", fields: defaultColumns._Hooks};
const _GlobalConfigSchema = { className: "_GlobalConfig", fields: defaultColumns._GlobalConfig } const _GlobalConfigSchema = { className: "_GlobalConfig", fields: defaultColumns._GlobalConfig }
const _PushStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ const _PushStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({
className: "_PushStatus", className: "_PushStatus",
fields: {}, fields: {},
classLevelPermissions: {} classLevelPermissions: {}
})); }));
const _JobStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({ const _JobStatusSchema = convertSchemaToAdapterSchema(injectDefaultSchema({
className: "_JobStatus", className: "_JobStatus",
fields: {}, fields: {},
classLevelPermissions: {} classLevelPermissions: {}
})); }));
const VolatileClassesSchemas = [_HooksSchema, _JobStatusSchema, _PushStatusSchema, _GlobalConfigSchema]; const VolatileClassesSchemas = [_HooksSchema, _JobStatusSchema, _PushStatusSchema, _GlobalConfigSchema];
@@ -325,7 +324,7 @@ export default class SchemaController {
reloadData(options = {clearCache: false}) { reloadData(options = {clearCache: false}) {
let promise = Promise.resolve(); let promise = Promise.resolve();
if (options.clearCache) { if (options.clearCache) {
promise = promise.then(() => { promise = promise.then(() => {
return this._cache.clear(); return this._cache.clear();
}); });
} }
@@ -334,7 +333,7 @@ export default class SchemaController {
} }
this.data = {}; this.data = {};
this.perms = {}; this.perms = {};
this.reloadDataPromise = promise.then(() => { this.reloadDataPromise = promise.then(() => {
return this.getAllClasses(options); return this.getAllClasses(options);
}) })
.then(allSchemas => { .then(allSchemas => {
@@ -352,7 +351,7 @@ export default class SchemaController {
}); });
}); });
delete this.reloadDataPromise; delete this.reloadDataPromise;
}, (err) => { }, (err) => {
delete this.reloadDataPromise; delete this.reloadDataPromise;
throw err; throw err;
}); });
@@ -364,16 +363,16 @@ export default class SchemaController {
if (options.clearCache) { if (options.clearCache) {
promise = this._cache.clear(); promise = this._cache.clear();
} }
return promise.then(() => { return promise.then(() => {
return this._cache.getAllClasses() return this._cache.getAllClasses()
}).then((allClasses) => { }).then((allClasses) => {
if (allClasses && allClasses.length && !options.clearCache) { if (allClasses && allClasses.length && !options.clearCache) {
return Promise.resolve(allClasses); return Promise.resolve(allClasses);
} }
return this._dbAdapter.getAllClasses() return this._dbAdapter.getAllClasses()
.then(allSchemas => allSchemas.map(injectDefaultSchema)) .then(allSchemas => allSchemas.map(injectDefaultSchema))
.then(allSchemas => { .then(allSchemas => {
return this._cache.setAllClasses(allSchemas).then(() => { return this._cache.setAllClasses(allSchemas).then(() => {
return allSchemas; return allSchemas;
}); });
}) })
@@ -385,18 +384,18 @@ export default class SchemaController {
if (options.clearCache) { if (options.clearCache) {
promise = this._cache.clear(); promise = this._cache.clear();
} }
return promise.then(() => { return promise.then(() => {
if (allowVolatileClasses && volatileClasses.indexOf(className) > -1) { if (allowVolatileClasses && volatileClasses.indexOf(className) > -1) {
return Promise.resolve(this.data[className]); return Promise.resolve(this.data[className]);
} }
return this._cache.getOneSchema(className).then((cached) => { return this._cache.getOneSchema(className).then((cached) => {
if (cached && !options.clearCache) { if (cached && !options.clearCache) {
return Promise.resolve(cached); return Promise.resolve(cached);
} }
return this._dbAdapter.getClass(className) return this._dbAdapter.getClass(className)
.then(injectDefaultSchema) .then(injectDefaultSchema)
.then((result) => { .then((result) => {
return this._cache.setOneSchema(className, result).then(() => { return this._cache.setOneSchema(className, result).then(() => {
return result; return result;
}) })
}); });
@@ -419,9 +418,9 @@ export default class SchemaController {
return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ fields, classLevelPermissions, className })) return this._dbAdapter.createClass(className, convertSchemaToAdapterSchema({ fields, classLevelPermissions, className }))
.then(convertAdapterSchemaToParseSchema) .then(convertAdapterSchemaToParseSchema)
.then((res) => { .then((res) => {
return this._cache.clear().then(() => { return this._cache.clear().then(() => {
return Promise.resolve(res); return Promise.resolve(res);
}); });
}) })
.catch(error => { .catch(error => {
@@ -504,7 +503,7 @@ export default class SchemaController {
return this.addClassIfNotExists(className) return this.addClassIfNotExists(className)
// The schema update succeeded. Reload the schema // The schema update succeeded. Reload the schema
.then(() => this.reloadData({ clearCache: true })) .then(() => this.reloadData({ clearCache: true }))
.catch(error => { .catch(() => {
// The schema update failed. This can be okay - it might // The schema update failed. This can be okay - it might
// have failed because there's a race condition and a different // have failed because there's a race condition and a different
// client is making the exact same schema update that we want. // client is making the exact same schema update that we want.
@@ -519,7 +518,7 @@ export default class SchemaController {
throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`); throw new Parse.Error(Parse.Error.INVALID_JSON, `Failed to add ${className}`);
} }
}) })
.catch(error => { .catch(() => {
// The schema still doesn't validate. Give up // The schema still doesn't validate. Give up
throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate'); throw new Parse.Error(Parse.Error.INVALID_JSON, 'schema class name does not revalidate');
}); });
@@ -586,7 +585,7 @@ export default class SchemaController {
// object if the provided className-fieldName-type tuple is valid. // object if the provided className-fieldName-type tuple is valid.
// The className must already be validated. // The className must already be validated.
// If 'freeze' is true, refuse to update the schema for this field. // If 'freeze' is true, refuse to update the schema for this field.
enforceFieldExists(className, fieldName, type, freeze) { enforceFieldExists(className, fieldName, type) {
if (fieldName.indexOf(".") > 0) { if (fieldName.indexOf(".") > 0) {
// subdocument key (x.y) => ok if x is of type 'object' // subdocument key (x.y) => ok if x is of type 'object'
fieldName = fieldName.split(".")[ 0 ]; fieldName = fieldName.split(".")[ 0 ];
@@ -620,14 +619,14 @@ export default class SchemaController {
return this._dbAdapter.addFieldIfNotExists(className, fieldName, type).then(() => { return this._dbAdapter.addFieldIfNotExists(className, fieldName, type).then(() => {
// The update succeeded. Reload the schema // The update succeeded. Reload the schema
return this.reloadData({ clearCache: true }); return this.reloadData({ clearCache: true });
}, error => { }, () => {
//TODO: introspect the error and only reload if the error is one for which is makes sense to reload //TODO: introspect the error and only reload if the error is one for which is makes sense to reload
// The update failed. This can be okay - it might have been a race // The update failed. This can be okay - it might have been a race
// condition where another client updated the schema in the same // condition where another client updated the schema in the same
// way that we wanted to. So, just reload the schema // way that we wanted to. So, just reload the schema
return this.reloadData({ clearCache: true }); return this.reloadData({ clearCache: true });
}).then(error => { }).then(() => {
// Ensure that the schema now validates // Ensure that the schema now validates
if (!dbTypeMatchesObjectType(this.getExpectedType(className, fieldName), type)) { if (!dbTypeMatchesObjectType(this.getExpectedType(className, fieldName), type)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, `Could not add field ${fieldName}`); throw new Parse.Error(Parse.Error.INVALID_JSON, `Could not add field ${fieldName}`);
@@ -676,7 +675,7 @@ export default class SchemaController {
.then(() => database.adapter.deleteClass(`_Join:${fieldName}:${className}`)); .then(() => database.adapter.deleteClass(`_Join:${fieldName}:${className}`));
} }
return database.adapter.deleteFields(className, schema, [fieldName]); return database.adapter.deleteFields(className, schema, [fieldName]);
}).then(() => { }).then(() => {
this._cache.clear(); this._cache.clear();
}); });
} }
@@ -772,7 +771,6 @@ export default class SchemaController {
return true; return true;
} }
let classPerms = this.perms[className]; let classPerms = this.perms[className];
let perms = classPerms[operation];
// No matching CLP, let's check the Pointer permissions // No matching CLP, let's check the Pointer permissions
// And handle those later // And handle those later
let permissionField = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields'; let permissionField = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields';
@@ -785,11 +783,11 @@ export default class SchemaController {
// Process the readUserFields later // Process the readUserFields later
if (Array.isArray(classPerms[permissionField]) && classPerms[permissionField].length > 0) { if (Array.isArray(classPerms[permissionField]) && classPerms[permissionField].length > 0) {
return Promise.resolve(); return Promise.resolve();
} }
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN,
`Permission denied for action ${operation} on class ${className}.`); `Permission denied for action ${operation} on class ${className}.`);
}; }
// Returns the expected type for a className+key combination // Returns the expected type for a className+key combination
// or undefined if the schema is not set // or undefined if the schema is not set
@@ -799,7 +797,7 @@ export default class SchemaController {
return expectedType === 'map' ? 'Object' : expectedType; return expectedType === 'map' ? 'Object' : expectedType;
} }
return undefined; return undefined;
}; }
// Checks if a given class is in the schema. // Checks if a given class is in the schema.
hasClass(className) { hasClass(className) {
@@ -859,23 +857,23 @@ function thenValidateRequiredColumns(schemaPromise, className, object, query) {
function getType(obj) { function getType(obj) {
let type = typeof obj; let type = typeof obj;
switch(type) { switch(type) {
case 'boolean': case 'boolean':
return 'Boolean'; return 'Boolean';
case 'string': case 'string':
return 'String'; return 'String';
case 'number': case 'number':
return 'Number'; return 'Number';
case 'map': case 'map':
case 'object': case 'object':
if (!obj) { if (!obj) {
return undefined; return undefined;
} }
return getObjectType(obj); return getObjectType(obj);
case 'function': case 'function':
case 'symbol': case 'symbol':
case 'undefined': case 'undefined':
default: default:
throw 'bad obj: ' + obj; throw 'bad obj: ' + obj;
} }
} }
@@ -888,63 +886,68 @@ function getObjectType(obj) {
} }
if (obj.__type){ if (obj.__type){
switch(obj.__type) { switch(obj.__type) {
case 'Pointer' : case 'Pointer' :
if(obj.className) { if(obj.className) {
return { return {
type: 'Pointer', type: 'Pointer',
targetClass: obj.className targetClass: obj.className
}
} }
case 'Relation' : }
if(obj.className) { break;
return { case 'Relation' :
type: 'Relation', if(obj.className) {
targetClass: obj.className return {
} type: 'Relation',
targetClass: obj.className
} }
case 'File' : }
if(obj.name) { break;
return 'File'; case 'File' :
} if(obj.name) {
case 'Date' : return 'File';
if(obj.iso) { }
return 'Date'; break;
} case 'Date' :
case 'GeoPoint' : if(obj.iso) {
if(obj.latitude != null && obj.longitude != null) { return 'Date';
return 'GeoPoint'; }
} break;
case 'Bytes' : case 'GeoPoint' :
if(obj.base64) { if(obj.latitude != null && obj.longitude != null) {
return; return 'GeoPoint';
} }
default: break;
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, "This is not a valid "+obj.__type); case 'Bytes' :
if(obj.base64) {
return;
}
break;
} }
throw new Parse.Error(Parse.Error.INCORRECT_TYPE, "This is not a valid "+obj.__type);
} }
if (obj['$ne']) { if (obj['$ne']) {
return getObjectType(obj['$ne']); return getObjectType(obj['$ne']);
} }
if (obj.__op) { if (obj.__op) {
switch(obj.__op) { switch(obj.__op) {
case 'Increment': case 'Increment':
return 'Number'; return 'Number';
case 'Delete': case 'Delete':
return null; return null;
case 'Add': case 'Add':
case 'AddUnique': case 'AddUnique':
case 'Remove': case 'Remove':
return 'Array'; return 'Array';
case 'AddRelation': case 'AddRelation':
case 'RemoveRelation': case 'RemoveRelation':
return { return {
type: 'Relation', type: 'Relation',
targetClass: obj.objects[0].className targetClass: obj.objects[0].className
} }
case 'Batch': case 'Batch':
return getObjectType(obj.ops[0]); return getObjectType(obj.ops[0]);
default: default:
throw 'unexpected op: ' + obj.__op; throw 'unexpected op: ' + obj.__op;
} }
} }
return 'Object'; return 'Object';

View File

@@ -3,10 +3,9 @@ import { inflate } from '../triggers';
import AdaptableController from './AdaptableController'; import AdaptableController from './AdaptableController';
import MailAdapter from '../Adapters/Email/MailAdapter'; import MailAdapter from '../Adapters/Email/MailAdapter';
import rest from '../rest'; import rest from '../rest';
import Parse from 'parse/node';
var RestWrite = require('../RestWrite');
var RestQuery = require('../RestQuery'); var RestQuery = require('../RestQuery');
var hash = require('../password').hash;
var Auth = require('../Auth'); var Auth = require('../Auth');
export class UserController extends AdaptableController { export class UserController extends AdaptableController {
@@ -118,7 +117,7 @@ export class UserController extends AdaptableController {
} }
const token = encodeURIComponent(user._email_verify_token); const token = encodeURIComponent(user._email_verify_token);
// We may need to fetch the user in case of update email // We may need to fetch the user in case of update email
this.getUserIfNeeded(user).then((user) => { this.getUserIfNeeded(user).then((user) => {
const username = encodeURIComponent(user.username); const username = encodeURIComponent(user.username);
let link = `${this.config.verifyEmailURL}?token=${token}&username=${username}`; let link = `${this.config.verifyEmailURL}?token=${token}&username=${username}`;
let options = { let options = {
@@ -148,7 +147,6 @@ export class UserController extends AdaptableController {
if (!this.adapter) { if (!this.adapter) {
throw "Trying to send a reset password but no adapter is set"; throw "Trying to send a reset password but no adapter is set";
// TODO: No adapter? // TODO: No adapter?
return;
} }
return this.setPasswordResetToken(email) return this.setPasswordResetToken(email)
@@ -173,7 +171,7 @@ export class UserController extends AdaptableController {
}); });
} }
updatePassword(username, token, password, config) { updatePassword(username, token, password) {
return this.checkResetTokenValidity(username, token) return this.checkResetTokenValidity(username, token)
.then(user => updateUserPassword(user.objectId, password, this.config)) .then(user => updateUserPassword(user.objectId, password, this.config))
// clear reset password token // clear reset password token
@@ -191,9 +189,9 @@ export class UserController extends AdaptableController {
defaultVerificationEmail({link, user, appName, }) { defaultVerificationEmail({link, user, appName, }) {
let text = "Hi,\n\n" + let text = "Hi,\n\n" +
"You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" + "You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" +
"" + "" +
"Click here to confirm it:\n" + link; "Click here to confirm it:\n" + link;
let to = user.get("email"); let to = user.get("email");
let subject = 'Please verify your e-mail for ' + appName; let subject = 'Please verify your e-mail for ' + appName;
return { text, to, subject }; return { text, to, subject };
@@ -215,6 +213,6 @@ function updateUserPassword(userId, password, config) {
return rest.update(config, Auth.master(config), '_User', userId, { return rest.update(config, Auth.master(config), '_User', userId, {
password: password password: password
}); });
} }
export default UserController; export default UserController;

View File

@@ -1,4 +1,3 @@
import Parse from 'parse/node';
import logger from '../logger'; import logger from '../logger';
import type { FlattenedObjectData } from './Subscription'; import type { FlattenedObjectData } from './Subscription';
@@ -54,7 +53,7 @@ class Client {
this.subscriptionInfos.set(requestId, subscriptionInfo); this.subscriptionInfos.set(requestId, subscriptionInfo);
} }
getSubscriptionInfo(requestId: numner): any { getSubscriptionInfo(requestId: number): any {
return this.subscriptionInfos.get(requestId); return this.subscriptionInfos.get(requestId);
} }

View File

@@ -251,21 +251,21 @@ class ParseLiveQueryServer {
} }
switch(request.op) { switch(request.op) {
case 'connect': case 'connect':
this._handleConnect(parseWebsocket, request); this._handleConnect(parseWebsocket, request);
break; break;
case 'subscribe': case 'subscribe':
this._handleSubscribe(parseWebsocket, request); this._handleSubscribe(parseWebsocket, request);
break; break;
case 'update': case 'update':
this._handleUpdateSubscription(parseWebsocket, request); this._handleUpdateSubscription(parseWebsocket, request);
break; break;
case 'unsubscribe': case 'unsubscribe':
this._handleUnsubscribe(parseWebsocket, request); this._handleUnsubscribe(parseWebsocket, request);
break; break;
default: default:
Client.pushError(parseWebsocket, 3, 'Get unknown operation'); Client.pushError(parseWebsocket, 3, 'Get unknown operation');
logger.error('Get unknown operation', request.op); logger.error('Get unknown operation', request.op);
} }
}); });
@@ -335,48 +335,48 @@ class ParseLiveQueryServer {
// Resolve false right away if the acl doesn't have any roles // Resolve false right away if the acl doesn't have any roles
const acl_has_roles = Object.keys(acl.permissionsById).some(key => key.startsWith("role:")); const acl_has_roles = Object.keys(acl.permissionsById).some(key => key.startsWith("role:"));
if (!acl_has_roles) { if (!acl_has_roles) {
return resolve(false); return resolve(false);
} }
this.sessionTokenCache.getUserId(subscriptionSessionToken) this.sessionTokenCache.getUserId(subscriptionSessionToken)
.then((userId) => { .then((userId) => {
// Pass along a null if there is no user id // Pass along a null if there is no user id
if (!userId) { if (!userId) {
return Parse.Promise.as(null); return Parse.Promise.as(null);
} }
// Prepare a user object to query for roles // Prepare a user object to query for roles
// To eliminate a query for the user, create one locally with the id // To eliminate a query for the user, create one locally with the id
var user = new Parse.User(); var user = new Parse.User();
user.id = userId; user.id = userId;
return user; return user;
}) })
.then((user) => { .then((user) => {
// Pass along an empty array (of roles) if no user // Pass along an empty array (of roles) if no user
if (!user) { if (!user) {
return Parse.Promise.as([]); return Parse.Promise.as([]);
} }
// Then get the user's roles // Then get the user's roles
var rolesQuery = new Parse.Query(Parse.Role); var rolesQuery = new Parse.Query(Parse.Role);
rolesQuery.equalTo("users", user); rolesQuery.equalTo("users", user);
return rolesQuery.find(); return rolesQuery.find();
}). }).
then((roles) => { then((roles) => {
// Finally, see if any of the user's roles allow them read access // Finally, see if any of the user's roles allow them read access
for (let role of roles) { for (let role of roles) {
if (acl.getRoleReadAccess(role)) { if (acl.getRoleReadAccess(role)) {
return resolve(true); return resolve(true);
}
} }
resolve(false); }
resolve(false);
}) })
.catch((error) => { .catch((error) => {
reject(error); reject(error);
}); });
}); });
@@ -393,7 +393,7 @@ class ParseLiveQueryServer {
}); });
}).then((isMatched) => { }).then((isMatched) => {
return Parse.Promise.as(isMatched); return Parse.Promise.as(isMatched);
}, (error) => { }, () => {
return Parse.Promise.as(false); return Parse.Promise.as(false);
}); });
} }

View File

@@ -38,7 +38,7 @@ export class ParseWebSocket {
this.ws.on(wsType, callback); this.ws.on(wsType, callback);
} }
send(message: any, channel: string): void { send(message: any): void {
this.ws.send(message); this.ws.send(message);
} }
} }

View File

@@ -167,117 +167,118 @@ function matchesKeyConstraints(object, key, constraints) {
compareTo = Parse._decode(key, compareTo); compareTo = Parse._decode(key, compareTo);
} }
switch (condition) { switch (condition) {
case '$lt': case '$lt':
if (object[key] >= compareTo) { if (object[key] >= compareTo) {
return false;
}
break;
case '$lte':
if (object[key] > compareTo) {
return false;
}
break;
case '$gt':
if (object[key] <= compareTo) {
return false;
}
break;
case '$gte':
if (object[key] < compareTo) {
return false;
}
break;
case '$ne':
if (equalObjects(object[key], compareTo)) {
return false;
}
break;
case '$in':
if (compareTo.indexOf(object[key]) < 0) {
return false;
}
break;
case '$nin':
if (compareTo.indexOf(object[key]) > -1) {
return false;
}
break;
case '$all':
for (i = 0; i < compareTo.length; i++) {
if (object[key].indexOf(compareTo[i]) < 0) {
return false; return false;
} }
break; }
case '$lte': break;
if (object[key] > compareTo) { case '$exists': {
return false; let propertyExists = typeof object[key] !== 'undefined';
} let existenceIsRequired = constraints['$exists'];
break; if (typeof constraints['$exists'] !== 'boolean') {
case '$gt':
if (object[key] <= compareTo) {
return false;
}
break;
case '$gte':
if (object[key] < compareTo) {
return false;
}
break;
case '$ne':
if (equalObjects(object[key], compareTo)) {
return false;
}
break;
case '$in':
if (compareTo.indexOf(object[key]) < 0) {
return false;
}
break;
case '$nin':
if (compareTo.indexOf(object[key]) > -1) {
return false;
}
break;
case '$all':
for (i = 0; i < compareTo.length; i++) {
if (object[key].indexOf(compareTo[i]) < 0) {
return false;
}
}
break;
case '$exists':
let propertyExists = typeof object[key] !== 'undefined';
let existenceIsRequired = constraints['$exists'];
if (typeof constraints['$exists'] !== 'boolean') {
// The SDK will never submit a non-boolean for $exists, but if someone // The SDK will never submit a non-boolean for $exists, but if someone
// tries to submit a non-boolean for $exits outside the SDKs, just ignore it. // tries to submit a non-boolean for $exits outside the SDKs, just ignore it.
break;
}
if ((!propertyExists && existenceIsRequired) || (propertyExists && !existenceIsRequired)) {
return false;
}
break; break;
case '$regex': }
if (typeof compareTo === 'object') { if ((!propertyExists && existenceIsRequired) || (propertyExists && !existenceIsRequired)) {
return compareTo.test(object[key]); return false;
} }
break;
}
case '$regex':
if (typeof compareTo === 'object') {
return compareTo.test(object[key]);
}
// JS doesn't support perl-style escaping // JS doesn't support perl-style escaping
var expString = ''; var expString = '';
var escapeEnd = -2; var escapeEnd = -2;
var escapeStart = compareTo.indexOf('\\Q'); var escapeStart = compareTo.indexOf('\\Q');
while (escapeStart > -1) { while (escapeStart > -1) {
// Add the unescaped portion // Add the unescaped portion
expString += compareTo.substring(escapeEnd + 2, escapeStart); expString += compareTo.substring(escapeEnd + 2, escapeStart);
escapeEnd = compareTo.indexOf('\\E', escapeStart); escapeEnd = compareTo.indexOf('\\E', escapeStart);
if (escapeEnd > -1) { if (escapeEnd > -1) {
expString += compareTo.substring(escapeStart + 2, escapeEnd) expString += compareTo.substring(escapeStart + 2, escapeEnd)
.replace(/\\\\\\\\E/g, '\\E').replace(/\W/g, '\\$&'); .replace(/\\\\\\\\E/g, '\\E').replace(/\W/g, '\\$&');
} }
escapeStart = compareTo.indexOf('\\Q', escapeEnd); escapeStart = compareTo.indexOf('\\Q', escapeEnd);
} }
expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2)); expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2));
var exp = new RegExp(expString, constraints.$options || ''); var exp = new RegExp(expString, constraints.$options || '');
if (!exp.test(object[key])) { if (!exp.test(object[key])) {
return false; return false;
} }
break; break;
case '$nearSphere': case '$nearSphere':
var distance = compareTo.radiansTo(object[key]); var distance = compareTo.radiansTo(object[key]);
var max = constraints.$maxDistance || Infinity; var max = constraints.$maxDistance || Infinity;
return distance <= max; return distance <= max;
case '$within': case '$within':
var southWest = compareTo.$box[0]; var southWest = compareTo.$box[0];
var northEast = compareTo.$box[1]; var northEast = compareTo.$box[1];
if (southWest.latitude > northEast.latitude || if (southWest.latitude > northEast.latitude ||
southWest.longitude > northEast.longitude) { southWest.longitude > northEast.longitude) {
// Invalid box, crosses the date line // Invalid box, crosses the date line
return false; return false;
} }
return ( return (
object[key].latitude > southWest.latitude && object[key].latitude > southWest.latitude &&
object[key].latitude < northEast.latitude && object[key].latitude < northEast.latitude &&
object[key].longitude > southWest.longitude && object[key].longitude > southWest.longitude &&
object[key].longitude < northEast.longitude object[key].longitude < northEast.longitude
); );
case '$options': case '$options':
// Not a query type, but a way to add options to $regex. Ignore and // Not a query type, but a way to add options to $regex. Ignore and
// avoid the default // avoid the default
break; break;
case '$maxDistance': case '$maxDistance':
// Not a query type, but a way to add a cap to $nearSphere. Ignore and // Not a query type, but a way to add a cap to $nearSphere. Ignore and
// avoid the default // avoid the default
break; break;
case '$select': case '$select':
return false; return false;
case '$dontSelect': case '$dontSelect':
return false; return false;
default: default:
return false; return false;
} }
} }
return true; return true;

View File

@@ -61,7 +61,7 @@ let subscribe = {
'fields': { 'fields': {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
}, },
"minItems": 1, "minItems": 1,
"uniqueItems": true "uniqueItems": true
@@ -99,7 +99,7 @@ let update = {
'fields': { 'fields': {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
}, },
"minItems": 1, "minItems": 1,
"uniqueItems": true "uniqueItems": true

View File

@@ -1,4 +1,3 @@
import {matchesQuery, queryHash} from './QueryTools';
import logger from '../logger'; import logger from '../logger';
export type FlattenedObjectData = { [attr: string]: any }; export type FlattenedObjectData = { [attr: string]: any };

View File

@@ -1,20 +1,18 @@
// ParseServer - open-source compatible API Server for Parse apps // ParseServer - open-source compatible API Server for Parse apps
var batch = require('./batch'), var batch = require('./batch'),
bodyParser = require('body-parser'), bodyParser = require('body-parser'),
express = require('express'), express = require('express'),
middlewares = require('./middlewares'), middlewares = require('./middlewares'),
multer = require('multer'), Parse = require('parse/node').Parse,
Parse = require('parse/node').Parse, path = require('path'),
path = require('path'), url = require('url'),
url = require('url'), authDataManager = require('./authDataManager');
authDataManager = require('./authDataManager');
import defaults from './defaults'; import defaults from './defaults';
import * as logging from './logger'; import * as logging from './logger';
import AppCache from './cache'; import AppCache from './cache';
import Config from './Config'; import Config from './Config';
import parseServerPackage from '../package.json';
import PromiseRouter from './PromiseRouter'; import PromiseRouter from './PromiseRouter';
import requiredParameter from './requiredParameter'; import requiredParameter from './requiredParameter';
import { AnalyticsRouter } from './Routers/AnalyticsRouter'; import { AnalyticsRouter } from './Routers/AnalyticsRouter';
@@ -43,7 +41,6 @@ import { PublicAPIRouter } from './Routers/PublicAPIRouter';
import { PushController } from './Controllers/PushController'; import { PushController } from './Controllers/PushController';
import { PushRouter } from './Routers/PushRouter'; import { PushRouter } from './Routers/PushRouter';
import { CloudCodeRouter } from './Routers/CloudCodeRouter'; import { CloudCodeRouter } from './Routers/CloudCodeRouter';
import { randomString } from './cryptoUtils';
import { RolesRouter } from './Routers/RolesRouter'; import { RolesRouter } from './Routers/RolesRouter';
import { SchemasRouter } from './Routers/SchemasRouter'; import { SchemasRouter } from './Routers/SchemasRouter';
import { SessionsRouter } from './Routers/SessionsRouter'; import { SessionsRouter } from './Routers/SessionsRouter';
@@ -260,20 +257,20 @@ class ParseServer {
try { try {
const parsedURI = url.parse(databaseURI); const parsedURI = url.parse(databaseURI);
protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null; protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null;
} catch(e) {} } catch(e) { /* */ }
switch (protocol) { switch (protocol) {
case 'postgres:': case 'postgres:':
return new PostgresStorageAdapter({ return new PostgresStorageAdapter({
uri: databaseURI, uri: databaseURI,
collectionPrefix, collectionPrefix,
databaseOptions databaseOptions
}); });
default: default:
return new MongoStorageAdapter({ return new MongoStorageAdapter({
uri: databaseURI, uri: databaseURI,
collectionPrefix, collectionPrefix,
mongoOptions: databaseOptions, mongoOptions: databaseOptions,
}); });
} }
} }
@@ -309,7 +306,9 @@ class ParseServer {
if (!process.env.TESTING) { if (!process.env.TESTING) {
process.on('uncaughtException', (err) => { process.on('uncaughtException', (err) => {
if ( err.code === "EADDRINUSE" ) { // user-friendly message for this common error if ( err.code === "EADDRINUSE" ) { // user-friendly message for this common error
/* eslint-disable no-console */
console.error(`Unable to listen on port ${err.port}. The port is already in use.`); console.error(`Unable to listen on port ${err.port}. The port is already in use.`);
/* eslint-enable no-console */
process.exit(0); process.exit(0);
} else { } else {
throw err; throw err;

Some files were not shown because too many files have changed in this diff Show More