var fs = require('fs'); var os = require('os'); var moment = require('moment') var exec = require('child_process').exec; var spawn = require('child_process').spawn; var execSync = require('child_process').execSync; module.exports = function(s,config,lang,app){ const { deleteMonitor, } = require('./monitor/utils.js')(s,config,lang) /** * API : Administrator : Edit Sub-Account (Account to share cameras with) */ app.all(config.webPaths.adminApiPrefix+':auth/accounts/:ke/edit', function (req,res){ s.auth(req.params,async (user) => { var endData = { ok : false } const { isSubAccount, } = s.checkPermission(user) if(isSubAccount){ s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']}); return } var form = s.getPostData(req) var uid = form.uid || s.getPostData(req,'uid',false) var mail = (form.mail || s.getPostData(req,'mail',false) || '').trim() if(form){ var keys = ['details'] form.details = s.parseJSON(form.details) || {"sub": 1, "allmonitors": "1"} form.details.sub = 1 const updateQuery = { details: s.stringJSON(form.details) } if(form.pass && form.pass === form.password_again){ updateQuery.pass = s.createHash(form.pass) } if(form.mail){ const userCheck = await s.knexQueryPromise({ action: "select", columns: "*", table: "Users", where: [ ['mail','=',form.mail], ] }) if(userCheck.rows[0]){ const foundUser = userCheck.rows[0] if(foundUser.uid === form.uid){ updateQuery.mail = form.mail }else{ endData.msg = lang['Email address is in use.'] s.closeJsonResponse(res,endData) return } }else{ updateQuery.mail = form.mail } } await s.knexQueryPromise({ action: "update", table: "Users", update: updateQuery, where: [ ['ke','=',req.params.ke], ['uid','=',uid], ] }) s.tx({ f: 'edit_sub_account', ke: req.params.ke, uid: uid, mail: mail, form: form },'ADM_'+req.params.ke) endData.ok = true s.knexQuery({ action: "select", columns: "*", table: "API", where: [ ['ke','=',req.params.ke], ['uid','=',uid], ] },function(err,rows){ if(rows && rows[0]){ rows.forEach(function(row){ delete(s.api[row.code]) }) } }) }else{ endData.msg = lang.postDataBroken } s.closeJsonResponse(res,endData) },res,req) }) /** * API : Administrator : Delete Sub-Account (Account to share cameras with) */ app.all(config.webPaths.adminApiPrefix+':auth/accounts/:ke/delete', function (req,res){ s.auth(req.params,function(user){ const groupKey = req.params.ke; var endData = { ok : false } const { isSubAccount, } = s.checkPermission(user) if(isSubAccount){ s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']}); return } var form = s.getPostData(req) || {} var uid = form.uid || s.getPostData(req,'uid',false) s.knexQuery({ action: "select", columns: "*", table: "Users", where: [ ['ke','=',groupKey], ['uid','=',uid], ] },function(err,usersFound){ const theUserUpForDeletion = usersFound[0] if(theUserUpForDeletion){ s.knexQuery({ action: "delete", table: "Users", where: { ke: groupKey, uid: uid, } }) s.knexQuery({ action: "select", columns: "*", table: "API", where: [ ['ke','=',groupKey], ['uid','=',uid], ] },function(err,rows){ if(rows && rows[0]){ rows.forEach(function(row){ delete(s.api[row.code]) }) s.knexQuery({ action: "delete", table: "API", where: { ke: groupKey, uid: uid, } }) } }) s.tx({ f: 'delete_sub_account', ke: groupKey, uid: uid, mail: theUserUpForDeletion.mail },'ADM_'+groupKey) endData.ok = true }else{ endData.msg = user.lang['User Not Found'] } s.closeJsonResponse(res,endData) }) },res,req) }) /** * API : Administrator : Get Sub-Account List */ app.get(config.webPaths.adminApiPrefix+':auth/accounts/:ke', function (req,res){ s.auth(req.params,function(user){ var endData = { ok : false } const { isSubAccount, } = s.checkPermission(user) if(isSubAccount){ s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']}); return }else{ endData.ok = true s.knexQuery({ action: "select", columns: "ke,uid,mail,details", table: "Users", where: [ ['ke','=',req.params.ke], ['details','LIKE','%"sub"%'] ] },function(err,rows){ endData.accounts = rows s.closeJsonResponse(res,endData) }) } },res,req) }) /** * API : Administrator : Add Sub-Account (Account to share cameras with) */ app.post([ config.webPaths.adminApiPrefix+':auth/accounts/:ke/register', //these two routes are for backwards compatibility config.webPaths.adminApiPrefix+':auth/register/:ke/:uid', config.webPaths.apiPrefix+':auth/register/:ke/:uid' ],function (req,res){ endData = { ok : false } res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ const { isSubAccount, } = s.checkPermission(user) if(isSubAccount){ s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']}); return } var form = s.getPostData(req) if(form.mail !== '' && form.pass !== ''){ if(form.pass === form.password_again || form.pass === form.pass_again){ s.knexQuery({ action: "select", columns: "*", table: "Users", where: [ ['mail','=',form.mail], ] },function(err,r){ if(r && r[0]){ //found one exist endData.msg = lang['Email address is in use.'] }else{ //create new endData.msg = 'New Account Created' endData.ok = true var newId = s.gid() var details = s.s(Object.assign({ allmonitors: "1" },s.parseJSON(form.details) || {}, { sub: "1", })) s.knexQuery({ action: "insert", table: "Users", insert: { ke: req.params.ke, uid: newId, mail: form.mail, pass: s.createHash(form.pass), details: details, } }) s.tx({ f: 'add_sub_account', details: details, ke: req.params.ke, uid: newId, mail: form.mail },'ADM_'+req.params.ke) endData.user = { details: s.parseJSON(details), ke: req.params.ke, uid: newId, mail: form.mail } } res.end(s.prettyPrint(endData)) }) }else{ endData.msg = user.lang["Passwords Don't Match"] } }else{ endData.msg = user.lang['Fields cannot be empty'] } if(endData.msg){ res.end(s.prettyPrint(endData)) } },res,req) }) /** * API : Administrator : Monitor : Add, Edit, and Delete */ app.all([ config.webPaths.apiPrefix+':auth/configureMonitor/:ke/:id', config.webPaths.apiPrefix+':auth/configureMonitor/:ke/:id/:f', config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id', config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id/:f' ], function (req,res){ s.auth(req.params,async function(user){ let endData = { ok: false } const groupKey = req.params.ke const monitorId = req.params.id const { monitorPermissions, monitorRestrictions, } = s.getMonitorsPermitted(user.details,monitorId) const { isRestricted, isRestrictedApiKey, apiKeyPermissions, userPermissions, } = s.checkPermission(user) if( userPermissions.monitor_create_disallowed || isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed || isRestricted && !monitorPermissions[`${monitorId}_monitor_edit`] ){ s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']}); return } switch(req.params.f){ case'delete': endData = await deleteMonitor({ ke: groupKey, mid: monitorId, user: user, deleteFiles: req.query.deleteFiles === 'true', }); break; default: var form = s.getPostData(req) if(!form){ endData.msg = user.lang.monitorEditText1; s.closeJsonResponse(res,endData) return } form.mid = req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'') if(form && form.name){ s.checkDetails(form) form.ke = req.params.ke endData = await s.addOrEditMonitor(form,null,user) }else{ endData.msg = user.lang.monitorEditText1; } break; } s.closeJsonResponse(res,endData) },res,req) }) /** * API : Add API Key, binded to the user who created it */ app.all([ config.webPaths.adminApiPrefix+':auth/api/:ke/add', config.webPaths.apiPrefix+':auth/api/:ke/add', ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ var endData = { ok : false } var form = s.getPostData(req) if(form){ const insertQuery = { ke : req.params.ke, uid : user.uid, code : s.gid(30), ip : form.ip, details : s.stringJSON(form.details) } s.knexQuery({ action: "insert", table: "API", insert: insertQuery },(err,r) => { insertQuery.time = s.formattedTime(new Date,'YYYY-DD-MM HH:mm:ss'); insertQuery.details = s.parseJSON(insertQuery.details) if(!err){ s.tx({ f: 'api_key_added', uid: user.uid, form: insertQuery },'GRP_' + req.params.ke) endData.ok = true } endData.api = insertQuery s.closeJsonResponse(res,endData) }) }else{ endData.msg = lang.postDataBroken s.closeJsonResponse(res,endData) } },res,req) }) /** * API : Delete API Key */ app.all([ config.webPaths.adminApiPrefix+':auth/api/:ke/delete', config.webPaths.apiPrefix+':auth/api/:ke/delete', ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ var endData = { ok : false } var form = s.getPostData(req) || {} const code = form.code || s.getPostData(req,'code',false) if(!code){ s.tx({ f:'form_incomplete', uid: user.uid, form:'APIs' },'GRP_' + req.params.ke) endData.msg = lang.postDataBroken s.closeJsonResponse(res,endData) return } if(code){ s.knexQuery({ action: "delete", table: "API", where: { ke: req.params.ke, uid: user.uid, code: code, } },(err,r) => { if(!err){ s.tx({ f: 'api_key_deleted', uid: user.uid, form: { code: code } },'GRP_' + req.params.ke) endData.ok = true delete(s.api[code]) } s.closeJsonResponse(res,endData) }) }else{ endData.msg = lang.postDataBroken s.closeJsonResponse(res,endData) } },res,req) }) /** * API : List API Keys for Authenticated user */ app.get([ config.webPaths.adminApiPrefix+':auth/api/:ke/list', config.webPaths.apiPrefix+':auth/api/:ke/list', ],function (req,res){ var endData = {ok:false} res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ var endData = { ok : false } const whereQuery = { ke : req.params.ke, uid : user.uid } s.knexQuery({ action: "select", columns: "*", table: "API", where: whereQuery },function(err,rows) { if(rows && rows[0]){ rows.forEach(function(row){ row.details = JSON.parse(row.details) }) endData.ok = true endData.uid = user.uid endData.ke = user.ke endData.keys = rows } s.closeJsonResponse(res,endData) }) },res,req) }) /** * API : Administrator : Get Monitor State Presets List */ app.all([ config.webPaths.apiPrefix+':auth/monitorStates/:ke', config.webPaths.adminApiPrefix+':auth/monitorStates/:ke' ],function (req,res){ s.auth(req.params,function(user){ var endData = { ok : false } const groupKey = req.params.ke const { isRestricted, isRestrictedApiKey, apiKeyPermissions, userPermissions, } = s.checkPermission(user) if( userPermissions.monitor_create_disallowed || isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed ){ s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']}); return } s.knexQuery({ action: "select", columns: "*", table: "Presets", where: [ ['ke','=',req.params.ke], ['type','=','monitorStates'], ] },function(err,presets) { if(presets && presets[0]){ endData.ok = true presets.forEach(function(preset){ preset.details = JSON.parse(preset.details) }) } endData.presets = presets || [] s.closeJsonResponse(res,endData) }) }) }) /** * API : Administrator : Change Group Preset. Currently affects Monitors only. */ app.all([ config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName', config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName/:action', config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName', config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName/:action', ],function (req,res){ s.auth(req.params,function(user){ var endData = { ok : false } const groupKey = req.params.ke const { isRestricted, isRestrictedApiKey, apiKeyPermissions, userPermissions, } = s.checkPermission(user) if( userPermissions.monitor_create_disallowed || isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed ){ s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']}); return } var presetQueryVals = [req.params.ke,'monitorStates',req.params.stateName] switch(req.params.action){ case'insert':case'edit': var form = s.getPostData(req) s.checkDetails(form) if(!form || !form.monitors){ endData.msg = user.lang['Form Data Not Found'] s.closeJsonResponse(res,endData) return } s.findPreset(presetQueryVals,function(notFound,preset){ if(notFound === true){ endData.msg = lang["Inserted State Configuration"] var details = { monitors : form.monitors } var insertData = { ke: req.params.ke, name: req.params.stateName, details: s.s(details), type: 'monitorStates' } s.knexQuery({ action: "insert", table: "Presets", insert: insertData }) s.tx({ f: 'add_group_state', details: details, ke: req.params.ke, name: req.params.stateName },'GRP_'+req.params.ke) }else{ endData.msg = lang["Edited State Configuration"] var details = Object.assign(preset.details,{ monitors : form.monitors }) s.knexQuery({ action: "update", table: "Presets", update: { details: s.s(details) }, where: [ ['ke','=',req.params.ke], ['name','=',req.params.stateName], ] }) s.tx({ f: 'edit_group_state', details: details, ke: req.params.ke, name: req.params.stateName },'GRP_'+req.params.ke) } endData.ok = true s.closeJsonResponse(res,endData) }) break; case'delete': s.findPreset(presetQueryVals,function(notFound,preset){ if(notFound === true){ endData.msg = user.lang['State Configuration Not Found'] s.closeJsonResponse(res,endData) }else{ s.knexQuery({ action: "delete", table: "Presets", where: { ke: req.params.ke, name: req.params.stateName, } },(err) => { if(!err){ endData.msg = lang["Deleted State Configuration"] endData.ok = true } s.closeJsonResponse(res,endData) }) } }) break; default://change monitors according to state s.activateMonitorStates(req.params.ke,req.params.stateName,user,function(endData){ s.closeJsonResponse(res,endData) }) break; } },res,req) }) }