Skip to content

Commit

Permalink
Begin isolating object creation code into an externalizable API. (#1569)
Browse files Browse the repository at this point in the history
* Tidy up transformKeyValue

* Specialize transformKeyValue for object creation

* remove keys that never appear in creation requests

* rename function

* remove local var

* early exit for simple keys

* Refactor create

* Force class creation when creating an object

* Pass parameters to key value transformer

* No need to check for array in this func

* start using Parse Format schema in MongoTransform

* Remove call to getExpectedType

* add tests to ensure client can't see _PushStatus
  • Loading branch information
drew-gross committed Apr 20, 2016
1 parent 59b4047 commit 9776362
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 71 deletions.
42 changes: 29 additions & 13 deletions spec/MongoTransform.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ var dummySchema = {
};


describe('parseObjectToMongoObject', () => {
describe('parseObjectToMongoObjectForCreate', () => {

it('a basic number', (done) => {
var input = {five: 5};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input, {
fields: {five: {type: 'Number'}}
});
jequal(input, output);
done();
});
Expand All @@ -37,7 +39,7 @@ describe('parseObjectToMongoObject', () => {
createdAt: "2015-10-06T21:24:50.332Z",
updatedAt: "2015-10-06T21:24:50.332Z"
};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input);
expect(output._created_at instanceof Date).toBe(true);
expect(output._updated_at instanceof Date).toBe(true);
done();
Expand All @@ -49,43 +51,53 @@ describe('parseObjectToMongoObject', () => {
objectId: 'myId',
className: 'Blah',
};
var out = transform.parseObjectToMongoObject(dummySchema, null, {pointers: [pointer]});
var out = transform.parseObjectToMongoObjectForCreate(dummySchema, null, {pointers: [pointer]},{
fields: {pointers: {type: 'Array'}}
});
jequal([pointer], out.pointers);
done();
});

it('a delete op', (done) => {
//TODO: object creation requests shouldn't be seeing __op delete, it makes no sense to
//have __op delete in a new object. Figure out what this should actually be testing.
notWorking('a delete op', (done) => {
var input = {deleteMe: {__op: 'Delete'}};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input);
jequal(output, {});
done();
});

it('basic ACL', (done) => {
var input = {ACL: {'0123': {'read': true, 'write': true}}};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input);
// This just checks that it doesn't crash, but it should check format.
done();
});

describe('GeoPoints', () => {
it('plain', (done) => {
var geoPoint = {__type: 'GeoPoint', longitude: 180, latitude: -180};
var out = transform.parseObjectToMongoObject(dummySchema, null, {location: geoPoint});
var out = transform.parseObjectToMongoObjectForCreate(dummySchema, null, {location: geoPoint},{
fields: {location: {type: 'GeoPoint'}}
});
expect(out.location).toEqual([180, -180]);
done();
});

it('in array', (done) => {
var geoPoint = {__type: 'GeoPoint', longitude: 180, latitude: -180};
var out = transform.parseObjectToMongoObject(dummySchema, null, {locations: [geoPoint, geoPoint]});
var out = transform.parseObjectToMongoObjectForCreate(dummySchema, null, {locations: [geoPoint, geoPoint]},{
fields: {locations: {type: 'Array'}}
});
expect(out.locations).toEqual([geoPoint, geoPoint]);
done();
});

it('in sub-object', (done) => {
var geoPoint = {__type: 'GeoPoint', longitude: 180, latitude: -180};
var out = transform.parseObjectToMongoObject(dummySchema, null, { locations: { start: geoPoint }});
var out = transform.parseObjectToMongoObjectForCreate(dummySchema, null, { locations: { start: geoPoint }},{
fields: {locations: {type: 'Object'}}
});
expect(out).toEqual({ locations: { start: geoPoint } });
done();
});
Expand Down Expand Up @@ -196,7 +208,9 @@ describe('transform schema key changes', () => {
var input = {
somePointer: {__type: 'Pointer', className: 'Micro', objectId: 'oft'}
};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input, {
fields: {somePointer: {type: 'Pointer'}}
});
expect(typeof output._p_somePointer).toEqual('string');
expect(output._p_somePointer).toEqual('Micro$oft');
done();
Expand All @@ -206,7 +220,9 @@ describe('transform schema key changes', () => {
var input = {
userPointer: {__type: 'Pointer', className: '_User', objectId: 'qwerty'}
};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input, {
fields: {userPointer: {type: 'Pointer'}}
});
expect(typeof output._p_userPointer).toEqual('string');
expect(output._p_userPointer).toEqual('_User$qwerty');
done();
Expand All @@ -219,7 +235,7 @@ describe('transform schema key changes', () => {
"Kevin": { "write": true }
}
};
var output = transform.parseObjectToMongoObject(dummySchema, null, input);
var output = transform.parseObjectToMongoObjectForCreate(dummySchema, null, input);
expect(typeof output._rperm).toEqual('object');
expect(typeof output._wperm).toEqual('object');
expect(output.ACL).toBeUndefined();
Expand Down
54 changes: 54 additions & 0 deletions spec/Parse.Push.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

let request = require('request');

describe('Parse.Push', () => {

Expand Down Expand Up @@ -89,4 +90,57 @@ describe('Parse.Push', () => {
done();
});
});

it('should not allow clients to query _PushStatus', done => {
setup()
.then(() => Parse.Push.send({
where: {
deviceType: 'ios'
},
data: {
badge: 'increment',
alert: 'Hello world!'
}
}, {useMasterKey: true}))
.then(() => {
request.get({
url: 'http://localhost:8378/1/classes/_PushStatus',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
},
}, (error, response, body) => {
expect(body.results.length).toEqual(0);
done();
});
});
});

it('should allow master key to query _PushStatus', done => {
setup()
.then(() => Parse.Push.send({
where: {
deviceType: 'ios'
},
data: {
badge: 'increment',
alert: 'Hello world!'
}
}, {useMasterKey: true}))
.then(() => {
request.get({
url: 'http://localhost:8378/1/classes/_PushStatus',
json: true,
headers: {
'X-Parse-Application-Id': 'test',
'X-Parse-Master-Key': 'test',
},
}, (error, response, body) => {
expect(body.results.length).toEqual(1);
expect(body.results[0].query).toEqual('{"deviceType":"ios"}');
expect(body.results[0].payload).toEqual('{"badge":"increment","alert":"Hello world!"}');
done();
});
});
});
});
14 changes: 8 additions & 6 deletions src/Adapters/Storage/Mongo/MongoStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,16 @@ export class MongoStorageAdapter {
// this adapter doesn't know about the schema, return a promise that rejects with
// undefined as the reason.
getOneSchema(className) {
return this.schemaCollection().then(schemasCollection => schemasCollection._fechOneSchemaFrom_SCHEMA(className));
return this.schemaCollection()
.then(schemasCollection => schemasCollection._fechOneSchemaFrom_SCHEMA(className));
}

// TODO: As yet not particularly well specified. Creates an object. Does it really need the schema?
// or can it fetch the schema itself? Also the schema is not currently a Parse format schema, and it
// should be, if we are passing it at all.
createObject(className, object, schema) {
const mongoObject = transform.parseObjectToMongoObject(schema, className, object);
// TODO: As yet not particularly well specified. Creates an object. Shouldn't need the
// schemaController, but MongoTransform still needs it :( maybe shouldn't even need the schema,
// and should infer from the type. Or maybe does need the schema for validations. Or maybe needs
// the schem only for the legacy mongo format. We'll figure that out later.
createObject(className, object, schemaController, parseFormatSchema) {
const mongoObject = transform.parseObjectToMongoObjectForCreate(schemaController, className, object, parseFormatSchema);
return this.adaptiveCollection(className)
.then(collection => collection.insertOne(mongoObject));
}
Expand Down
Loading

0 comments on commit 9776362

Please sign in to comment.