Expand Up
@@ -12,6 +12,7 @@ var Parse = require('parse/node').Parse;
var RestQuery = require ( './RestQuery' ) ;
var RestWrite = require ( './RestWrite' ) ;
var triggers = require ( './triggers' ) ;
const { enforceRoleSecurity } = require ( './SharedRest' ) ;
function checkTriggers ( className , config , types ) {
return types . some ( triggerType => {
Expand All
@@ -24,65 +25,34 @@ function checkLiveQuery(className, config) {
}
// Returns a promise for an object with optional keys 'results' and 'count'.
function find ( config , auth , className , restWhere , restOptions , clientSDK , context ) {
enforceRoleSecurity ( 'find' , className , auth ) ;
return triggers
. maybeRunQueryTrigger (
triggers . Types . beforeFind ,
className ,
restWhere ,
restOptions ,
config ,
auth ,
context
)
. then ( result => {
restWhere = result . restWhere || restWhere ;
restOptions = result . restOptions || restOptions ;
const query = new RestQuery (
config ,
auth ,
className ,
restWhere ,
restOptions ,
clientSDK ,
true ,
context
) ;
return query . execute ( ) ;
} ) ;
}
const find = async ( config , auth , className , restWhere , restOptions , clientSDK , context ) => {
const query = await RestQuery ( {
method : RestQuery . Method . find ,
config,
auth,
className,
restWhere,
restOptions,
clientSDK,
context,
} ) ;
return query . execute ( ) ;
} ;
// get is just like find but only queries an objectId.
const get = ( config , auth , className , objectId , restOptions , clientSDK , context ) => {
const get = async ( config , auth , className , objectId , restOptions , clientSDK , context ) => {
var restWhere = { objectId } ;
enforceRoleSecurity ( 'get' , className , auth ) ;
return triggers
. maybeRunQueryTrigger (
triggers . Types . beforeFind ,
className ,
restWhere ,
restOptions ,
config ,
auth ,
context ,
true
)
. then ( result => {
restWhere = result . restWhere || restWhere ;
restOptions = result . restOptions || restOptions ;
const query = new RestQuery (
config ,
auth ,
className ,
restWhere ,
restOptions ,
clientSDK ,
true ,
context
) ;
return query . execute ( ) ;
} ) ;
const query = await RestQuery ( {
method : RestQuery . Method . get ,
config,
auth,
className,
restWhere,
restOptions,
clientSDK,
context,
} ) ;
return query . execute ( ) ;
} ;
// Returns a promise that doesn't resolve to any useful value.
Expand All
@@ -101,35 +71,40 @@ function del(config, auth, className, objectId, context) {
let schemaController ;
return Promise . resolve ( )
. then ( ( ) => {
. then ( async ( ) => {
const hasTriggers = checkTriggers ( className , config , [ 'beforeDelete' , 'afterDelete' ] ) ;
const hasLiveQuery = checkLiveQuery ( className , config ) ;
if ( hasTriggers || hasLiveQuery || className == '_Session' ) {
return new RestQuery ( config , auth , className , { objectId } )
. execute ( { op : 'delete' } )
. then ( response => {
if ( response && response . results && response . results . length ) {
const firstResult = response . results [ 0 ] ;
firstResult . className = className ;
if ( className === '_Session' && ! auth . isMaster && ! auth . isMaintenance ) {
if ( ! auth . user || firstResult . user . objectId !== auth . user . id ) {
throw new Parse . Error ( Parse . Error . INVALID_SESSION_TOKEN , 'Invalid session token' ) ;
}
const query = await RestQuery ( {
method : RestQuery . Method . get ,
config,
auth,
className,
restWhere : { objectId } ,
} ) ;
return query . execute ( { op : 'delete' } ) . then ( response => {
if ( response && response . results && response . results . length ) {
const firstResult = response . results [ 0 ] ;
firstResult . className = className ;
if ( className === '_Session' && ! auth . isMaster && ! auth . isMaintenance ) {
if ( ! auth . user || firstResult . user . objectId !== auth . user . id ) {
throw new Parse . Error ( Parse . Error . INVALID_SESSION_TOKEN , 'Invalid session token' ) ;
}
var cacheAdapter = config . cacheController ;
cacheAdapter . user . del ( firstResult . sessionToken ) ;
inflatedObject = Parse . Object . fromJSON ( firstResult ) ;
return triggers . maybeRunTrigger (
triggers . Types . beforeDelete ,
auth ,
inflatedObject ,
null ,
config ,
context
) ;
}
throw new Parse . Error ( Parse . Error . OBJECT_NOT_FOUND , 'Object not found for delete.' ) ;
} ) ;
var cacheAdapter = config . cacheController ;
cacheAdapter . user . del ( firstResult . sessionToken ) ;
inflatedObject = Parse . Object . fromJSON ( firstResult ) ;
return triggers . maybeRunTrigger (
triggers . Types . beforeDelete ,
auth ,
inflatedObject ,
null ,
config ,
context
) ;
}
throw new Parse . Error ( Parse . Error . OBJECT_NOT_FOUND , 'Object not found for delete.' ) ;
} ) ;
}
return Promise . resolve ( { } ) ;
} )
Expand Down
Expand Up
@@ -193,21 +168,22 @@ function update(config, auth, className, restWhere, restObject, clientSDK, conte
enforceRoleSecurity ( 'update' , className , auth ) ;
return Promise . resolve ( )
. then ( ( ) => {
. then ( async ( ) => {
const hasTriggers = checkTriggers ( className , config , [ 'beforeSave' , 'afterSave' ] ) ;
const hasLiveQuery = checkLiveQuery ( className , config ) ;
if ( hasTriggers || hasLiveQuery ) {
// Do not use find, as it runs the before finds
return new RestQuery (
const query = await RestQuery ( {
method : RestQuery . Method . get ,
config,
auth,
className,
restWhere,
undefined ,
undefined ,
false ,
context
) . execute ( {
runAfterFind : false ,
runBeforeFind : false ,
context ,
} ) ;
return query . execute ( {
op : 'update' ,
} ) ;
}
Expand Down
Expand Up
@@ -248,40 +224,6 @@ function handleSessionMissingError(error, className, auth) {
throw error ;
}
const classesWithMasterOnlyAccess = [
'_JobStatus' ,
'_PushStatus' ,
'_Hooks' ,
'_GlobalConfig' ,
'_JobSchedule' ,
'_Idempotency' ,
] ;
// Disallowing access to the _Role collection except by master key
function enforceRoleSecurity ( method , className , auth ) {
if ( className === '_Installation' && ! auth . isMaster && ! auth . isMaintenance ) {
if ( method === 'delete' || method === 'find' ) {
const error = `Clients aren't allowed to perform the ${ method } operation on the installation collection.` ;
throw new Parse . Error ( Parse . Error . OPERATION_FORBIDDEN , error ) ;
}
}
//all volatileClasses are masterKey only
if (
classesWithMasterOnlyAccess . indexOf ( className ) >= 0 &&
! auth . isMaster &&
! auth . isMaintenance
) {
const error = `Clients aren't allowed to perform the ${ method } operation on the ${ className } collection.` ;
throw new Parse . Error ( Parse . Error . OPERATION_FORBIDDEN , error ) ;
}
// readOnly masterKey is not allowed
if ( auth . isReadOnly && ( method === 'delete' || method === 'create' || method === 'update' ) ) {
const error = `read-only masterKey isn't allowed to perform the ${ method } operation.` ;
throw new Parse . Error ( Parse . Error . OPERATION_FORBIDDEN , error ) ;
}
}
module . exports = {
create,
del,
Expand Down