2018-12-17 16:37:19 +01:00
'use strict' ;
exports = module . exports = {
NotificationsError : NotificationsError ,
get : get ,
ack : ack ,
2019-01-04 17:13:52 +01:00
getAllPaged : getAllPaged ,
2018-12-17 17:35:19 +01:00
2019-02-27 16:10:54 -08:00
onEvent : onEvent ,
2019-02-28 14:52:14 -08:00
// NOTE: if you add an alert, be sure to add title below
ALERT _BACKUP _CONFIG : 'backupConfig' ,
ALERT _DISK _SPACE : 'diskSpace' ,
ALERT _MAIL _STATUS : 'mailStatus' ,
ALERT _REBOOT : 'reboot' ,
2019-03-02 19:23:39 -08:00
alert : alert ,
// exported for testing
_add : add
2018-12-17 16:37:19 +01:00
} ;
2019-02-28 14:52:14 -08:00
let assert = require ( 'assert' ) ,
2018-12-17 17:35:19 +01:00
async = require ( 'async' ) ,
2019-01-10 12:00:04 +01:00
config = require ( './config.js' ) ,
2018-12-17 16:37:19 +01:00
DatabaseError = require ( './databaseerror.js' ) ,
debug = require ( 'debug' ) ( 'box:notifications' ) ,
2019-02-27 16:10:54 -08:00
eventlog = require ( './eventlog.js' ) ,
2018-12-17 17:35:19 +01:00
mailer = require ( './mailer.js' ) ,
2018-12-17 16:37:19 +01:00
notificationdb = require ( './notificationdb.js' ) ,
2019-03-01 14:40:28 -08:00
path = require ( 'path' ) ,
paths = require ( './paths.js' ) ,
2019-01-19 13:22:29 +01:00
safe = require ( 'safetydance' ) ,
2018-12-17 17:35:19 +01:00
users = require ( './users.js' ) ,
2018-12-17 16:37:19 +01:00
util = require ( 'util' ) ;
2019-02-28 14:52:14 -08:00
// These titles are matched for upsert
const ALERT _TITLES = {
backupConfig : 'Backup configuration is unsafe' ,
diskSpace : 'Out of Disk Space' ,
mailStatus : 'Email is not configured properly' ,
reboot : 'Reboot Required'
} ;
2018-12-17 16:37:19 +01:00
function NotificationsError ( reason , errorOrMessage ) {
assert . strictEqual ( typeof reason , 'string' ) ;
assert ( errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined' ) ;
Error . call ( this ) ;
Error . captureStackTrace ( this , this . constructor ) ;
this . name = this . constructor . name ;
this . reason = reason ;
if ( typeof errorOrMessage === 'undefined' ) {
this . message = reason ;
} else if ( typeof errorOrMessage === 'string' ) {
this . message = errorOrMessage ;
} else {
this . message = 'Internal error' ;
this . nestedError = errorOrMessage ;
}
}
util . inherits ( NotificationsError , Error ) ;
NotificationsError . INTERNAL _ERROR = 'Internal Error' ;
NotificationsError . NOT _FOUND = 'Not Found' ;
2019-02-28 14:59:33 -08:00
function add ( userId , eventId , title , message , callback ) {
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof userId , 'string' ) ;
2019-02-06 16:18:12 +01:00
assert ( typeof eventId === 'string' || eventId === null ) ;
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof title , 'string' ) ;
assert . strictEqual ( typeof message , 'string' ) ;
2018-12-17 17:40:53 +01:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-12-17 16:37:19 +01:00
2019-02-28 14:59:33 -08:00
debug ( 'add: ' , userId , title ) ;
2018-12-17 16:37:19 +01:00
notificationdb . add ( {
userId : userId ,
2019-01-19 13:22:29 +01:00
eventId : eventId ,
2018-12-17 16:37:19 +01:00
title : title ,
2019-03-04 20:44:41 -08:00
message : message ,
acknowledged : false
2018-12-17 16:37:19 +01:00
} , function ( error , result ) {
2019-01-21 08:51:04 +01:00
if ( error && error . reason === DatabaseError . NOT _FOUND ) return callback ( new NotificationsError ( NotificationsError . NOT _FOUND , error . message ) ) ;
2018-12-17 16:37:19 +01:00
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
callback ( null , { id : result } ) ;
} ) ;
}
function get ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
notificationdb . get ( id , function ( error , result ) {
if ( error && error . reason === DatabaseError . NOT _FOUND ) return callback ( new NotificationsError ( NotificationsError . NOT _FOUND ) ) ;
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
callback ( null , result ) ;
} ) ;
}
function ack ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
notificationdb . update ( id , { acknowledged : true } , function ( error ) {
if ( error && error . reason === DatabaseError . NOT _FOUND ) return callback ( new NotificationsError ( NotificationsError . NOT _FOUND ) ) ;
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
}
// if acknowledged === null we return all, otherwise yes or no based on acknowledged as a boolean
2019-01-04 17:13:52 +01:00
function getAllPaged ( userId , acknowledged , page , perPage , callback ) {
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof userId , 'string' ) ;
assert ( acknowledged === null || typeof acknowledged === 'boolean' ) ;
assert . strictEqual ( typeof page , 'number' ) ;
assert . strictEqual ( typeof perPage , 'number' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
notificationdb . listByUserIdPaged ( userId , page , perPage , function ( error , result ) {
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
if ( acknowledged === null ) return callback ( null , result ) ;
callback ( null , result . filter ( function ( r ) { return r . acknowledged === acknowledged ; } ) ) ;
} ) ;
}
2018-12-17 17:35:19 +01:00
2019-01-07 14:56:43 +01:00
// Calls iterator with (admin, callback)
2019-01-17 13:36:54 +01:00
function actionForAllAdmins ( skippingUserIds , iterator , callback ) {
assert ( Array . isArray ( skippingUserIds ) ) ;
2019-01-07 14:56:43 +01:00
assert . strictEqual ( typeof iterator , 'function' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
users . getAllAdmins ( function ( error , result ) {
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
2019-01-17 13:36:54 +01:00
// filter out users we want to skip (like the user who did the action or the user the action was performed on)
result = result . filter ( function ( r ) { return skippingUserIds . indexOf ( r . id ) === - 1 ; } ) ;
2019-01-07 14:56:43 +01:00
async . each ( result , iterator , callback ) ;
} ) ;
}
2019-03-01 15:14:35 -08:00
function userAdded ( performedBy , eventId , user , callback ) {
2019-01-17 13:36:54 +01:00
assert . strictEqual ( typeof performedBy , 'string' ) ;
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2018-12-17 17:35:19 +01:00
assert . strictEqual ( typeof user , 'object' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-12-17 17:35:19 +01:00
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ performedBy , user . id ] , function ( admin , done ) {
2019-01-07 14:56:43 +01:00
mailer . userAdded ( admin . email , user ) ;
2019-03-01 15:14:35 -08:00
add ( admin . id , eventId , 'User added' , ` User ${ user . fallbackEmail } was added ` , done ) ;
} , callback ) ;
2018-12-17 17:35:19 +01:00
}
2019-01-07 12:57:57 +01:00
2019-03-01 15:14:35 -08:00
function userRemoved ( performedBy , eventId , user , callback ) {
2019-01-17 13:36:54 +01:00
assert . strictEqual ( typeof performedBy , 'string' ) ;
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-01-10 12:00:04 +01:00
assert . strictEqual ( typeof user , 'object' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-10 12:00:04 +01:00
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ performedBy , user . id ] , function ( admin , done ) {
2019-01-10 12:00:04 +01:00
mailer . userRemoved ( admin . email , user ) ;
2019-03-01 15:14:35 -08:00
add ( admin . id , eventId , 'User removed' , ` User ${ user . username || user . email || user . fallbackEmail } was removed ` , done ) ;
} , callback ) ;
2019-01-10 12:00:04 +01:00
}
2019-03-01 15:14:35 -08:00
function adminChanged ( performedBy , eventId , user , callback ) {
2019-01-17 13:36:54 +01:00
assert . strictEqual ( typeof performedBy , 'string' ) ;
2019-01-10 12:00:04 +01:00
assert . strictEqual ( typeof user , 'object' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-10 12:00:04 +01:00
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ performedBy , user . id ] , function ( admin , done ) {
2019-01-17 13:12:26 +01:00
mailer . adminChanged ( admin . email , user , user . admin ) ;
2019-03-01 15:14:35 -08:00
add ( admin . id , eventId , 'Admin status change' , ` User ${ user . username || user . email || user . fallbackEmail } ${ user . admin ? 'is now an admin' : 'is no more an admin' } ` , done ) ;
} , callback ) ;
2019-01-10 12:00:04 +01:00
}
2019-03-06 11:54:37 -08:00
function oomEvent ( eventId , app , addon , containerId , event , callback ) {
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-03-06 11:54:37 -08:00
assert . strictEqual ( typeof app , 'object' ) ;
assert . strictEqual ( typeof addon , 'object' ) ;
assert . strictEqual ( typeof containerId , 'string' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-07 12:57:57 +01:00
2019-03-06 11:54:37 -08:00
let title , message , program ;
if ( app ) {
2019-03-06 16:08:12 -08:00
program = ` App ${ app . fqdn } ` ;
2019-03-06 11:54:37 -08:00
title = ` The application ${ app . fqdn } ( ${ app . manifest . title } ) ran out of memory. ` ;
message = 'The application has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https://cloudron.io/documentation/apps/#increasing-the-memory-limit-of-an-app)' ;
} else if ( addon ) {
2019-03-06 16:08:12 -08:00
program = ` ${ addon . name } service ` ;
2019-03-06 11:54:37 -08:00
title = ` The ${ addon . name } service ran out of memory ` ;
message = 'The service has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https://cloudron.io/documentation/troubleshooting/#services)' ;
2019-03-06 15:59:35 -08:00
} else { // this never happens currently
2019-03-06 16:08:12 -08:00
program = ` Container ${ containerId } ` ;
2019-03-06 11:54:37 -08:00
title = ` The container ${ containerId } ran out of memory ` ;
message = 'The container has been restarted automatically. Consider increasing the [memory limit](https://docs.docker.com/v17.09/edge/engine/reference/commandline/update/#update-a-containers-kernel-memory-constraints)' ;
}
2019-01-10 12:00:04 +01:00
// also send us a notification mail
2019-03-06 11:54:37 -08:00
if ( config . provider ( ) === 'caas' ) mailer . oomEvent ( 'support@cloudron.io' , program , event ) ;
2019-01-10 12:00:04 +01:00
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ ] , function ( admin , done ) {
2019-03-06 11:54:37 -08:00
mailer . oomEvent ( admin . email , program , event ) ;
2019-01-08 14:20:08 +01:00
2019-03-06 11:54:37 -08:00
add ( admin . id , eventId , title , message , done ) ;
2019-03-01 15:14:35 -08:00
} , callback ) ;
2019-01-07 12:57:57 +01:00
}
2019-01-07 13:01:27 +01:00
2019-03-01 15:14:35 -08:00
function appUp ( eventId , app , callback ) {
2019-02-11 12:32:02 -08:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-02-11 12:32:02 -08:00
// also send us a notification mail
2019-03-01 15:14:35 -08:00
if ( config . provider ( ) === 'caas' ) mailer . appUp ( 'support@cloudron.io' , app ) ;
2019-02-11 12:32:02 -08:00
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ ] , function ( admin , done ) {
2019-02-11 12:32:02 -08:00
mailer . appUp ( admin . email , app ) ;
2019-03-01 15:14:35 -08:00
add ( admin . id , eventId , ` App ${ app . fqdn } is back online ` , ` The application ${ app . manifest . title } installed at ${ app . fqdn } is back online. ` , done ) ;
} , callback ) ;
2019-02-11 12:32:02 -08:00
}
2019-03-01 15:14:35 -08:00
function appDied ( eventId , app , callback ) {
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-01-07 13:01:27 +01:00
assert . strictEqual ( typeof app , 'object' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-07 13:01:27 +01:00
2019-01-10 12:00:04 +01:00
// also send us a notification mail
if ( config . provider ( ) === 'caas' ) mailer . appDied ( 'support@cloudron.io' , app ) ;
2019-01-17 13:36:54 +01:00
actionForAllAdmins ( [ ] , function ( admin , callback ) {
2019-01-10 12:00:04 +01:00
mailer . appDied ( admin . email , app ) ;
2019-02-28 14:59:33 -08:00
add ( admin . id , eventId , ` App ${ app . fqdn } is down ` , ` The application ${ app . manifest . title } installed at ${ app . fqdn } is not responding. ` , callback ) ;
2019-03-01 15:14:35 -08:00
} , callback ) ;
2019-01-07 13:01:27 +01:00
}
2019-01-10 13:57:47 +01:00
2019-03-01 15:45:44 -08:00
function processCrash ( eventId , processName , crashId , callback ) {
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof processName , 'string' ) ;
2019-03-01 15:45:44 -08:00
assert . strictEqual ( typeof crashId , 'string' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-10 13:57:47 +01:00
2019-01-19 13:22:29 +01:00
var subject = ` ${ processName } exited unexpectedly ` ;
2019-03-01 15:45:44 -08:00
var crashLogs = safe . fs . readFileSync ( path . join ( paths . CRASH _LOG _DIR , crashId , '.log' ) , 'utf8' ) || ` No logs found at ${ crashId } .log ` ;
2019-01-10 13:57:47 +01:00
// also send us a notification mail
2019-01-19 13:22:29 +01:00
if ( config . provider ( ) === 'caas' ) mailer . unexpectedExit ( 'support@cloudron.io' , subject , crashLogs ) ;
2019-01-10 13:57:47 +01:00
2019-01-17 13:36:54 +01:00
actionForAllAdmins ( [ ] , function ( admin , callback ) {
2019-01-19 13:22:29 +01:00
mailer . unexpectedExit ( admin . email , subject , crashLogs ) ;
2019-03-01 15:45:44 -08:00
add ( admin . id , eventId , subject , ` The service has been restarted automatically. Crash logs are available [here](/logs.html?crashId= ${ crashId } ). ` , callback ) ;
2019-03-01 15:14:35 -08:00
} , callback ) ;
2019-01-10 13:57:47 +01:00
}
2019-01-19 13:30:24 +01:00
2019-03-01 15:14:35 -08:00
function apptaskCrash ( eventId , appId , crashLogFile , callback ) {
2019-01-19 13:30:24 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof crashLogFile , 'string' ) ;
2019-03-01 15:14:35 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-01-19 13:30:24 +01:00
var subject = ` Apptask for ${ appId } crashed ` ;
2019-01-19 15:23:54 +01:00
var crashLogs = safe . fs . readFileSync ( crashLogFile , 'utf8' ) || ` No logs found at ${ crashLogFile } ` ;
2019-01-19 13:30:24 +01:00
// also send us a notification mail
if ( config . provider ( ) === 'caas' ) mailer . unexpectedExit ( 'support@cloudron.io' , subject , crashLogs ) ;
2019-03-01 15:14:35 -08:00
actionForAllAdmins ( [ ] , function ( admin , done ) {
2019-01-19 13:30:24 +01:00
mailer . unexpectedExit ( admin . email , subject , crashLogs ) ;
2019-03-01 15:14:35 -08:00
add ( admin . id , eventId , subject , 'Detailed logs have been sent to your email address.' , done ) ;
} , callback ) ;
2019-01-19 13:30:24 +01:00
}
2019-02-06 15:47:31 +01:00
2019-03-04 14:50:56 -08:00
function certificateRenewalError ( eventId , vhost , errorMessage , callback ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof vhost , 'string' ) ;
assert . strictEqual ( typeof errorMessage , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
actionForAllAdmins ( [ ] , function ( admin , callback ) {
mailer . certificateRenewalError ( vhost , errorMessage ) ;
add ( admin . id , eventId , ` Certificate renewal of ${ vhost } failed ` , ` Failed to new certs of ${ vhost } : ${ errorMessage } . Renewal will be retried in 12 hours ` , callback ) ;
} , callback ) ;
}
2019-03-04 17:52:31 -08:00
function backupFailed ( eventId , taskId , errorMessage , callback ) {
2019-03-04 15:00:23 -08:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-03-04 17:52:31 -08:00
assert . strictEqual ( typeof taskId , 'string' ) ;
2019-03-04 15:00:23 -08:00
assert . strictEqual ( typeof errorMessage , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
actionForAllAdmins ( [ ] , function ( admin , callback ) {
mailer . backupFailed ( errorMessage ) ;
2019-03-04 17:52:31 -08:00
add ( admin . id , eventId , 'Failed to backup' , ` Backup failed: ${ errorMessage } . Logs are available [here](/logs.html?taskId= ${ taskId } ). Will be retried in 4 hours ` , callback ) ;
2019-03-04 15:00:23 -08:00
} , callback ) ;
}
2019-02-28 14:52:14 -08:00
function upsert ( userId , eventId , title , message , callback ) {
assert . strictEqual ( typeof userId , 'string' ) ;
assert ( typeof eventId === 'string' || eventId === null ) ;
assert . strictEqual ( typeof title , 'string' ) ;
2019-02-06 15:47:31 +01:00
assert . strictEqual ( typeof message , 'string' ) ;
2019-02-28 14:52:14 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-02-06 15:47:31 +01:00
2019-03-04 20:58:27 -08:00
const acknowledged = ! message ;
2019-02-06 15:47:31 +01:00
2019-03-04 20:58:27 -08:00
const data = {
2019-02-28 14:52:14 -08:00
userId : userId ,
eventId : eventId ,
title : title ,
message : message ,
2019-03-04 20:58:27 -08:00
acknowledged : acknowledged
} ;
2019-02-06 14:58:45 -08:00
2019-03-04 20:58:27 -08:00
notificationdb . getByUserIdAndTitle ( userId , title , function ( error , result ) {
if ( error && error . reason !== DatabaseError . NOT _FOUND ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
if ( ! result && acknowledged ) return callback ( ) ; // do not add acked alerts
let updateFunc = ! result ? notificationdb . add . bind ( null , data ) : notificationdb . update . bind ( null , result . id , data ) ;
updateFunc ( function ( error ) {
if ( error && error . reason === DatabaseError . NOT _FOUND ) return callback ( new NotificationsError ( NotificationsError . NOT _FOUND , error . message ) ) ;
if ( error ) return callback ( new NotificationsError ( NotificationsError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
2019-02-06 14:58:45 -08:00
} ) ;
}
2019-02-28 14:52:14 -08:00
function alert ( id , message , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
2019-02-19 09:19:56 -08:00
assert . strictEqual ( typeof message , 'string' ) ;
2019-02-28 14:52:14 -08:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-02-19 09:19:56 -08:00
2019-02-28 14:52:14 -08:00
const title = ALERT _TITLES [ id ] ;
if ( ! title ) return callback ( ) ;
2019-02-06 15:47:31 +01:00
2019-03-04 20:21:41 -08:00
debug ( ` alert: id= ${ id } title= ${ title } message= ${ message } ` ) ;
2019-02-06 15:47:31 +01:00
actionForAllAdmins ( [ ] , function ( admin , callback ) {
2019-02-28 14:52:14 -08:00
upsert ( admin . id , null , title , message , callback ) ;
2019-02-06 15:47:31 +01:00
} , function ( error ) {
if ( error ) console . error ( error ) ;
2019-02-28 14:52:14 -08:00
2019-03-04 20:21:41 -08:00
callback ( ) ;
} ) ;
2019-02-06 15:47:31 +01:00
}
2019-02-27 16:10:54 -08:00
function onEvent ( id , action , source , data , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof action , 'string' ) ;
assert . strictEqual ( typeof source , 'object' ) ;
assert . strictEqual ( typeof data , 'object' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2019-03-01 15:14:35 -08:00
switch ( action ) {
case eventlog . ACTION _USER _ADD : return userAdded ( source . userId , id , data . user , callback ) ;
case eventlog . ACTION _USER _REMOVE : return userRemoved ( source . userId , id , data . user , callback ) ;
case eventlog . ACTION _USER _UPDATE : return data . adminStatusChanged ? adminChanged ( source . userId , id , data . user , callback ) : callback ( ) ;
2019-03-06 11:54:37 -08:00
case eventlog . ACTION _APP _OOM : return oomEvent ( id , data . app , data . addon , data . containerId , data . event , callback ) ;
2019-03-01 15:14:35 -08:00
case eventlog . ACTION _APP _DOWN : return appDied ( id , data . app , callback ) ;
case eventlog . ACTION _APP _UP : return appUp ( id , data . app , callback ) ;
case eventlog . ACTION _APP _TASK _CRASH : return apptaskCrash ( id , data . appId , data . crashLogFile , callback ) ;
2019-03-01 15:45:44 -08:00
case eventlog . ACTION _PROCESS _CRASH : return processCrash ( id , data . processName , data . crashId , callback ) ;
2019-03-04 14:50:56 -08:00
case eventlog . ACTION _CERTIFICATE _RENEWAL :
case eventlog . ACTION _CERTIFICATE _NEW :
return data . errorMessage ? certificateRenewalError ( id , data . domain , data . errorMessage , callback ) : callback ( ) ;
2019-03-04 17:52:31 -08:00
case eventlog . ACTION _BACKUP _FINISH : return data . errorMessage ? backupFailed ( id , data . taskId , data . errorMessage , callback ) : callback ( ) ;
2019-03-04 15:00:23 -08:00
2019-03-01 15:14:35 -08:00
default : return callback ( ) ;
2019-02-27 16:10:54 -08:00
}
}