2016-02-29 19:41:05 -08:00
'use strict' ;
2016-02-08 20:20:08 -08:00
var Config = require ( '../src/Config' ) ;
2016-04-18 18:59:57 -07:00
var SchemaController = require ( '../src/Controllers/SchemaController' ) ;
2016-02-05 11:21:17 -08:00
var dd = require ( 'deep-diff' ) ;
2016-01-28 10:58:12 -08:00
2016-07-23 06:23:59 +02:00
var config ;
2016-01-28 10:58:12 -08:00
2016-02-09 20:16:53 -08:00
var hasAllPODobject = ( ) => {
var obj = new Parse . Object ( 'HasAllPOD' ) ;
obj . set ( 'aNumber' , 5 ) ;
obj . set ( 'aString' , 'string' ) ;
obj . set ( 'aBool' , true ) ;
obj . set ( 'aDate' , new Date ( ) ) ;
obj . set ( 'aObject' , { k1 : 'value' , k2 : true , k3 : 5 } ) ;
obj . set ( 'aArray' , [ 'contents' , true , 5 ] ) ;
obj . set ( 'aGeoPoint' , new Parse . GeoPoint ( { latitude : 0 , longitude : 0 } ) ) ;
obj . set ( 'aFile' , new Parse . File ( 'f.txt' , { base64 : 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE=' } ) ) ;
return obj ;
} ;
2016-04-18 18:59:57 -07:00
describe ( 'SchemaController' , ( ) => {
2016-11-24 15:47:41 -05:00
beforeEach ( ( ) => {
2016-07-23 06:23:59 +02:00
config = new Config ( 'test' ) ;
} ) ;
2016-01-28 10:58:12 -08:00
it ( 'can validate one object' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'TestObject' , { a : 1 , b : 'yo' , c : false } ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
done ( ) ;
} , ( error ) => {
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-01-28 10:58:12 -08:00
done ( ) ;
} ) ;
} ) ;
2016-02-22 16:45:41 +01:00
it ( 'can validate one object with dot notation' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'TestObjectWithSubDoc' , { x : false , y : 'YY' , z : 1 , 'aObject.k1' : 'newValue' } ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-02-22 16:45:41 +01:00
done ( ) ;
} , ( error ) => {
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-02-22 16:45:41 +01:00
done ( ) ;
} ) ;
} ) ;
2016-01-28 10:58:12 -08:00
it ( 'can validate two objects in a row' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'Foo' , { x : true , y : 'yyy' , z : 0 } ) ;
} ) . then ( ( schema ) => {
return schema . validateObject ( 'Foo' , { x : false , y : 'YY' , z : 1 } ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
done ( ) ;
} ) ;
} ) ;
2016-11-20 23:00:34 +09:00
it ( 'can validate Relation object' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { aRelation : { _ _type : 'Relation' , className : 'Stuff' } } ) ;
} ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { aRelation : { _ _type : 'Pointer' , className : 'Stuff' } } )
2016-11-24 15:47:41 -05:00
. then ( ( ) => {
2016-11-20 23:00:34 +09:00
fail ( 'expected invalidity' ) ;
done ( ) ;
} , done ) ;
} , ( err ) => {
fail ( err ) ;
done ( ) ;
} ) ;
} ) ;
2016-01-28 10:58:12 -08:00
it ( 'rejects inconsistent types' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { bacon : 7 } ) ;
} ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { bacon : 'z' } ) ;
} ) . then ( ( ) => {
fail ( 'expected invalidity' ) ;
done ( ) ;
} , done ) ;
} ) ;
it ( 'updates when new fields are added' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { bacon : 7 } ) ;
} ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { sausage : 8 } ) ;
} ) . then ( ( schema ) => {
return schema . validateObject ( 'Stuff' , { sausage : 'ate' } ) ;
} ) . then ( ( ) => {
fail ( 'expected invalidity' ) ;
done ( ) ;
} , done ) ;
} ) ;
it ( 'class-level permissions test find' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'find' : { }
} ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
var query = new Parse . Query ( 'Stuff' ) ;
return query . find ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
fail ( 'Class permissions should have rejected this query.' ) ;
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( ) => {
2016-01-28 10:58:12 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'class-level permissions test user' , ( done ) => {
2016-01-28 10:58:12 -08:00
var user ;
createTestUser ( ) . then ( ( u ) => {
user = u ;
return config . database . loadSchema ( ) ;
} ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
var find = { } ;
find [ user . id ] = true ;
return schema . setPermissions ( 'Stuff' , {
'find' : find
} ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
var query = new Parse . Query ( 'Stuff' ) ;
return query . find ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-01-28 10:58:12 -08:00
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( ) => {
2016-01-28 10:58:12 -08:00
fail ( 'Class permissions should have allowed this query.' ) ;
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'class-level permissions test get' , ( done ) => {
2016-01-28 10:58:12 -08:00
var obj ;
2016-04-22 14:05:21 -07:00
createTestUser ( )
. then ( user => {
return config . database . loadSchema ( )
// Create a valid class
. then ( schema => schema . validateObject ( 'Stuff' , { foo : 'bar' } ) )
. then ( schema => {
var find = { } ;
var get = { } ;
get [ user . id ] = true ;
return schema . setPermissions ( 'Stuff' , {
2016-06-06 12:31:50 -04:00
'create' : { '*' : true } ,
2016-04-22 14:05:21 -07:00
'find' : find ,
'get' : get
} ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-04-22 14:05:21 -07:00
obj = new Parse . Object ( 'Stuff' ) ;
obj . set ( 'foo' , 'bar' ) ;
return obj . save ( ) ;
} ) . then ( ( o ) => {
obj = o ;
var query = new Parse . Query ( 'Stuff' ) ;
return query . find ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-04-22 14:05:21 -07:00
fail ( 'Class permissions should have rejected this query.' ) ;
2016-01-28 10:58:12 -08:00
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( ) => {
2016-04-22 14:05:21 -07:00
var query = new Parse . Query ( 'Stuff' ) ;
2016-11-24 15:47:41 -05:00
return query . get ( obj . id ) . then ( ( ) => {
2016-04-22 14:05:21 -07:00
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( ) => {
2016-04-22 14:05:21 -07:00
fail ( 'Class permissions should have allowed this get query' ) ;
2016-06-06 12:31:50 -04:00
done ( ) ;
2016-04-22 14:05:21 -07:00
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
} ) ;
} ) ;
2016-02-05 09:42:35 -08:00
2016-08-15 16:48:39 -04:00
it ( 'can add classes without needing an object' , done => {
2016-02-05 09:42:35 -08:00
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
2017-04-23 18:25:33 -03:00
foo : { type : 'String' } ,
2016-02-05 09:42:35 -08:00
} ) )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : 'NewClass' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
foo : { type : 'String' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
}
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-02-05 09:42:35 -08:00
done ( ) ;
2016-02-16 12:30:30 -08:00
} )
. catch ( error => {
fail ( 'Error creating class: ' + JSON . stringify ( error ) ) ;
2016-02-05 09:42:35 -08:00
} ) ;
} ) ;
2017-04-23 18:25:33 -03:00
it ( 'can update classes without needing an object' , done => {
const levelPermissions = {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ;
config . database . loadSchema ( )
. then ( schema => {
schema . validateObject ( 'NewClass' , { foo : 2 } )
. then ( ( ) => schema . reloadData ( ) )
. then ( ( ) => schema . updateClass ( 'NewClass' , {
fooOne : { type : 'Number' } ,
fooTwo : { type : 'Array' } ,
fooThree : { type : 'Date' } ,
fooFour : { type : 'Object' } ,
fooFive : { type : 'Relation' , targetClass : '_User' } ,
fooSix : { type : 'String' } ,
fooSeven : { type : 'Object' } ,
fooEight : { type : 'String' } ,
fooNine : { type : 'String' } ,
fooTeen : { type : 'Number' } ,
fooEleven : { type : 'String' } ,
fooTwelve : { type : 'String' } ,
fooThirteen : { type : 'String' } ,
fooFourteen : { type : 'String' } ,
fooFifteen : { type : 'String' } ,
fooSixteen : { type : 'String' } ,
fooEighteen : { type : 'String' } ,
fooNineteen : { type : 'String' } ,
} , levelPermissions , config . database ) )
. then ( actualSchema => {
const expectedSchema = {
className : 'NewClass' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
foo : { type : 'Number' } ,
fooOne : { type : 'Number' } ,
fooTwo : { type : 'Array' } ,
fooThree : { type : 'Date' } ,
fooFour : { type : 'Object' } ,
fooFive : { type : 'Relation' , targetClass : '_User' } ,
fooSix : { type : 'String' } ,
fooSeven : { type : 'Object' } ,
fooEight : { type : 'String' } ,
fooNine : { type : 'String' } ,
fooTeen : { type : 'Number' } ,
fooEleven : { type : 'String' } ,
fooTwelve : { type : 'String' } ,
fooThirteen : { type : 'String' } ,
fooFourteen : { type : 'String' } ,
fooFifteen : { type : 'String' } ,
fooSixteen : { type : 'String' } ,
fooEighteen : { type : 'String' } ,
fooNineteen : { type : 'String' } ,
} ,
classLevelPermissions : { ... levelPermissions } ,
} ;
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
done ( ) ;
} )
. catch ( error => {
console . trace ( error ) ;
done ( ) ;
fail ( 'Error creating class: ' + JSON . stringify ( error ) ) ;
} ) ;
} ) ;
} ) ;
2016-02-05 09:42:35 -08:00
it ( 'will fail to create a class if that class was already created by an object' , done => {
config . database . loadSchema ( )
2016-03-04 01:02:44 -08:00
. then ( schema => {
schema . validateObject ( 'NewClass' , { foo : 7 } )
. then ( ( ) => schema . reloadData ( ) )
. then ( ( ) => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'String' }
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
expect ( error . message ) . toEqual ( 'Class NewClass already exists.' ) ;
done ( ) ;
} ) ;
2016-02-05 09:42:35 -08:00
} ) ;
} ) ;
2016-08-18 18:05:26 -04:00
it ( 'will resolve class creation races appropriately' , done => {
2016-02-05 09:42:35 -08:00
// If two callers race to create the same schema, the response to the
2016-02-05 12:56:45 -08:00
// race loser should be the same as if they hadn't been racing.
2016-02-05 09:42:35 -08:00
config . database . loadSchema ( )
. then ( schema => {
var p1 = schema . addClassIfNotExists ( 'NewClass' , { foo : { type : 'String' } } ) ;
var p2 = schema . addClassIfNotExists ( 'NewClass' , { foo : { type : 'String' } } ) ;
2016-04-05 21:16:39 -07:00
Promise . race ( [ p1 , p2 ] )
. then ( actualSchema => {
const expectedSchema = {
className : 'NewClass' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
foo : { type : 'String' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
}
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-02-05 09:42:35 -08:00
} ) ;
Promise . all ( [ p1 , p2 ] )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
2016-03-02 21:38:06 -08:00
expect ( error . message ) . toEqual ( 'Class NewClass already exists.' ) ;
2016-02-05 09:42:35 -08:00
done ( ) ;
} ) ;
} ) ;
} ) ;
it ( 'refuses to create classes with invalid names' , done => {
config . database . loadSchema ( )
. then ( schema => {
schema . addClassIfNotExists ( '_InvalidName' , { foo : { type : 'String' } } )
. catch ( error => {
expect ( error . error ) . toEqual (
'Invalid classname: _InvalidName, classnames can only have alphanumeric characters and _, and must start with an alpha character '
) ;
done ( ) ;
} ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with invalid names' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , { '0InvalidName' : { type : 'String' } } ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _KEY _NAME ) ;
expect ( error . error ) . toEqual ( 'invalid field name: 0InvalidName' ) ;
done ( ) ;
} ) ;
} ) ;
2016-02-05 12:48:36 -08:00
it ( 'refuses to explicitly create the default fields for custom classes' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , { objectId : { type : 'String' } } ) )
. catch ( error => {
expect ( error . code ) . toEqual ( 136 ) ;
expect ( error . error ) . toEqual ( 'field objectId cannot be added' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to explicitly create the default fields for non-custom classes' , done => {
2016-02-05 09:42:35 -08:00
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( '_Installation' , { localeIdentifier : { type : 'String' } } ) )
. catch ( error => {
expect ( error . code ) . toEqual ( 136 ) ;
expect ( error . error ) . toEqual ( 'field localeIdentifier cannot be added' ) ;
done ( ) ;
} ) ;
} ) ;
2016-02-05 11:21:17 -08:00
it ( 'refuses to add fields with invalid types' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 7 }
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _JSON ) ;
expect ( error . error ) . toEqual ( 'invalid JSON' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with invalid pointer types' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
2016-02-08 20:20:08 -08:00
foo : { type : 'Pointer' }
2016-02-05 11:21:17 -08:00
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( 135 ) ;
expect ( error . error ) . toEqual ( 'type Pointer needs a class name' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with invalid pointer target' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Pointer' , targetClass : 7 } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _JSON ) ;
expect ( error . error ) . toEqual ( 'invalid JSON' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with invalid Relation type' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Relation' , uselessKey : 7 } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( 135 ) ;
expect ( error . error ) . toEqual ( 'type Relation needs a class name' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with invalid relation target' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Relation' , targetClass : 7 } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _JSON ) ;
expect ( error . error ) . toEqual ( 'invalid JSON' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with uncreatable pointer target class' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Pointer' , targetClass : 'not a valid class name' } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
expect ( error . error ) . toEqual ( 'Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to add fields with uncreatable relation target class' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Relation' , targetClass : 'not a valid class name' } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
expect ( error . error ) . toEqual ( 'Invalid classname: not a valid class name, classnames can only have alphanumeric characters and _, and must start with an alpha character ' ) ;
done ( ) ;
} ) ;
} ) ;
2016-02-05 12:48:36 -08:00
it ( 'refuses to add fields with unknown types' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
foo : { type : 'Unknown' } ,
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INCORRECT _TYPE ) ;
expect ( error . error ) . toEqual ( 'invalid field type: Unknown' ) ;
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'will create classes' , done => {
2016-02-05 11:21:17 -08:00
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
aNumber : { type : 'Number' } ,
aString : { type : 'String' } ,
aBool : { type : 'Boolean' } ,
aDate : { type : 'Date' } ,
aObject : { type : 'Object' } ,
aArray : { type : 'Array' } ,
aGeoPoint : { type : 'GeoPoint' } ,
aFile : { type : 'File' } ,
aPointer : { type : 'Pointer' , targetClass : 'ThisClassDoesNotExistYet' } ,
aRelation : { type : 'Relation' , targetClass : 'NewClass' } ,
} ) )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : 'NewClass' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
aString : { type : 'String' } ,
aNumber : { type : 'Number' } ,
aBool : { type : 'Boolean' } ,
aDate : { type : 'Date' } ,
aObject : { type : 'Object' } ,
aArray : { type : 'Array' } ,
aGeoPoint : { type : 'GeoPoint' } ,
aFile : { type : 'File' } ,
aPointer : { type : 'Pointer' , targetClass : 'ThisClassDoesNotExistYet' } ,
aRelation : { type : 'Relation' , targetClass : 'NewClass' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
}
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-02-05 11:21:17 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'creates the default fields for non-custom classes' , done => {
2016-02-05 12:48:36 -08:00
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( '_Installation' , {
foo : { type : 'Number' } ,
} ) )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : '_Installation' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
foo : { type : 'Number' } ,
installationId : { type : 'String' } ,
deviceToken : { type : 'String' } ,
channels : { type : 'Array' } ,
deviceType : { type : 'String' } ,
pushType : { type : 'String' } ,
GCMSenderId : { type : 'String' } ,
timeZone : { type : 'String' } ,
localeIdentifier : { type : 'String' } ,
badge : { type : 'Number' } ,
2016-05-20 21:15:47 -04:00
appVersion : { type : 'String' } ,
appName : { type : 'String' } ,
appIdentifier : { type : 'String' } ,
parseVersion : { type : 'String' } ,
2016-04-05 21:16:39 -07:00
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
}
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-02-05 12:48:36 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'creates non-custom classes which include relation field' , done => {
2016-03-03 16:37:30 +08:00
config . database . loadSchema ( )
2017-03-04 22:42:19 +02:00
//as `_Role` is always created by default, we only get it here
. then ( schema => schema . getOneSchema ( '_Role' ) )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : '_Role' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
name : { type : 'String' } ,
users : { type : 'Relation' , targetClass : '_User' } ,
roles : { type : 'Relation' , targetClass : '_Role' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
} ;
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-03-03 16:37:30 +08:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'creates non-custom classes which include pointer field' , done => {
2016-03-03 16:37:30 +08:00
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( '_Session' , { } ) )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : '_Session' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
restricted : { type : 'Boolean' } ,
user : { type : 'Pointer' , targetClass : '_User' } ,
installationId : { type : 'String' } ,
sessionToken : { type : 'String' } ,
expiresAt : { type : 'Date' } ,
createdWith : { type : 'Object' } ,
ACL : { type : 'ACL' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
} ;
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-03-03 16:37:30 +08:00
done ( ) ;
} ) ;
} ) ;
2016-02-05 11:21:17 -08:00
it ( 'refuses to create two geopoints' , done => {
config . database . loadSchema ( )
. then ( schema => schema . addClassIfNotExists ( 'NewClass' , {
geo1 : { type : 'GeoPoint' } ,
2016-02-08 20:20:08 -08:00
geo2 : { type : 'GeoPoint' }
2016-02-05 11:21:17 -08:00
} ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INCORRECT _TYPE ) ;
expect ( error . error ) . toEqual ( 'currently, only one GeoPoint field may exist in an object. Adding geo2 when geo1 already exists.' ) ;
done ( ) ;
} ) ;
} ) ;
2016-02-09 16:23:46 -08:00
2016-08-15 16:48:39 -04:00
it ( 'can check if a class exists' , done => {
2016-02-09 16:23:46 -08:00
config . database . loadSchema ( )
. then ( schema => {
return schema . addClassIfNotExists ( 'NewClass' , { } )
. then ( ( ) => {
schema . hasClass ( 'NewClass' )
. then ( hasClass => {
expect ( hasClass ) . toEqual ( true ) ;
done ( ) ;
} )
. catch ( fail ) ;
schema . hasClass ( 'NonexistantClass' )
. then ( hasClass => {
expect ( hasClass ) . toEqual ( false ) ;
done ( ) ;
} )
. catch ( fail ) ;
} )
. catch ( error => {
fail ( 'Couldn\'t create class' ) ;
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-02-09 16:23:46 -08:00
} ) ;
} )
2016-11-24 15:47:41 -05:00
. catch ( ( ) => fail ( 'Couldn\'t load schema' ) ) ;
2016-02-09 16:23:46 -08:00
} ) ;
it ( 'refuses to delete fields from invalid class names' , done => {
config . database . loadSchema ( )
. then ( schema => schema . deleteField ( 'fieldName' , 'invalid class name' ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to delete invalid fields' , done => {
config . database . loadSchema ( )
. then ( schema => schema . deleteField ( 'invalid field name' , 'ValidClassName' ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _KEY _NAME ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'refuses to delete the default fields' , done => {
config . database . loadSchema ( )
. then ( schema => schema . deleteField ( 'installationId' , '_Installation' ) )
. catch ( error => {
expect ( error . code ) . toEqual ( 136 ) ;
2016-02-29 17:41:09 -08:00
expect ( error . message ) . toEqual ( 'field installationId cannot be changed' ) ;
2016-02-09 16:23:46 -08:00
done ( ) ;
} ) ;
} ) ;
2016-02-09 20:16:53 -08:00
it ( 'refuses to delete fields from nonexistant classes' , done => {
config . database . loadSchema ( )
. then ( schema => schema . deleteField ( 'field' , 'NoClass' ) )
. catch ( error => {
expect ( error . code ) . toEqual ( Parse . Error . INVALID _CLASS _NAME ) ;
2016-02-29 17:41:09 -08:00
expect ( error . message ) . toEqual ( 'Class NoClass does not exist.' ) ;
2016-02-09 20:16:53 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-18 18:05:26 -04:00
it ( 'refuses to delete fields that dont exist' , done => {
2016-02-09 20:16:53 -08:00
hasAllPODobject ( ) . save ( )
. then ( ( ) => config . database . loadSchema ( ) )
. then ( schema => schema . deleteField ( 'missingField' , 'HasAllPOD' ) )
. fail ( error => {
expect ( error . code ) . toEqual ( 255 ) ;
2016-02-29 17:41:09 -08:00
expect ( error . message ) . toEqual ( 'Field missingField does not exist, cannot delete.' ) ;
2016-02-09 20:16:53 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-18 18:05:26 -04:00
it ( 'drops related collection when deleting relation field' , done => {
2016-02-09 20:16:53 -08:00
var obj1 = hasAllPODobject ( ) ;
obj1 . save ( )
2016-02-29 19:41:05 -08:00
. then ( savedObj1 => {
var obj2 = new Parse . Object ( 'HasPointersAndRelations' ) ;
obj2 . set ( 'aPointer' , savedObj1 ) ;
var relation = obj2 . relation ( 'aRelation' ) ;
relation . add ( obj1 ) ;
return obj2 . save ( ) ;
} )
. then ( ( ) => config . database . collectionExists ( '_Join:aRelation:HasPointersAndRelations' ) )
. then ( exists => {
if ( ! exists ) {
2016-03-02 21:38:06 -08:00
fail ( 'Relation collection ' +
'should exist after save.' ) ;
2016-02-29 19:41:05 -08:00
}
} )
. then ( ( ) => config . database . loadSchema ( ) )
. then ( schema => schema . deleteField ( 'aRelation' , 'HasPointersAndRelations' , config . database ) )
. then ( ( ) => config . database . collectionExists ( '_Join:aRelation:HasPointersAndRelations' ) )
. then ( exists => {
if ( exists ) {
fail ( 'Relation collection should not exist after deleting relation field.' ) ;
}
done ( ) ;
} , error => {
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-02-29 19:41:05 -08:00
done ( ) ;
2016-02-09 20:16:53 -08:00
} ) ;
} ) ;
2016-02-10 14:11:42 -08:00
2016-08-18 18:05:26 -04:00
it ( 'can delete relation field when related _Join collection not exist' , done => {
2016-03-06 17:22:36 +08:00
config . database . loadSchema ( )
. then ( schema => {
schema . addClassIfNotExists ( 'NewClass' , {
relationField : { type : 'Relation' , targetClass : '_User' }
} )
2016-04-05 21:16:39 -07:00
. then ( actualSchema => {
const expectedSchema = {
className : 'NewClass' ,
fields : {
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
ACL : { type : 'ACL' } ,
relationField : { type : 'Relation' , targetClass : '_User' } ,
} ,
classLevelPermissions : {
find : { '*' : true } ,
get : { '*' : true } ,
create : { '*' : true } ,
update : { '*' : true } ,
delete : { '*' : true } ,
addField : { '*' : true } ,
} ,
} ;
expect ( dd ( actualSchema , expectedSchema ) ) . toEqual ( undefined ) ;
2016-03-06 17:22:36 +08:00
} )
. then ( ( ) => config . database . collectionExists ( '_Join:relationField:NewClass' ) )
. then ( exist => {
2016-11-24 15:47:41 -05:00
on _db ( 'postgres' , ( ) => {
2016-08-18 18:05:26 -04:00
// We create the table when creating the column
expect ( exist ) . toEqual ( true ) ;
2016-11-24 15:47:41 -05:00
} , ( ) => {
2016-08-18 18:05:26 -04:00
expect ( exist ) . toEqual ( false ) ;
} ) ;
2016-12-01 18:45:49 -08:00
2016-03-06 17:22:36 +08:00
} )
. then ( ( ) => schema . deleteField ( 'relationField' , 'NewClass' , config . database ) )
. then ( ( ) => schema . reloadData ( ) )
. then ( ( ) => {
2016-04-12 19:06:58 -07:00
const expectedSchema = {
2016-04-12 17:39:27 -04:00
objectId : { type : 'String' } ,
updatedAt : { type : 'Date' } ,
createdAt : { type : 'Date' } ,
2016-06-13 12:57:20 -07:00
ACL : { type : 'ACL' } ,
2016-04-12 19:06:58 -07:00
} ;
expect ( dd ( schema . data . NewClass , expectedSchema ) ) . toEqual ( undefined ) ;
2016-03-06 17:22:36 +08:00
done ( ) ;
} ) ;
} ) ;
} ) ;
2016-08-18 18:05:26 -04:00
it ( 'can delete string fields and resave as number field' , done => {
2016-02-10 16:25:28 -08:00
Parse . Object . disableSingleInstance ( ) ;
2016-02-10 14:11:42 -08:00
var obj1 = hasAllPODobject ( ) ;
var obj2 = hasAllPODobject ( ) ;
2016-11-24 15:47:41 -05:00
Parse . Object . saveAll ( [ obj1 , obj2 ] )
2016-02-10 14:11:42 -08:00
. then ( ( ) => config . database . loadSchema ( ) )
2016-02-29 17:41:09 -08:00
. then ( schema => schema . deleteField ( 'aString' , 'HasAllPOD' , config . database ) )
2016-02-10 14:11:42 -08:00
. then ( ( ) => new Parse . Query ( 'HasAllPOD' ) . get ( obj1 . id ) )
2016-02-10 16:25:28 -08:00
. then ( obj1Reloaded => {
expect ( obj1Reloaded . get ( 'aString' ) ) . toEqual ( undefined ) ;
obj1Reloaded . set ( 'aString' , [ 'not a string' , 'this time' ] ) ;
obj1Reloaded . save ( )
. then ( obj1reloadedAgain => {
expect ( obj1reloadedAgain . get ( 'aString' ) ) . toEqual ( [ 'not a string' , 'this time' ] ) ;
2016-02-10 14:11:42 -08:00
return new Parse . Query ( 'HasAllPOD' ) . get ( obj2 . id ) ;
} )
2016-02-10 16:25:28 -08:00
. then ( obj2reloaded => {
expect ( obj2reloaded . get ( 'aString' ) ) . toEqual ( undefined ) ;
2016-02-10 14:11:42 -08:00
done ( ) ;
2016-02-10 16:25:28 -08:00
Parse . Object . enableSingleInstance ( ) ;
2016-02-10 14:11:42 -08:00
} ) ;
2016-04-12 19:06:58 -07:00
} )
. catch ( error => {
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-04-12 19:06:58 -07:00
done ( ) ;
2016-02-22 17:33:11 -08:00
} ) ;
2016-02-10 14:11:42 -08:00
} ) ;
2016-08-18 18:05:26 -04:00
it ( 'can delete pointer fields and resave as string' , done => {
2016-02-10 16:25:28 -08:00
Parse . Object . disableSingleInstance ( ) ;
2016-02-10 14:11:42 -08:00
var obj1 = new Parse . Object ( 'NewClass' ) ;
obj1 . save ( )
. then ( ( ) => {
obj1 . set ( 'aPointer' , obj1 ) ;
return obj1 . save ( ) ;
} )
. then ( obj1 => {
expect ( obj1 . get ( 'aPointer' ) . id ) . toEqual ( obj1 . id ) ;
} )
. then ( ( ) => config . database . loadSchema ( ) )
2016-02-29 17:41:09 -08:00
. then ( schema => schema . deleteField ( 'aPointer' , 'NewClass' , config . database ) )
2016-02-10 14:11:42 -08:00
. then ( ( ) => new Parse . Query ( 'NewClass' ) . get ( obj1 . id ) )
. then ( obj1 => {
expect ( obj1 . get ( 'aPointer' ) ) . toEqual ( undefined ) ;
obj1 . set ( 'aPointer' , 'Now a string' ) ;
return obj1 . save ( ) ;
} )
. then ( obj1 => {
expect ( obj1 . get ( 'aPointer' ) ) . toEqual ( 'Now a string' ) ;
done ( ) ;
2016-02-10 16:25:28 -08:00
Parse . Object . enableSingleInstance ( ) ;
2016-02-10 14:11:42 -08:00
} ) ;
} ) ;
2016-02-16 12:30:30 -08:00
it ( 'can merge schemas' , done => {
2016-04-18 18:59:57 -07:00
expect ( SchemaController . buildMergedSchemaObject ( {
2016-02-16 12:30:30 -08:00
_id : 'SomeClass' ,
2016-04-12 17:39:27 -04:00
someType : { type : 'Number' }
2016-02-16 12:30:30 -08:00
} , {
newType : { type : 'Number' }
} ) ) . toEqual ( {
someType : { type : 'Number' } ,
newType : { type : 'Number' } ,
} ) ;
done ( ) ;
} ) ;
it ( 'can merge deletions' , done => {
2016-04-18 18:59:57 -07:00
expect ( SchemaController . buildMergedSchemaObject ( {
2016-02-16 12:30:30 -08:00
_id : 'SomeClass' ,
2016-04-12 17:39:27 -04:00
someType : { type : 'Number' } ,
outDatedType : { type : 'String' } ,
2016-02-16 12:30:30 -08:00
} , {
newType : { type : 'GeoPoint' } ,
outDatedType : { _ _op : 'Delete' } ,
} ) ) . toEqual ( {
someType : { type : 'Number' } ,
newType : { type : 'GeoPoint' } ,
} ) ;
done ( ) ;
} ) ;
2016-03-04 03:06:53 +08:00
it ( 'ignore default field when merge with system class' , done => {
2016-04-18 18:59:57 -07:00
expect ( SchemaController . buildMergedSchemaObject ( {
2016-03-04 03:06:53 +08:00
_id : '_User' ,
2016-04-12 17:39:27 -04:00
username : { type : 'String' } ,
password : { type : 'String' } ,
email : { type : 'String' } ,
emailVerified : { type : 'Boolean' } ,
2016-03-04 03:06:53 +08:00
} , {
2016-06-16 15:39:05 -07:00
emailVerified : { type : 'String' } ,
2016-04-12 17:39:27 -04:00
customField : { type : 'String' } ,
2016-03-04 03:06:53 +08:00
} ) ) . toEqual ( {
2016-04-12 17:39:27 -04:00
customField : { type : 'String' }
2016-03-04 03:06:53 +08:00
} ) ;
done ( ) ;
} ) ;
2016-09-09 14:41:11 -04:00
2016-11-24 15:47:41 -05:00
it ( 'yields a proper schema mismatch error (#2661)' , done => {
2016-12-07 15:17:05 -08:00
const anObject = new Parse . Object ( 'AnObject' ) ;
const anotherObject = new Parse . Object ( 'AnotherObject' ) ;
const someObject = new Parse . Object ( 'SomeObject' ) ;
2016-11-24 15:47:41 -05:00
Parse . Object . saveAll ( [ anObject , anotherObject , someObject ] ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'pointer' , anotherObject ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'pointer' , someObject ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
fail ( 'shoud not save correctly' ) ;
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( err ) => {
2016-09-09 14:41:11 -04:00
expect ( err instanceof Parse . Error ) . toBeTruthy ( ) ;
expect ( err . message ) . toEqual ( 'schema mismatch for AnObject.pointer; expected Pointer<AnotherObject> but got Pointer<SomeObject>' )
done ( ) ;
} ) ;
} ) ;
2016-11-24 15:47:41 -05:00
it ( 'yields a proper schema mismatch error bis (#2661)' , done => {
2016-12-07 15:17:05 -08:00
const anObject = new Parse . Object ( 'AnObject' ) ;
const someObject = new Parse . Object ( 'SomeObject' ) ;
2016-11-24 15:47:41 -05:00
Parse . Object . saveAll ( [ anObject , someObject ] ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'number' , 1 ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'number' , someObject ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
fail ( 'shoud not save correctly' ) ;
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( err ) => {
2016-09-09 14:41:11 -04:00
expect ( err instanceof Parse . Error ) . toBeTruthy ( ) ;
expect ( err . message ) . toEqual ( 'schema mismatch for AnObject.number; expected Number but got Pointer<SomeObject>' )
done ( ) ;
} ) ;
} ) ;
2016-11-24 15:47:41 -05:00
it ( 'yields a proper schema mismatch error ter (#2661)' , done => {
2016-12-07 15:17:05 -08:00
const anObject = new Parse . Object ( 'AnObject' ) ;
const someObject = new Parse . Object ( 'SomeObject' ) ;
2016-11-24 15:47:41 -05:00
Parse . Object . saveAll ( [ anObject , someObject ] ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'pointer' , someObject ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
anObject . set ( 'pointer' , 1 ) ;
return anObject . save ( ) ;
2016-11-24 15:47:41 -05:00
} ) . then ( ( ) => {
2016-09-09 14:41:11 -04:00
fail ( 'shoud not save correctly' ) ;
done ( ) ;
2016-11-24 15:47:41 -05:00
} , ( err ) => {
2016-09-09 14:41:11 -04:00
expect ( err instanceof Parse . Error ) . toBeTruthy ( ) ;
expect ( err . message ) . toEqual ( 'schema mismatch for AnObject.pointer; expected Pointer<SomeObject> but got Number' )
done ( ) ;
} ) ;
} ) ;
2016-12-06 16:42:54 -05:00
it ( 'properly handles volatile _Schemas' , done => {
function validateSchemaStructure ( schema ) {
expect ( schema . hasOwnProperty ( 'className' ) ) . toBe ( true ) ;
expect ( schema . hasOwnProperty ( 'fields' ) ) . toBe ( true ) ;
expect ( schema . hasOwnProperty ( 'classLevelPermissions' ) ) . toBe ( true ) ;
}
function validateSchemaDataStructure ( schemaData ) {
Object . keys ( schemaData ) . forEach ( className => {
2016-12-07 15:17:05 -08:00
const schema = schemaData [ className ] ;
2016-12-06 16:42:54 -05:00
// Hooks has className...
if ( className != '_Hooks' ) {
expect ( schema . hasOwnProperty ( 'className' ) ) . toBe ( false ) ;
}
expect ( schema . hasOwnProperty ( 'fields' ) ) . toBe ( false ) ;
expect ( schema . hasOwnProperty ( 'classLevelPermissions' ) ) . toBe ( false ) ;
} ) ;
}
let schema ;
config . database . loadSchema ( ) . then ( s => {
schema = s ;
return schema . getOneSchema ( '_User' , false ) ;
} ) . then ( userSchema => {
validateSchemaStructure ( userSchema ) ;
validateSchemaDataStructure ( schema . data ) ;
return schema . getOneSchema ( '_PushStatus' , true ) ;
} ) . then ( pushStatusSchema => {
validateSchemaStructure ( pushStatusSchema ) ;
validateSchemaDataStructure ( schema . data ) ;
done ( ) ;
} ) ;
} ) ;
2016-01-28 10:58:12 -08:00
} ) ;
2016-12-02 19:47:33 -05:00
describe ( 'Class Level Permissions for requiredAuth' , ( ) => {
beforeEach ( ( ) => {
config = new Config ( 'test' ) ;
} ) ;
function createUser ( ) {
2016-12-07 15:17:05 -08:00
const user = new Parse . User ( ) ;
2016-12-02 19:47:33 -05:00
user . set ( "username" , "hello" ) ;
user . set ( "password" , "world" ) ;
return user . signUp ( null ) ;
}
it ( 'required auth test find' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'find' : {
'requiresAuthentication' : true
}
} ) ;
} ) . then ( ( ) => {
var query = new Parse . Query ( 'Stuff' ) ;
return query . find ( ) ;
} ) . then ( ( ) => {
fail ( 'Class permissions should have rejected this query.' ) ;
done ( ) ;
} , ( e ) => {
expect ( e . message ) . toEqual ( 'Permission denied, user needs to be authenticated.' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth test find authenticated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'find' : {
'requiresAuthentication' : true
}
} ) ;
} ) . then ( ( ) => {
return createUser ( ) ;
} ) . then ( ( ) => {
var query = new Parse . Query ( 'Stuff' ) ;
return query . find ( ) ;
} ) . then ( ( results ) => {
expect ( results . length ) . toEqual ( 0 ) ;
done ( ) ;
} , ( e ) => {
console . error ( e ) ;
fail ( "Should not have failed" ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth should allow create authenticated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'create' : {
'requiresAuthentication' : true
}
} ) ;
} ) . then ( ( ) => {
return createUser ( ) ;
} ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const stuff = new Parse . Object ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
stuff . set ( 'foo' , 'bar' ) ;
return stuff . save ( ) ;
} ) . then ( ( ) => {
done ( ) ;
} , ( e ) => {
console . error ( e ) ;
fail ( "Should not have failed" ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth should reject create when not authenticated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'create' : {
'requiresAuthentication' : true
}
} ) ;
} ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const stuff = new Parse . Object ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
stuff . set ( 'foo' , 'bar' ) ;
return stuff . save ( ) ;
} ) . then ( ( ) => {
fail ( 'Class permissions should have rejected this query.' ) ;
done ( ) ;
} , ( e ) => {
expect ( e . message ) . toEqual ( 'Permission denied, user needs to be authenticated.' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth test create/get/update/delete authenticated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'create' : {
'requiresAuthentication' : true
} ,
'get' : {
'requiresAuthentication' : true
} ,
'delete' : {
'requiresAuthentication' : true
} ,
'update' : {
'requiresAuthentication' : true
}
} ) ;
} ) . then ( ( ) => {
return createUser ( ) ;
} ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const stuff = new Parse . Object ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
stuff . set ( 'foo' , 'bar' ) ;
return stuff . save ( ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const query = new Parse . Query ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
return query . get ( stuff . id ) ;
} ) ;
} ) . then ( ( gotStuff ) => {
return gotStuff . save ( { 'foo' : 'baz' } ) . then ( ( ) => {
return gotStuff . destroy ( ) ;
} )
} ) . then ( ( ) => {
done ( ) ;
} , ( e ) => {
console . error ( e ) ;
fail ( "Should not have failed" ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth test create/get/update/delete not authenitcated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'get' : {
'requiresAuthentication' : true
} ,
'delete' : {
'requiresAuthentication' : true
} ,
'update' : {
'requiresAuthentication' : true
} ,
'create' : {
'*' : true
}
} ) ;
} ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const stuff = new Parse . Object ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
stuff . set ( 'foo' , 'bar' ) ;
return stuff . save ( ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const query = new Parse . Query ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
return query . get ( stuff . id ) ;
} ) ;
} ) . then ( ( ) => {
fail ( "Should not succeed!" ) ;
done ( ) ;
} , ( e ) => {
expect ( e . message ) . toEqual ( 'Permission denied, user needs to be authenticated.' ) ;
done ( ) ;
} ) ;
} ) ;
it ( 'required auth test create/get/update/delete not authenitcated' , ( done ) => {
config . database . loadSchema ( ) . then ( ( schema ) => {
// Just to create a valid class
return schema . validateObject ( 'Stuff' , { foo : 'bar' } ) ;
} ) . then ( ( schema ) => {
return schema . setPermissions ( 'Stuff' , {
'find' : {
'requiresAuthentication' : true
} ,
'delete' : {
'requiresAuthentication' : true
} ,
'update' : {
'requiresAuthentication' : true
} ,
'create' : {
'*' : true
} ,
'get' : {
'*' : true
}
} ) ;
} ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const stuff = new Parse . Object ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
stuff . set ( 'foo' , 'bar' ) ;
return stuff . save ( ) . then ( ( ) => {
2016-12-07 15:17:05 -08:00
const query = new Parse . Query ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
return query . get ( stuff . id ) ;
} )
} ) . then ( ( result ) => {
expect ( result . get ( 'foo' ) ) . toEqual ( 'bar' ) ;
2016-12-07 15:17:05 -08:00
const query = new Parse . Query ( 'Stuff' ) ;
2016-12-02 19:47:33 -05:00
return query . find ( ) ;
} ) . then ( ( ) => {
fail ( "Should not succeed!" ) ;
done ( ) ;
} , ( e ) => {
expect ( e . message ) . toEqual ( 'Permission denied, user needs to be authenticated.' ) ;
done ( ) ;
} ) ;
} ) ;
} )