2013-08-29 05:45:19 +00:00
/* @see ./routes.coffee for routing*/
2013-10-06 23:52:54 +00:00
var url = require ( 'url' ) ;
2013-10-13 16:46:22 +00:00
var ipn = require ( 'paypal-ipn' ) ;
2013-08-29 05:45:19 +00:00
var _ = require ( 'lodash' ) ;
var nconf = require ( 'nconf' ) ;
var async = require ( 'async' ) ;
2013-12-11 16:30:39 +00:00
var shared = require ( 'habitrpg-shared' ) ;
2013-09-04 04:20:49 +00:00
var validator = require ( 'validator' ) ;
2013-08-29 05:45:19 +00:00
var check = validator . check ;
var sanitize = validator . sanitize ;
var User = require ( './../models/user' ) . model ;
var Group = require ( './../models/group' ) . model ;
2013-10-27 22:27:01 +00:00
var Challenge = require ( './../models/challenge' ) . model ;
2013-12-10 15:55:04 +00:00
var acceptablePUTPaths ;
2013-08-29 05:45:19 +00:00
var api = module . exports ;
2013-09-06 04:28:18 +00:00
// FIXME put this in a proper location
api . marketBuy = function ( req , res , next ) {
var user = res . locals . user ,
type = req . query . type ,
item = req . body ;
2013-11-10 04:15:55 +00:00
if ( ! _ . contains ( [ 'hatchingPotion' , 'egg' , 'food' ] , type ) )
return res . json ( 400 , { err : "Type must be 'hatchingPotion', 'egg', or 'food'" } ) ;
type = ( type == 'food' ? type : type + 's' ) ; // I'm stupid, we're passing up 'hatchingPotion' but we need 'hatchingPotions'
if ( ! user . items [ type ] [ item . name ] ) user . items [ type ] [ item . name ] = 0 ;
user . items [ type ] [ item . name ] ++ ;
2013-09-06 04:28:18 +00:00
user . balance -= ( item . value / 4 ) ;
user . save ( function ( err , saved ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . json ( saved ) ;
} )
}
2013-08-29 05:45:19 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Tasks
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
/ *
Local Methods
-- -- -- -- -- -- -- -
* /
/ *
Validate task
* /
api . verifyTaskExists = function ( req , res , next ) {
2013-10-27 00:23:52 +00:00
// If we're updating, get the task from the user
var task = res . locals . user . tasks [ req . params . id ] ;
if ( _ . isEmpty ( task ) ) return res . json ( 400 , { err : "No task found." } ) ;
2013-08-29 05:45:19 +00:00
res . locals . task = task ;
return next ( ) ;
} ;
/ *
API Routes
-- -- -- -- -- -- -- -
* /
2013-09-04 00:08:49 +00:00
/ * *
2013-08-29 05:45:19 +00:00
This is called form deprecated . coffee ' s score function , and the req . headers are setup properly to handle the login
Export it also so we can call it from deprecated . coffee
* /
2013-12-11 16:30:39 +00:00
api . score = function ( req , res , next ) {
2013-10-27 00:23:52 +00:00
var id = req . params . id ,
direction = req . params . direction ,
user = res . locals . user ,
task ;
2013-08-29 05:45:19 +00:00
2013-09-04 00:08:49 +00:00
// Send error responses for improper API call
2013-10-27 00:23:52 +00:00
if ( ! id ) return res . json ( 500 , { err : ':id required' } ) ;
2013-08-29 05:45:19 +00:00
if ( direction !== 'up' && direction !== 'down' ) {
2013-10-27 22:27:01 +00:00
if ( direction == 'unlink' ) return next ( ) ;
2013-10-27 00:23:52 +00:00
return res . json ( 500 , { err : ":direction must be 'up' or 'down'" } ) ;
2013-08-29 05:45:19 +00:00
}
2013-10-27 00:23:52 +00:00
// If exists already, score it
2013-11-01 19:45:13 +00:00
if ( task = user . tasks [ id ] ) {
2013-10-27 00:23:52 +00:00
// Set completed if type is daily or todo and task exists
2013-11-01 19:45:13 +00:00
if ( task . type === 'daily' || task . type === 'todo' ) {
task . completed = direction === 'up' ;
2013-08-29 05:45:19 +00:00
}
} else {
2013-10-27 00:23:52 +00:00
// If it doesn't exist, this is likely a 3rd party up/down - create a new one, then score it
2013-08-29 05:45:19 +00:00
task = {
id : id ,
value : 0 ,
2013-10-27 00:23:52 +00:00
type : req . body . type || 'habit' ,
text : req . body . title || id ,
2013-08-29 05:45:19 +00:00
notes : "This task was created by a third-party service. Feel free to edit, it won't harm the connection to that service. Additionally, multiple services may piggy-back off this task."
} ;
if ( task . type === 'habit' ) {
task . up = task . down = true ;
}
2013-10-27 00:23:52 +00:00
if ( task . type === 'daily' || task . type === 'todo' ) {
2013-08-29 05:45:19 +00:00
task . completed = direction === 'up' ;
}
2013-12-11 16:30:39 +00:00
task = user . ops . addTask ( { body : task } ) ;
2013-08-29 05:45:19 +00:00
}
2013-12-11 16:30:39 +00:00
var delta = user . ops . score ( { params : { id : task . id , direction : direction } } ) ;
2013-10-27 22:27:01 +00:00
//user.markModified('flags');
2013-09-17 18:44:02 +00:00
user . save ( function ( err , saved ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . json ( 200 , _ . extend ( {
2013-08-29 05:45:19 +00:00
delta : delta
} , saved . toJSON ( ) . stats ) ) ;
} ) ;
2013-10-27 22:27:01 +00:00
// if it's a challenge task, sync the score
2013-11-04 06:33:53 +00:00
user . syncScoreToChallenge ( task , delta ) ;
2013-08-29 05:45:19 +00:00
} ;
2013-10-27 00:23:52 +00:00
/ * *
* Get all tasks
* /
2013-08-29 05:45:19 +00:00
api . getTasks = function ( req , res , next ) {
2013-11-01 20:13:42 +00:00
var user = res . locals . user ;
2013-10-27 00:23:52 +00:00
if ( req . query . type ) {
return res . json ( user [ req . query . type + 's' ] ) ;
} else {
return res . json ( _ . toArray ( user . tasks ) ) ;
}
2013-08-29 05:45:19 +00:00
} ;
2013-10-27 00:23:52 +00:00
/ * *
* Get Task
* /
2013-08-29 05:45:19 +00:00
api . getTask = function ( req , res , next ) {
2013-10-27 00:23:52 +00:00
var task = res . locals . user . tasks [ req . params . id ] ;
if ( _ . isEmpty ( task ) ) return res . json ( 400 , { err : "No task found." } ) ;
2013-08-29 05:45:19 +00:00
return res . json ( 200 , task ) ;
} ;
2013-10-27 00:23:52 +00:00
/ * *
* Delete Task
* /
2013-08-29 05:45:19 +00:00
api . deleteTask = function ( req , res , next ) {
2013-12-11 16:30:39 +00:00
api . verifyTaskExists ( req , res , function ( ) {
var user = res . locals . user ;
user . deleteTask ( res . locals . task . id ) ;
user . save ( function ( err ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . send ( 204 ) ;
} ) ;
} )
2013-08-29 05:45:19 +00:00
} ;
/ *
Update Task
* /
2013-12-11 16:30:39 +00:00
// api.updateTask // handled in Shared.ops
// api.addTask // handled in Shared.ops
2013-12-13 00:32:54 +00:00
// api.sortTask // handled in Shared.ops #TODO updated api, mention in docs
2013-08-29 05:45:19 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Items
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2013-12-11 16:30:39 +00:00
// api.buy // handled in Shard.ops
2013-08-29 05:45:19 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
User
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2013-10-27 00:23:52 +00:00
/ * *
* Get User
* /
2013-08-29 05:45:19 +00:00
api . getUser = function ( req , res , next ) {
2013-09-04 14:19:55 +00:00
var user = res . locals . user . toJSON ( ) ;
2013-12-11 16:30:39 +00:00
user . stats . toNextLevel = shared . tnl ( user . stats . lvl ) ;
2013-08-29 05:45:19 +00:00
user . stats . maxHealth = 50 ;
delete user . apiToken ;
if ( user . auth ) {
delete user . auth . hashed _password ;
delete user . auth . salt ;
}
return res . json ( 200 , user ) ;
} ;
2013-12-10 15:55:04 +00:00
/ * *
* This tells us for which paths users can call ` PUT /user ` ( or batch - update equiv , which use ` User.set() ` on our client ) .
* The trick here is to only accept leaf paths , not root / intermediate paths ( see http : //goo.gl/OEzkAs)
* FIXME - one - by - one we want to widdle down this list , instead replacing each needed set path with API operations
* /
acceptablePUTPaths = _ . reduce ( require ( './../models/user' ) . schema . paths , function ( m , v , leaf ) {
2013-12-13 02:29:20 +00:00
var found = _ . find ( 'achievements filters flags invitations lastCron party preferences profile stats tags' . split ( ' ' ) , function ( root ) {
2013-12-10 15:55:04 +00:00
return leaf . indexOf ( root ) == 0 ;
} ) ;
if ( found ) m [ leaf ] = true ;
return m ;
} , { } )
2013-10-27 00:23:52 +00:00
/ * *
* Update user
2013-12-10 15:55:04 +00:00
* Send up PUT / user as ` req.body={path1:val, path2:val, etc} ` . Example :
* PUT / user { 'stats.hp' : 50 , 'tasks.TASK_ID.repeat.m' : false }
* See acceptablePUTPaths for which user paths are supported
2013-08-29 05:45:19 +00:00
* /
2013-12-11 16:30:39 +00:00
api . update = function ( req , res , next ) {
2013-12-10 15:55:04 +00:00
var user = res . locals . user ;
var errors = [ ] ;
if ( _ . isEmpty ( req . body ) ) return res . json ( 200 , user ) ;
2013-08-29 05:45:19 +00:00
_ . each ( req . body , function ( v , k ) {
2013-12-10 15:55:04 +00:00
if ( acceptablePUTPaths [ k ] )
2013-12-11 16:30:39 +00:00
user . fns . dotSet ( k , v ) ;
2013-12-10 15:55:04 +00:00
else
2013-08-29 05:45:19 +00:00
errors . push ( "path `" + k + "` was not saved, as it's a protected path. Make sure to send `PUT /api/v1/user` request bodies as `{'set.this.path':value}` instead of `{set:{this:{path:value}}}`" ) ;
return true ;
} ) ;
2013-11-10 04:15:55 +00:00
user . save ( function ( err ) {
if ( ! _ . isEmpty ( errors ) ) return res . json ( 500 , { err : errors } ) ;
if ( err ) { return res . json ( 500 , { err : err } ) }
res . json ( 200 , user ) ;
2013-08-29 05:45:19 +00:00
} ) ;
} ;
api . cron = function ( req , res , next ) {
2013-10-27 00:23:52 +00:00
var user = res . locals . user ;
2013-12-14 00:08:25 +00:00
user . fns . cron ( ) ;
2013-12-13 03:23:25 +00:00
if ( user . isModified ( ) )
2013-08-29 16:07:29 +00:00
res . locals . wasModified = true ;
user . save ( next ) ;
2013-08-29 05:45:19 +00:00
} ;
api . reroll = function ( req , res , next ) {
2013-10-27 00:23:52 +00:00
var user = res . locals . user ;
if ( user . balance < 1 ) return res . json ( 401 , { err : "Not enough tokens." } ) ;
2013-08-29 05:45:19 +00:00
user . balance -= 1 ;
2013-10-27 00:23:52 +00:00
_ . each ( [ 'habits' , 'dailys' , 'todos' ] , function ( type ) {
2013-11-02 23:58:24 +00:00
_ . each ( user [ type ] , function ( task ) {
2013-10-27 00:23:52 +00:00
task . value = 0 ;
} )
} )
2013-08-29 05:45:19 +00:00
user . stats . hp = 50 ;
2013-10-27 00:23:52 +00:00
user . save ( function ( err , saved ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
2013-08-29 05:45:19 +00:00
return res . json ( 200 , saved ) ;
} ) ;
} ;
2013-09-08 19:11:04 +00:00
api . reset = function ( req , res ) {
var user = res . locals . user ;
2013-10-27 00:23:52 +00:00
user . habits = [ ] ;
user . dailys = [ ] ;
user . todos = [ ] ;
user . rewards = [ ] ;
2013-09-08 19:11:04 +00:00
user . stats . hp = 50 ;
user . stats . lvl = 1 ;
user . stats . gp = 0 ;
user . stats . exp = 0 ;
user . items . armor = 0 ;
user . items . weapon = 0 ;
user . items . head = 0 ;
user . items . shield = 0 ;
user . save ( function ( err , saved ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . json ( saved ) ;
} )
2013-09-08 19:17:49 +00:00
}
2013-09-08 19:11:04 +00:00
2013-09-08 19:17:49 +00:00
api [ 'delete' ] = function ( req , res ) {
res . locals . user . remove ( function ( err ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . send ( 200 ) ;
} )
2013-09-08 19:11:04 +00:00
}
2013-10-22 19:19:43 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Unlock Preferences
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2013-12-11 16:30:39 +00:00
// api.unlock // see Shared.ops
2013-10-22 19:19:43 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Buy Gems
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
2013-10-31 22:14:19 +00:00
api . addTenGems = function ( req , res ) {
var user = res . locals . user ;
user . balance += 2.5 ;
user . save ( function ( err ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . send ( 204 ) ;
} )
}
2013-08-29 05:45:19 +00:00
/ *
Setup Stripe response when posting payment
* /
api . buyGems = function ( req , res ) {
var api _key = nconf . get ( 'STRIPE_API_KEY' ) ;
var stripe = require ( "stripe" ) ( api _key ) ;
var token = req . body . id ;
// console.dir {token:token, req:req}, 'stripe'
async . waterfall ( [
function ( cb ) {
stripe . charges . create ( {
amount : "500" , // $5
currency : "usd" ,
card : token
} , cb ) ;
} ,
function ( response , cb ) {
res . locals . user . balance += 5 ;
2013-10-23 01:50:50 +00:00
res . locals . user . purchased . ads = true ;
2013-08-29 05:45:19 +00:00
res . locals . user . save ( cb ) ;
}
] , function ( err , saved ) {
if ( err ) return res . send ( 500 , err . toString ( ) ) ; // don't json this, let toString() handle errors
res . send ( 200 , saved ) ;
} ) ;
} ;
2013-10-06 23:52:54 +00:00
api . buyGemsPaypalIPN = function ( req , res ) {
2013-10-13 16:46:22 +00:00
res . send ( 200 ) ;
2013-10-06 23:52:54 +00:00
ipn . verify ( req . body , function callback ( err , msg ) {
if ( err ) {
console . error ( msg ) ;
res . send ( 500 , msg ) ;
} else {
if ( req . body . payment _status == 'Completed' ) {
//Payment has been confirmed as completed
var parts = url . parse ( req . body . custom , true ) ;
var uid = parts . query . uid ; //, apiToken = query.apiToken;
if ( ! uid ) throw new Error ( "uuid or apiToken not found when completing paypal transaction" ) ;
User . findById ( uid , function ( err , user ) {
if ( err ) throw err ;
if ( _ . isEmpty ( user ) ) throw "user not found with uuid " + uuid + " when completing paypal transaction"
user . balance += 5 ;
2013-10-23 01:50:50 +00:00
user . purchased . ads = true ;
2013-10-06 23:52:54 +00:00
user . save ( ) ;
2013-10-13 16:46:22 +00:00
console . log ( 'PayPal transaction completed and user updated' ) ;
2013-10-06 23:52:54 +00:00
} ) ;
}
}
} ) ;
}
2013-09-09 04:04:02 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Tags
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
api . deleteTag = function ( req , res ) {
var user = res . locals . user ;
2013-10-24 16:21:34 +00:00
var tid = req . params . tid || req . body . tag ;
var i = _ . findIndex ( user . tags , { id : tid } ) ;
2013-09-09 04:04:02 +00:00
if ( ~ i ) {
var tag = user . tags [ i ] ;
2013-09-09 04:13:11 +00:00
delete user . filters [ tag . id ] ;
2013-09-09 04:04:02 +00:00
user . tags . splice ( i , 1 ) ;
// remove tag from all tasks
2013-10-27 00:23:52 +00:00
_ . each ( [ 'habits' , 'dailys' , 'todos' , 'rewards' ] , function ( type ) {
_ . each ( user [ type ] , function ( task ) {
delete task . tags [ tag . id ] ;
} )
} )
2013-11-22 19:23:41 +00:00
user . markModified ( 'habits' ) ;
user . markModified ( 'dailys' ) ;
user . markModified ( 'todos' ) ;
user . markModified ( 'rewards' ) ;
2013-09-09 04:04:02 +00:00
user . save ( function ( err , saved ) {
2013-10-24 16:21:34 +00:00
if ( err ) return res . json ( 500 , { err : err } ) ;
2013-11-18 16:03:09 +00:00
res . send ( 204 ) ;
2013-10-24 16:21:34 +00:00
} ) ;
2013-09-09 04:04:02 +00:00
} else {
res . json ( 400 , { err : 'Tag not found' } ) ;
}
}
2013-11-16 10:22:12 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Spells
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
api . cast = function ( req , res ) {
var user = res . locals . user ;
var type = req . body . type , target = req . body . target ;
2013-12-11 16:30:39 +00:00
var spell = shared . content . spells [ user . stats . class ] [ req . params . spell ] ;
2013-11-16 10:22:12 +00:00
var done = function ( ) {
var err = arguments [ 0 ] ;
var saved = _ . size ( arguments == 3 ) ? arguments [ 2 ] : arguments [ 1 ] ;
if ( err ) return res . json ( 500 , { err : err } ) ;
res . json ( saved ) ;
}
switch ( type ) {
case 'task' :
spell . cast ( user , user . tasks [ target . id ] ) ;
user . save ( done ) ;
break ;
case 'self' :
spell . cast ( user ) ;
user . save ( done ) ;
break ;
case 'party' :
async . waterfall ( [
function ( cb ) {
Group . findOne ( { type : 'party' , members : { '$in' : [ user . _id ] } } ) . populate ( 'members' ) . exec ( cb ) ;
} ,
function ( group , cb ) {
2013-12-05 18:05:47 +00:00
if ( ! group ) group = { members : [ user ] } ;
2013-11-16 10:22:12 +00:00
spell . cast ( user , group . members ) ;
2013-12-05 18:05:47 +00:00
var series = _ . transform ( group . members , function ( m , v , k ) {
m [ k ] = function ( cb2 ) { v . save ( cb2 ) ; }
} ) ;
2013-11-16 10:22:12 +00:00
async . series ( series , cb ) ;
2013-12-05 18:05:47 +00:00
} ,
function ( whatever , cb ) {
user . save ( cb ) ;
2013-11-16 10:22:12 +00:00
}
] , done ) ;
break ;
case 'user' :
async . waterfall ( [
function ( cb ) {
User . findById ( target . _id , cb ) ;
} ,
function ( member , cb ) {
spell . cast ( user , member ) ;
member . save ( cb ) ; // not parallel because target could be user, which causes race condition when saving
} ,
function ( saved , num , cb ) {
user . save ( cb ) ;
}
] , done ) ;
break ;
}
}
2013-12-11 16:30:39 +00:00
/ * *
* All other user . ops which can easily be mapped to habitrpg - shared / index . coffee , not requiring custom API - wrapping
* /
_ . each ( shared . wrap ( { } ) . ops , function ( op , k ) {
if ( ! api [ k ] ) {
api [ k ] = function ( req , res , next ) {
2013-12-13 00:38:01 +00:00
res . locals . user . ops [ k ] ( req , function ( err ) {
// If we want to send something other than 500, pass err as {code: 200, message: "Not enough GP"}
2013-12-11 16:30:39 +00:00
if ( err ) {
2013-12-13 00:38:01 +00:00
if ( ! err . code ) return res . json ( 500 , { err : err } ) ;
if ( err . code >= 400 ) return res . json ( err . code , { err : err . message } ) ;
// In the case of 200s, they're friendly alert messages like "You're pet has hatched!" - still send the op
2013-12-11 16:30:39 +00:00
}
2013-12-13 00:38:01 +00:00
res . locals . user . save ( function ( err ) {
if ( err ) return res . json ( 500 , { err : err } ) ;
res . send ( 200 ) ;
} )
2013-12-11 16:30:39 +00:00
} )
}
}
} )
2013-08-29 05:45:19 +00:00
/ *
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Batch Update
Run a bunch of updates all at once
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
* /
api . batchUpdate = function ( req , res , next ) {
2013-12-12 22:58:01 +00:00
if ( req . body [ 0 ] && req . body [ 0 ] . data )
return res . json ( 400 , { err : "API has been updated, please refresh your browser or upgrade your mobile app." } )
2013-10-27 00:23:52 +00:00
var user = res . locals . user ;
var oldSend = res . send ;
var oldJson = res . json ;
2013-12-11 16:30:39 +00:00
var callOp = function ( _req , cb ) {
2013-08-29 05:45:19 +00:00
res . send = res . json = function ( code , data ) {
2013-12-11 16:30:39 +00:00
if ( _ . isNumber ( code ) && code >= 400 )
console . error ( { code : code , data : data } ) ;
2013-09-02 22:40:20 +00:00
//FIXME send error messages down
2013-08-29 05:45:19 +00:00
return cb ( ) ;
} ;
2013-12-11 16:30:39 +00:00
api [ _req . op ] ( _req , res ) ;
2013-08-29 05:45:19 +00:00
} ;
2013-10-27 00:23:52 +00:00
// Setup the array of functions we're going to call in parallel with async
2013-12-11 16:30:39 +00:00
var ops = _ . transform ( req . body || [ ] , function ( result , _req ) {
if ( ! _ . isEmpty ( _req ) ) {
2013-10-27 00:23:52 +00:00
result . push ( function ( cb ) {
2013-12-11 16:30:39 +00:00
callOp ( _req , cb ) ;
2013-08-29 05:45:19 +00:00
} ) ;
}
} ) ;
2013-10-27 00:23:52 +00:00
// call all the operations, then return the user object to the requester
2013-12-11 16:30:39 +00:00
async . series ( ops , function ( err ) {
2013-08-29 05:45:19 +00:00
res . json = oldJson ;
res . send = oldSend ;
2013-10-27 00:23:52 +00:00
if ( err ) return res . json ( 500 , { err : err } ) ;
var response = user . toJSON ( ) ;
2013-08-29 05:45:19 +00:00
response . wasModified = res . locals . wasModified ;
2013-11-20 20:36:18 +00:00
if ( response . _tmp && response . _tmp . drop ) {
res . json ( 200 , { _tmp : { drop : response . _tmp . drop } , _v : response . _v } ) ;
} else if ( response . wasModified ) {
2013-09-20 14:01:09 +00:00
res . json ( 200 , response ) ;
} else {
2013-09-20 14:09:55 +00:00
res . json ( 200 , { _v : response . _v } ) ;
2013-09-20 14:01:09 +00:00
}
2013-08-29 05:45:19 +00:00
} ) ;
} ;