2018-12-17 16:37:19 +01:00
'use strict' ;
exports = module . exports = {
2020-12-29 12:43:53 -08:00
get ,
2021-04-21 12:00:07 -07:00
update ,
list ,
2021-05-28 14:34:18 -07:00
del ,
2018-12-17 17:35:19 +01:00
2020-12-29 12:43:53 -08:00
onEvent ,
2023-09-26 12:58:19 +02:00
// these are notification types, keep in sync with client.js
2024-12-11 15:18:00 +01:00
TYPE _CLOUDRON _INSTALLED : 'cloudronInstalled' ,
TYPE _CLOUDRON _UPDATED : 'cloudronUpdated' ,
TYPE _CLOUDRON _UPDATE _FAILED : 'cloudronUpdateFailed' ,
TYPE _CERTIFICATE _RENEWAL _FAILED : 'certificateRenewalFailed' ,
TYPE _BACKUP _CONFIG : 'backupConfig' ,
2024-12-11 15:47:41 +01:00
TYPE _APP _OOM : 'appOutOfMemory' ,
TYPE _APP _UPDATED : 'appUpdated' ,
TYPE _BACKUP _FAILED : 'backupFailed' ,
2024-12-11 20:44:46 +01:00
TYPE _APP _DOWN : 'appDown' ,
TYPE _APP _UP : 'appUp' ,
2024-12-11 15:47:41 +01:00
// these are singleton types allowed in pin() and unpin()
2024-12-11 15:18:00 +01:00
TYPE _DISK _SPACE : 'diskSpace' ,
TYPE _MAIL _STATUS : 'mailStatus' ,
TYPE _REBOOT : 'reboot' ,
TYPE _UPDATE _UBUNTU : 'ubuntuUpdate' ,
2024-12-11 15:47:41 +01:00
TYPE _BOX _UPDATE : 'boxUpdate' ,
2024-12-11 18:24:20 +01:00
TYPE _MANUAL _APP _UPDATE _NEEDED : 'manualAppUpdate' ,
2025-02-17 19:01:53 +01:00
TYPE _DOMAIN _CONFIG _CHECK _FAILED : 'domainConfigCheckFailed' ,
2019-02-28 14:52:14 -08:00
2024-12-11 15:47:41 +01:00
// these work off singleton types
pin ,
unpin ,
2019-03-02 19:23:39 -08:00
// exported for testing
_add : add
2018-12-17 16:37:19 +01:00
} ;
2025-08-14 11:17:38 +05:30
const assert = require ( 'node:assert' ) ,
2021-09-30 09:50:30 -07:00
AuditSource = require ( './auditsource.js' ) ,
2019-10-22 12:59:26 -07:00
BoxError = require ( './boxerror.js' ) ,
2019-08-03 13:59:11 -07:00
changelog = require ( './changelog.js' ) ,
2022-04-01 13:44:46 -07:00
constants = require ( './constants.js' ) ,
2023-08-11 19:41:05 +05:30
dashboard = require ( './dashboard.js' ) ,
2021-05-28 14:34:18 -07:00
database = require ( './database.js' ) ,
2024-12-11 15:47:41 +01:00
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' ) ,
2025-08-06 10:18:05 +02:00
safe = require ( 'safetydance' ) ,
2021-06-30 17:19:30 +02:00
users = require ( './users.js' ) ;
2021-05-28 14:34:18 -07:00
2024-12-11 22:29:00 +01:00
const NOTIFICATION _FIELDS = [ 'id' , 'eventId' , 'type' , 'title' , 'message' , 'creationTime' , 'acknowledged' , 'context' ] ;
2021-05-28 14:34:18 -07:00
function postProcess ( result ) {
assert . strictEqual ( typeof result , 'object' ) ;
result . id = String ( result . id ) ;
2023-03-26 14:42:38 +02:00
result . acknowledged = ! ! result . acknowledged ; // convert to boolean
2021-05-28 14:34:18 -07:00
return result ;
}
2023-09-22 17:58:13 +02:00
async function add ( type , title , message , data ) {
assert . strictEqual ( typeof type , 'string' ) ;
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof title , 'string' ) ;
assert . strictEqual ( typeof message , 'string' ) ;
2023-03-26 14:42:38 +02:00
assert . strictEqual ( typeof data , 'object' ) ;
2021-05-28 14:34:18 -07:00
2024-12-11 23:32:11 +01:00
debug ( ` add: ${ type } ${ title } ` ) ;
2024-12-11 22:29:00 +01:00
const query = 'INSERT INTO notifications (type, title, message, acknowledged, eventId, context) VALUES (?, ?, ?, ?, ?, ?)' ;
const args = [ type , title , message , false , data ? . eventId || null , data . context || '' ] ;
2021-05-28 14:34:18 -07:00
const result = await database . query ( query , args ) ;
return String ( result . insertId ) ;
2018-12-17 16:37:19 +01:00
}
2021-05-28 14:34:18 -07:00
async function get ( id ) {
2018-12-17 16:37:19 +01:00
assert . strictEqual ( typeof id , 'string' ) ;
2023-03-26 14:42:38 +02:00
const result = await database . query ( ` SELECT ${ NOTIFICATION _FIELDS } FROM notifications WHERE id = ? ` , [ id ] ) ;
2021-05-28 14:34:18 -07:00
if ( result . length === 0 ) return null ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
return postProcess ( result [ 0 ] ) ;
2018-12-17 16:37:19 +01:00
}
2024-12-11 22:29:00 +01:00
async function getByType ( type , context ) {
2024-12-11 15:47:41 +01:00
assert . strictEqual ( typeof type , 'string' ) ;
2024-12-11 22:29:00 +01:00
assert . strictEqual ( typeof context , 'string' ) ;
2018-12-17 16:37:19 +01:00
2024-12-11 22:29:00 +01:00
const results = await database . query ( ` SELECT ${ NOTIFICATION _FIELDS } from notifications WHERE type = ? AND context = ? ORDER BY creationTime LIMIT 1 ` , [ type , context || '' ] ) ;
2021-05-28 14:34:18 -07:00
if ( results . length === 0 ) return null ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
return postProcess ( results [ 0 ] ) ;
2018-12-17 16:37:19 +01:00
}
2021-05-28 14:34:18 -07:00
async function update ( notification , data ) {
assert . strictEqual ( typeof notification , 'object' ) ;
assert . strictEqual ( typeof data , 'object' ) ;
2018-12-17 16:37:19 +01:00
2023-03-26 14:42:38 +02:00
const args = [ ] ;
const fields = [ ] ;
for ( const k in data ) {
2021-05-28 14:34:18 -07:00
fields . push ( k + ' = ?' ) ;
args . push ( data [ k ] ) ;
}
args . push ( notification . id ) ;
2018-12-17 16:37:19 +01:00
2021-05-28 14:34:18 -07:00
const result = await database . query ( 'UPDATE notifications SET ' + fields . join ( ', ' ) + ' WHERE id = ?' , args ) ;
if ( result . affectedRows !== 1 ) throw new BoxError ( BoxError . NOT _FOUND , 'Notification not found' ) ;
2018-12-17 16:37:19 +01:00
}
2018-12-17 17:35:19 +01:00
2021-05-28 14:34:18 -07:00
async function del ( id ) {
assert . strictEqual ( typeof id , 'string' ) ;
2019-01-07 14:56:43 +01:00
2021-05-28 14:34:18 -07:00
const result = await database . query ( 'DELETE FROM notifications WHERE id = ?' , [ id ] ) ;
if ( result . affectedRows !== 1 ) throw new BoxError ( BoxError . NOT _FOUND , 'Notification not found' ) ;
}
2019-01-17 13:36:54 +01:00
2021-05-28 14:34:18 -07:00
async function list ( filters , page , perPage ) {
assert . strictEqual ( typeof filters , 'object' ) ;
assert . strictEqual ( typeof page , 'number' ) ;
assert . strictEqual ( typeof perPage , 'number' ) ;
2019-01-17 13:36:54 +01:00
2023-03-26 14:42:38 +02:00
const args = [ ] ;
2019-01-07 14:56:43 +01:00
2023-03-26 14:42:38 +02:00
const where = [ ] ;
2021-05-28 14:34:18 -07:00
if ( 'acknowledged' in filters ) {
where . push ( 'acknowledged=?' ) ;
args . push ( filters . acknowledged ) ;
}
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
let query = ` SELECT ${ NOTIFICATION _FIELDS } FROM notifications ` ;
if ( where . length ) query += ' WHERE ' + where . join ( ' AND ' ) ;
2025-01-02 16:50:23 +01:00
query += ' ORDER BY acknowledged ASC, creationTime DESC LIMIT ?,?' ;
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
args . push ( ( page - 1 ) * perPage ) ;
args . push ( perPage ) ;
2021-04-19 20:52:10 -07:00
2021-05-28 14:34:18 -07:00
const results = await database . query ( query , args ) ;
results . forEach ( postProcess ) ;
return results ;
2021-04-19 20:52:10 -07:00
}
2024-12-11 23:32:11 +01:00
async function oomEvent ( eventId , containerId , app , addonName , event ) {
2019-01-19 13:22:29 +01:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-03-06 11:54:37 -08:00
assert . strictEqual ( typeof containerId , 'string' ) ;
2021-09-19 17:32:48 -07:00
assert . strictEqual ( typeof app , 'object' ) ;
assert ( addonName === null || typeof addonName === 'string' ) ;
2019-01-07 12:57:57 +01:00
2021-09-19 17:32:48 -07:00
assert ( app || addonName ) ;
2021-01-02 11:07:44 -08:00
2023-08-11 19:41:05 +05:30
const { fqdn : dashboardFqdn } = await dashboard . getLocation ( ) ;
2021-01-02 11:07:44 -08:00
let title , message ;
2021-09-19 17:32:48 -07:00
if ( addonName ) {
if ( app ) {
title = ` The ${ addonName } service of the app at ${ app . fqdn } ran out of memory ` ;
} else {
title = ` The ${ addonName } service ran out of memory ` ;
}
2023-08-11 19:41:05 +05:30
message = ` The service has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https:// ${ dashboardFqdn } /#/services) ` ;
2021-09-19 17:32:48 -07:00
} else if ( app ) {
title = ` The app at ${ app . fqdn } ran out of memory. ` ;
2023-08-11 19:41:05 +05:30
message = ` The app has been restarted automatically. If you see this notification often, consider increasing the [memory limit](https:// ${ dashboardFqdn } /#/app/ ${ app . id } /resources) ` ;
2019-03-06 11:54:37 -08:00
}
2024-12-11 15:18:00 +01:00
await add ( exports . TYPE _APP _OOM , title , message , { eventId } ) ;
2024-12-11 20:44:46 +01:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _APP _OOM ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . oomEvent ( admin . email , containerId , app , addonName , event ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
}
async function appUp ( eventId , app ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _APP _UP ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . appUp ( admin . email , app ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
}
async function appDown ( eventId , app ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _APP _DOWN ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . appDown ( admin . email , app ) , { debug } ) ;
2024-12-11 20:44:46 +01:00
}
}
2019-01-07 12:57:57 +01:00
}
2019-01-07 13:01:27 +01:00
2021-07-30 14:30:08 +02:00
async function appUpdated ( eventId , app , fromManifest , toManifest ) {
2019-05-07 12:04:43 +02:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
2021-07-30 14:30:08 +02:00
assert . strictEqual ( typeof fromManifest , 'object' ) ;
assert . strictEqual ( typeof toManifest , 'object' ) ;
2019-05-07 12:04:43 +02:00
2021-05-28 14:34:18 -07:00
if ( ! app . appStoreId ) return ; // skip notification of dev apps
2020-09-03 13:26:51 -07:00
2021-07-30 14:30:08 +02:00
const tmp = toManifest . description . match ( /<upstream>(.*)<\/upstream>/i ) ;
2019-08-02 20:56:25 -07:00
const upstreamVersion = ( tmp && tmp [ 1 ] ) ? tmp [ 1 ] : '' ;
2021-07-30 14:30:08 +02:00
const title = upstreamVersion ? ` ${ toManifest . title } at ${ app . fqdn } updated to ${ upstreamVersion } (package version ${ toManifest . version } ) `
: ` ${ toManifest . title } at ${ app . fqdn } updated to package version ${ toManifest . version } ` ;
2019-08-02 20:56:25 -07:00
2024-12-11 15:18:00 +01:00
await add ( exports . TYPE _APP _UPDATED , title , ` The application installed at https:// ${ app . fqdn } was updated. \n \n Changelog: \n ${ toManifest . changelog } \n ` , { eventId } ) ;
2019-05-07 12:04:43 +02:00
}
2024-12-11 20:44:46 +01:00
async function boxUpdated ( eventId , oldVersion , newVersion ) {
2022-04-01 13:44:46 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2024-12-11 20:44:46 +01:00
assert . strictEqual ( typeof oldVersion , 'string' ) ;
assert . strictEqual ( typeof newVersion , 'string' ) ;
2022-04-01 13:44:46 -07:00
2024-12-11 20:44:46 +01:00
const changes = changelog . getChanges ( newVersion ) ;
2022-04-01 13:44:46 -07:00
const changelogMarkdown = changes . map ( ( m ) => ` * ${ m } \n ` ) . join ( '' ) ;
2024-12-11 20:44:46 +01:00
await add ( exports . TYPE _CLOUDRON _UPDATED , ` Cloudron updated to v ${ newVersion } ` , ` Cloudron was updated from v ${ oldVersion } to v ${ newVersion } . \n \n Changelog: \n ${ changelogMarkdown } \n ` , { eventId } ) ;
2022-04-01 13:44:46 -07:00
}
2024-12-11 20:44:46 +01:00
async function boxInstalled ( eventId , version ) {
2019-10-14 09:30:20 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2024-12-11 20:44:46 +01:00
assert . strictEqual ( typeof version , 'string' ) ;
2019-08-03 13:59:11 -07:00
2024-12-11 20:44:46 +01:00
const changes = changelog . getChanges ( version . replace ( /\.([^.]*)$/ , '.0' ) ) ; // last .0 release
2019-08-03 13:59:11 -07:00
const changelogMarkdown = changes . map ( ( m ) => ` * ${ m } \n ` ) . join ( '' ) ;
2025-09-25 08:31:16 +02:00
await add ( exports . TYPE _CLOUDRON _INSTALLED , ` Cloudron v ${ version } installed ` , ` Cloudron v ${ version } was installed. \n \n Changelog: \n ${ changelogMarkdown } \n ` , { eventId } ) ;
2019-10-14 09:30:20 -07:00
}
2021-05-28 14:34:18 -07:00
async function boxUpdateError ( eventId , errorMessage ) {
2019-10-14 09:30:20 -07:00
assert . strictEqual ( typeof eventId , 'string' ) ;
assert . strictEqual ( typeof errorMessage , 'string' ) ;
2024-12-11 15:18:00 +01:00
await add ( exports . TYPE _CLOUDRON _UPDATE _FAILED , 'Cloudron update failed' , ` Failed to update Cloudron: ${ errorMessage } . ` , { eventId } ) ;
2025-01-24 18:44:12 +01:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _CLOUDRON _UPDATE _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . boxUpdateError ( admin . email , errorMessage ) , { debug } ) ;
2025-01-24 18:44:12 +01:00
}
}
2019-08-03 13:59:11 -07:00
}
2022-07-13 09:26:27 +05:30
async function certificateRenewalError ( eventId , fqdn , errorMessage ) {
2019-03-04 14:50:56 -08:00
assert . strictEqual ( typeof eventId , 'string' ) ;
2022-07-13 09:26:27 +05:30
assert . strictEqual ( typeof fqdn , 'string' ) ;
2019-03-04 14:50:56 -08:00
assert . strictEqual ( typeof errorMessage , 'string' ) ;
2024-12-11 15:18:00 +01:00
await add ( exports . TYPE _CERTIFICATE _RENEWAL _FAILED , ` Certificate renewal of ${ fqdn } failed ` , ` Failed to renew certs of ${ fqdn } : ${ errorMessage } . Renewal will be retried in 12 hours. ` , { eventId } ) ;
2021-05-28 14:34:18 -07:00
2021-07-15 09:50:11 -07:00
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
2024-12-11 18:24:20 +01:00
if ( admin . notificationConfig . includes ( exports . TYPE _CERTIFICATE _RENEWAL _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . certificateRenewalError ( admin . email , fqdn , errorMessage ) , { debug } ) ;
2024-12-11 18:24:20 +01:00
}
2021-07-15 09:50:11 -07:00
}
2019-03-04 14:50:56 -08:00
}
2021-05-28 14:34:18 -07:00
async function backupFailed ( eventId , taskId , errorMessage ) {
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' ) ;
2024-12-11 15:18:00 +01:00
await add ( exports . TYPE _BACKUP _FAILED , 'Backup failed' , ` Backup failed: ${ errorMessage } . Logs are available [here](/logs.html?taskId= ${ taskId } ). ` , { eventId } ) ;
2021-06-23 16:50:19 -07:00
2023-08-11 19:41:05 +05:30
const { fqdn : dashboardFqdn } = await dashboard . getLocation ( ) ;
2021-07-15 09:50:11 -07:00
const superadmins = await users . getSuperadmins ( ) ;
for ( const superadmin of superadmins ) {
2024-12-11 18:24:20 +01:00
if ( superadmin . notificationConfig . includes ( exports . TYPE _BACKUP _FAILED ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . backupFailed ( superadmin . email , errorMessage , ` https:// ${ dashboardFqdn } /logs.html?taskId= ${ taskId } ` ) , { debug } ) ;
2024-12-11 18:24:20 +01:00
}
2021-07-15 09:50:11 -07:00
}
2019-03-04 15:00:23 -08:00
}
2025-01-19 10:34:12 +01:00
async function rebootRequired ( ) {
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _REBOOT ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . rebootRequired ( admin . email ) , { debug } ) ;
2025-01-19 10:34:12 +01:00
}
}
}
2025-05-07 13:15:08 +02:00
async function lowDiskSpace ( message ) {
assert . strictEqual ( typeof message , 'string' ) ;
const admins = await users . getAdmins ( ) ;
for ( const admin of admins ) {
if ( admin . notificationConfig . includes ( exports . TYPE _DISK _SPACE ) ) {
2025-08-06 10:18:05 +02:00
await safe ( mailer . lowDiskSpace ( admin . email , message ) , { debug } ) ;
2025-05-07 13:15:08 +02:00
}
}
}
async function onPin ( type , message ) {
2025-01-19 10:34:12 +01:00
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
2025-05-07 13:15:08 +02:00
assert . strictEqual ( typeof message , 'string' ) ;
2025-01-19 10:34:12 +01:00
switch ( type ) {
case exports . TYPE _REBOOT :
return await rebootRequired ( ) ;
2025-05-07 13:15:08 +02:00
case exports . TYPE _DISK _SPACE :
return await lowDiskSpace ( message ) ;
2025-01-19 10:34:12 +01:00
default :
break ;
}
}
2024-12-11 15:47:41 +01:00
async function pin ( type , title , message , options ) {
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
2019-02-28 14:52:14 -08:00
assert . strictEqual ( typeof title , 'string' ) ;
2019-02-06 15:47:31 +01:00
assert . strictEqual ( typeof message , 'string' ) ;
2023-03-26 15:12:00 +02:00
assert . strictEqual ( typeof options , 'object' ) ;
2019-02-06 15:47:31 +01:00
2024-12-11 22:29:00 +01:00
const result = await getByType ( type , options . context || '' ) ;
2025-01-19 10:34:12 +01:00
if ( ! result ) {
2025-05-07 13:15:08 +02:00
await onPin ( type , message ) ;
2025-01-19 10:34:12 +01:00
return await add ( type , title , message , { eventId : null , context : options . context || '' } ) ;
}
2024-12-11 15:47:41 +01:00
// do not reset the ack state if user has already seen the update notification
2024-12-11 22:29:00 +01:00
const isUpdateType = type === exports . TYPE _BOX _UPDATE || type === exports . TYPE _MANUAL _APP _UPDATE _NEEDED ;
2024-12-11 15:47:41 +01:00
const acknowledged = ( isUpdateType && result . message === message ) ? result . acknowledged : false ;
2025-05-07 13:15:08 +02:00
if ( result . acknowledged && ! acknowledged ) await onPin ( type , message ) ;
2025-01-19 10:34:12 +01:00
2024-12-11 22:29:00 +01:00
await update ( result , { title , message , acknowledged , creationTime : new Date ( ) } ) ;
2023-03-26 15:12:00 +02:00
return result . id ;
2019-02-06 15:47:31 +01:00
}
2019-02-27 16:10:54 -08:00
2024-12-11 15:47:41 +01:00
async function unpin ( type , options ) {
assert . strictEqual ( typeof type , 'string' ) ; // TYPE_
assert . strictEqual ( typeof options , 'object' ) ;
2023-03-26 14:18:37 +02:00
2024-12-11 22:29:00 +01:00
await database . query ( 'UPDATE notifications SET acknowledged=1 WHERE type = ? AND context = ?' , [ type , options . context || '' ] ) ;
2023-03-26 14:18:37 +02:00
}
2025-01-19 10:34:12 +01:00
async function onEvent ( eventId , action , source , data ) {
assert . strictEqual ( typeof eventId , 'string' ) ;
2019-02-27 16:10:54 -08:00
assert . strictEqual ( typeof action , 'string' ) ;
assert . strictEqual ( typeof source , 'object' ) ;
assert . strictEqual ( typeof data , 'object' ) ;
2019-03-01 15:14:35 -08:00
switch ( action ) {
2019-03-25 14:02:23 -07:00
case eventlog . ACTION _APP _OOM :
2025-01-19 10:34:12 +01:00
return await oomEvent ( eventId , data . containerId , data . app , data . addonName , data . event ) ;
2019-03-25 14:02:23 -07:00
2024-12-11 20:44:46 +01:00
case eventlog . ACTION _APP _UP :
2025-01-19 10:34:12 +01:00
return await appUp ( eventId , data . app ) ;
2024-12-11 20:44:46 +01:00
case eventlog . ACTION _APP _DOWN :
2025-01-19 10:34:12 +01:00
return await appDown ( eventId , data . app ) ;
2024-12-11 20:44:46 +01:00
2019-05-07 12:04:43 +02:00
case eventlog . ACTION _APP _UPDATE _FINISH :
2021-09-30 09:50:30 -07:00
if ( source . username !== AuditSource . CRON . username ) return ; // updated by user
2021-07-13 13:29:42 -07:00
if ( data . errorMessage ) return ; // the update indicator will still appear, so no need to notify user
2025-01-19 10:34:12 +01:00
return await appUpdated ( eventId , data . app , data . fromManifest , data . toManifest ) ;
2019-05-07 12:04:43 +02:00
2019-03-04 14:50:56 -08:00
case eventlog . ACTION _CERTIFICATE _RENEWAL :
case eventlog . ACTION _CERTIFICATE _NEW :
2021-05-28 14:34:18 -07:00
if ( ! data . errorMessage ) return ;
2021-06-24 00:48:54 -07:00
if ( ! data . notAfter || ( data . notAfter - new Date ( ) >= ( 10 * 24 * 60 * 60 * 1000 ) ) ) return ; // more than 10 days left to expire
2025-01-19 10:34:12 +01:00
return await certificateRenewalError ( eventId , data . domain , data . errorMessage ) ;
2019-03-04 14:50:56 -08:00
2019-03-25 14:02:23 -07:00
case eventlog . ACTION _BACKUP _FINISH :
2021-05-28 14:34:18 -07:00
if ( ! data . errorMessage ) return ;
2021-09-30 09:50:30 -07:00
if ( source . username !== AuditSource . CRON . username && ! data . timedOut ) return ; // manual stop by user
2019-10-11 19:35:21 -07:00
2025-01-19 10:34:12 +01:00
return await backupFailed ( eventId , data . taskId , data . errorMessage ) ; // only notify for automated backups or timedout
2019-03-04 15:00:23 -08:00
2022-04-01 13:44:46 -07:00
case eventlog . ACTION _INSTALL _FINISH :
2025-01-19 10:34:12 +01:00
return await boxInstalled ( eventId , data . version ) ;
2022-04-01 13:44:46 -07:00
2019-08-03 13:59:11 -07:00
case eventlog . ACTION _UPDATE _FINISH :
2025-01-19 10:34:12 +01:00
if ( ! data . errorMessage ) return await boxUpdated ( eventId , data . oldVersion , data . newVersion ) ;
if ( data . timedOut ) return await boxUpdateError ( eventId , data . errorMessage ) ;
2021-05-28 14:34:18 -07:00
return ;
2019-08-03 13:59:11 -07:00
2019-03-25 14:02:23 -07:00
default :
2021-05-28 14:34:18 -07:00
return ;
2019-02-27 16:10:54 -08:00
}
}