2014-06-30 22:16:26 -04:00
Patch = require ' ./Patch '
2014-04-17 20:09:01 -04:00
User = require ' ../users/User '
2014-06-30 22:16:26 -04:00
Handler = require ' ../commons/Handler '
2014-04-12 13:51:02 -04:00
schema = require ' ../../app/schemas/models/patch '
2014-04-08 22:26:19 -04:00
{ handlers } = require ' ../commons/mapping '
2014-06-30 22:16:26 -04:00
mongoose = require ' mongoose '
2014-04-17 20:09:01 -04:00
log = require ' winston '
sendwithus = require ' ../sendwithus '
2014-08-28 21:55:08 -04:00
hipchat = require ' ../hipchat '
2014-04-08 22:26:19 -04:00
PatchHandler = class PatchHandler extends Handler
modelClass: Patch
editableProperties: [ ]
2014-04-10 16:09:44 -04:00
postEditableProperties: [ ' delta ' , ' target ' , ' commitMessage ' ]
2014-04-12 13:51:02 -04:00
jsonSchema: require ' ../../app/schemas/models/patch '
2014-04-08 22:26:19 -04:00
makeNewInstance: (req) ->
patch = super ( req )
patch . set ' creator ' , req . user . _id
patch . set ' created ' , new Date ( ) . toISOString ( )
patch . set ' status ' , ' pending '
patch
getByRelationship: (req, res, args...) ->
return @ setStatus ( req , res , args [ 0 ] ) if req . route . method is ' put ' and args [ 1 ] is ' status '
super ( arguments . . . )
2014-06-30 22:16:26 -04:00
2014-04-08 22:26:19 -04:00
setStatus: (req, res, id) ->
newStatus = req . body . status
unless newStatus in [ ' rejected ' , ' accepted ' , ' withdrawn ' ]
2014-06-30 22:16:26 -04:00
return @ sendBadInputError ( res , ' Status must be " rejected " , " accepted " , or " withdrawn " ' )
2014-04-08 22:26:19 -04:00
@ getDocumentForIdOrSlug id , (err, patch) =>
return @ sendDatabaseError ( res , err ) if err
return @ sendNotFoundError ( res ) unless patch ?
targetInfo = patch . get ( ' target ' )
targetHandler = require ( ' ../ ' + handlers [ targetInfo . collection ] )
targetModel = targetHandler . modelClass
query = { ' original ' : targetInfo . original }
sort = { ' version.major ' : - 1 , ' version.minor ' : - 1 }
targetModel . findOne ( query ) . sort ( sort ) . exec (err, target) =>
return @ sendDatabaseError ( res , err ) if err
return @ sendNotFoundError ( res ) unless target ?
2014-09-19 05:26:18 -04:00
return @ sendForbiddenError ( res ) unless targetHandler . hasAccessToDocument ( req , target , ' get ' )
2014-04-08 22:26:19 -04:00
if newStatus in [ ' rejected ' , ' accepted ' ]
2014-09-19 05:26:18 -04:00
return @ sendForbiddenError ( res ) unless targetHandler . hasAccessToDocument ( req , target , ' put ' )
2014-06-30 22:16:26 -04:00
2014-04-08 22:26:19 -04:00
if newStatus is ' withdrawn '
2014-09-19 05:26:18 -04:00
return @ sendForbiddenError ( res ) unless req . user . get ( ' _id ' ) . equals patch . get ( ' creator ' )
2014-06-27 15:30:31 -04:00
2014-06-28 11:44:07 -04:00
patch . set ' status ' , newStatus
# Only increment statistics upon very first accept
if patch . isNewlyAccepted ( )
2014-08-15 13:35:35 -04:00
patch . set ' acceptor ' , req . user . get ( ' id ' )
acceptor = req . user . get ' id '
2014-06-28 11:44:07 -04:00
submitter = patch . get ' creator '
2014-08-15 13:35:35 -04:00
User . incrementStat acceptor , ' stats.patchesAccepted '
2014-06-28 11:44:07 -04:00
# TODO maybe merge these increments together
if patch . isTranslationPatch ( )
User . incrementStat submitter , ' stats.totalTranslationPatches '
User . incrementStat submitter , User . statsMapping . translations [ targetModel . modelName ]
if patch . isMiscPatch ( )
User . incrementStat submitter , ' stats.totalMiscPatches '
User . incrementStat submitter , User . statsMapping . misc [ targetModel . modelName ]
2014-06-27 15:30:31 -04:00
2014-04-08 22:26:19 -04:00
# these require callbacks
2014-06-27 15:30:31 -04:00
patch . save (err) =>
log . error err if err ?
target . update { $pull : { patches : patch . get ( ' _id ' ) } } , { } , ->
@ sendSuccess ( res , null )
2014-04-17 20:09:01 -04:00
onPostSuccess: (req, doc) ->
2014-06-30 22:16:26 -04:00
log . error ' Error sending patch created: could not find the loaded target on the patch object. ' unless doc . targetLoaded
2014-04-17 20:09:01 -04:00
return unless doc . targetLoaded
2014-08-28 21:55:08 -04:00
docLink = " http://codecombat.com #{ req . headers [ ' x-current-path ' ] } "
@ sendPatchCreatedHipChatMessage creator: req . user , patch: doc , target: doc . targetLoaded , docLink: docLink
2014-04-17 20:30:55 -04:00
watchers = doc . targetLoaded . get ( ' watchers ' ) or [ ]
2014-04-21 19:15:23 -04:00
watchers = ( w for w in watchers when not w . equals ( req . user . get ( ' _id ' ) ) )
2014-04-17 20:09:01 -04:00
return unless watchers ? . length
2014-06-30 22:16:26 -04:00
User . find ( { _id: { $in: watchers } } ) . select ( { email: 1 , name: 1 } ) . exec (err, watchers) =>
2014-04-17 20:09:01 -04:00
for watcher in watchers
2014-08-28 21:55:08 -04:00
@ sendPatchCreatedEmail req . user , watcher , doc , doc . targetLoaded , docLink
2014-06-30 22:16:26 -04:00
2014-08-28 21:55:08 -04:00
sendPatchCreatedEmail: (patchCreator, watcher, patch, target, docLink) ->
2014-04-17 20:09:01 -04:00
# return if watcher._id is patchCreator._id
context =
email_id: sendwithus . templates . patch_created
recipient:
address: watcher . get ( ' email ' )
name: watcher . get ( ' name ' )
email_data:
doc_name: target . get ( ' name ' ) or ' ??? '
submitter_name: patchCreator . get ( ' name ' ) or ' ??? '
2014-08-28 21:55:08 -04:00
doc_link: docLink
2014-04-17 20:09:01 -04:00
commit_message: patch . get ( ' commitMessage ' )
sendwithus . api . send context , (err, result) ->
2014-04-08 22:26:19 -04:00
2014-08-28 21:55:08 -04:00
sendPatchCreatedHipChatMessage: (options) ->
message = " #{ options . creator . get ( ' name ' ) } submitted a patch to <a href= \" #{ options . docLink } \" > #{ options . target . get ( ' name ' ) } </a>: #{ options . patch . get ( ' commitMessage ' ) } "
2015-02-04 19:17:53 -05:00
hipchat . sendHipChatMessage message , [ ' main ' ]
2014-08-28 21:55:08 -04:00
2014-04-08 22:26:19 -04:00
module.exports = new PatchHandler ( )