From c589df31e036ffb95c3c29a9d213001431c5fe51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E9=A5=BC?= Date: Wed, 9 Aug 2023 06:14:24 +0000 Subject: [PATCH 001/112] Update preQueries.js Add logs first . because it has some error when something is done and it will write to logs but table logs is no exist now as Shinobi run at an empty db. --- libs/database/preQueries.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/database/preQueries.js b/libs/database/preQueries.js index 0726f896..c2e0beac 100644 --- a/libs/database/preQueries.js +++ b/libs/database/preQueries.js @@ -6,6 +6,16 @@ module.exports = function(s,config){ isMySQL, } = require('./utils.js')(s,config) s.preQueries = async function(){ + await createTable('Logs',[ + isMySQL ? {name: 'utf8', type: 'charset'} : null, + isMySQL ? {name: 'utf8_general_ci', type: 'collate'} : null, + {name: 'ke', length: 50, type: 'string'}, + {name: 'mid', length: 100, type: 'string'}, + {name: 'info', type: 'text'}, + {name: 'time', type: 'timestamp', defaultTo: currentTimestamp()}, + // KEY `logs_index` (`ke`,`mid`,`time`) + {name: ['ke', 'mid', 'time'], type: 'index', length: 'logs_index'}, + ]); await createTable('Users',[ isMySQL ? {name: 'utf8', type: 'charset'} : null, isMySQL ? {name: 'utf8_general_ci', type: 'collate'} : null, @@ -130,16 +140,6 @@ module.exports = function(s,config){ {name: 'size', type: 'bigint'}, {name: 'details', type: 'text'}, ]); - await createTable('Logs',[ - isMySQL ? {name: 'utf8', type: 'charset'} : null, - isMySQL ? {name: 'utf8_general_ci', type: 'collate'} : null, - {name: 'ke', length: 50, type: 'string'}, - {name: 'mid', length: 100, type: 'string'}, - {name: 'info', type: 'text'}, - {name: 'time', type: 'timestamp', defaultTo: currentTimestamp()}, - // KEY `logs_index` (`ke`,`mid`,`time`) - {name: ['ke', 'mid', 'time'], type: 'index', length: 'logs_index'}, - ]); await createTable('Monitors',[ isMySQL ? {name: 'utf8', type: 'charset'} : null, isMySQL ? {name: 'utf8_general_ci', type: 'collate'} : null, From 0d935c17786bec62ab9b3e56fadfa627da25c558 Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 14 Sep 2023 21:24:23 -0700 Subject: [PATCH 002/112] Fix Auto Port set for RTMP on startup --- definitions/base.js | 3 +-- libs/ffmpeg/possibleWarnings.js | 7 ++++--- libs/ffmpeg/utils.js | 13 ++++++++++++ libs/monitor.js | 13 +++++++++++- libs/monitor/utils.js | 36 ++++++++++++++++++++------------- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/definitions/base.js b/definitions/base.js index 80f6498b..136b50b1 100644 --- a/definitions/base.js +++ b/definitions/base.js @@ -748,8 +748,7 @@ module.exports = function(s,config,lang){ "name": "detail=stream_type", "field": lang["Stream Type"], "description": lang["fieldTextStreamType"], - "default": "mp4", - "example": "", + "default": "hls", "selector": "h_st", "fieldType": "select", "attribute": `triggerChange="#add_monitor [detail=stream_vcodec]" triggerChangeIgnore="b64,mjpeg,jpeg,gif"`, diff --git a/libs/ffmpeg/possibleWarnings.js b/libs/ffmpeg/possibleWarnings.js index 8f4097bc..d271743b 100644 --- a/libs/ffmpeg/possibleWarnings.js +++ b/libs/ffmpeg/possibleWarnings.js @@ -1,5 +1,6 @@ module.exports = (monitor,probeResult,config,lang) => { const primaryVideoStream = probeResult.video[0] + const noPortOr554 = !monitor.port || monitor.port === 554 return [ { isTrue: monitor.details.stream_vcodec === 'copy' && primaryVideoStream.codec === 'hevc', @@ -83,7 +84,7 @@ module.exports = (monitor,probeResult,config,lang) => { }, { isTrue: ( - !monitor.port && + noPortOr554 && monitor.protocol === 'rtmp' ), title: lang['Automatic Field Fill'], @@ -95,7 +96,7 @@ module.exports = (monitor,probeResult,config,lang) => { }, { isTrue: ( - !monitor.port && + noPortOr554 && monitor.protocol === 'http' ), title: lang['Automatic Field Fill'], @@ -107,7 +108,7 @@ module.exports = (monitor,probeResult,config,lang) => { }, { isTrue: ( - !monitor.port && + noPortOr554 && (monitor.protocol === 'rtmps' || monitor.protocol === 'https') ), diff --git a/libs/ffmpeg/utils.js b/libs/ffmpeg/utils.js index e20402ec..e678051b 100644 --- a/libs/ffmpeg/utils.js +++ b/libs/ffmpeg/utils.js @@ -367,6 +367,18 @@ Run "npm install ffbinaries" to get this static FFmpeg downloader.` } return response } + async function getWarningChangesForMonitor(monitorConfig){ + const probeResponse = await probeMonitor(monitorConfig,2000,true) + const probeStreams = getStreamInfoFromProbe(probeResponse.result) + const warnings = createWarningsForConfiguration(monitorConfig,probeStreams) + const configPartial = warnings.length > 0 ? buildMonitorConfigPartialFromWarnings(warnings) : {} + return { + configPartial, + warnings, + probeResponse, + probeStreams, + } + } return { ffprobe: runFFprobe, probeMonitor: probeMonitor, @@ -386,5 +398,6 @@ Run "npm install ffbinaries" to get this static FFmpeg downloader.` checkStaticBuilds: checkStaticBuilds, checkVersion: checkVersion, checkHwAccelMethods: checkHwAccelMethods, + getWarningChangesForMonitor, } } diff --git a/libs/monitor.js b/libs/monitor.js index 4a366722..95506de6 100644 --- a/libs/monitor.js +++ b/libs/monitor.js @@ -13,6 +13,8 @@ module.exports = function(s,config,lang){ } = require('./basic/utils.js')(process.cwd(),config) const { splitForFFMPEG, + applyPartialToConfiguration, + getWarningChangesForMonitor, } = require('./ffmpeg/utils.js')(s,config,lang) const { processKill, @@ -551,7 +553,6 @@ module.exports = function(s,config,lang){ return } form.mid = form.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'') - form = s.cleanMonitorObjectForDatabase(form) const selectResponse = await s.knexQueryPromise({ action: "select", columns: "*", @@ -570,6 +571,16 @@ module.exports = function(s,config,lang){ ke: form.ke, mon: form } + // auto correct + const { + configPartial, + warnings, + probeResponse, + probeStreams, + } = await getWarningChangesForMonitor(form) + applyPartialToConfiguration(form,configPartial) + form = s.cleanMonitorObjectForDatabase(form) + // if(monitorExists){ txData.new = false Object.keys(form).forEach(function(v){ diff --git a/libs/monitor/utils.js b/libs/monitor/utils.js index 5db663da..024124e5 100644 --- a/libs/monitor/utils.js +++ b/libs/monitor/utils.js @@ -10,11 +10,8 @@ const SoundDetection = require('shinobi-sound-detection') const streamViewerCountTimeouts = {} module.exports = (s,config,lang) => { const { - probeMonitor, - getStreamInfoFromProbe, applyPartialToConfiguration, - createWarningsForConfiguration, - buildMonitorConfigPartialFromWarnings, + getWarningChangesForMonitor, createPipeArray, splitForFFMPEG, sanitizedFfmpegCommand, @@ -40,6 +37,9 @@ module.exports = (s,config,lang) => { selectNodeForOperation, bindMonitorToChildNode } = require('../childNode/utils.js')(s,config,lang) + const { + asyncSetTimeout, + } = require('../basic/utils.js')(process.cwd(),config) const isMasterNode = ( ( config.childNodes.enabled === true && @@ -769,6 +769,7 @@ module.exports = (s,config,lang) => { code: 4, }); await s.camera('stop',e) + await asyncSetTimeout(2500) if(e.mode !== 'restart')await s.camera(`${e.mode}`,e); } function monitorAddViewer(e,cn){ @@ -898,7 +899,7 @@ module.exports = (s,config,lang) => { status: lang.Restarting, code: 4, }) - await launchMonitorProcesses(monitorConfig) + await monitorRestart(monitorConfig) s.userLog({ ke: groupKey, mid: monitorId, @@ -1353,6 +1354,7 @@ module.exports = (s,config,lang) => { // doFatalErrorCatch(e,d) // },15000) break; + case checkLog(d,'Could not find codec parameters'): case checkLog(d,'No route to host'): activeMonitor.timeoutToRestart = setTimeout(async () => { doFatalErrorCatch(e,d) @@ -1662,17 +1664,18 @@ module.exports = (s,config,lang) => { return; } if(config.probeMonitorOnStart === true){ - const probeResponse = await probeMonitor(monitorConfig,2000,true) - const probeStreams = getStreamInfoFromProbe(probeResponse.result) - activeMonitor.probeResult = probeStreams - const warnings = createWarningsForConfiguration(monitorConfig,probeStreams) - activeMonitor.warnings = warnings + const { + configPartial, + warnings, + probeResponse, + probeStreams, + } = await getWarningChangesForMonitor(monitorConfig) if(warnings.length > 0){ - const configPartial = buildMonitorConfigPartialFromWarnings(warnings) applyPartialToConfiguration(e,configPartial) applyPartialToConfiguration(activeMonitor,configPartial) applyPartialToConfiguration(s.group[groupKey].rawMonitorConfigurations[monitorId],configPartial) } + activeMonitor.warnings = warnings } activeMonitor.isStarted = true if(e.details && e.details.dir && e.details.dir !== ''){ @@ -1694,6 +1697,7 @@ module.exports = (s,config,lang) => { } try{ await launchMonitorProcesses(e) + resetStreamCheck(e) }catch(err){ console.error(err) } @@ -1748,9 +1752,13 @@ module.exports = (s,config,lang) => { } function isGroupBelowMaxMonitorCount(groupKey){ const theGroup = s.group[groupKey]; - const initData = theGroup.init; - const maxCamerasAllowed = parseInt(initData.max_camera) || false; - return (!maxCamerasAllowed || Object.keys(theGroup.activeMonitors).length <= parseInt(maxCamerasAllowed)) + try{ + const initData = theGroup.init; + const maxCamerasAllowed = parseInt(initData.max_camera) || false; + return (!maxCamerasAllowed || Object.keys(theGroup.activeMonitors).length <= parseInt(maxCamerasAllowed)) + }catch(err){ + return true + } } function getStreamDirectory(options){ const streamDir = s.dir.streams + options.ke + '/' + options.mid + '/' From f22d4d180053b24723960455f94eb1448f5cce47 Mon Sep 17 00:00:00 2001 From: Moe Date: Thu, 14 Sep 2023 21:26:20 -0700 Subject: [PATCH 003/112] undo some experiments --- libs/monitor/utils.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libs/monitor/utils.js b/libs/monitor/utils.js index 024124e5..00cd7ddf 100644 --- a/libs/monitor/utils.js +++ b/libs/monitor/utils.js @@ -37,9 +37,6 @@ module.exports = (s,config,lang) => { selectNodeForOperation, bindMonitorToChildNode } = require('../childNode/utils.js')(s,config,lang) - const { - asyncSetTimeout, - } = require('../basic/utils.js')(process.cwd(),config) const isMasterNode = ( ( config.childNodes.enabled === true && @@ -769,7 +766,6 @@ module.exports = (s,config,lang) => { code: 4, }); await s.camera('stop',e) - await asyncSetTimeout(2500) if(e.mode !== 'restart')await s.camera(`${e.mode}`,e); } function monitorAddViewer(e,cn){ @@ -899,7 +895,7 @@ module.exports = (s,config,lang) => { status: lang.Restarting, code: 4, }) - await monitorRestart(monitorConfig) + await launchMonitorProcesses(monitorConfig) s.userLog({ ke: groupKey, mid: monitorId, From dcd69e3c09fd20ad950313870f1349c2a2e9e6e8 Mon Sep 17 00:00:00 2001 From: Moe Date: Sat, 16 Sep 2023 07:53:20 -0700 Subject: [PATCH 004/112] Add "noDefaultRecordingSegmentFormatOptions" bool --- libs/ffmpeg/builders.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ffmpeg/builders.js b/libs/ffmpeg/builders.js index 727ee359..faa52386 100644 --- a/libs/ffmpeg/builders.js +++ b/libs/ffmpeg/builders.js @@ -548,7 +548,7 @@ module.exports = (s,config,lang) => { recordingFilters.push(`fps=${videoFps}`) } } - if(videoExtIsMp4){ + if(videoExtIsMp4 && !config.noDefaultRecordingSegmentFormatOptions){ customRecordingFlags.push(`-segment_format_options movflags=faststart`) } if(videoCodec === 'h264_vaapi'){ From cfa9c926db492a31c1fee4a88ac2e694003bf9f1 Mon Sep 17 00:00:00 2001 From: Moe Date: Sun, 17 Sep 2023 07:36:10 -0700 Subject: [PATCH 005/112] fix missing matrices array in getObjectTagsFromMatrices --- libs/events/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/events/utils.js b/libs/events/utils.js index 98e50cdb..22f5bee5 100644 --- a/libs/events/utils.js +++ b/libs/events/utils.js @@ -837,7 +837,7 @@ module.exports = (s,config,lang) => { if(d.details.reason === 'motion'){ return [getTagWithIcon(lang.Motion)] }else{ - const matrices = d.details.matrices + const matrices = d.details.matrices || [] return [...new Set(matrices.map(matrix => getTagWithIcon(matrix.tag)))]; } } From 26713bde3c56f86004d862b41446bda54e368a11 Mon Sep 17 00:00:00 2001 From: Moe Date: Sun, 17 Sep 2023 07:48:57 -0700 Subject: [PATCH 006/112] better patch for getObjectTagsFromMatrices --- libs/events/utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/events/utils.js b/libs/events/utils.js index 22f5bee5..f366fb8d 100644 --- a/libs/events/utils.js +++ b/libs/events/utils.js @@ -836,10 +836,11 @@ module.exports = (s,config,lang) => { function getObjectTagsFromMatrices(d){ if(d.details.reason === 'motion'){ return [getTagWithIcon(lang.Motion)] - }else{ - const matrices = d.details.matrices || [] + }else if(d.details.matrices){ + const matrices = d.details.matrices return [...new Set(matrices.map(matrix => getTagWithIcon(matrix.tag)))]; } + return [getTagWithIcon(d.details.reason)] } function getObjectTagNotifyText(d){ const monitorId = d.mid || d.id From 83fbd5f623d48e95a3cd6e790cd36fceddb6b147 Mon Sep 17 00:00:00 2001 From: Moe Date: Mon, 18 Sep 2023 12:01:24 -0700 Subject: [PATCH 007/112] add onCloudVideoUploaded action handler to backblaze --- libs/extenders.js | 1 + libs/uploaders/backblazeB2.js | 52 +++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/libs/extenders.js b/libs/extenders.js index 61b66361..51535c93 100644 --- a/libs/extenders.js +++ b/libs/extenders.js @@ -62,6 +62,7 @@ module.exports = function(s,config){ createExtension(`onEventBasedRecordingComplete`) createExtension(`onEventBasedRecordingStart`) createExtension(`onBeforeInsertCompletedVideo`) + createExtension(`onCloudVideoUploaded`) /////// TIMELAPSE //////// createExtension(`onInsertTimelapseFrame`) } diff --git a/libs/uploaders/backblazeB2.js b/libs/uploaders/backblazeB2.js index c28b0d90..b06294fb 100644 --- a/libs/uploaders/backblazeB2.js +++ b/libs/uploaders/backblazeB2.js @@ -3,18 +3,19 @@ const { Readable } = require('stream'); const B2 = require('backblaze-b2') module.exports = function(s,config,lang){ //Backblaze B2 + var serviceProvider = 'b2' var beforeAccountSaveForBackblazeB2 = function(d){ //d = save event d.formDetails.b2_use_global=d.d.b2_use_global d.formDetails.use_bb_b2=d.d.use_bb_b2 } var cloudDiskUseStartupForBackblazeB2 = function(group,userDetails){ - group.cloudDiskUse['b2'].name = 'Backblaze B2' - group.cloudDiskUse['b2'].sizeLimitCheck = (userDetails.use_bb_b2_size_limit === '1') + group.cloudDiskUse[serviceProvider].name = 'Backblaze B2' + group.cloudDiskUse[serviceProvider].sizeLimitCheck = (userDetails.use_bb_b2_size_limit === '1') if(!userDetails.bb_b2_size_limit || userDetails.bb_b2_size_limit === ''){ - group.cloudDiskUse['b2'].sizeLimit = 10000 + group.cloudDiskUse[serviceProvider].sizeLimit = 10000 }else{ - group.cloudDiskUse['b2'].sizeLimit = parseFloat(userDetails.bb_b2_size_limit) + group.cloudDiskUse[serviceProvider].sizeLimit = parseFloat(userDetails.bb_b2_size_limit) } } var loadBackblazeB2ForUser = function(e){ @@ -83,7 +84,7 @@ module.exports = function(s,config,lang){ }catch(err){ var videoDetails = video.details } - if(video.type !== 'b2'){ + if(video.type !== serviceProvider){ callback() return } @@ -128,30 +129,35 @@ module.exports = function(s,config,lang){ }).then(function(resp){ const uploadResponse = resp.data if(theGroup.init.bb_b2_log === '1' && uploadResponse.fileId){ + const insertDetails = { + bucketId : uploadResponse.bucketId, + fileId : uploadResponse.fileId, + fileName : uploadResponse.fileName + } + const insertQuery = { + mid: e.mid, + ke: e.ke, + time: k.startTime, + status: 1, + type : serviceProvider, + details: insertDetails, + size: k.filesize, + end: k.endTime, + href: '' + } s.knexQuery({ action: "insert", table: "Cloud Videos", - insert: { - mid: e.mid, - ke: e.ke, - time: k.startTime, - status: 1, - type : 'b2', - details: s.s({ - bucketId : uploadResponse.bucketId, - fileId : uploadResponse.fileId, - fileName : uploadResponse.fileName - }), - size: k.filesize, - end: k.endTime, - href: '' - } + insert: Object.assign({},insertQuery,{details: s.s(insertDetails)}) }) s.setCloudDiskUsedForGroup(e.ke,{ amount : k.filesizeMB, - storageType : 'b2' + storageType : serviceProvider + }) + s.purgeCloudDiskForGroup(e,serviceProvider) + s.onCloudVideoUploadedExtensions.forEach((extender) => { + extender(insertQuery) }) - s.purgeCloudDiskForGroup(e,'b2') } }).catch(backblazeErr) }) @@ -183,7 +189,7 @@ module.exports = function(s,config,lang){ } //backblaze b2 s.addCloudUploader({ - name: 'b2', + name: serviceProvider, loadGroupAppExtender: loadBackblazeB2ForUser, unloadGroupAppExtender: unloadBackblazeB2ForUser, insertCompletedVideoExtender: uploadVideoToBackblazeB2, From 794fbba2a39107e8a822ec83b31987d08bcd8995 Mon Sep 17 00:00:00 2001 From: Moe Date: Tue, 19 Sep 2023 20:38:08 -0700 Subject: [PATCH 008/112] Add more S3 Region locations based on #496 --- libs/uploaders/amazonS3.js | 190 +++++++++++++++++++++-------------- libs/uploaders/s3based.js | 196 ++++++++++++++++++++++--------------- 2 files changed, 235 insertions(+), 151 deletions(-) diff --git a/libs/uploaders/amazonS3.js b/libs/uploaders/amazonS3.js index c9f02149..95dd6497 100644 --- a/libs/uploaders/amazonS3.js +++ b/libs/uploaders/amazonS3.js @@ -315,79 +315,123 @@ module.exports = function(s,config,lang){ "default": "", "example": "", "possible": [ - { - "name": "US West (N. California)", - "value": "us-west-1" - }, - { - "name": "US West (Oregon)", - "value": "us-west-2" - }, - { - "name": "US East (Ohio)", - "value": "us-east-2" - }, - { - "name": "US East (N. Virginia)", - "value": "us-east-1" - }, - { - "name": "Asia Pacific (Mumbai)", - "value": "ap-south-1" - }, - { - "name": "Asia Pacific (Seoul)", - "value": "ap-northeast-2" - }, - { - "name": "Asia Pacific (Osaka-Local)**", - "value": "ap-northeast-3" - }, - { - "name": "Asia Pacific (Singapore)", - "value": "ap-southeast-1" - }, - { - "name": "Asia Pacific (Sydney)", - "value": "ap-southeast-2" - }, - { - "name": "Asia Pacific (Tokyo)", - "value": "ap-northeast-1" - }, - { - "name": "Canada (Central)", - "value": "ca-central-1" - }, - { - "name": "China (Beijing)", - "value": "cn-north-1" - }, - { - "name": "China (Ningxia)", - "value": "cn-northwest-1" - }, - { - "name": "EU (Frankfurt)", - "value": "eu-central-1" - }, - { - "name": "EU (Ireland)", - "value": "eu-west-1" - }, - { - "name": "EU (London)", - "value": "eu-west-2" - }, - { - "name": "EU (Paris)", - "value": "eu-west-3" - }, - { - "name": "South America (São Paulo)", - "value": "sa-east-1" - } - ] + { + "name": "US West (N. California)", + "value": "us-west-1" + }, + { + "name": "US West (Oregon)", + "value": "us-west-2" + }, + { + "name": "US East (Ohio)", + "value": "us-east-2" + }, + { + "name": "US East (N. Virginia)", + "value": "us-east-1" + }, + { + "name": "Canada (Central)", + "value": "ca-central-1" + }, + { + "name": "South America (São Paulo)", + "value": "sa-east-1" + }, + { + "name": "EU (Frankfurt)", + "value": "eu-central-1" + }, + { + "name": "EU (Ireland)", + "value": "eu-west-1" + }, + { + "name": "EU (London)", + "value": "eu-west-2" + }, + { + "name": "EU (Paris)", + "value": "eu-west-3" + }, + { + "name": "Europe (Milan)", + "value": "eu-south-1" + }, + { + "name": "Europe (Spain)", + "value": "eu-south-2" + }, + { + "name": "Europe (Zurich)", + "value": "eu-central-2" + }, + { + "name": "Asia Pacific (Mumbai)", + "value": "ap-south-1" + }, + { + "name": "Asia Pacific (Seoul)", + "value": "ap-northeast-2" + }, + { + "name": "Asia Pacific (Osaka-Local)**", + "value": "ap-northeast-3" + }, + { + "name": "Asia Pacific (Singapore)", + "value": "ap-southeast-1" + }, + { + "name": "Asia Pacific (Sydney)", + "value": "ap-southeast-2" + }, + { + "name": "Asia Pacific (Tokyo)", + "value": "ap-northeast-1" + }, + { + "name": "Asia Pacific (Hong Kong)", + "value": "ap-east-1" + }, + { + "name": "Asia Pacific (Hyderabad)", + "value": "ap-south-2" + }, + { + "name": "Asia Pacific (Jakarta)", + "value": "ap-southeast-3" + }, + { + "name": "Asia Pacific (Melbourne)", + "value": "ap-southeast-4" + }, + { + "name": "China (Beijing)", + "value": "cn-north-1" + }, + { + "name": "China (Ningxia)", + "value": "cn-northwest-1" + }, + { + "name": "Africa (Cape Town)", + "value": "af-south-1" + }, + { + "name": "Middle East (Bahrain)", + "value": "me-south-1" + }, + { + "name": "Middle East (UAE)", + "value": "me-central-1" + }, + { + "name": "il-central-1", + "value": "il-central-1" + } + ] }, { "hidden": true, diff --git a/libs/uploaders/s3based.js b/libs/uploaders/s3based.js index 34c053be..5ac2c52d 100644 --- a/libs/uploaders/s3based.js +++ b/libs/uploaders/s3based.js @@ -324,84 +324,124 @@ module.exports = function(s,config,lang){ "description": "", "default": "", "example": "", - "possible": [ - { - "name": lang['No Region'], - "value": "" - }, - { - "name": "US West 1", - "value": "us-west-1" - }, - { - "name": "US West 2", - "value": "us-west-2" - }, - { - "name": "US East 1", - "value": "us-east-1" - }, - { - "name": "US East 2", - "value": "us-east-2" - }, - { - "name": "Asia Pacific 1", - "value": "ap-south-1" - }, - { - "name": "Asia Pacific 2", - "value": "ap-northeast-2" - }, - { - "name": "Asia Pacific 3", - "value": "ap-northeast-3" - }, - { - "name": "Asia Pacific 4", - "value": "ap-southeast-1" - }, - { - "name": "Asia Pacific 5", - "value": "ap-southeast-2" - }, - { - "name": "Asia Pacific 6", - "value": "ap-northeast-1" - }, - { - "name": "Canada 1", - "value": "ca-central-1" - }, - { - "name": "China 1", - "value": "cn-north-1" - }, - { - "name": "China 1", - "value": "cn-northwest-1" - }, - { - "name": "EU 1", - "value": "eu-central-1" - }, - { - "name": "EU 2", - "value": "eu-west-1" - }, - { - "name": "EU 3", - "value": "eu-west-2" - }, - { - "name": "EU 4", - "value": "eu-west-3" - }, - { - "name": "South America 1", - "value": "sa-east-1" - } - ] + "possible": [ + { + "name": "US West (N. California)", + "value": "us-west-1" + }, + { + "name": "US West (Oregon)", + "value": "us-west-2" + }, + { + "name": "US East (Ohio)", + "value": "us-east-2" + }, + { + "name": "US East (N. Virginia)", + "value": "us-east-1" + }, + { + "name": "Canada (Central)", + "value": "ca-central-1" + }, + { + "name": "South America (São Paulo)", + "value": "sa-east-1" + }, + { + "name": "EU (Frankfurt)", + "value": "eu-central-1" + }, + { + "name": "EU (Ireland)", + "value": "eu-west-1" + }, + { + "name": "EU (London)", + "value": "eu-west-2" + }, + { + "name": "EU (Paris)", + "value": "eu-west-3" + }, + { + "name": "Europe (Milan)", + "value": "eu-south-1" + }, + { + "name": "Europe (Spain)", + "value": "eu-south-2" + }, + { + "name": "Europe (Zurich)", + "value": "eu-central-2" + }, + { + "name": "Asia Pacific (Mumbai)", + "value": "ap-south-1" + }, + { + "name": "Asia Pacific (Seoul)", + "value": "ap-northeast-2" + }, + { + "name": "Asia Pacific (Osaka-Local)**", + "value": "ap-northeast-3" + }, + { + "name": "Asia Pacific (Singapore)", + "value": "ap-southeast-1" + }, + { + "name": "Asia Pacific (Sydney)", + "value": "ap-southeast-2" + }, + { + "name": "Asia Pacific (Tokyo)", + "value": "ap-northeast-1" + }, + { + "name": "Asia Pacific (Hong Kong)", + "value": "ap-east-1" + }, + { + "name": "Asia Pacific (Hyderabad)", + "value": "ap-south-2" + }, + { + "name": "Asia Pacific (Jakarta)", + "value": "ap-southeast-3" + }, + { + "name": "Asia Pacific (Melbourne)", + "value": "ap-southeast-4" + }, + { + "name": "China (Beijing)", + "value": "cn-north-1" + }, + { + "name": "China (Ningxia)", + "value": "cn-northwest-1" + }, + { + "name": "Africa (Cape Town)", + "value": "af-south-1" + }, + { + "name": "Middle East (Bahrain)", + "value": "me-south-1" + }, + { + "name": "Middle East (UAE)", + "value": "me-central-1" + }, + { + "name": "il-central-1", + "value": "il-central-1" + } + ] }, { "hidden": true, From 5da361c6feaf668ec624876585669a812f0f2f6e Mon Sep 17 00:00:00 2001 From: Moe Date: Tue, 19 Sep 2023 20:39:10 -0700 Subject: [PATCH 009/112] re-add "No Region" to s3based --- libs/uploaders/s3based.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/uploaders/s3based.js b/libs/uploaders/s3based.js index 5ac2c52d..7894e08c 100644 --- a/libs/uploaders/s3based.js +++ b/libs/uploaders/s3based.js @@ -325,6 +325,10 @@ module.exports = function(s,config,lang){ "default": "", "example": "", "possible": [ + { + "name": lang['No Region'], + "value": "" + }, { "name": "US West (N. California)", "value": "us-west-1" From 38f5522627d9b1385b044828b0fd5e794b99d1a4 Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 20 Sep 2023 11:31:50 -0700 Subject: [PATCH 010/112] "Video Access" and "User Logged Out" user logging --- languages/en_CA.json | 2 ++ libs/extenders.js | 2 ++ libs/user.js | 1 + libs/user/logger.js | 31 +++++++++++++++++++++++++++++++ libs/webServerPaths.js | 25 +++++++++++++++++++------ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 libs/user/logger.js diff --git a/languages/en_CA.json b/languages/en_CA.json index f4b4e075..e1923e31 100644 --- a/languages/en_CA.json +++ b/languages/en_CA.json @@ -145,6 +145,7 @@ "Input Settings": "Input Settings", "Connection": "Connection", "Video Set": "Video Set", + "Video Accessed": "Video Accessed", "notEnoughFramesText1": "Not Enough Frames for compilation.", "Allow API Trigger": "Allow API Trigger", "When Detector is Off": "When Detector is Off", @@ -480,6 +481,7 @@ "Database": "Database", "Database Not Found": "Database Not Found", "User Not Found": "User Not Found", + "User Logged Out": "User Logged Out", "Not Found": "Not Found", "Save Links to Database": "Save Links to Database", "Uploaders": "Uploaders", diff --git a/libs/extenders.js b/libs/extenders.js index 51535c93..7cf3595d 100644 --- a/libs/extenders.js +++ b/libs/extenders.js @@ -25,6 +25,8 @@ module.exports = function(s,config){ createExtension(`beforeAccountSave`) createExtension(`onTwoFactorAuthCodeNotification`) createExtension(`onStalePurgeLock`) + createExtension(`onVideoAccess`) + createExtension(`onLogout`) ////// EVENTS ////// createExtension(`onEventTrigger`) createExtension(`onEventTriggerBeforeFilter`) diff --git a/libs/user.js b/libs/user.js index ea580253..3187c250 100644 --- a/libs/user.js +++ b/libs/user.js @@ -18,6 +18,7 @@ module.exports = function(s,config,lang){ deleteCloudTimelapseFrames, resetAllStorageCounters, } = require("./user/utils.js")(s,config,lang); + require("./user/logger.js")(s,config,lang) let purgeDiskGroup = () => {} const runQuery = async.queue(function(groupKey, callback) { purgeDiskGroup(groupKey,callback) diff --git a/libs/user/logger.js b/libs/user/logger.js new file mode 100644 index 00000000..f26c25a6 --- /dev/null +++ b/libs/user/logger.js @@ -0,0 +1,31 @@ +module.exports = function(s,config,lang){ + s.onVideoAccess((videoRow,user,groupKey,monitorId,ip) => { + s.userLog({ + ke: groupKey, + mid: '$USER', + },{ + type: lang['Video Accessed'], + msg: { + user: { + mail: user.mail, + uid: user.uid, + ip, + }, + video: videoRow + } + }) + }) + s.onLogout((user,groupKey,userId,ip) => { + s.userLog({ + ke: groupKey, + mid: '$USER', + },{ + type: lang['User Logged Out'], + msg: { + mail: user.mail, + uid: user.uid, + ip, + } + }) + }) +} diff --git a/libs/webServerPaths.js b/libs/webServerPaths.js index 104fa3b3..25db79b2 100644 --- a/libs/webServerPaths.js +++ b/libs/webServerPaths.js @@ -107,9 +107,18 @@ module.exports = function(s,config,lang,app,io){ * API : Logout */ app.get(config.webPaths.apiPrefix+':auth/logout/:ke/:id', function (req,res){ - if(s.group[req.params.ke] && s.group[req.params.ke].users[req.params.auth] && s.group[req.params.ke].users[req.params.auth].details){ - delete(s.api[req.params.auth]); - delete(s.group[req.params.ke].users[req.params.auth]); + const groupKey = req.params.ke + const userId = req.params.id + const authToken = req.params.auth + const user = s.group[groupKey] && s.group[groupKey].users[authToken] && s.group[groupKey].users[authToken].details ? s.group[groupKey].users[authToken] : null; + if(user){ + const clientIp = s.getClientIp(req) + const user = s.group[groupKey].users[authToken] + s.onLogoutExtensions.forEach((extender) => { + extender(user,groupKey,userId,clientIp) + }); + delete(s.api[authToken]); + delete(s.group[groupKey].users[authToken]); s.knexQuery({ action: "update", table: "Users", @@ -117,9 +126,9 @@ module.exports = function(s,config,lang,app,io){ auth: '', }, where: [ - ['auth','=',req.params.auth], - ['ke','=',req.params.ke], - ['uid','=',req.params.id], + ['auth','=',authToken], + ['ke','=',groupKey], + ['uid','=',userId], ] }) res.end(s.prettyPrint({ok:true,msg:'You have been logged out, session key is now inactive.'})) @@ -1454,6 +1463,10 @@ module.exports = function(s,config,lang,app,io){ }else{ s.streamMp4FileOverHttp(filePath,req,res,!!req.query.pureStream) } + const clientIp = s.getClientIp(req) + s.onVideoAccessExtensions.forEach((extender) => { + extender(videoRow,user,groupKey,monitorId,clientIp) + }) }else{ s.closeJsonResponse(res,{ ok: false, From a70a4b00bf8279520758709404e2d59a972305ac Mon Sep 17 00:00:00 2001 From: Moe Date: Wed, 20 Sep 2023 11:32:54 -0700 Subject: [PATCH 011/112] better tree draw Log items in log page --- web/assets/css/dashboard.css | 5 +++++ web/assets/js/bs5.dashboard-base.js | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/web/assets/css/dashboard.css b/web/assets/css/dashboard.css index e007b649..7a61b7fd 100644 --- a/web/assets/css/dashboard.css +++ b/web/assets/css/dashboard.css @@ -431,3 +431,8 @@ ul.squeeze { flex-direction: column; height: 100vh; } + +.log-item .msg-tree > ul { + list-style: none; + padding-left: 0; +} diff --git a/web/assets/js/bs5.dashboard-base.js b/web/assets/js/bs5.dashboard-base.js index 0edb4b92..a8d7cc1c 100644 --- a/web/assets/js/bs5.dashboard-base.js +++ b/web/assets/js/bs5.dashboard-base.js @@ -327,11 +327,13 @@ function compileConnectUrl(options){ function jsonToHtmlBlock(target){ var html = '' if(target instanceof Object){ + var html = '
    ' $.each(target,function(key,value){ - html += `
    - ${key} : ${jsonToHtmlBlock(value)} -
    ` + html += ` +
  • ${key} : ${jsonToHtmlBlock(value)}
  • + ` }) + html += '
' }else{ html += `${target}` } @@ -836,7 +838,7 @@ function buildLogRow(v){ ${humanMonitorName}${v.info && v.info.type ? v.info.type : v.mid}
-
${jsonToHtmlBlock(v.info.msg)}
+
${jsonToHtmlBlock(v.info.msg)}
-
${jsonToHtmlBlock(v.info.msg)}
+
${jsonToHtmlBlock(v.info.msg)}