DBController refactoring (#1228)

* Moves transform to MongoTransform

- Adds ACL query injection in MongoTransform

* Removes adaptiveCollection from DatabaseController

- All collections manipulations are now handled by a DBController
- Adds optional flags to configure an unsafe databaseController for direct
  access
- Adds ability to configure RestWrite with multiple writes
- Moves some transfirmations to MongoTransform as they output specific code

* Renames Unsafe to WithoutValidation
This commit is contained in:
Florent Vilmart
2016-04-14 19:24:56 -04:00
parent 51970fb470
commit 1023baf20d
17 changed files with 317 additions and 291 deletions

View File

@@ -1,7 +1,7 @@
// These tests are unit tests designed to only test transform.js.
"use strict";
let transform = require('../src/transform');
let transform = require('../src/Adapters/Storage/Mongo/MongoTransform');
let dd = require('deep-diff');
let mongodb = require('mongodb');

View File

@@ -7,7 +7,7 @@ let Config = require('../src/Config');
describe('a GlobalConfig', () => {
beforeEach(done => {
let config = new Config('test');
config.database.adaptiveCollection('_GlobalConfig')
config.database.adapter.adaptiveCollection('_GlobalConfig')
.then(coll => coll.upsertOne({ '_id': 1 }, { $set: { params: { companies: ['US', 'DK'] } } }))
.then(() => { done(); });
});
@@ -43,6 +43,35 @@ describe('a GlobalConfig', () => {
});
});
it('properly handles delete op', (done) => {
request.put({
url : 'http://localhost:8378/1/config',
json : true,
body : { params: { companies: {__op: 'Delete'}, foo: 'bar' } },
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-Master-Key' : 'test'
}
}, (error, response, body) => {
expect(response.statusCode).toEqual(200);
expect(body.result).toEqual(true);
request.get({
url : 'http://localhost:8378/1/config',
json : true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-Master-Key' : 'test'
}
}, (error, response, body) => {
expect(response.statusCode).toEqual(200);
expect(body.params.companies).toBeUndefined();
expect(body.params.foo).toBe('bar');
expect(Object.keys(body.params).length).toBe(1);
done();
});
});
});
it('fail to update if master key is missing', (done) => {
request.put({
url : 'http://localhost:8378/1/config',
@@ -61,7 +90,7 @@ describe('a GlobalConfig', () => {
it('failed getting config when it is missing', (done) => {
let config = new Config('test');
config.database.adaptiveCollection('_GlobalConfig')
config.database.adapter.adaptiveCollection('_GlobalConfig')
.then(coll => coll.deleteOne({ '_id': 1 }))
.then(() => {
request.get({

View File

@@ -16,7 +16,7 @@ app.listen(12345);
describe('Hooks', () => {
it("should have some hooks registered", (done) => {
Parse.Hooks.getFunctions().then((res) => {
expect(res.constructor).toBe(Array.prototype.constructor);
@@ -26,7 +26,7 @@ describe('Hooks', () => {
done();
});
});
it("should have some triggers registered", (done) => {
Parse.Hooks.getTriggers().then( (res) => {
expect(res.constructor).toBe(Array.prototype.constructor);
@@ -59,7 +59,7 @@ describe('Hooks', () => {
}).then((res) => {
expect(res.functionName).toBe("My-Test-Function");
expect(res.url).toBe("http://anotherurl")
return Parse.Hooks.deleteFunction("My-Test-Function");
}, (err) => {
fail(err);
@@ -81,7 +81,7 @@ describe('Hooks', () => {
done();
})
});
it("should CRUD a trigger registration", (done) => {
// Create
Parse.Hooks.createTrigger("MyClass","beforeDelete", "http://someurl").then((res) => {
@@ -105,7 +105,7 @@ describe('Hooks', () => {
}).then((res) => {
expect(res.className).toBe("MyClass");
expect(res.url).toBe("http://anotherurl")
return Parse.Hooks.deleteTrigger("MyClass","beforeDelete");
}, (err) => {
fail(err);
@@ -127,7 +127,7 @@ describe('Hooks', () => {
done();
});
});
it("should fail to register hooks without Master Key", (done) => {
request.post(Parse.serverURL+"/hooks/functions", {
headers: {
@@ -141,7 +141,7 @@ describe('Hooks', () => {
done();
})
});
it("should fail trying to create two times the same function", (done) => {
Parse.Hooks.createFunction("my_new_function", "http://url.com").then( () => {
return Parse.Hooks.createFunction("my_new_function", "http://url.com")
@@ -162,7 +162,7 @@ describe('Hooks', () => {
done();
})
});
it("should fail trying to create two times the same trigger", (done) => {
Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com").then( () => {
return Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com")
@@ -181,7 +181,7 @@ describe('Hooks', () => {
done();
})
});
it("should fail trying to update a function that don't exist", (done) => {
Parse.Hooks.updateFunction("A_COOL_FUNCTION", "http://url.com").then( () => {
fail("Should not succeed")
@@ -198,7 +198,7 @@ describe('Hooks', () => {
done();
});
});
it("should fail trying to update a trigger that don't exist", (done) => {
Parse.Hooks.updateTrigger("AClassName","beforeSave", "http://url.com").then( () => {
fail("Should not succeed")
@@ -215,8 +215,8 @@ describe('Hooks', () => {
done();
});
});
it("should fail trying to create a malformed function", (done) => {
Parse.Hooks.createFunction("MyFunction").then( (res) => {
fail(res);
@@ -226,7 +226,7 @@ describe('Hooks', () => {
done();
});
});
it("should fail trying to create a malformed function (REST)", (done) => {
request.post(Parse.serverURL+"/hooks/functions", {
headers: {
@@ -241,16 +241,16 @@ describe('Hooks', () => {
done();
})
});
it("should create hooks and properly preload them", (done) => {
var promises = [];
for (var i = 0; i<5; 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));
}
Parse.Promise.when(promises).then(function(results){
for (var i=0; i<5; i++) {
// Delete everything from memory, as the server just started
@@ -263,7 +263,7 @@ describe('Hooks', () => {
return hooksController.load()
}, (err) => {
console.error(err);
fail();
fail('Should properly create all hooks');
done();
}).then(function() {
for (var i=0; i<5; i++) {
@@ -273,17 +273,17 @@ describe('Hooks', () => {
done();
}, (err) => {
console.error(err);
fail();
fail('should properly load all hooks');
done();
})
});
it("should run the function on the test server", (done) => {
app.post("/SomeFunction", function(req, res) {
res.json({success:"OK!"});
});
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunction").then(function(){
return Parse.Cloud.run("SOME_TEST_FUNCTION")
}, (err) => {
@@ -299,9 +299,9 @@ describe('Hooks', () => {
done();
})
});
it("should run the function on the test server", (done) => {
app.post("/SomeFunctionError", function(req, res) {
res.json({error: {code: 1337, error: "hacking that one!"}});
});
@@ -322,8 +322,8 @@ describe('Hooks', () => {
done();
});
});
it("should run the beforeSave hook on the test server", (done) => {
var triggerCount = 0;
app.post("/BeforeSaveSome", function(req, res) {
@@ -350,7 +350,7 @@ describe('Hooks', () => {
done();
});
});
it("should run the afterSave hook on the test server", (done) => {
var triggerCount = 0;
var newObjectId;
@@ -387,4 +387,4 @@ describe('Hooks', () => {
done();
});
});
});
});

View File

@@ -184,7 +184,6 @@ describe('PushController', () => {
}).then((result) => {
done();
}, (err) => {
console.error(err);
fail("should not fail");
done();
});
@@ -233,7 +232,6 @@ describe('PushController', () => {
}).then((result) => {
done();
}, (err) => {
console.error(err);
fail("should not fail");
done();
});

View File

@@ -266,7 +266,10 @@ describe("Email Verification", () => {
.then((user) => {
return user.save();
}).then((user) => {
return Parse.User.requestPasswordReset("cool_guy@parse.com");
return Parse.User.requestPasswordReset("cool_guy@parse.com").catch((err) => {
fail('Should not fail requesting a password');
done();
})
}).then(() => {
expect(calls).toBe(2);
done();
@@ -551,7 +554,7 @@ describe("Password Reset", () => {
Parse.User.requestPasswordReset('user@parse.com', {
error: (err) => {
console.error(err);
fail("Should not fail");
fail("Should not fail requesting a password");
done();
}
});
@@ -628,7 +631,7 @@ describe("Password Reset", () => {
Parse.User.logIn("zxcv", "hello").then(function(user){
let config = new Config('test');
config.database.adaptiveCollection('_User')
config.database.adapter.adaptiveCollection('_User')
.then(coll => coll.find({ 'username': 'zxcv' }, { limit: 1 }))
.then((results) => {
// _perishable_token should be unset after reset password