2018-09-28 05:37:08 +00:00
var express = require ( 'express' ) ;
var fs = require ( 'fs' ) ;
var bodyParser = require ( 'body-parser' ) ;
var os = require ( 'os' ) ;
var moment = require ( 'moment' ) ;
var request = require ( 'request' ) ;
var execSync = require ( 'child_process' ) . execSync ;
var exec = require ( 'child_process' ) . exec ;
var spawn = require ( 'child_process' ) . spawn ;
var httpProxy = require ( 'http-proxy' ) ;
2019-01-26 20:21:55 +00:00
var onvif = require ( 'node-onvif' ) ;
2018-09-28 05:37:08 +00:00
var proxy = httpProxy . createProxyServer ( { } )
var ejs = require ( 'ejs' ) ;
2019-11-03 15:59:18 +00:00
var fileupload = require ( "express-fileupload" ) ;
2018-11-11 03:59:02 +00:00
module . exports = function ( s , config , lang , app , io ) {
2018-09-28 20:26:24 +00:00
if ( config . productType === 'Pro' ) {
var LdapAuth = require ( 'ldapauth-fork' ) ;
}
2018-11-06 04:27:19 +00:00
s . renderPage = function ( req , res , paths , passables , callback ) {
passables . window = { }
2019-04-06 05:27:22 +00:00
passables . data = req . params
2018-11-06 04:27:19 +00:00
passables . originalURL = s . getOriginalUrl ( req )
2019-04-06 05:27:22 +00:00
passables . baseUrl = req . protocol + '://' + req . hostname
2019-04-03 03:47:03 +00:00
passables . config = s . getConfigWithBranding ( req . hostname )
2018-11-06 04:27:19 +00:00
res . render ( paths , passables , callback )
2018-09-28 05:37:08 +00:00
}
2018-09-29 15:00:51 +00:00
//child node proxy check
//params = parameters
//cb = callback
//res = response, only needed for express (http server)
//request = request, only needed for express (http server)
s . checkChildProxy = function ( params , cb , res , req ) {
2019-07-08 03:39:41 +00:00
if ( s . group [ params . ke ] && s . group [ params . ke ] . activeMonitors [ params . id ] && s . group [ params . ke ] . activeMonitors [ params . id ] . childNode ) {
var url = 'http://' + s . group [ params . ke ] . activeMonitors [ params . id ] . childNode // + req.originalUrl
2018-09-29 15:00:51 +00:00
proxy . web ( req , res , { target : url } )
} else {
cb ( )
}
}
2018-11-02 23:44:53 +00:00
s . closeJsonResponse = function ( res , endData ) {
res . setHeader ( 'Content-Type' , 'application/json' )
res . end ( s . prettyPrint ( endData ) )
}
2018-10-05 21:19:48 +00:00
//get post data
2018-10-24 23:41:02 +00:00
s . getPostData = function ( req , target , parseJSON ) {
if ( ! target ) target = 'data'
if ( ! parseJSON ) parseJSON = true
2018-10-05 21:19:48 +00:00
var postData = false
2018-10-24 23:41:02 +00:00
if ( req . query && req . query [ target ] ) {
postData = req . query [ target ]
} else {
postData = req . body [ target ]
}
if ( parseJSON === true ) {
postData = s . parseJSON ( postData )
2018-10-05 21:19:48 +00:00
}
return postData
}
2018-10-08 06:01:27 +00:00
//get client ip address
s . getClientIp = function ( req ) {
return req . headers [ 'cf-connecting-ip' ] || req . headers [ "CF-Connecting-IP" ] || req . headers [ "'x-forwarded-for" ] || req . connection . remoteAddress ;
}
2018-09-28 05:37:08 +00:00
////Pages
app . enable ( 'trust proxy' ) ;
2018-11-06 04:27:19 +00:00
if ( config . webPaths . home !== '/' ) {
app . use ( '/libs' , express . static ( s . mainDirectory + '/web/libs' ) )
}
app . use ( s . checkCorrectPathEnding ( config . webPaths . home ) + 'libs' , express . static ( s . mainDirectory + '/web/libs' ) )
app . use ( s . checkCorrectPathEnding ( config . webPaths . admin ) + 'libs' , express . static ( s . mainDirectory + '/web/libs' ) )
app . use ( s . checkCorrectPathEnding ( config . webPaths . super ) + 'libs' , express . static ( s . mainDirectory + '/web/libs' ) )
2018-09-28 05:37:08 +00:00
app . use ( bodyParser . json ( ) ) ;
app . use ( bodyParser . urlencoded ( { extended : true } ) ) ;
2019-02-20 03:14:11 +00:00
app . use ( function ( req , res , next ) {
2020-01-15 21:47:59 +00:00
res . header ( "Access-Control-Allow-Origin" , '*' ) ;
2019-02-20 03:14:11 +00:00
next ( )
} )
2018-09-29 02:02:53 +00:00
app . set ( 'views' , s . mainDirectory + '/web' ) ;
2018-09-28 05:37:08 +00:00
app . set ( 'view engine' , 'ejs' ) ;
//add template handler
2018-11-11 03:59:02 +00:00
if ( config . renderPaths . handler !== undefined ) { require ( s . mainDirectory + '/web/' + config . renderPaths . handler + '.js' ) . addHandlers ( s , app , io , config ) }
2018-09-28 05:37:08 +00:00
2018-10-06 16:46:48 +00:00
/ * *
* API : Logout
* /
2018-09-28 05:37:08 +00:00
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 ] ) {
delete ( s . api [ req . params . auth ] ) ;
delete ( s . group [ req . params . ke ] . users [ req . params . auth ] ) ;
s . sqlQuery ( "UPDATE Users SET auth=? WHERE auth=? AND ke=? AND uid=?" , [ '' , req . params . auth , req . params . ke , req . params . id ] )
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : true , msg : 'You have been logged out, session key is now inactive.' } ) )
2018-09-28 05:37:08 +00:00
} else {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : false , msg : 'This group key does not exist or this user is not logged in.' } ) )
2018-09-28 05:37:08 +00:00
}
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* Page : Login Screen
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . home , function ( req , res ) {
2019-04-06 05:27:22 +00:00
s . renderPage ( req , res , config . renderPaths . index , { lang : lang , config : s . getConfigWithBranding ( req . hostname ) , screen : 'dashboard' } )
2018-09-28 05:37:08 +00:00
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* Page : Administrator Login Screen
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . admin , function ( req , res ) {
2019-04-06 05:27:22 +00:00
s . renderPage ( req , res , config . renderPaths . index , { lang : lang , config : s . getConfigWithBranding ( req . hostname ) , screen : 'admin' } )
2018-09-28 05:37:08 +00:00
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* Page : Superuser Login Screen
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . super , function ( req , res ) {
2019-07-31 00:05:00 +00:00
s . renderPage ( req , res , config . renderPaths . index , {
lang : lang ,
config : s . getConfigWithBranding ( req . hostname ) ,
screen : 'super'
} )
2018-09-28 05:37:08 +00:00
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get User Info
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/userInfo/:ke' , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
req . ret . ok = true
req . ret . user = user
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
} , res , req ) ;
} )
//login function
s . deleteFactorAuth = function ( r ) {
delete ( s . factorAuth [ r . ke ] [ r . uid ] )
if ( Object . keys ( s . factorAuth [ r . ke ] ) . length === 0 ) {
delete ( s . factorAuth [ r . ke ] )
}
}
2018-10-06 16:46:48 +00:00
/ * *
* API : Login handler . Dashboard , Streamer , Dashcam Administrator , Superuser
* /
2018-11-06 04:27:19 +00:00
app . post ( [
config . webPaths . home ,
config . webPaths . admin ,
config . webPaths . super ,
s . checkCorrectPathEnding ( config . webPaths . home ) + ':screen' ,
s . checkCorrectPathEnding ( config . webPaths . admin ) + ':screen' ,
s . checkCorrectPathEnding ( config . webPaths . super ) + ':screen' ,
] , function ( req , res ) {
2018-10-08 06:01:27 +00:00
req . ip = s . getClientIp ( req )
2018-11-06 18:09:38 +00:00
var screenChooser = function ( screen ) {
var search = function ( screen ) {
if ( req . url . indexOf ( screen ) > - 1 ) {
return true
}
return false
}
switch ( true ) {
case search ( config . webPaths . admin ) :
return 'admin'
break ;
case search ( config . webPaths . super ) :
return 'super'
break ;
default :
return 'dashboard'
break ;
}
}
2018-09-28 05:37:08 +00:00
// brute check
if ( s . failedLoginAttempts [ req . body . mail ] && s . failedLoginAttempts [ req . body . mail ] . failCount >= 5 ) {
if ( req . query . json == 'true' ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : false } ) )
2018-09-28 05:37:08 +00:00
} else {
2018-11-06 04:27:19 +00:00
s . renderPage ( req , res , config . renderPaths . index , {
2018-11-06 18:09:38 +00:00
failedLogin : true ,
message : lang . failedLoginText1 ,
2018-12-12 23:53:49 +00:00
lang : s . copySystemDefaultLanguage ( ) ,
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2018-11-06 18:09:38 +00:00
screen : screenChooser ( req . params . screen )
2018-10-06 02:52:02 +00:00
} )
2018-09-28 05:37:08 +00:00
}
return false
}
//
2018-10-06 02:52:02 +00:00
renderPage = function ( focus , data ) {
2018-09-28 05:37:08 +00:00
if ( s . failedLoginAttempts [ req . body . mail ] ) {
clearTimeout ( s . failedLoginAttempts [ req . body . mail ] . timeout )
delete ( s . failedLoginAttempts [ req . body . mail ] )
}
if ( req . query . json == 'true' ) {
delete ( data . config )
data . ok = true ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( data ) )
2018-09-28 05:37:08 +00:00
} else {
data . screen = req . params . screen
2019-04-06 05:27:22 +00:00
s . renderPage ( req , res , focus , data )
2018-09-28 05:37:08 +00:00
}
}
2018-10-06 02:52:02 +00:00
failedAuthentication = function ( board ) {
2018-09-28 05:37:08 +00:00
// brute protector
if ( ! s . failedLoginAttempts [ req . body . mail ] ) {
s . failedLoginAttempts [ req . body . mail ] = {
failCount : 0 ,
ips : { }
}
}
++ s . failedLoginAttempts [ req . body . mail ] . failCount
if ( ! s . failedLoginAttempts [ req . body . mail ] . ips [ req . ip ] ) {
s . failedLoginAttempts [ req . body . mail ] . ips [ req . ip ] = 0
}
++ s . failedLoginAttempts [ req . body . mail ] . ips [ req . ip ]
clearTimeout ( s . failedLoginAttempts [ req . body . mail ] . timeout )
s . failedLoginAttempts [ req . body . mail ] . timeout = setTimeout ( function ( ) {
delete ( s . failedLoginAttempts [ req . body . mail ] )
} , 1000 * 60 * 15 )
// check if JSON
2018-10-02 00:21:48 +00:00
if ( req . query . json === 'true' ) {
2018-10-06 02:52:02 +00:00
res . setHeader ( 'Content-Type' , 'application/json' )
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : false } ) )
2018-09-28 05:37:08 +00:00
} else {
2018-11-06 04:27:19 +00:00
s . renderPage ( req , res , config . renderPaths . index , {
2018-11-06 18:09:38 +00:00
failedLogin : true ,
message : lang . failedLoginText2 ,
2018-12-12 23:53:49 +00:00
lang : s . copySystemDefaultLanguage ( ) ,
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2018-11-06 18:09:38 +00:00
screen : screenChooser ( req . params . screen )
2018-10-06 02:52:02 +00:00
} )
}
var logTo = {
ke : '$' ,
mid : '$USER'
}
var logData = {
type : lang [ 'Authentication Failed' ] ,
msg : {
for : board ,
mail : req . body . mail ,
ip : req . ip
}
2018-09-28 05:37:08 +00:00
}
if ( board === 'super' ) {
2018-10-07 18:45:38 +00:00
s . userLog ( logTo , logData )
2018-09-28 05:37:08 +00:00
} else {
s . sqlQuery ( 'SELECT ke,uid,details FROM Users WHERE mail=?' , [ req . body . mail ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
2018-10-06 02:52:02 +00:00
r = r [ 0 ]
2018-09-28 05:37:08 +00:00
r . details = JSON . parse ( r . details ) ;
r . lang = s . getLanguageFile ( r . details . lang )
2018-10-06 02:52:02 +00:00
logData . id = r . uid
logData . type = r . lang [ 'Authentication Failed' ]
logTo . ke = r . ke
2018-09-28 05:37:08 +00:00
}
2018-10-07 18:45:38 +00:00
s . userLog ( logTo , logData )
2018-09-28 05:37:08 +00:00
} )
}
}
2018-10-06 02:52:02 +00:00
checkRoute = function ( r ) {
2018-09-28 05:37:08 +00:00
switch ( req . body . function ) {
case 'cam' :
s . sqlQuery ( 'SELECT * FROM Monitors WHERE ke=? AND type=?' , [ r . ke , "dashcam" ] , function ( err , rr ) {
req . resp . mons = rr ;
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . dashcam , {
2019-04-03 03:47:03 +00:00
// config: s.getConfigWithBranding(req.hostname),
2018-10-06 02:52:02 +00:00
$user : req . resp ,
lang : r . lang ,
2019-01-24 06:15:17 +00:00
define : s . getDefinitonFile ( r . details . lang ) ,
customAutoLoad : s . customAutoLoadTree
2018-10-06 02:52:02 +00:00
} )
2018-09-28 05:37:08 +00:00
} )
break ;
case 'streamer' :
s . sqlQuery ( 'SELECT * FROM Monitors WHERE ke=? AND type=?' , [ r . ke , "socket" ] , function ( err , rr ) {
req . resp . mons = rr ;
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . streamer , {
2019-04-03 03:47:03 +00:00
// config: s.getConfigWithBranding(req.hostname),
2018-10-06 02:52:02 +00:00
$user : req . resp ,
lang : r . lang ,
2019-01-24 06:15:17 +00:00
define : s . getDefinitonFile ( r . details . lang ) ,
customAutoLoad : s . customAutoLoadTree
2018-10-06 02:52:02 +00:00
} )
2018-09-28 05:37:08 +00:00
} )
break ;
case 'admin' :
if ( ! r . details . sub ) {
s . sqlQuery ( 'SELECT uid,mail,details FROM Users WHERE ke=? AND details LIKE \'%"sub"%\'' , [ r . ke ] , function ( err , rr ) {
s . sqlQuery ( 'SELECT * FROM Monitors WHERE ke=?' , [ r . ke ] , function ( err , rrr ) {
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . admin , {
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2018-10-06 02:52:02 +00:00
$user : req . resp ,
$subs : rr ,
$mons : rrr ,
lang : r . lang ,
2019-01-24 06:15:17 +00:00
define : s . getDefinitonFile ( r . details . lang ) ,
customAutoLoad : s . customAutoLoadTree
2018-10-06 02:52:02 +00:00
} )
2018-09-28 05:37:08 +00:00
} )
} )
} else {
//not admin user
2019-04-20 18:52:53 +00:00
var chosenRender = 'home'
if ( r . details . landing _page && r . details . landing _page !== '' && config . renderPaths [ r . details . landing _page ] ) {
chosenRender = r . details . landing _page
}
renderPage ( config . renderPaths [ chosenRender ] , {
2019-01-24 06:15:17 +00:00
$user : req . resp ,
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2019-01-24 06:15:17 +00:00
lang : r . lang ,
define : s . getDefinitonFile ( r . details . lang ) ,
addStorage : s . dir . addStorage ,
fs : fs ,
_ _dirname : s . mainDirectory ,
customAutoLoad : s . customAutoLoadTree
} ) ;
2018-09-28 05:37:08 +00:00
}
break ;
default :
2019-04-20 18:52:53 +00:00
var chosenRender = 'home'
if ( r . details . sub && r . details . landing _page && r . details . landing _page !== '' && config . renderPaths [ r . details . landing _page ] ) {
chosenRender = r . details . landing _page
}
renderPage ( config . renderPaths [ chosenRender ] , {
2019-01-24 06:15:17 +00:00
$user : req . resp ,
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2019-01-24 06:15:17 +00:00
lang : r . lang ,
define : s . getDefinitonFile ( r . details . lang ) ,
addStorage : s . dir . addStorage ,
fs : fs ,
_ _dirname : s . mainDirectory ,
customAutoLoad : s . customAutoLoadTree
2019-04-06 05:27:22 +00:00
} )
2018-09-28 05:37:08 +00:00
break ;
}
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : r . ke , mid : '$USER' } , { type : r . lang [ 'New Authentication Token' ] , msg : { for : req . body . function , mail : r . mail , id : r . uid , ip : req . ip } } )
2018-09-28 05:37:08 +00:00
// res.end();
}
if ( req . body . mail && req . body . pass ) {
req . default = function ( ) {
s . sqlQuery ( 'SELECT * FROM Users WHERE mail=? AND pass=?' , [ req . body . mail , s . createHash ( req . body . pass ) ] , function ( err , r ) {
req . resp = { ok : false } ;
if ( ! err && r && r [ 0 ] ) {
r = r [ 0 ] ; r . auth = s . md5 ( s . gid ( ) ) ;
s . sqlQuery ( "UPDATE Users SET auth=? WHERE ke=? AND uid=?" , [ r . auth , r . ke , r . uid ] )
req . resp = { ok : true , auth _token : r . auth , ke : r . ke , uid : r . uid , mail : r . mail , details : r . details } ;
r . details = JSON . parse ( r . details ) ;
r . lang = s . getLanguageFile ( r . details . lang )
req . factorAuth = function ( cb ) {
2019-04-06 05:27:22 +00:00
req . params . auth = r . auth
req . params . ke = r . ke
2018-11-11 03:59:02 +00:00
if ( r . details . factorAuth === "1" ) {
2018-09-28 05:37:08 +00:00
if ( ! r . details . acceptedMachines || ! ( r . details . acceptedMachines instanceof Object ) ) {
r . details . acceptedMachines = { }
}
if ( ! r . details . acceptedMachines [ req . body . machineID ] ) {
req . complete = function ( ) {
s . factorAuth [ r . ke ] [ r . uid ] . function = req . body . function
s . factorAuth [ r . ke ] [ r . uid ] . info = req . resp
clearTimeout ( s . factorAuth [ r . ke ] [ r . uid ] . expireAuth )
s . factorAuth [ r . ke ] [ r . uid ] . expireAuth = setTimeout ( function ( ) {
s . deleteFactorAuth ( r )
} , 1000 * 60 * 15 )
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . factorAuth , { $user : req . resp , lang : r . lang } )
2018-09-28 05:37:08 +00:00
}
if ( ! s . factorAuth [ r . ke ] ) { s . factorAuth [ r . ke ] = { } }
if ( ! s . factorAuth [ r . ke ] [ r . uid ] ) {
s . factorAuth [ r . ke ] [ r . uid ] = { key : s . nid ( ) , user : r }
2018-10-01 05:44:35 +00:00
s . onTwoFactorAuthCodeNotificationExtensions . forEach ( function ( extender ) {
extender ( r )
} )
2018-09-28 05:37:08 +00:00
req . complete ( )
} else {
req . complete ( )
}
} else {
2018-10-06 02:52:02 +00:00
checkRoute ( r )
2018-09-28 05:37:08 +00:00
}
} else {
2018-10-06 02:52:02 +00:00
checkRoute ( r )
2018-09-28 05:37:08 +00:00
}
}
if ( r . details . sub ) {
s . sqlQuery ( 'SELECT details FROM Users WHERE ke=? AND details NOT LIKE ?' , [ r . ke , '%"sub"%' ] , function ( err , rr ) {
2018-10-27 17:36:20 +00:00
if ( rr && rr [ 0 ] ) {
rr = rr [ 0 ] ;
rr . details = JSON . parse ( rr . details ) ;
r . details . mon _groups = rr . details . mon _groups ;
req . resp . details = JSON . stringify ( r . details ) ;
req . factorAuth ( )
} else {
failedAuthentication ( req . body . function )
}
2018-09-28 05:37:08 +00:00
} )
} else {
req . factorAuth ( )
}
} else {
2018-10-06 02:52:02 +00:00
failedAuthentication ( req . body . function )
2018-09-28 05:37:08 +00:00
}
} )
}
if ( LdapAuth && req . body . function === 'ldap' && req . body . key !== '' ) {
s . sqlQuery ( 'SELECT * FROM Users WHERE ke=? AND details NOT LIKE ?' , [ req . body . key , '%"sub"%' ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
r = r [ 0 ]
r . details = JSON . parse ( r . details )
r . lang = s . getLanguageFile ( r . details . lang )
if ( r . details . use _ldap !== '0' && r . details . ldap _enable === '1' && r . details . ldap _url && r . details . ldap _url !== '' ) {
req . mailArray = { }
req . body . mail . split ( ',' ) . forEach ( function ( v ) {
v = v . split ( '=' )
req . mailArray [ v [ 0 ] ] = v [ 1 ]
} )
if ( ! r . details . ldap _bindDN || r . details . ldap _bindDN === '' ) {
r . details . ldap _bindDN = req . body . mail
}
if ( ! r . details . ldap _bindCredentials || r . details . ldap _bindCredentials === '' ) {
r . details . ldap _bindCredentials = req . body . pass
}
if ( ! r . details . ldap _searchFilter || r . details . ldap _searchFilter === '' ) {
r . details . ldap _searchFilter = req . body . mail
if ( req . mailArray . cn ) {
r . details . ldap _searchFilter = 'cn=' + req . mailArray . cn
}
if ( req . mailArray . uid ) {
r . details . ldap _searchFilter = 'uid=' + req . mailArray . uid
}
} else {
r . details . ldap _searchFilter = r . details . ldap _searchFilter . replace ( '{{username}}' , req . body . mail )
}
if ( ! r . details . ldap _searchBase || r . details . ldap _searchBase === '' ) {
r . details . ldap _searchBase = 'dc=test,dc=com'
}
req . auth = new LdapAuth ( {
url : r . details . ldap _url ,
bindDN : r . details . ldap _bindDN ,
bindCredentials : r . details . ldap _bindCredentials ,
searchBase : r . details . ldap _searchBase ,
searchFilter : '(' + r . details . ldap _searchFilter + ')' ,
reconnect : true
} ) ;
req . auth . on ( 'error' , function ( err ) {
console . error ( 'LdapAuth: ' , err ) ;
} ) ;
req . auth . authenticate ( req . body . mail , req . body . pass , function ( err , user ) {
if ( user ) {
//found user
if ( ! user . uid ) {
user . uid = s . gid ( )
}
req . resp = {
ke : req . body . key ,
uid : user . uid ,
auth : s . createHash ( s . gid ( ) ) ,
mail : user . mail ,
pass : s . createHash ( req . body . pass ) ,
details : JSON . stringify ( {
sub : '1' ,
ldap : '1' ,
allmonitors : '1' ,
2018-09-29 02:02:53 +00:00
filter : { }
2018-09-28 05:37:08 +00:00
} )
}
user . post = [ ]
Object . keys ( req . resp ) . forEach ( function ( v ) {
user . post . push ( req . resp [ v ] )
} )
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : req . body . key , mid : '$USER' } , { type : r . lang [ 'LDAP Success' ] , msg : { user : user } } )
2018-09-28 05:37:08 +00:00
s . sqlQuery ( 'SELECT * FROM Users WHERE ke=? AND mail=?' , [ req . body . key , user . cn ] , function ( err , rr ) {
if ( rr && rr [ 0 ] ) {
//already registered
rr = rr [ 0 ]
req . resp = rr ;
rr . details = JSON . parse ( rr . details )
req . resp . lang = s . getLanguageFile ( rr . details . lang )
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : req . body . key , mid : '$USER' } , { type : r . lang [ 'LDAP User Authenticated' ] , msg : { user : user , shinobiUID : rr . uid } } )
2018-09-28 05:37:08 +00:00
s . sqlQuery ( "UPDATE Users SET auth=? WHERE ke=? AND uid=?" , [ req . resp . auth , req . resp . ke , rr . uid ] )
} else {
//new ldap login
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : req . body . key , mid : '$USER' } , { type : r . lang [ 'LDAP User is New' ] , msg : { info : r . lang [ 'Creating New Account' ] , user : user } } )
2018-09-28 05:37:08 +00:00
req . resp . lang = r . lang
s . sqlQuery ( 'INSERT INTO Users (ke,uid,auth,mail,pass,details) VALUES (?,?,?,?,?,?)' , user . post )
}
2019-04-06 05:27:22 +00:00
req . resp . details = JSON . stringify ( req . resp . details )
req . resp . auth _token = req . resp . auth
2018-09-28 05:37:08 +00:00
req . resp . ok = true
2018-10-06 02:52:02 +00:00
checkRoute ( req . resp )
2018-09-28 05:37:08 +00:00
} )
return
}
2018-10-07 18:45:38 +00:00
s . userLog ( { ke : req . body . key , mid : '$USER' } , { type : r . lang [ 'LDAP Failed' ] , msg : { err : err } } )
2018-09-28 05:37:08 +00:00
//no user
req . default ( )
} ) ;
req . auth . close ( function ( err ) {
} )
} else {
req . default ( )
}
} else {
req . default ( )
}
} )
} else {
2018-10-06 06:20:16 +00:00
if ( req . body . function === 'super' ) {
2018-09-28 20:26:24 +00:00
if ( ! fs . existsSync ( s . location . super ) ) {
2018-09-28 05:37:08 +00:00
res . end ( lang . superAdminText )
return
}
2018-10-06 02:52:02 +00:00
var ok = s . superAuth ( {
mail : req . body . mail ,
pass : req . body . pass ,
users : true ,
md5 : true
} , function ( data ) {
2018-09-28 05:37:08 +00:00
s . sqlQuery ( 'SELECT * FROM Logs WHERE ke=? ORDER BY `time` DESC LIMIT 30' , [ '$' ] , function ( err , r ) {
if ( ! r ) {
r = [ ]
}
2018-10-06 02:52:02 +00:00
data . Logs = r
2019-01-24 06:15:17 +00:00
data . customAutoLoad = s . customAutoLoadTree
2019-07-31 00:05:00 +00:00
data . currentVersion = s . currentVersion
2018-09-28 20:26:24 +00:00
fs . readFile ( s . location . config , 'utf8' , function ( err , file ) {
2018-10-03 00:52:49 +00:00
data . plainConfig = JSON . parse ( file )
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . super , data )
2018-09-28 05:37:08 +00:00
} )
} )
} )
2018-10-06 02:52:02 +00:00
if ( ok === false ) {
failedAuthentication ( req . body . function )
2018-09-28 05:37:08 +00:00
}
} else {
req . default ( )
}
}
} else {
if ( req . body . machineID && req . body . factorAuthKey ) {
if ( s . factorAuth [ req . body . ke ] && s . factorAuth [ req . body . ke ] [ req . body . id ] && s . factorAuth [ req . body . ke ] [ req . body . id ] . key === req . body . factorAuthKey ) {
if ( s . factorAuth [ req . body . ke ] [ req . body . id ] . key === req . body . factorAuthKey ) {
if ( req . body . remember === "1" ) {
req . details = JSON . parse ( s . factorAuth [ req . body . ke ] [ req . body . id ] . info . details )
req . lang = s . getLanguageFile ( req . details . lang )
if ( ! req . details . acceptedMachines || ! ( req . details . acceptedMachines instanceof Object ) ) {
req . details . acceptedMachines = { }
}
if ( ! req . details . acceptedMachines [ req . body . machineID ] ) {
req . details . acceptedMachines [ req . body . machineID ] = { }
2018-09-30 22:44:04 +00:00
s . sqlQuery ( "UPDATE Users SET details=? WHERE ke=? AND uid=?" , [ s . prettyPrint ( req . details ) , req . body . ke , req . body . id ] )
2018-09-28 05:37:08 +00:00
}
}
req . body . function = s . factorAuth [ req . body . ke ] [ req . body . id ] . function
req . resp = s . factorAuth [ req . body . ke ] [ req . body . id ] . info
2018-10-06 02:52:02 +00:00
checkRoute ( s . factorAuth [ req . body . ke ] [ req . body . id ] . user )
2018-09-28 05:37:08 +00:00
} else {
2018-10-06 02:52:02 +00:00
renderPage ( config . renderPaths . factorAuth , { $user : s . factorAuth [ req . body . ke ] [ req . body . id ] . info , lang : req . lang } ) ;
2018-09-28 05:37:08 +00:00
res . end ( ) ;
}
} else {
2018-10-06 02:52:02 +00:00
failedAuthentication ( lang [ '2-Factor Authentication' ] )
2018-09-28 05:37:08 +00:00
}
} else {
2018-10-06 02:52:02 +00:00
failedAuthentication ( lang [ '2-Factor Authentication' ] )
2018-09-28 05:37:08 +00:00
}
}
2018-10-05 21:19:48 +00:00
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : Brute Protection Lock Reset by API
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/resetBruteProtection/:ke' ] , function ( req , res ) {
s . auth ( req . params , function ( user ) {
if ( s . failedLoginAttempts [ user . mail ] ) {
clearTimeout ( s . failedLoginAttempts [ user . mail ] . timeout )
delete ( s . failedLoginAttempts [ user . mail ] )
}
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : true } ) )
2018-09-28 05:37:08 +00:00
} )
} )
2018-10-06 16:46:48 +00:00
/ * *
* Page : Montage - stand alone squished view with gridstackjs
* /
2018-09-28 05:37:08 +00:00
app . get ( [
config . webPaths . apiPrefix + ':auth/grid/:ke' ,
config . webPaths . apiPrefix + ':auth/grid/:ke/:group' ,
config . webPaths . apiPrefix + ':auth/cycle/:ke' ,
config . webPaths . apiPrefix + ':auth/cycle/:ke/:group'
] , function ( req , res ) {
s . auth ( req . params , function ( user ) {
if ( user . permissions . get _monitors === "0" ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
req . params . protocol = req . protocol ;
req . sql = 'SELECT * FROM Monitors WHERE mode!=? AND mode!=? AND ke=?' ; req . ar = [ 'stop' , 'idle' , req . params . ke ] ;
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
} else {
res . end ( user . lang [ 'There are no monitors that you can view with this account.' ] ) ;
return ;
}
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( req . params . group ) {
var filteredByGroupCheck = { } ;
var filteredByGroup = [ ] ;
r . forEach ( function ( v , n ) {
var details = JSON . parse ( r [ n ] . details ) ;
try {
req . params . group . split ( '|' ) . forEach ( function ( group ) {
var groups = JSON . parse ( details . groups ) ;
if ( groups . indexOf ( group ) > - 1 && ! filteredByGroupCheck [ v . mid ] ) {
filteredByGroupCheck [ v . mid ] = true ;
filteredByGroup . push ( v )
}
} )
} catch ( err ) {
}
} )
r = filteredByGroup ;
}
r . forEach ( function ( v , n ) {
2019-07-08 03:39:41 +00:00
if ( s . group [ v . ke ] && s . group [ v . ke ] . activeMonitors [ v . mid ] && s . group [ v . ke ] . activeMonitors [ v . mid ] . watch ) {
r [ n ] . currentlyWatching = Object . keys ( s . group [ v . ke ] . activeMonitors [ v . mid ] . watch ) . length
2018-09-28 05:37:08 +00:00
}
r [ n ] . subStream = { }
var details = JSON . parse ( r [ n ] . details )
if ( details . snap === '1' ) {
r [ n ] . subStream . jpeg = '/' + req . params . auth + '/jpeg/' + v . ke + '/' + v . mid + '/s.jpg'
}
if ( details . stream _channels && details . stream _channels !== '' ) {
try {
details . stream _channels = JSON . parse ( details . stream _channels )
r [ n ] . channels = [ ]
details . stream _channels . forEach ( function ( b , m ) {
var streamURL
switch ( b . stream _type ) {
case 'mjpeg' :
streamURL = '/' + req . params . auth + '/mjpeg/' + v . ke + '/' + v . mid + '/' + m
break ;
case 'hls' :
streamURL = '/' + req . params . auth + '/hls/' + v . ke + '/' + v . mid + '/' + m + '/s.m3u8'
break ;
case 'h264' :
streamURL = '/' + req . params . auth + '/h264/' + v . ke + '/' + v . mid + '/' + m
break ;
case 'flv' :
streamURL = '/' + req . params . auth + '/flv/' + v . ke + '/' + v . mid + '/' + m + '/s.flv'
break ;
case 'mp4' :
streamURL = '/' + req . params . auth + '/mp4/' + v . ke + '/' + v . mid + '/' + m + '/s.mp4'
break ;
}
r [ n ] . channels . push ( streamURL )
} )
} catch ( err ) {
2018-10-07 18:45:38 +00:00
s . userLog ( req . params , { type : 'Broken Monitor Object' , msg : 'Stream Channels Field is damaged. Skipping.' } )
2018-09-28 05:37:08 +00:00
}
}
} )
var page = config . renderPaths . grid
if ( req . path . indexOf ( '/cycle/' ) > - 1 ) {
page = config . renderPaths . cycle
}
2018-11-06 04:27:19 +00:00
s . renderPage ( req , res , page , {
2018-09-28 05:37:08 +00:00
data : Object . assign ( req . params , req . query ) ,
baseUrl : req . protocol + '://' + req . hostname ,
2019-04-03 03:47:03 +00:00
config : s . getConfigWithBranding ( req . hostname ) ,
2018-09-28 05:37:08 +00:00
lang : user . lang ,
$user : user ,
monitors : r ,
query : req . query
} ) ;
} )
} , res , req )
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get TV Channels ( Monitor Streams ) json
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/tvChannels/:ke' , config . webPaths . apiPrefix + ':auth/tvChannels/:ke/:id' , '/get.php' ] , function ( req , res ) {
req . ret = { ok : false } ;
if ( req . query . username && req . query . password ) {
req . params . username = req . query . username
req . params . password = req . query . password
}
var output = [ 'h264' , 'hls' , 'mp4' ]
if ( req . query . output && req . query . output !== '' ) {
output = req . query . output . split ( ',' )
output . forEach ( function ( type , n ) {
if ( type === 'ts' ) {
output [ n ] = 'h264'
if ( output . indexOf ( 'hls' ) === - 1 ) {
output . push ( 'hls' )
}
}
} )
}
var isM3u8 = false ;
if ( req . query . type === 'm3u8' || req . query . type === 'm3u_plus' ) {
//is m3u8
isM3u8 = true ;
} else {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
}
req . fn = function ( user ) {
if ( user . permissions . get _monitors === "0" ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
if ( ! req . params . ke ) {
req . params . ke = user . ke ;
}
if ( req . query . id && ! req . params . id ) {
req . params . id = req . query . id ;
}
req . sql = 'SELECT * FROM Monitors WHERE mode!=? AND ke=?' ; req . ar = [ 'stop' , req . params . ke ] ;
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
} else {
res . end ( '[]' ) ;
return ;
}
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
var tvChannelMonitors = [ ] ;
r . forEach ( function ( v , n ) {
var buildStreamURL = function ( channelRow , type , channelNumber ) {
var streamURL
if ( channelNumber ) { channelNumber = '/' + channelNumber } else { channelNumber = '' }
switch ( type ) {
case 'mjpeg' :
streamURL = '/' + req . params . auth + '/mjpeg/' + v . ke + '/' + v . mid + channelNumber
break ;
case 'hls' :
streamURL = '/' + req . params . auth + '/hls/' + v . ke + '/' + v . mid + channelNumber + '/s.m3u8'
break ;
case 'h264' :
streamURL = '/' + req . params . auth + '/h264/' + v . ke + '/' + v . mid + channelNumber
break ;
case 'flv' :
streamURL = '/' + req . params . auth + '/flv/' + v . ke + '/' + v . mid + channelNumber + '/s.flv'
break ;
case 'mp4' :
streamURL = '/' + req . params . auth + '/mp4/' + v . ke + '/' + v . mid + channelNumber + '/s.ts'
break ;
}
if ( streamURL ) {
if ( ! channelRow . streamsSortedByType [ type ] ) {
channelRow . streamsSortedByType [ type ] = [ ]
}
channelRow . streamsSortedByType [ type ] . push ( streamURL )
channelRow . streams . push ( streamURL )
}
return streamURL
}
var details = JSON . parse ( r [ n ] . details ) ;
if ( ! details . tv _channel _id || details . tv _channel _id === '' ) details . tv _channel _id = 'temp_' + s . gid ( 5 )
var channelRow = {
ke : v . ke ,
mid : v . mid ,
type : v . type ,
groupTitle : details . tv _channel _group _title ,
channel : details . tv _channel _id ,
} ;
if ( details . snap === '1' ) {
channelRow . snapshot = '/' + req . params . auth + '/jpeg/' + v . ke + '/' + v . mid + '/s.jpg'
}
channelRow . streams = [ ]
channelRow . streamsSortedByType = { }
buildStreamURL ( channelRow , details . stream _type )
if ( details . stream _channels && details . stream _channels !== '' ) {
details . stream _channels = JSON . parse ( details . stream _channels )
details . stream _channels . forEach ( function ( b , m ) {
buildStreamURL ( channelRow , b . stream _type , m . toString ( ) )
} )
}
if ( details . tv _channel === '1' ) {
tvChannelMonitors . push ( channelRow )
}
} )
if ( isM3u8 ) {
var m3u8 = '#EXTM3U' + '\n'
tvChannelMonitors . forEach ( function ( channelRow , n ) {
output . forEach ( function ( type ) {
if ( channelRow . streamsSortedByType [ type ] ) {
if ( req . query . type === 'm3u_plus' ) {
m3u8 += '#EXTINF-1 tvg-id="' + channelRow . mid + '" tvg-name="' + channelRow . channel + '" tvg-logo="' + req . protocol + '://' + req . headers . host + channelRow . snapshot + '" group-title="' + channelRow . groupTitle + '",' + channelRow . channel + '\n'
} else {
m3u8 += '#EXTINF:-1,' + channelRow . channel + ' (' + type . toUpperCase ( ) + ') \n'
}
m3u8 += req . protocol + '://' + req . headers . host + channelRow . streamsSortedByType [ type ] [ 0 ] + '\n'
}
} )
} )
res . end ( m3u8 )
} else {
if ( tvChannelMonitors . length === 1 ) { tvChannelMonitors = tvChannelMonitors [ 0 ] ; }
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( tvChannelMonitors ) ) ;
2018-09-28 05:37:08 +00:00
}
} )
}
s . auth ( req . params , req . fn , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Monitors
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/monitor/:ke' , config . webPaths . apiPrefix + ':auth/monitor/:ke/:id' ] , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
req . fn = function ( user ) {
if ( user . permissions . get _monitors === "0" ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
req . sql = 'SELECT * FROM Monitors WHERE ke=?' ; req . ar = [ req . params . ke ] ;
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
} else {
res . end ( '[]' ) ;
return ;
}
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
r . forEach ( function ( v , n ) {
2019-07-08 03:39:41 +00:00
if ( s . group [ v . ke ] && s . group [ v . ke ] . activeMonitors [ v . mid ] ) {
r [ n ] . currentlyWatching = Object . keys ( s . group [ v . ke ] . activeMonitors [ v . mid ] . watch ) . length
r [ n ] . currentCpuUsage = s . group [ v . ke ] . activeMonitors [ v . mid ] . currentCpuUsage
r [ n ] . status = s . group [ v . ke ] . activeMonitors [ v . mid ] . monitorStatus
2018-09-28 05:37:08 +00:00
}
var buildStreamURL = function ( type , channelNumber ) {
var streamURL
if ( channelNumber ) { channelNumber = '/' + channelNumber } else { channelNumber = '' }
switch ( type ) {
case 'mjpeg' :
streamURL = '/' + req . params . auth + '/mjpeg/' + v . ke + '/' + v . mid + channelNumber
break ;
case 'hls' :
streamURL = '/' + req . params . auth + '/hls/' + v . ke + '/' + v . mid + channelNumber + '/s.m3u8'
break ;
case 'h264' :
streamURL = '/' + req . params . auth + '/h264/' + v . ke + '/' + v . mid + channelNumber
break ;
case 'flv' :
streamURL = '/' + req . params . auth + '/flv/' + v . ke + '/' + v . mid + channelNumber + '/s.flv'
break ;
case 'mp4' :
streamURL = '/' + req . params . auth + '/mp4/' + v . ke + '/' + v . mid + channelNumber + '/s.mp4'
break ;
}
if ( streamURL ) {
if ( ! r [ n ] . streamsSortedByType [ type ] ) {
r [ n ] . streamsSortedByType [ type ] = [ ]
}
r [ n ] . streamsSortedByType [ type ] . push ( streamURL )
r [ n ] . streams . push ( streamURL )
}
return streamURL
}
var details = JSON . parse ( r [ n ] . details ) ;
if ( ! details . tv _channel _id || details . tv _channel _id === '' ) details . tv _channel _id = 'temp_' + s . gid ( 5 )
if ( details . snap === '1' ) {
r [ n ] . snapshot = '/' + req . params . auth + '/jpeg/' + v . ke + '/' + v . mid + '/s.jpg'
}
r [ n ] . streams = [ ]
r [ n ] . streamsSortedByType = { }
buildStreamURL ( details . stream _type )
if ( details . stream _channels && details . stream _channels !== '' ) {
2019-03-15 07:32:18 +00:00
details . stream _channels = s . parseJSON ( details . stream _channels )
2018-09-28 05:37:08 +00:00
details . stream _channels . forEach ( function ( b , m ) {
buildStreamURL ( b . stream _type , m . toString ( ) )
} )
}
} )
if ( r . length === 1 ) { r = r [ 0 ] ; }
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( r ) ) ;
2018-09-28 05:37:08 +00:00
} )
}
s . auth ( req . params , req . fn , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
2019-01-29 01:41:14 +00:00
* API : Merge Recorded Videos into one file
* /
app . get ( config . webPaths . apiPrefix + ':auth/videosMerge/:ke' , function ( req , res ) {
var failed = function ( resp ) {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
res . end ( s . prettyPrint ( resp ) )
}
if ( req . query . videos && req . query . videos !== '' ) {
s . auth ( req . params , function ( user ) {
var videosSelected = JSON . parse ( req . query . videos )
var where = [ ]
var values = [ ]
videosSelected . forEach ( function ( video ) {
where . push ( "(ke=? AND mid=? AND `time`=?)" )
if ( ! video . ke ) video . ke = req . params . ke
values . push ( video . ke )
values . push ( video . mid )
var time = s . nameToTime ( video . filename )
if ( req . query . isUTC === 'true' ) {
time = s . utcToLocal ( time )
}
time = new Date ( time )
values . push ( time )
} )
s . sqlQuery ( 'SELECT * FROM Videos WHERE ' + where . join ( ' OR ' ) , values , function ( err , r ) {
var resp = { ok : false }
if ( r && r [ 0 ] ) {
s . mergeRecordedVideos ( r , req . params . ke , function ( fullPath , filename ) {
res . setHeader ( 'Content-Disposition' , 'attachment; filename="' + filename + '"' )
var file = fs . createReadStream ( fullPath )
file . on ( 'close' , function ( ) {
2019-01-31 18:51:35 +00:00
setTimeout ( function ( ) {
s . file ( 'delete' , fullPath )
} , 1000 * 60 * 3 )
2019-01-29 01:41:14 +00:00
res . end ( )
} )
file . pipe ( res )
} )
} else {
failed ( { ok : false , msg : 'No Videos Found' } )
}
} )
} , res , req ) ;
} else {
failed ( { ok : false , msg : '"videos" query variable is missing from request.' } )
}
} )
/ * *
2018-10-06 16:46:48 +00:00
* API : Get Videos
* /
2018-09-28 05:37:08 +00:00
app . get ( [
config . webPaths . apiPrefix + ':auth/videos/:ke' ,
config . webPaths . apiPrefix + ':auth/videos/:ke/:id' ,
config . webPaths . apiPrefix + ':auth/cloudVideos/:ke' ,
config . webPaths . apiPrefix + ':auth/cloudVideos/:ke/:id'
] , function ( req , res ) {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
var hasRestrictions = user . details . sub && user . details . allmonitors !== '1'
if (
user . permissions . watch _videos === "0" ||
hasRestrictions && ( ! user . details . video _view || user . details . video _view . indexOf ( req . params . id ) === - 1 )
) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
var origURL = req . originalUrl . split ( '/' )
var videoParam = origURL [ origURL . indexOf ( req . params . auth ) + 1 ]
var videoSet = 'Videos'
switch ( videoParam ) {
case 'cloudVideos' :
videoSet = 'Cloud Videos'
break ;
}
req . sql = 'SELECT * FROM `' + videoSet + '` WHERE ke=?' ; req . ar = [ req . params . ke ] ;
req . count _sql = 'SELECT COUNT(*) FROM `' + videoSet + '` WHERE ke=?' ; req . count _ar = [ req . params . ke ] ;
if ( req . query . archived == '1' ) {
req . sql += ' AND details LIKE \'%"archived":"1"\''
req . count _sql += ' AND details LIKE \'%"archived":"1"\''
}
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
req . count _sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
req . count _sql += ' and mid=?' ; req . count _ar . push ( req . params . id )
} else {
res . end ( '[]' ) ;
return ;
}
}
if ( req . query . start || req . query . end ) {
if ( req . query . start && req . query . start !== '' ) {
req . query . start = s . stringToSqlTime ( req . query . start )
}
if ( req . query . end && req . query . end !== '' ) {
req . query . end = s . stringToSqlTime ( req . query . end )
}
if ( ! req . query . startOperator || req . query . startOperator == '' ) {
req . query . startOperator = '>='
}
if ( ! req . query . endOperator || req . query . endOperator == '' ) {
req . query . endOperator = '<='
}
2018-10-23 18:36:02 +00:00
var endIsStartTo
var theEndParameter = '`end`'
if ( req . query . endIsStartTo ) {
endIsStartTo = true
theEndParameter = '`time`'
}
2018-09-28 05:37:08 +00:00
switch ( true ) {
case ( req . query . start && req . query . start !== '' && req . query . end && req . query . end !== '' ) :
2018-10-23 18:36:02 +00:00
req . sql += ' AND `time` ' + req . query . startOperator + ' ? AND ' + theEndParameter + ' ' + req . query . endOperator + ' ?' ;
req . count _sql += ' AND `time` ' + req . query . startOperator + ' ? AND ' + theEndParameter + ' ' + req . query . endOperator + ' ?' ;
2018-09-28 05:37:08 +00:00
req . ar . push ( req . query . start )
req . ar . push ( req . query . end )
req . count _ar . push ( req . query . start )
req . count _ar . push ( req . query . end )
break ;
case ( req . query . start && req . query . start !== '' ) :
req . sql += ' AND `time` ' + req . query . startOperator + ' ?' ;
req . count _sql += ' AND `time` ' + req . query . startOperator + ' ?' ;
req . ar . push ( req . query . start )
req . count _ar . push ( req . query . start )
break ;
case ( req . query . end && req . query . end !== '' ) :
2018-10-23 18:36:02 +00:00
req . sql += ' AND ' + theEndParameter + ' ' + req . query . endOperator + ' ?' ;
req . count _sql += ' AND ' + theEndParameter + ' ' + req . query . endOperator + ' ?' ;
2018-09-28 05:37:08 +00:00
req . ar . push ( req . query . end )
req . count _ar . push ( req . query . end )
break ;
}
}
req . sql += ' ORDER BY `time` DESC' ;
if ( ! req . query . limit || req . query . limit == '' ) {
req . query . limit = '100'
}
if ( req . query . limit !== '0' ) {
req . sql += ' LIMIT ' + req . query . limit
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( ! r ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { total : 0 , limit : req . query . limit , skip : 0 , videos : [ ] } ) ) ;
2018-09-28 05:37:08 +00:00
return
}
s . sqlQuery ( req . count _sql , req . count _ar , function ( err , count ) {
2018-09-29 15:00:51 +00:00
s . buildVideoLinks ( r , {
2018-09-28 05:37:08 +00:00
auth : req . params . auth ,
videoParam : videoParam ,
2019-11-24 00:53:54 +00:00
hideRemote : config . hideCloudSaveUrls ,
videoParam : videoParam
2018-09-28 05:37:08 +00:00
} )
if ( req . query . limit . indexOf ( ',' ) > - 1 ) {
req . skip = parseInt ( req . query . limit . split ( ',' ) [ 0 ] )
req . query . limit = parseInt ( req . query . limit . split ( ',' ) [ 1 ] )
} else {
req . skip = 0
req . query . limit = parseInt ( req . query . limit )
}
2018-10-23 18:36:02 +00:00
res . end ( s . prettyPrint ( { isUTC : config . useUTC , total : count [ 0 ] [ 'COUNT(*)' ] , limit : req . query . limit , skip : req . skip , videos : r , endIsStartTo : endIsStartTo } ) ) ;
2018-09-28 05:37:08 +00:00
} )
} )
} , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Events
* /
2019-07-19 20:43:05 +00:00
app . get ( [
config . webPaths . apiPrefix + ':auth/events/:ke' ,
config . webPaths . apiPrefix + ':auth/events/:ke/:id'
] , function ( req , res ) {
2018-09-28 05:37:08 +00:00
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
if ( user . permissions . watch _videos === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . video _view . indexOf ( req . params . id ) === - 1 ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
req . sql = 'SELECT * FROM Events WHERE ke=?' ; req . ar = [ req . params . ke ] ;
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
} else {
res . end ( '[]' ) ;
return ;
}
}
2019-07-19 20:43:05 +00:00
if ( req . query . start || req . query . end ) {
if ( req . query . start && req . query . start !== '' ) {
req . query . start = s . stringToSqlTime ( req . query . start )
}
if ( req . query . end && req . query . end !== '' ) {
req . query . end = s . stringToSqlTime ( req . query . end )
}
if ( ! req . query . startOperator || req . query . startOperator == '' ) {
req . query . startOperator = '>='
}
if ( ! req . query . endOperator || req . query . endOperator == '' ) {
req . query . endOperator = '<='
}
switch ( true ) {
case ( req . query . start && req . query . start !== '' && req . query . end && req . query . end !== '' ) :
req . sql += ' AND `time` ' + req . query . startOperator + ' ? AND `time` ' + req . query . endOperator + ' ?' ;
req . ar . push ( req . query . start )
req . ar . push ( req . query . end )
break ;
case ( req . query . start && req . query . start !== '' ) :
req . sql += ' AND `time` ' + req . query . startOperator + ' ?' ;
req . ar . push ( req . query . start )
break ;
case ( req . query . end && req . query . end !== '' ) :
req . sql += ' AND `time` ' + req . query . endOperator + ' ?' ;
req . ar . push ( req . query . end )
break ;
2018-09-28 05:37:08 +00:00
}
}
2019-07-19 20:43:05 +00:00
req . sql += ' ORDER BY `time` DESC' ;
if ( ! req . query . limit || req . query . limit == '' ) {
req . query . limit = '100'
}
if ( req . query . limit !== '0' ) {
req . sql += ' LIMIT ' + req . query . limit
}
2018-09-28 05:37:08 +00:00
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( err ) {
err . sql = req . sql ;
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( err ) ) ;
2018-09-28 05:37:08 +00:00
return
}
if ( ! r ) { r = [ ] }
r . forEach ( function ( v , n ) {
r [ n ] . details = JSON . parse ( v . details ) ;
} )
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( r ) ) ;
2018-09-28 05:37:08 +00:00
} )
} , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Logs
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/logs/:ke' , config . webPaths . apiPrefix + ':auth/logs/:ke/:id' ] , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
if ( user . permissions . get _logs === "0" || user . details . sub && user . details . view _logs !== '1' ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
req . sql = 'SELECT * FROM Logs WHERE ke=?' ; req . ar = [ req . params . ke ] ;
if ( ! req . params . id ) {
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
} else {
if ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 || req . params . id . indexOf ( '$' ) > - 1 ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
} else {
res . end ( '[]' ) ;
return ;
}
}
if ( req . query . start || req . query . end ) {
if ( ! req . query . startOperator || req . query . startOperator == '' ) {
req . query . startOperator = '>='
}
if ( ! req . query . endOperator || req . query . endOperator == '' ) {
req . query . endOperator = '<='
}
if ( req . query . start && req . query . start !== '' && req . query . end && req . query . end !== '' ) {
req . query . start = s . stringToSqlTime ( req . query . start )
req . query . end = s . stringToSqlTime ( req . query . end )
req . sql += ' AND `time` ' + req . query . startOperator + ' ? AND `time` ' + req . query . endOperator + ' ?' ;
req . ar . push ( req . query . start )
req . ar . push ( req . query . end )
} else if ( req . query . start && req . query . start !== '' ) {
req . query . start = s . stringToSqlTime ( req . query . start )
req . sql += ' AND `time` ' + req . query . startOperator + ' ?' ;
req . ar . push ( req . query . start )
}
}
if ( ! req . query . limit || req . query . limit == '' ) { req . query . limit = 50 }
req . sql += ' ORDER BY `time` DESC LIMIT ' + req . query . limit + '' ;
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( err ) {
err . sql = req . sql ;
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( err ) ) ;
2018-09-28 05:37:08 +00:00
return
}
if ( ! r ) { r = [ ] }
r . forEach ( function ( v , n ) {
r [ n ] . info = JSON . parse ( v . info )
} )
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( r ) ) ;
2018-09-28 05:37:08 +00:00
} )
} , res , req ) ;
2018-10-05 21:19:48 +00:00
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Monitors Online
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/smonitor/:ke' , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
req . fn = function ( user ) {
if ( user . permissions . get _monitors === "0" ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( [ ] ) )
2018-09-28 05:37:08 +00:00
return
}
req . sql = 'SELECT * FROM Monitors WHERE ke=?' ; req . ar = [ req . params . ke ] ;
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( r && r [ 0 ] ) {
req . ar = [ ] ;
r . forEach ( function ( v ) {
2019-07-08 03:39:41 +00:00
if ( s . group [ req . params . ke ] && s . group [ req . params . ke ] . activeMonitors [ v . mid ] && s . group [ req . params . ke ] . activeMonitors [ v . mid ] . isStarted === true ) {
2018-09-28 05:37:08 +00:00
req . ar . push ( v )
}
} )
} else {
req . ar = [ ] ;
}
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ar ) ) ;
2018-09-28 05:37:08 +00:00
} )
}
s . auth ( req . params , req . fn , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Monitor Mode Controller
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/monitor/:ke/:id/:f' , config . webPaths . apiPrefix + ':auth/monitor/:ke/:id/:f/:ff' , config . webPaths . apiPrefix + ':auth/monitor/:ke/:id/:f/:ff/:fff' ] , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
if ( user . permissions . control _monitors === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . monitor _edit . indexOf ( req . params . id ) === - 1 ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
2018-09-30 22:44:04 +00:00
if ( req . params . f === '' ) { req . ret . msg = user . lang . monitorGetText1 ; res . end ( s . prettyPrint ( req . ret ) ) ; return }
2018-09-28 05:37:08 +00:00
if ( req . params . f !== 'stop' && req . params . f !== 'start' && req . params . f !== 'record' ) {
req . ret . msg = 'Mode not recognized.' ;
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
return ;
}
s . sqlQuery ( 'SELECT * FROM Monitors WHERE ke=? AND mid=?' , [ req . params . ke , req . params . id ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
r = r [ 0 ] ;
2019-07-08 03:39:41 +00:00
if ( req . query . reset === '1' || ( s . group [ r . ke ] && s . group [ r . ke ] . rawMonitorConfigurations [ r . mid ] . mode !== req . params . f ) || req . query . fps && ( ! s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState || ! s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . trigger _on ) ) {
if ( req . query . reset !== '1' || ! s . group [ r . ke ] . activeMonitors [ r . mid ] . trigger _timer ) {
if ( ! s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState ) s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState = { }
s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . mode = r . mode . toString ( )
s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . fps = r . fps . toString ( )
if ( ! s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . trigger _on ) {
s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . trigger _on = true
2018-09-28 05:37:08 +00:00
} else {
2019-07-08 03:39:41 +00:00
s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . trigger _on = false
2018-09-28 05:37:08 +00:00
}
r . mode = req . params . f ;
try { r . details = JSON . parse ( r . details ) ; } catch ( er ) { }
if ( req . query . fps ) {
r . fps = parseFloat ( r . details . detector _trigger _record _fps )
2019-07-08 03:39:41 +00:00
s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . detector _trigger _record _fps = r . fps
2018-09-28 05:37:08 +00:00
}
r . id = r . mid ;
s . sqlQuery ( 'UPDATE Monitors SET mode=? WHERE ke=? AND mid=?' , [ r . mode , r . ke , r . mid ] ) ;
2019-07-08 03:39:41 +00:00
s . group [ r . ke ] . rawMonitorConfigurations [ r . mid ] = r ;
2018-09-28 05:37:08 +00:00
s . tx ( { f : 'monitor_edit' , mid : r . mid , ke : r . ke , mon : r } , 'GRP_' + r . ke ) ;
s . tx ( { f : 'monitor_edit' , mid : r . mid , ke : r . ke , mon : r } , 'STR_' + r . ke ) ;
2018-09-29 01:38:14 +00:00
s . camera ( 'stop' , s . cleanMonitorObject ( r ) ) ;
2018-09-28 05:37:08 +00:00
if ( req . params . f !== 'stop' ) {
2018-09-29 01:38:14 +00:00
s . camera ( req . params . f , s . cleanMonitorObject ( r ) ) ;
2018-09-28 05:37:08 +00:00
}
req . ret . msg = user . lang [ 'Monitor mode changed' ] + ' : ' + req . params . f ;
} else {
req . ret . msg = user . lang [ 'Reset Timer' ] ;
}
req . ret . cmd _at = s . formattedTime ( new Date , 'YYYY-MM-DD HH:mm:ss' ) ;
req . ret . ok = true ;
if ( req . params . ff && req . params . f !== 'stop' ) {
req . params . ff = parseFloat ( req . params . ff ) ;
2019-07-08 03:39:41 +00:00
clearTimeout ( s . group [ r . ke ] . activeMonitors [ r . mid ] . trigger _timer )
2018-09-28 05:37:08 +00:00
switch ( req . params . fff ) {
case 'day' : case 'days' :
req . timeout = req . params . ff * 1000 * 60 * 60 * 24
break ;
case 'hr' : case 'hour' : case 'hours' :
req . timeout = req . params . ff * 1000 * 60 * 60
break ;
case 'min' : case 'minute' : case 'minutes' :
req . timeout = req . params . ff * 1000 * 60
break ;
default : //seconds
req . timeout = req . params . ff * 1000
break ;
}
2019-07-08 03:39:41 +00:00
s . group [ r . ke ] . activeMonitors [ r . mid ] . trigger _timer = setTimeout ( function ( ) {
delete ( s . group [ r . ke ] . activeMonitors [ r . mid ] . trigger _timer )
s . sqlQuery ( 'UPDATE Monitors SET mode=? WHERE ke=? AND mid=?' , [ s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . mode , r . ke , r . mid ] ) ;
2018-09-28 05:37:08 +00:00
r . neglectTriggerTimer = 1 ;
2019-07-08 03:39:41 +00:00
r . mode = s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . mode ;
r . fps = s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . fps ;
2018-09-29 01:38:14 +00:00
s . camera ( 'stop' , s . cleanMonitorObject ( r ) , function ( ) {
2019-07-08 03:39:41 +00:00
if ( s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . mode !== 'stop' ) {
s . camera ( s . group [ r . ke ] . activeMonitors [ r . mid ] . currentState . mode , s . cleanMonitorObject ( r ) ) ;
2018-09-28 05:37:08 +00:00
}
2019-07-08 03:39:41 +00:00
s . group [ r . ke ] . rawMonitorConfigurations [ r . mid ] = r ;
2018-09-28 05:37:08 +00:00
} ) ;
s . tx ( { f : 'monitor_edit' , mid : r . mid , ke : r . ke , mon : r } , 'GRP_' + r . ke ) ;
s . tx ( { f : 'monitor_edit' , mid : r . mid , ke : r . ke , mon : r } , 'STR_' + r . ke ) ;
} , req . timeout ) ;
// req.ret.end_at=s.formattedTime(new Date,'YYYY-MM-DD HH:mm:ss').add(req.timeout,'milliseconds');
}
} else {
req . ret . msg = user . lang [ 'Monitor mode is already' ] + ' : ' + req . params . f ;
}
} else {
req . ret . msg = user . lang [ 'Monitor or Key does not exist.' ] ;
}
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
} )
} , res , req ) ;
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : Get fileBin files
* /
2018-09-28 05:37:08 +00:00
app . get ( [ config . webPaths . apiPrefix + ':auth/fileBin/:ke' , config . webPaths . apiPrefix + ':auth/fileBin/:ke/:id' ] , function ( req , res ) {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
req . fn = function ( user ) {
req . sql = 'SELECT * FROM Files WHERE ke=?' ; req . ar = [ req . params . ke ] ;
if ( user . details . sub && user . details . monitors && user . details . allmonitors !== '1' ) {
try { user . details . monitors = JSON . parse ( user . details . monitors ) ; } catch ( er ) { }
req . or = [ ] ;
user . details . monitors . forEach ( function ( v , n ) {
req . or . push ( 'mid=?' ) ; req . ar . push ( v )
} )
req . sql += ' AND (' + req . or . join ( ' OR ' ) + ')'
} else {
if ( req . params . id && ( ! user . details . sub || user . details . allmonitors !== '0' || user . details . monitors . indexOf ( req . params . id ) > - 1 ) ) {
req . sql += ' and mid=?' ; req . ar . push ( req . params . id )
}
}
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( ! r ) {
r = [ ]
} else {
r . forEach ( function ( v ) {
v . details = JSON . parse ( v . details )
v . href = '/' + req . params . auth + '/fileBin/' + req . params . ke + '/' + req . params . id + '/' + v . details . year + '/' + v . details . month + '/' + v . details . day + '/' + v . name ;
} )
}
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( r ) ) ;
2018-09-28 05:37:08 +00:00
} )
}
s . auth ( req . params , req . fn , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get fileBin file
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/fileBin/:ke/:id/:year/:month/:day/:file' , function ( req , res ) {
2019-10-28 20:31:10 +00:00
s . auth ( req . params , function ( user ) {
var failed = function ( ) {
2018-09-28 05:37:08 +00:00
res . end ( user . lang [ 'File Not Found' ] )
}
if ( ! s . group [ req . params . ke ] . fileBin [ req . params . id + '/' + req . params . file ] ) {
s . sqlQuery ( 'SELECT * FROM Files WHERE ke=? AND mid=? AND name=?' , [ req . params . ke , req . params . id , req . params . file ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
2019-10-28 20:31:10 +00:00
r = r [ 0 ]
r . details = JSON . parse ( r . details )
req . dir = s . dir . fileBin + req . params . ke + '/' + req . params . id + '/' + r . details . year + '/' + r . details . month + '/' + r . details . day + '/' + req . params . file ;
fs . stat ( req . dir , function ( err , stats ) {
if ( ! err ) {
res . on ( 'finish' , function ( ) { res . end ( ) } )
fs . createReadStream ( req . dir ) . pipe ( res )
} else {
failed ( )
}
} )
2018-09-28 05:37:08 +00:00
} else {
2019-10-28 20:31:10 +00:00
failed ( )
2018-09-28 05:37:08 +00:00
}
} )
} else {
res . end ( user . lang [ 'Please Wait for Completion' ] )
}
2019-10-28 20:31:10 +00:00
} , res , req ) ;
2018-09-28 05:37:08 +00:00
} ) ;
2019-10-28 20:31:10 +00:00
// /**
// * API : Zip Videos and Get Link from fileBin
// */
// app.get(config.webPaths.apiPrefix+':auth/zipVideos/:ke', function (req,res){
// var failed = function(resp){
// res.setHeader('Content-Type', 'application/json');
// res.end(s.prettyPrint(resp))
// }
// if(req.query.videos && req.query.videos !== ''){
// s.auth(req.params,function(user){
// var videosSelected = JSON.parse(req.query.videos)
// var where = []
// var values = []
// videosSelected.forEach(function(video){
// where.push("(ke=? AND mid=? AND `time`=?)")
// if(!video.ke)video.ke = req.params.ke
// values.push(video.ke)
// values.push(video.mid)
// var time = s.nameToTime(video.filename)
// if(req.query.isUTC === 'true'){
// time = s.utcToLocal(time)
// }
// time = new Date(time)
// values.push(time)
// })
// s.sqlQuery('SELECT * FROM Videos WHERE '+where.join(' OR '),values,function(err,r){
// var resp = {ok: false}
// if(r && r[0]){
// resp.ok = true
// var zipDownload = null
// var tempFiles = []
// var fileId = s.gid()
// var fileBinDir = s.dir.fileBin+req.params.ke+'/'
// var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh'
// var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Recordings.zip'
// var zippedFile = fileBinDir+zippedFilename
// var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile
// res.on('close', () => {
// if(zipDownload && zipDownload.destroy){
// zipDownload.destroy()
// }
// fs.unlink(zippedFile);
// })
// fs.mkdir(fileBinDir,function(err){
// s.handleFolderError(err)
// r.forEach(function(video){
// var timeFormatted = s.formattedTime(video.time)
// video.filename = timeFormatted+'.'+video.ext
// var dir = s.getVideoDirectory(video)+video.filename
// var tempVideoFile = timeFormatted+' - '+video.mid+'.'+video.ext
// fs.writeFileSync(fileBinDir+tempVideoFile, fs.readFileSync(dir))
// tempFiles.push(fileBinDir+tempVideoFile)
// script += ' "'+tempVideoFile+'"'
// })
// fs.writeFileSync(tempScript,script,'utf8')
// var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true})
// zipCreate.stderr.on('data',function(data){
// s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()})
// })
// zipCreate.on('exit',function(data){
// fs.unlinkSync(tempScript)
// tempFiles.forEach(function(file){
// fs.unlink(file,function(){})
// })
// res.setHeader('Content-Disposition', 'attachment; filename="'+zippedFilename+'"')
// var zipDownload = fs.createReadStream(zippedFile)
// zipDownload.pipe(res)
// zipDownload.on('error', function (error) {
// var errorString = error.toString()
// s.userLog({
// ke: req.params.ke,
// mid: '$USER'
// },{
// title: 'Zip Download Error',
// msg: errorString
// })
// if(zipDownload && zipDownload.destroy){
// zipDownload.destroy()
// }
// res.end(s.prettyPrint({
// ok: false,
// msg: errorString
// }))
// })
// zipDownload.on('close', function () {
// res.end()
// zipDownload.destroy()
// fs.unlinkSync(zippedFile)
// })
// })
// })
// }else{
// failed({ok:false,msg:'No Videos Found'})
// }
// })
// },res,req);
// }else{
// failed({ok:false,msg:'"videos" query variable is missing from request.'})
// }
// })
// /**
// * API : Zip Cloud Videos and Get Link from fileBin
// */
// app.get(config.webPaths.apiPrefix+':auth/zipCloudVideos/:ke', function (req,res){
// var failed = function(resp){
// res.setHeader('Content-Type', 'application/json');
// res.end(s.prettyPrint(resp))
// }
// if(req.query.videos && req.query.videos !== ''){
// s.auth(req.params,function(user){
// var videosSelected = JSON.parse(req.query.videos)
// var where = []
// var values = []
// videosSelected.forEach(function(video){
// where.push("(ke=? AND mid=? AND `time`=?)")
// if(!video.ke)video.ke = req.params.ke
// values.push(video.ke)
// values.push(video.mid)
// var time = s.nameToTime(video.filename)
// if(req.query.isUTC === 'true'){
// time = s.utcToLocal(time)
// }
// time = new Date(time)
// values.push(time)
// })
// s.sqlQuery('SELECT * FROM `Cloud Videos` WHERE '+where.join(' OR '),values,function(err,r){
// var resp = {ok: false}
// if(r && r[0]){
// resp.ok = true
// var zipDownload = null
// var tempFiles = []
// var fileId = s.gid()
// var fileBinDir = s.dir.fileBin+req.params.ke+'/'
// var tempScript = s.dir.streams+req.params.ke+'/'+fileId+'.sh'
// var zippedFilename = s.formattedTime()+'-'+fileId+'-Shinobi_Cloud_Backed_Recordings.zip'
// var zippedFile = fileBinDir+zippedFilename
// var script = 'cd '+fileBinDir+' && zip -9 -r '+zippedFile
// res.on('close', () => {
// if(zipDownload && zipDownload.destroy){
// zipDownload.destroy()
// }
// fs.unlink(zippedFile);
// })
// fs.mkdir(fileBinDir,function(err){
// var cloudDownloadCount = 0
// var getFile = function(video,completed){
// if(!video)completed();
// s.checkDetails(video)
// var filename = video.href.split('/')
// filename = filename[filename.length - 1]
// var timeFormatted = s.formattedTime(video.time)
// var tempVideoFile = video.details.type + '-' + video.mid + '-' + filename
// var tempFileWriteStream = fs.createWriteStream(fileBinDir+tempVideoFile)
// tempFileWriteStream.on('finish', function() {
// ++cloudDownloadCount
// getFile(r[cloudDownloadCount],completed)
// })
// var cloudVideoDownload = request(video.href)
// cloudVideoDownload.on('response', function (res) {
// res.pipe(tempFileWriteStream)
// })
// tempFiles.push(fileBinDir+tempVideoFile)
// script += ' "'+tempVideoFile+'"'
// }
// getFile(r[cloudDownloadCount],function(){
// fs.writeFileSync(tempScript,script,'utf8')
// var zipCreate = spawn('sh',(tempScript).split(' '),{detached: true})
// zipCreate.stderr.on('data',function(data){
// s.userLog({ke:req.params.ke,mid:'$USER'},{title:'Zip Create Error',msg:data.toString()})
// })
// zipCreate.on('exit',function(data){
// fs.unlinkSync(tempScript)
// tempFiles.forEach(function(file){
// fs.unlink(file,function(){})
// })
// res.setHeader('Content-Disposition', 'attachment; filename="' + zippedFilename + '"')
// var zipDownload = fs.createReadStream(zippedFile)
// zipDownload.pipe(res)
// zipDownload.on('error', function (error) {
// var errorString = error.toString()
// s.userLog({
// ke: req.params.ke,
// mid: '$USER'
// },{
// title: 'Zip Download Error',
// msg: errorString
// })
// if(zipDownload && zipDownload.destroy){
// zipDownload.destroy()
// }
// res.end(s.prettyPrint({
// ok: false,
// msg: errorString
// }))
// })
// zipDownload.on('close', function () {
// res.end()
// zipDownload.destroy()
// fs.unlinkSync(zippedFile)
// })
// })
// })
// })
// }else{
// failed({ok:false,msg:'No Videos Found'})
// }
// })
// },res,req);
// }else{
// failed({ok:false,msg:'"videos" query variable is missing from request.'})
// }
// })
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Cloud Video File ( proxy )
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/cloudVideos/:ke/:id/:file' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
if ( user . permissions . watch _videos === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . monitors . indexOf ( req . params . id ) === - 1 ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
var time = s . nameToTime ( req . params . file )
if ( req . query . isUTC === 'true' ) {
time = s . utcToLocal ( time )
}
time = new Date ( time )
s . sqlQuery ( 'SELECT * FROM `Cloud Videos` WHERE ke=? AND mid=? AND `time`=? LIMIT 1' , [ req . params . ke , req . params . id , time ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
r = r [ 0 ]
req . pipe ( request ( r . href ) ) . pipe ( res )
} else {
res . end ( user . lang [ 'File Not Found in Database' ] )
}
} )
} , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Get Video File
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/videos/:ke/:id/:file' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
if ( user . permissions . watch _videos === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . monitors . indexOf ( req . params . id ) === - 1 ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
var time = s . nameToTime ( req . params . file )
if ( req . query . isUTC === 'true' ) {
time = s . utcToLocal ( time )
}
time = new Date ( time )
s . sqlQuery ( 'SELECT * FROM Videos WHERE ke=? AND mid=? AND `time`=? LIMIT 1' , [ req . params . ke , req . params . id , time ] , function ( err , r ) {
if ( r && r [ 0 ] ) {
2018-09-29 15:00:51 +00:00
req . dir = s . getVideoDirectory ( r [ 0 ] ) + req . params . file
2019-10-28 20:31:10 +00:00
fs . stat ( req . dir , function ( err , stats ) {
if ( ! err ) {
s . streamMp4FileOverHttp ( req . dir , req , res )
} else {
res . end ( user . lang [ 'File Not Found in Filesystem' ] )
}
} )
2018-09-28 05:37:08 +00:00
} else {
res . end ( user . lang [ 'File Not Found in Database' ] )
}
} )
} , res , req ) ;
} ) ;
2018-10-06 16:46:48 +00:00
/ * *
* API : Motion Trigger via GET request
* /
2019-01-24 06:15:17 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/motion/:ke/:id' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
if ( req . query . data ) {
try {
var d = {
id : req . params . id ,
ke : req . params . ke ,
2019-07-15 02:38:28 +00:00
details : s . parseJSON ( req . query . data )
2019-01-24 06:15:17 +00:00
}
} catch ( err ) {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
ok : false ,
msg : user . lang [ 'Data Broken' ]
} )
2019-01-24 06:15:17 +00:00
return
}
} else {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
ok : false ,
msg : user . lang [ 'No Data' ]
} )
2019-01-24 06:15:17 +00:00
return
}
if ( ! d . ke || ! d . id || ! s . group [ d . ke ] ) {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
ok : false ,
msg : user . lang [ 'No Group with this key exists' ]
} )
2019-01-24 06:15:17 +00:00
return
}
2019-07-15 01:02:15 +00:00
if ( ! s . group [ d . ke ] . rawMonitorConfigurations [ d . id ] ) {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
ok : false ,
msg : user . lang [ 'Monitor or Key does not exist.' ]
} )
2019-07-15 01:02:15 +00:00
return
}
var details = s . group [ d . ke ] . rawMonitorConfigurations [ d . id ] . details
var detectorHttpApi = details . detector _http _api
2019-07-15 02:38:28 +00:00
var detectorOn = ( details . detector === '1' )
2019-07-15 01:02:15 +00:00
switch ( detectorHttpApi ) {
case '0' :
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
2019-07-15 01:02:15 +00:00
ok : false ,
msg : user . lang [ 'Trigger Blocked' ]
} )
return
break ;
case '2' :
if ( ! detectorOn ) {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
2019-07-15 01:02:15 +00:00
ok : false ,
msg : user . lang [ 'Trigger Blocked' ]
} )
return
}
break ;
case '2' :
if ( detectorOn ) {
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
2019-07-15 01:02:15 +00:00
ok : false ,
msg : user . lang [ 'Trigger Blocked' ]
} )
return
}
break ;
}
2020-01-18 07:20:16 +00:00
d . doObjectDetection = ( ! d . details . matrices || d . details . matrices . length === 0 ) && ( s . isAtleatOneDetectorPluginConnected && details . detector _use _detect _object === '1' )
2019-01-24 06:15:17 +00:00
s . triggerEvent ( d )
2019-07-15 02:38:28 +00:00
s . closeJsonResponse ( res , {
2019-07-15 01:02:15 +00:00
ok : true ,
msg : user . lang [ 'Trigger Successful' ]
} )
2019-01-24 06:15:17 +00:00
} , res , req )
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : WebHook Tester
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/hookTester/:ke/:id' , function ( req , res ) {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
2018-10-07 18:45:38 +00:00
s . userLog ( req . params , { type : 'Test' , msg : 'Hook Test' } )
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( { ok : true } ) )
2018-09-28 05:37:08 +00:00
} , res , req ) ;
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : Camera PTZ Controller
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/control/:ke/:id/:direction' , function ( req , res ) {
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
2018-10-07 18:45:38 +00:00
s . cameraControl ( req . params , function ( resp ) {
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( resp ) )
2018-09-28 05:37:08 +00:00
} ) ;
} , res , req ) ;
} )
2018-10-06 16:46:48 +00:00
/ * *
2019-11-03 15:59:18 +00:00
* API : Upload Video File
2019-11-24 00:53:54 +00:00
* API : Add "streamIn" query string to Push to "Dashcam (Streamer v2)" FFMPEG Process
2019-11-03 15:59:18 +00:00
* /
app . post ( config . webPaths . apiPrefix + ':auth/videos/:ke/:id' , fileupload ( ) , async ( req , res ) => {
var response = { ok : false }
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
if ( user . permissions . watch _videos === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . video _delete . indexOf ( req . params . id ) === - 1 ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
2019-11-24 00:53:54 +00:00
var groupKey = req . params . ke
var monitorId = req . params . id
2019-11-03 15:59:18 +00:00
var origURL = req . originalUrl . split ( '/' )
var videoParam = origURL [ origURL . indexOf ( req . params . auth ) + 1 ]
var videoSet = 'Videos'
req . sql = 'SELECT * FROM `Monitors` WHERE ke=? AND mid=?' ;
2019-11-24 00:53:54 +00:00
req . ar = [ groupKey , monitorId ] ;
2019-11-03 15:59:18 +00:00
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( r && r [ 0 ] ) {
var monitor = r [ 0 ]
// req.query.overwrite === '1'
2019-11-24 00:53:54 +00:00
if ( s . group [ groupKey ] && s . group [ groupKey ] . activeMonitors [ monitorId ] ) {
2019-11-03 15:59:18 +00:00
try {
if ( ! req . files ) {
res . send ( {
status : false ,
message : 'No file uploaded'
} ) ;
} else {
let video = req . files . video ;
2019-11-24 00:53:54 +00:00
if ( req . query . streamIn === '1' ) {
var tempLocation = s . getStreamsDirectory ( monitor ) + video . name ;
video . mv ( tempLocation , function ( ) {
var fileStream = fs . createReadStream ( tempLocation )
fileStream . on ( 'close' , function ( ) {
} )
fileStream . on ( 'data' , function ( data ) {
try {
console . log ( data )
s . group [ groupKey ] . activeMonitors [ monitorId ] . spawn . stdin . write ( data ) ;
} catch ( err ) {
console . log ( err )
}
} )
// s.group[groupKey].activeMonitors[monitorId].spawn.stdin.write(fs.readFileSync(tempLocation,'binary'));
2019-11-03 15:59:18 +00:00
res . end ( s . prettyPrint ( {
ok : true ,
2019-11-24 00:53:54 +00:00
message : 'File is transcoding' ,
2019-11-03 15:59:18 +00:00
data : {
name : video . name ,
mimetype : video . mimetype ,
size : video . size
}
} ) )
2019-11-24 00:53:54 +00:00
} ) ;
} else {
var time = new Date ( parseInt ( video . name . split ( '.' ) [ 0 ] ) )
var filename = s . formattedTime ( time ) + '.' + monitor . ext
video . mv ( s . getVideoDirectory ( monitor ) + filename , function ( ) {
s . insertCompletedVideo ( monitor , {
file : filename ,
endTime : req . body . endTime . indexOf ( '-' ) > - 1 ? s . nameToTime ( req . body . endTime ) : parseInt ( req . body . endTime ) || null ,
} , function ( ) {
response . ok = true
response . filename = filename
res . end ( s . prettyPrint ( {
ok : true ,
message : 'File is uploaded' ,
data : {
name : video . name ,
mimetype : video . mimetype ,
size : video . size
}
} ) )
} )
} ) ;
}
2019-11-03 15:59:18 +00:00
}
} catch ( err ) {
response . err = err
2019-11-04 16:47:20 +00:00
res . status ( 500 ) . end ( response )
2019-11-03 15:59:18 +00:00
}
} else {
response . error = 'Non Existant Monitor'
res . end ( s . prettyPrint ( response ) )
}
} else {
response . msg = user . lang [ 'No such file' ]
res . end ( s . prettyPrint ( response ) )
}
} )
} , res , req ) ;
} )
/ * *
2018-10-06 16:46:48 +00:00
* API : Modify Video File
* /
2018-09-28 05:37:08 +00:00
app . get ( [
config . webPaths . apiPrefix + ':auth/videos/:ke/:id/:file/:mode' ,
config . webPaths . apiPrefix + ':auth/videos/:ke/:id/:file/:mode/:f' ,
config . webPaths . apiPrefix + ':auth/cloudVideos/:ke/:id/:file/:mode' ,
config . webPaths . apiPrefix + ':auth/cloudVideos/:ke/:id/:file/:mode/:f'
] , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
if ( user . permissions . watch _videos === "0" || user . details . sub && user . details . allmonitors !== '1' && user . details . video _delete . indexOf ( req . params . id ) === - 1 ) {
res . end ( user . lang [ 'Not Permitted' ] )
return
}
var time = s . nameToTime ( req . params . file )
if ( req . query . isUTC === 'true' ) {
time = s . utcToLocal ( time )
}
time = new Date ( time )
var origURL = req . originalUrl . split ( '/' )
var videoParam = origURL [ origURL . indexOf ( req . params . auth ) + 1 ]
var videoSet = 'Videos'
switch ( videoParam ) {
case 'cloudVideos' :
videoSet = 'Cloud Videos'
break ;
}
req . sql = 'SELECT * FROM `' + videoSet + '` WHERE ke=? AND mid=? AND `time`=?' ;
req . ar = [ req . params . ke , req . params . id , time ] ;
s . sqlQuery ( req . sql , req . ar , function ( err , r ) {
if ( r && r [ 0 ] ) {
r = r [ 0 ] ; r . filename = s . formattedTime ( r . time ) + '.' + r . ext ;
switch ( req . params . mode ) {
case 'fix' :
req . ret . ok = true ;
s . video ( 'fix' , r )
break ;
case 'status' :
r . f = 'video_edit'
switch ( videoParam ) {
case 'cloudVideos' :
r . f += '_cloud'
break ;
}
r . status = parseInt ( req . params . f )
if ( isNaN ( req . params . f ) || req . params . f === 0 ) {
req . ret . msg = 'Not a valid value.' ;
} else {
req . ret . ok = true ;
s . sqlQuery ( 'UPDATE `' + videoSet + '` SET status=? WHERE ke=? AND mid=? AND `time`=?' , [ req . params . f , req . params . ke , req . params . id , time ] )
s . tx ( r , 'GRP_' + r . ke ) ;
}
break ;
case 'delete' :
req . ret . ok = true ;
switch ( videoParam ) {
case 'cloudVideos' :
2018-09-29 15:00:51 +00:00
s . deleteVideoFromCloud ( r )
2018-09-28 05:37:08 +00:00
break ;
default :
2018-09-29 15:00:51 +00:00
s . deleteVideo ( r )
2018-09-28 05:37:08 +00:00
break ;
}
break ;
default :
req . ret . msg = user . lang . modifyVideoText1 ;
break ;
}
} else {
req . ret . msg = user . lang [ 'No such file' ] ;
}
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
} )
} , res , req ) ;
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : Stream In to push data to ffmpeg by HTTP
* /
2018-09-28 05:37:08 +00:00
app . all ( [ '/streamIn/:ke/:id' , '/streamIn/:ke/:id/:feed' ] , function ( req , res ) {
var checkOrigin = function ( search ) { return req . headers . host . indexOf ( search ) > - 1 }
if ( checkOrigin ( '127.0.0.1' ) ) {
if ( ! req . params . feed ) { req . params . feed = '1' }
2019-07-08 03:39:41 +00:00
if ( ! s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . streamIn [ req . params . feed ] ) {
s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . streamIn [ req . params . feed ] = new events . EventEmitter ( ) . setMaxListeners ( 0 )
2018-09-28 05:37:08 +00:00
}
//req.params.feed = Feed Number
res . connection . setTimeout ( 0 ) ;
req . on ( 'data' , function ( buffer ) {
2019-07-08 03:39:41 +00:00
s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . streamIn [ req . params . feed ] . emit ( 'data' , buffer )
2018-09-28 05:37:08 +00:00
} ) ;
req . on ( 'end' , function ( ) {
// console.log('streamIn closed',req.params);
} ) ;
} else {
res . end ( 'Local connection is only allowed.' )
}
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : FFprobe
* /
2018-09-28 05:37:08 +00:00
app . get ( config . webPaths . apiPrefix + ':auth/probe/:ke' , function ( req , res ) {
req . ret = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
switch ( req . query . action ) {
// case'stop':
// exec('kill -9 '+user.ffprobe.pid,{detatched: true})
// break;
default :
if ( ! req . query . url ) {
req . ret . error = 'Missing URL'
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
return
}
if ( user . ffprobe ) {
req . ret . error = 'Account is already probing'
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
return
}
user . ffprobe = 1 ;
if ( req . query . flags === 'default' ) {
req . query . flags = '-v quiet -print_format json -show_format -show_streams'
} else {
if ( ! req . query . flags ) {
req . query . flags = ''
}
}
req . probeCommand = s . splitForFFPMEG ( req . query . flags + ' -i ' + req . query . url ) . join ( ' ' )
exec ( 'ffprobe ' + req . probeCommand + ' | echo ' , function ( err , stdout , stderr ) {
delete ( user . ffprobe )
if ( err ) {
req . ret . error = ( err )
} else {
req . ret . ok = true
req . ret . result = stdout + stderr
}
req . ret . probe = req . probeCommand
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( req . ret ) ) ;
2018-09-28 05:37:08 +00:00
} )
break ;
}
} , res , req ) ;
} )
2018-10-06 16:46:48 +00:00
/ * *
* API : ONVIF Method Controller
* /
2019-10-28 20:31:10 +00:00
app . all ( [
config . webPaths . apiPrefix + ':auth/onvif/:ke/:id/:action' ,
config . webPaths . apiPrefix + ':auth/onvif/:ke/:id/:service/:action'
] , function ( req , res ) {
2018-09-28 05:37:08 +00:00
var response = { ok : false } ;
res . setHeader ( 'Content-Type' , 'application/json' ) ;
s . auth ( req . params , function ( user ) {
var errorMessage = function ( msg , error ) {
response . ok = false
response . msg = msg
response . error = error
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( response ) )
2018-09-28 05:37:08 +00:00
}
var actionCallback = function ( onvifActionResponse ) {
response . ok = true
if ( onvifActionResponse . data ) {
response . responseFromDevice = onvifActionResponse . data
} else {
response . responseFromDevice = onvifActionResponse
}
if ( onvifActionResponse . soap ) response . soap = onvifActionResponse . soap
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( response ) )
2018-09-28 05:37:08 +00:00
}
var isEmpty = function ( obj ) {
for ( var key in obj ) {
if ( obj . hasOwnProperty ( key ) )
return false ;
}
return true ;
}
var doAction = function ( Camera ) {
var completeAction = function ( command ) {
if ( command . then ) {
command . then ( actionCallback ) . catch ( function ( error ) {
2019-10-28 20:31:10 +00:00
errorMessage ( 'Device Action responded with an error' , error )
2018-09-28 05:37:08 +00:00
} )
} else if ( command ) {
response . ok = true
response . repsonseFromDevice = command
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( response ) )
2018-09-28 05:37:08 +00:00
} else {
response . error = 'Big Errors, Please report it to Shinobi Development'
2018-09-30 22:44:04 +00:00
res . end ( s . prettyPrint ( response ) )
2018-09-28 05:37:08 +00:00
}
}
var action
if ( req . params . service ) {
if ( Camera . services [ req . params . service ] === undefined ) {
return errorMessage ( 'This is not an available service. Please use one of the following : ' + Object . keys ( Camera . services ) . join ( ', ' ) )
}
if ( Camera . services [ req . params . service ] === null ) {
return errorMessage ( 'This service is not activated. Maybe you are not connected through ONVIF. You can test by attempting to use the "Control" feature with ONVIF in Shinobi.' )
}
action = Camera . services [ req . params . service ] [ req . params . action ]
} else {
action = Camera [ req . params . action ]
}
2019-10-28 20:31:10 +00:00
// console.log(s.parseJSON(req.query.options))
2018-09-28 05:37:08 +00:00
if ( ! action || typeof action !== 'function' ) {
errorMessage ( req . params . action + ' is not an available ONVIF function. See https://github.com/futomi/node-onvif for functions.' )
} else {
var argNames = s . getFunctionParamNames ( action )
var options
var command
if ( argNames [ 0 ] === 'options' || argNames [ 0 ] === 'params' ) {
options = { }
if ( req . query . options ) {
var jsonRevokedText = 'JSON not formated correctly'
try {
options = JSON . parse ( req . query . options )
} catch ( err ) {
return errorMessage ( jsonRevokedText , err )
}
} else if ( req . body . options ) {
try {
options = JSON . parse ( req . body . options )
} catch ( err ) {
return errorMessage ( jsonRevokedText , err )
}
} else if ( req . query . params ) {
try {
options = JSON . parse ( req . query . params )
} catch ( err ) {
return errorMessage ( jsonRevokedText , err )
}
} else if ( req . body . params ) {
try {
options = JSON . parse ( req . body . params )
} catch ( err ) {
return errorMessage ( jsonRevokedText , err )
}
}
}
if ( req . params . service ) {
command = Camera . services [ req . params . service ] [ req . params . action ] ( options )
} else {
command = Camera [ req . params . action ] ( options )
}
completeAction ( command )
}
}
2019-07-08 03:39:41 +00:00
if ( ! s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . onvifConnection ) {
2018-09-28 05:37:08 +00:00
//prepeare onvif connection
var controlURL
2019-07-08 03:39:41 +00:00
var monitorConfig = s . group [ req . params . ke ] . rawMonitorConfigurations [ req . params . id ]
2018-09-28 05:37:08 +00:00
if ( ! monitorConfig . details . control _base _url || monitorConfig . details . control _base _url === '' ) {
2018-09-29 01:38:14 +00:00
controlURL = s . buildMonitorUrl ( monitorConfig , true )
2018-09-28 05:37:08 +00:00
} else {
controlURL = monitorConfig . details . control _base _url
}
2018-10-07 18:45:38 +00:00
var controlURLOptions = s . cameraControlOptionsFromUrl ( controlURL , monitorConfig )
2018-09-28 05:37:08 +00:00
//create onvif connection
2019-07-08 03:39:41 +00:00
s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . onvifConnection = new onvif . OnvifDevice ( {
2018-09-28 05:37:08 +00:00
xaddr : 'http://' + controlURLOptions . host + ':' + controlURLOptions . port + '/onvif/device_service' ,
user : controlURLOptions . username ,
pass : controlURLOptions . password
} )
2019-07-08 03:39:41 +00:00
var device = s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . onvifConnection
2018-09-28 05:37:08 +00:00
device . init ( ) . then ( ( info ) => {
if ( info ) doAction ( device )
} ) . catch ( function ( error ) {
return errorMessage ( 'Device responded with an error' , error )
} )
} else {
2019-07-08 03:39:41 +00:00
doAction ( s . group [ req . params . ke ] . activeMonitors [ req . params . id ] . onvifConnection )
2018-09-28 05:37:08 +00:00
}
} , res , req ) ;
} )
2018-11-02 23:44:53 +00:00
/ * *
* API : Account Edit from Dashboard
* /
app . all ( config . webPaths . apiPrefix + ':auth/accounts/:ke/edit' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
var endData = {
ok : false
}
var form = s . getPostData ( req )
if ( form ) {
endData . ok = true
s . accountSettingsEdit ( {
ke : req . params . ke ,
uid : user . uid ,
form : form ,
cnid : user . cnid
} )
} else {
endData . msg = lang . postDataBroken
}
s . closeJsonResponse ( res , endData )
} , res , req )
} )
2018-12-04 16:34:59 +00:00
/ * *
2019-07-31 00:05:00 +00:00
* API : Get Definitions JSON
* /
app . get ( config . webPaths . apiPrefix + ':auth/definitions/:ke' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
var endData = {
ok : true ,
definitions : s . getDefinitonFile ( user . details . lang )
}
s . closeJsonResponse ( res , endData )
} , res , req )
} )
/ * *
* API : Get Language JSON
* /
app . get ( config . webPaths . apiPrefix + ':auth/language/:ke' , function ( req , res ) {
s . auth ( req . params , function ( user ) {
var endData = {
ok : true ,
definitions : s . getLanguageFile ( user . details . lang )
}
s . closeJsonResponse ( res , endData )
} , res , req )
} )
/ * *
2018-12-04 16:34:59 +00:00
* Robots . txt
* /
app . get ( '/robots.txt' , function ( req , res ) {
res . on ( 'finish' , function ( ) {
res . end ( )
} )
fs . createReadStream ( s . mainDirectory + '/web/pages/robots.txt' ) . pipe ( res )
} )
2018-09-28 05:37:08 +00:00
}