upgrade-sftp-uploader
Moe 2022-08-07 21:26:35 -07:00
commit c4627b3c62
31 changed files with 912 additions and 4410 deletions

View File

@ -7592,31 +7592,37 @@ module.exports = function(s,config,lang){
label: `${lang['Monitor Settings']}`, label: `${lang['Monitor Settings']}`,
pageOpen: 'monitorSettings', pageOpen: 'monitorSettings',
addUl: true, addUl: true,
eval: `!$user.details.sub || $user.details.monitor_create !== 0`,
}, },
{ {
icon: 'grav', icon: 'grav',
label: `${lang['Region Editor']}`, label: `${lang['Region Editor']}`,
pageOpen: 'regionEditor', pageOpen: 'regionEditor',
eval: `!$user.details.sub`,
}, },
{ {
icon: 'filter', icon: 'filter',
label: `${lang['Event Filters']}`, label: `${lang['Event Filters']}`,
pageOpen: 'eventFilters', pageOpen: 'eventFilters',
eval: `!$user.details.sub`,
}, },
{ {
icon: 'align-right', icon: 'align-right',
label: `${lang['Monitor States']}`, label: `${lang['Monitor States']}`,
pageOpen: 'monitorStates', pageOpen: 'monitorStates',
eval: `!$user.details.sub`,
}, },
{ {
icon: 'clock', icon: 'clock',
label: `${lang['Schedules']}`, label: `${lang['Schedules']}`,
pageOpen: 'schedules', pageOpen: 'schedules',
eval: `!$user.details.sub`,
}, },
{ {
icon: 'exclamation-triangle', icon: 'exclamation-triangle',
label: `${lang['Logs']}`, label: `${lang['Logs']}`,
pageOpen: 'logViewer', pageOpen: 'logViewer',
eval: `!$user.details.sub || $user.details.view_logs !== 0`,
}, },
{ {
divider: true, divider: true,
@ -7625,6 +7631,7 @@ module.exports = function(s,config,lang){
icon: 'gears', icon: 'gears',
label: `${lang['Account Settings']}`, label: `${lang['Account Settings']}`,
pageOpen: 'accountSettings', pageOpen: 'accountSettings',
eval: `!$user.details.sub || $user.details.user_change !== 0`,
addUl: true, addUl: true,
}, },
{ {
@ -7632,6 +7639,7 @@ module.exports = function(s,config,lang){
label: `${lang.subAccountManager}`, label: `${lang.subAccountManager}`,
pageOpen: 'subAccountManager', pageOpen: 'subAccountManager',
addUl: true, addUl: true,
eval: `!$user.details.sub`,
}, },
{ {
icon: 'key', icon: 'key',
@ -7645,12 +7653,14 @@ module.exports = function(s,config,lang){
icon: 'search', icon: 'search',
label: `${lang['ONVIF Scanner']}`, label: `${lang['ONVIF Scanner']}`,
pageOpen: 'onvifScanner', pageOpen: 'onvifScanner',
addUl:true addUl:true,
eval: `!$user.details.sub || $user.details.monitor_create !== 0`,
}, },
{ {
icon: 'opera', icon: 'opera',
label: `${lang['ONVIF Device Manager']}`, label: `${lang['ONVIF Device Manager']}`,
pageOpen: 'onvifDeviceManager', pageOpen: 'onvifDeviceManager',
eval: `!$user.details.sub || $user.details.monitor_create !== 0`,
}, },
{ {
icon: 'eyedropper', icon: 'eyedropper',
@ -7662,6 +7672,7 @@ module.exports = function(s,config,lang){
label: `${lang['ShinobiHub']}`, label: `${lang['ShinobiHub']}`,
pageOpen: 'configFinder', pageOpen: 'configFinder',
addUl: true, addUl: true,
eval: `!$user.details.sub || $user.details.monitor_create !== 0`,
}, },
{ {
divider: true, divider: true,
@ -8449,32 +8460,62 @@ module.exports = function(s,config,lang){
"Editor": { "Editor": {
noHeader: true, noHeader: true,
"color": "grey", "color": "grey",
"noDefaultSectionClasses": true,
"box-wrapper-class": "row",
"info": [ "info": [
{ {
"name": "mail", isFormGroupGroup: true,
"field": lang.Email, "noHeader": true,
"section-pre-class": "col-md-6",
info: [
{
"name": "mail",
"field": lang.Email,
},
{
"name": "pass",
"type": "password",
"fieldType": "password",
"field": lang['Password'],
},
{
"name": "pass_again",
"type": "password",
"fieldType": "password",
"field": lang['Password Again'],
},
{
"fieldType": "btn-group",
"btns": [
{
"fieldType": "btn",
"class": `submit btn-success`,
"btnContent": `${lang['Save']}`,
},
],
},
]
}, },
{ {
"name": "pass", isFormGroupGroup: true,
"type": "password", "name": lang["API Keys"],
"fieldType": "password", "section-pre-class": "col-md-6",
"field": lang['Password'], info: [
}, {
{ "fieldType": "btn-group",
"name": "pass_again", "btns": [
"type": "password", {
"fieldType": "password", "fieldType": "btn",
"field": lang['Password Again'], "class": `new-token btn-success`,
}, "btnContent": `${lang['Add']}`,
{ },
"fieldType": "btn-group", ],
"btns": [ },
{ {
"fieldType": "btn", "id": "super-tokens",
"class": `submit btn-success`, "fieldType": "div",
"btnContent": `${lang['Save']}`, },
}, ]
],
}, },
] ]
} }

View File

@ -78,24 +78,21 @@ module.exports = function(s,config,lang){
var isSessionKey = false var isSessionKey = false
if(apiKey){ if(apiKey){
var sessionKey = params.auth var sessionKey = params.auth
createSession(apiKey,{
auth: sessionKey,
permissions: s.parseJSON(apiKey.details),
details: {}
})
getUserByUid(apiKey,'mail,details',function(err,user){ getUserByUid(apiKey,'mail,details',function(err,user){
if(user){ if(user){
try{ createSession(apiKey,{
editSession({ auth: sessionKey,
auth: sessionKey permissions: s.parseJSON(apiKey.details),
},{ mail: user.mail,
mail: user.mail, details: s.parseJSON(user.details),
details: s.parseJSON(user.details), lang: s.getLanguageFile(user.details.lang)
lang: s.getLanguageFile(user.details.lang) })
}) }else{
}catch(er){ createSession(apiKey,{
console.log('FAILED TO EDIT',er) auth: sessionKey,
} permissions: s.parseJSON(apiKey.details),
details: {}
})
} }
callback(err,s.api[params.auth]) callback(err,s.api[params.auth])
}) })

View File

@ -14,7 +14,7 @@ module.exports = function(s,config,lang,app,io){
if(!config.logoLocation196x196)config.logoLocation196x196 = 'libs/img/icon/favicon-196x196.png'; if(!config.logoLocation196x196)config.logoLocation196x196 = 'libs/img/icon/favicon-196x196.png';
if(config.logoLocation76x76Link === undefined){config.logoLocation76x76Link='https://shinobi.video'} if(config.logoLocation76x76Link === undefined){config.logoLocation76x76Link='https://shinobi.video'}
if(config.logoLocation76x76Style === undefined){config.logoLocation76x76Style='border-radius:50%'} if(config.logoLocation76x76Style === undefined){config.logoLocation76x76Style='border-radius:50%'}
if(config.loginScreenBackground === undefined){config.loginScreenBackground='https://shinobi.video/libs/assets/backgrounds/7.jpg'} if(config.loginScreenBackground === undefined){config.loginScreenBackground='assets/img/splash.avif'}
if(config.showLoginSelector === undefined){config.showLoginSelector=true} if(config.showLoginSelector === undefined){config.showLoginSelector=true}
if(config.defaultTheme === undefined)config.defaultTheme = 'Ice-v3'; if(config.defaultTheme === undefined)config.defaultTheme = 'Ice-v3';
if(config.socialLinks === undefined){ if(config.socialLinks === undefined){

View File

@ -87,11 +87,11 @@ module.exports = function(s,config){
const knexError = (dbQuery,options,err) => { const knexError = (dbQuery,options,err) => {
console.error('knexError----------------------------------- START') console.error('knexError----------------------------------- START')
if(config.debugLogVerbose && config.debugLog === true){ if(config.debugLogVerbose && config.debugLog === true){
s.debugLog('s.knexQuery QUERY',JSON.stringify(options,null,3))
s.debugLog('STACK TRACE, NOT AN ',new Error()) s.debugLog('STACK TRACE, NOT AN ',new Error())
} }
console.error(err) console.error(err)
console.error(dbQuery.toString()) // CANNOT USE `dbQuery.toString()` because it breaks the query
console.error(options)
console.error('knexError----------------------------------- END') console.error('knexError----------------------------------- END')
} }
const knexQuery = (options,callback) => { const knexQuery = (options,callback) => {
@ -149,7 +149,8 @@ module.exports = function(s,config){
} }
} }
if(config.debugLog === true){ if(config.debugLog === true){
console.log(dbQuery.toString()) // CANNOT USE `dbQuery.toString()` because it breaks the query
console.log(options)
} }
if(callback || options.update || options.insert || options.action === 'delete'){ if(callback || options.update || options.insert || options.action === 'delete'){
dbQuery.asCallback(function(err,r) { dbQuery.asCallback(function(err,r) {

View File

@ -215,12 +215,20 @@ module.exports = function(s,config,lang,app,io){
} }
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ monitorPermissions,
s.closeJsonResponse(res,{ monitorRestrictions,
ok: false, } = s.getMonitorsPermitted(user.details,monitorId)
msg: lang['Not Permitted'] const {
}) isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_view`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
s.knexQuery({ s.knexQuery({

View File

@ -1773,6 +1773,7 @@ module.exports = function(s,config,lang){
monitorRestrictions.push(['or','mid','=',v]) monitorRestrictions.push(['or','mid','=',v])
} }
}) })
console.log(monitorRestrictions)
}catch(er){ }catch(er){
} }
}else if( }else if(
@ -1790,20 +1791,104 @@ module.exports = function(s,config,lang){
){} ){}
return monitorRestrictions return monitorRestrictions
} }
// s.checkViewerConnectionsForMonitor = function(monitorObject){ s.checkPermission = (user) => {
// var monitorConfig = s.group[monitorObject.ke].rawMonitorConfigurations[monitorObject.mid] // provide "user" object given from "s.auth"
// if(monitorConfig.mode === 'start'){ const isSubAccount = !!user.details.sub
// const response = {
// } isSubAccount,
// } hasAllPermissions: isSubAccount && user.details.allmonitors === '1',
// s.addViewerConnectionForMonitor = function(monitorObject,viewerDetails){ isRestricted: isSubAccount && user.details.allmonitors !== '1',
// s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnection[viewerDetails.viewerId] = viewerDetails isRestrictedApiKey: false,
// s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnectionCount += 1 apiKeyPermissions: {},
// return s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnectionCount userPermissions: {},
// } }
// s.removeViewerConnectionForMonitor = function(monitorObject,viewerDetails){ const permissions = user.permissions
// delete(s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnection[viewerDetails.viewerId]) const details = user.details;
// s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnectionCount -= 1 [
// return s.group[monitorObject.ke].activeMonitors[monitorObject.mid].viewerConnectionCount 'auth_socket',
// } 'get_monitors',
'control_monitors',
'get_logs',
'watch_stream',
'watch_snapshot',
'watch_videos',
'delete_videos',
].forEach((key) => {
const permissionOff = permissions[key] === '0';
response.apiKeyPermissions[key] = permissions[key] === '1';
response.apiKeyPermissions[`${key}_disallowed`] = permissionOff;
response.isRestrictedApiKey = response.isRestrictedApiKey || permissionOff;
});
// Base Level Permissions
// allmonitors : All Monitors and Privileges
// monitor_create : Can Create and Delete Monitors
// user_change : Can Change User Settings
// view_logs : Can View Logs
[
'allmonitors',
'monitor_create',
'user_change',
'view_logs',
].forEach((key) => {
response.userPermissions[key] = details[key] === '1' || !details[key];
response.userPermissions[`${key}_disallowed`] = details[key] === '0';
});
return response
}
s.getMonitorsPermitted = (userDetails,monitorId) => {
const monitorRestrictions = []
const monitors = {}
function setMonitorPermissions(mid){
// monitors : Can View Monitor
// monitor_edit : Can Edit Monitor (Delete as well)
// video_view : Can View Videos and Events
// video_delete : Can Delete Videos and Events
[
'monitors',
'monitor_edit',
'video_view',
'video_delete',
].forEach((key) => {
monitors[`${mid}_${key}`] = userDetails[key] && userDetails[key].indexOf(mid) > -1 || false;
});
return true
}
function addToQuery(mid,n){
if(n === 0){
monitorRestrictions.push(['mid','=',mid])
}else{
monitorRestrictions.push(['or','mid','=',mid])
}
};
if(
!monitorId &&
userDetails.sub &&
userDetails.monitors &&
userDetails.allmonitors !== '1'
){
try{
userDetails.monitors = s.parseJSON(userDetails.monitors)
userDetails.monitors.forEach(function(v,n){
setMonitorPermissions(v)
addToQuery(v,n)
})
}catch(err){
s.debugLog(err)
}
}else if(
monitorId && (
!userDetails.sub ||
userDetails.allmonitors !== '0' ||
userDetails.monitors.indexOf(monitorId) >- 1
)
){
setMonitorPermissions(monitorId)
addToQuery(monitorId,0)
}
return {
monitorPermissions: monitors,
// queryConditions
monitorRestrictions: monitorRestrictions,
}
}
} }

View File

@ -26,10 +26,26 @@ module.exports = function(s,config,lang,app,io){
*/ */
app.get(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id',function (req,res){ app.get(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id',function (req,res){
s.auth(req.params,async (user) => { s.auth(req.params,async (user) => {
const groupKey = req.params.ke
const monitorId = req.params.id
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.get_monitors_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_monitors`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return
}
const endData = {ok: true} const endData = {ok: true}
try{ try{
const groupKey = req.params.ke
const monitorId = req.params.id
const onvifDevice = await getOnvifDevice(groupKey,monitorId) const onvifDevice = await getOnvifDevice(groupKey,monitorId)
const cameraInfo = await getUIFieldValues(onvifDevice) const cameraInfo = await getUIFieldValues(onvifDevice)
endData.onvifData = cameraInfo endData.onvifData = cameraInfo
@ -46,11 +62,29 @@ module.exports = function(s,config,lang,app,io){
*/ */
app.post(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id/save',function (req,res){ app.post(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id/save',function (req,res){
s.auth(req.params,async (user) => { s.auth(req.params,async (user) => {
const groupKey = req.params.ke
const monitorId = req.params.id
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId);
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed
){
s.closeJsonResponse(res,{
ok: false,
msg: lang['Not Authorized']
});
return
}
const endData = {ok: true} const endData = {ok: true}
const responses = {} const responses = {}
try{ try{
const groupKey = req.params.ke
const monitorId = req.params.id
const onvifDevice = await getOnvifDevice(groupKey,monitorId) const onvifDevice = await getOnvifDevice(groupKey,monitorId)
const form = s.getPostData(req) const form = s.getPostData(req)
const videoToken = form.VideoConfiguration && form.VideoConfiguration.videoToken ? form.VideoConfiguration.videoToken : null const videoToken = form.VideoConfiguration && form.VideoConfiguration.videoToken ? form.VideoConfiguration.videoToken : null
@ -100,10 +134,28 @@ module.exports = function(s,config,lang,app,io){
*/ */
app.get(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id/reboot',function (req,res){ app.get(config.webPaths.apiPrefix+':auth/onvifDeviceManager/:ke/:id/reboot',function (req,res){
s.auth(req.params,async (user) => { s.auth(req.params,async (user) => {
const groupKey = req.params.ke
const monitorId = req.params.id
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId);
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed
){
s.closeJsonResponse(res,{
ok: false,
msg: lang['Not Authorized']
});
return
}
const endData = {ok: true} const endData = {ok: true}
try{ try{
const groupKey = req.params.ke
const monitorId = req.params.id
const onvifDevice = await getOnvifDevice(groupKey,monitorId) const onvifDevice = await getOnvifDevice(groupKey,monitorId)
const cameraInfo = await rebootCamera(onvifDevice) const cameraInfo = await rebootCamera(onvifDevice)
endData.onvifData = cameraInfo endData.onvifData = cameraInfo

View File

@ -21,6 +21,20 @@ module.exports = function(s,config,lang,app,io){
*/ */
app.get(config.webPaths.apiPrefix+':auth/probe/:ke',function (req,res){ app.get(config.webPaths.apiPrefix+':auth/probe/:ke',function (req,res){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed
){
s.closeJsonResponse(res,{
ok: false,
msg: lang['Not Authorized']
});
return
}
ffprobe(req.query.url,req.params.auth,(endData) => { ffprobe(req.query.url,req.params.auth,(endData) => {
s.closeJsonResponse(res,endData) s.closeJsonResponse(res,endData)
}) })

View File

@ -194,9 +194,11 @@ module.exports = function(s,config,lang,app,io){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const {
endData.msg = user.lang['Not Permitted'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
} }
var whereQuery = [ var whereQuery = [
@ -234,9 +236,11 @@ module.exports = function(s,config,lang,app,io){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const {
endData.msg = user.lang['Not Permitted'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
} }
switch(req.params.action){ switch(req.params.action){

View File

@ -431,19 +431,27 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' const monitorId = req.params.id
const groupKey = req.params.ke
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if( if(
user.permissions.watch_videos==="0" || isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
hasRestrictions && isRestricted && (
( monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
!user.details.video_view || monitorRestrictions.length === 0
user.details.video_view.indexOf(req.params.id) === -1
) )
){ ){
s.closeJsonResponse(res,[]) s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], frames: []});
return return
} }
const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id)
s.getDatabaseRows({ s.getDatabaseRows({
monitorRestrictions: monitorRestrictions, monitorRestrictions: monitorRestrictions,
table: 'Timelapse Frames', table: 'Timelapse Frames',
@ -474,23 +482,21 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' const actionParameter = !!req.params.action
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if( if(
user.permissions.watch_videos==="0" || isRestrictedApiKey && apiKeyPermissions.delete_videos_disallowed ||
hasRestrictions && isRestricted && !monitorPermissions[`${monitorId}_video_delete`]
(
!user.details.video_view ||
user.details.video_view.indexOf(req.params.id) === -1
)
){ ){
s.closeJsonResponse(res,[]) s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return
}
const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id)
if(monitorRestrictions.length === 0){
s.closeJsonResponse(res,{
ok: false
})
return return
} }
const framesPerSecond = s.getPostData(req, 'fps') const framesPerSecond = s.getPostData(req, 'fps')
@ -514,15 +520,31 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' const groupKey = req.params.ke
const monitorId = req.params.id
const actionParameter = !!req.params.action
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if( if(
user.permissions.watch_videos==="0" || actionParameter && (
hasRestrictions && (!user.details.video_view || user.details.video_view.indexOf(req.params.id)===-1) isRestrictedApiKey && apiKeyPermissions.delete_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_delete`]
) ||
!actionParameter && (
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && monitorId && !monitorPermissions[`${monitorId}_video_view`]
)
){ ){
res.end(s.prettyPrint([])) s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id)
const cacheKey = req.params.ke + req.params.id + req.params.filename const cacheKey = req.params.ke + req.params.id + req.params.filename
const processFrame = (frame) => { const processFrame = (frame) => {
var fileLocation var fileLocation
@ -536,7 +558,7 @@ module.exports = function(s,config,lang,app,io){
selectedDate = req.params.filename.split('T')[0] selectedDate = req.params.filename.split('T')[0]
} }
fileLocation = `${fileLocation}${frame.ke}/${frame.mid}_timelapse/${selectedDate}/${req.params.filename}` fileLocation = `${fileLocation}${frame.ke}/${frame.mid}_timelapse/${selectedDate}/${req.params.filename}`
if(req.params.action === 'delete'){ if(actionParameter === 'delete'){
deleteTimelapseFrame({ deleteTimelapseFrame({
ke: frame.ke, ke: frame.ke,
mid: frame.mid, mid: frame.mid,

View File

@ -16,9 +16,11 @@ module.exports = function(s,config,lang,app){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const {
endData.msg = user.lang['Not Permitted'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
} }
var form = s.getPostData(req) var form = s.getPostData(req)
@ -103,9 +105,11 @@ module.exports = function(s,config,lang,app){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const {
endData.msg = user.lang['Not Permitted'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
} }
var form = s.getPostData(req) || {} var form = s.getPostData(req) || {}
@ -174,9 +178,11 @@ module.exports = function(s,config,lang,app){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const {
endData.msg = user.lang['Not Permitted'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
}else{ }else{
endData.ok = true endData.ok = true
@ -209,9 +215,11 @@ module.exports = function(s,config,lang,app){
} }
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
if(user.details.sub){ const {
endData.msg = user.lang['Not an Administrator Account'] isSubAccount,
s.closeJsonResponse(res,endData) } = s.checkPermission(user)
if(isSubAccount){
s.closeJsonResponse(res,{ok: false, msg: lang['Not an Administrator Account']});
return return
} }
var form = s.getPostData(req) var form = s.getPostData(req)
@ -290,7 +298,26 @@ module.exports = function(s,config,lang,app){
} }
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
var hasRestrictions = user.details.sub && user.details.allmonitors !== '1' 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
}
if(req.params.f !== 'delete'){ if(req.params.f !== 'delete'){
var form = s.getPostData(req) var form = s.getPostData(req)
if(!form){ if(!form){
@ -299,66 +326,46 @@ module.exports = function(s,config,lang,app){
return return
} }
form.mid = req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'') form.mid = req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'')
if(!user.details.sub || if(form && form.name){
user.details.allmonitors === '1' || s.checkDetails(form)
hasRestrictions && user.details.monitor_edit.indexOf(form.mid) >- 1 || form.ke = req.params.ke
hasRestrictions && user.details.monitor_create === '1'){ s.addOrEditMonitor(form,function(err,endData){
if(form && form.name){
s.checkDetails(form)
form.ke = req.params.ke
s.addOrEditMonitor(form,function(err,endData){
res.end(s.prettyPrint(endData))
},user)
}else{
endData.msg = user.lang.monitorEditText1;
res.end(s.prettyPrint(endData))
}
}else{
endData.msg = user.lang['Not Permitted']
res.end(s.prettyPrint(endData)) res.end(s.prettyPrint(endData))
},user)
}else{
endData.msg = user.lang.monitorEditText1;
res.end(s.prettyPrint(endData))
} }
}else{ }else{
if(!user.details.sub || user.details.allmonitors === '1' || user.details.monitor_edit.indexOf(req.params.id) > -1 || hasRestrictions && user.details.monitor_create === '1'){ s.userLog({
s.userLog({ ke: req.params.ke,
mid: req.params.id
},{
type: 'Monitor Deleted',
msg: 'by user : '+user.uid
});
req.params.delete=1;
s.camera('stop',req.params);
s.tx({f:'monitor_delete',uid:user.uid,mid:req.params.id,ke:req.params.ke},'GRP_'+req.params.ke);
s.knexQuery({
action: "delete",
table: "Monitors",
where: {
ke: req.params.ke, ke: req.params.ke,
mid: req.params.id mid: req.params.id,
},{ }
type: 'Monitor Deleted', })
msg: 'by user : '+user.uid if(req.query.deleteFiles === 'true'){
}); deleteMonitorData(req.params.ke,req.params.id).then(() => {
req.params.delete=1;s.camera('stop',req.params); s.debugLog(`Deleted Monitor Data`,{
s.tx({f:'monitor_delete',uid:user.uid,mid:req.params.id,ke:req.params.ke},'GRP_'+req.params.ke);
s.knexQuery({
action: "delete",
table: "Monitors",
where: {
ke: req.params.ke, ke: req.params.ke,
mid: req.params.id, mid: req.params.id,
}
})
// s.knexQuery({
// action: "delete",
// table: "Files",
// where: {
// ke: req.params.ke,
// mid: req.params.id,
// }
// })
if(req.query.deleteFiles === 'true'){
deleteMonitorData(req.params.ke,req.params.id).then(() => {
s.debugLog(`Deleted Monitor Data`,{
ke: req.params.ke,
mid: req.params.id,
})
}) })
} })
endData.ok=true;
endData.msg='Monitor Deleted by user : '+user.uid
res.end(s.prettyPrint(endData))
}else{
endData.msg=user.lang['Not Permitted'];
res.end(s.prettyPrint(endData))
} }
endData.ok=true;
endData.msg='Monitor Deleted by user : '+user.uid
res.end(s.prettyPrint(endData))
} }
},res,req) },res,req)
}) })
@ -509,9 +516,18 @@ module.exports = function(s,config,lang,app){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const groupKey = req.params.ke
endData.msg = user.lang['Not Permitted'] const {
s.closeJsonResponse(res,endData) 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 return
} }
s.knexQuery({ s.knexQuery({
@ -547,9 +563,18 @@ module.exports = function(s,config,lang,app){
var endData = { var endData = {
ok : false ok : false
} }
if(user.details.sub){ const groupKey = req.params.ke
endData.msg = user.lang['Not Permitted'] const {
s.closeJsonResponse(res,endData) 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 return
} }
var presetQueryVals = [req.params.ke,'monitorStates',req.params.stateName] var presetQueryVals = [req.params.ke,'monitorStates',req.params.stateName]

View File

@ -647,8 +647,22 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.get_monitors_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_monitors`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,[]); s.closeJsonResponse(res,[]);
return return
} }
@ -752,8 +766,22 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,(user) => { s.auth(req.params,(user) => {
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){ monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.get_monitors_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_monitors`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,[]); s.closeJsonResponse(res,[]);
return return
} }
@ -831,11 +859,19 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,async (user) => { s.auth(req.params,async (user) => {
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
userPermissions,
apiKeyPermissions,
isRestrictedApiKey,
} = s.checkPermission(user)
if( if(
user.permissions.control_monitors === "0" || isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed ||
user.details.sub && isRestricted && !monitorPermissions[`${monitorId}_monitor_edit`]
user.details.allmonitors !== '1' &&
user.details.monitor_edit.indexOf(monitorId) === -1
){ ){
response.msg = user.lang['Not Permitted'] response.msg = user.lang['Not Permitted']
}else{ }else{
@ -860,64 +896,64 @@ module.exports = function(s,config,lang,app,io){
s.closeJsonResponse(res,response); s.closeJsonResponse(res,response);
},res,req); },res,req);
}); });
/** // /**
* API : Merge Recorded Videos into one file // * API : Merge Recorded Videos into one file
*/ // */
app.get(config.webPaths.apiPrefix+':auth/videosMerge/:ke', function (req,res){ // app.get(config.webPaths.apiPrefix+':auth/videosMerge/:ke', function (req,res){
var failed = function(resp){ // var failed = function(resp){
res.setHeader('Content-Type', 'application/json'); // res.setHeader('Content-Type', 'application/json');
res.end(s.prettyPrint(resp)) // res.end(s.prettyPrint(resp))
} // }
if(req.query.videos && req.query.videos !== ''){ // if(req.query.videos && req.query.videos !== ''){
s.auth(req.params,function(user){ // s.auth(req.params,function(user){
var videosSelected = JSON.parse(req.query.videos) // var videosSelected = JSON.parse(req.query.videos)
const whereQuery = [] // const whereQuery = []
var didOne = false // var didOne = false
videosSelected.forEach(function(video){ // videosSelected.forEach(function(video){
var time = s.nameToTime(video.filename) // var time = s.nameToTime(video.filename)
if(req.query.isUTC === 'true'){ // if(req.query.isUTC === 'true'){
time = s.utcToLocal(time) // time = s.utcToLocal(time)
} // }
if(didOne){ // if(didOne){
whereQuery.push(['or','ke','=',req.params.ke]) // whereQuery.push(['or','ke','=',req.params.ke])
}else{ // }else{
didOne = true // didOne = true
whereQuery.push(['ke','=',req.params.ke]) // whereQuery.push(['ke','=',req.params.ke])
} // }
whereQuery.push( // whereQuery.push(
['mid','=',video.mid], // ['mid','=',video.mid],
['time','=',time], // ['time','=',time],
) // )
//
}) // })
s.knexQuery({ // s.knexQuery({
action: "select", // action: "select",
columns: "*", // columns: "*",
table: "Videos", // table: "Videos",
where: whereQuery // where: whereQuery
},(err,r) => { // },(err,r) => {
var resp = {ok: false} // var resp = {ok: false}
if(r && r[0]){ // if(r && r[0]){
s.mergeRecordedVideos(r,req.params.ke,function(fullPath,filename){ // s.mergeRecordedVideos(r,req.params.ke,function(fullPath,filename){
res.setHeader('Content-Disposition', 'attachment; filename="'+filename+'"') // res.setHeader('Content-Disposition', 'attachment; filename="'+filename+'"')
var file = fs.createReadStream(fullPath) // var file = fs.createReadStream(fullPath)
file.on('close',function(){ // file.on('close',function(){
setTimeout(function(){ // setTimeout(function(){
s.file('delete',fullPath) // s.file('delete',fullPath)
},1000 * 60 * 3) // },1000 * 60 * 3)
res.end() // res.end()
}) // })
file.pipe(res) // file.pipe(res)
}) // })
}else{ // }else{
failed({ok:false,msg:'No Videos Found'}) // failed({ok:false,msg:'No Videos Found'})
} // }
}) // })
},res,req); // },res,req);
}else{ // }else{
failed({ok:false,msg:'"videos" query variable is missing from request.'}) // failed({ok:false,msg:'"videos" query variable is missing from request.'})
} // }
}) // })
/** /**
* API : Get Videos * API : Get Videos
*/ */
@ -929,10 +965,27 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const userDetails = user.details
const monitorId = req.params.id const monitorId = req.params.id
const groupKey = req.params.ke const groupKey = req.params.ke
const hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1'; const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], videos: []});
return
}
var origURL = req.originalUrl.split('/') var origURL = req.originalUrl.split('/')
var videoParam = origURL[origURL.indexOf(req.params.auth) + 1] var videoParam = origURL[origURL.indexOf(req.params.auth) + 1]
var videoSet = 'Videos' var videoSet = 'Videos'
@ -957,11 +1010,7 @@ module.exports = function(s,config,lang,app,io){
endIsStartTo: !!req.query.endIsStartTo, endIsStartTo: !!req.query.endIsStartTo,
parseRowDetails: false, parseRowDetails: false,
rowName: 'videos', rowName: 'videos',
preliminaryValidationFailed: ( preliminaryValidationFailed: false
user.permissions.watch_videos === "0" ||
hasRestrictions &&
(!userDetails.video_view || userDetails.video_view.indexOf(monitorId)===-1)
)
},(response) => { },(response) => {
if(response && response.videos){ if(response && response.videos){
s.buildVideoLinks(response.videos,{ s.buildVideoLinks(response.videos,{
@ -986,10 +1035,27 @@ module.exports = function(s,config,lang,app,io){
const searchQuery = s.getPostData(req,'search') const searchQuery = s.getPostData(req,'search')
const startTime = s.getPostData(req,'start') const startTime = s.getPostData(req,'start')
const endTime = s.getPostData(req,'end') const endTime = s.getPostData(req,'end')
const userDetails = user.details
const monitorId = req.params.id const monitorId = req.params.id
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], videos: []});
return
}
getVideosBasedOnTagFoundInMatrixOfAssociatedEvent({ getVideosBasedOnTagFoundInMatrixOfAssociatedEvent({
groupKey, groupKey,
monitorId, monitorId,
@ -1020,17 +1086,28 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const userDetails = user.details
const monitorId = req.params.id const monitorId = req.params.id
const groupKey = req.params.ke const groupKey = req.params.ke
const hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1'; const {
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) monitorPermissions,
const preliminaryValidationFailed = ( monitorRestrictions,
user.permissions.watch_videos === "0" || } = s.getMonitorsPermitted(user.details,monitorId)
hasRestrictions && const {
(!userDetails.video_view || userDetails.video_view.indexOf(monitorId)===-1) isRestricted,
); isRestrictedApiKey,
if(req.query.onlyCount === '1' && !preliminaryValidationFailed){ apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], events: []});
return
}
if(req.query.onlyCount === '1'){
const response = {ok: true} const response = {ok: true}
s.knexQuery({ s.knexQuery({
action: "count", action: "count",
@ -1068,7 +1145,7 @@ module.exports = function(s,config,lang,app,io){
noFormat: true, noFormat: true,
noCount: true, noCount: true,
rowName: 'events', rowName: 'events',
preliminaryValidationFailed: preliminaryValidationFailed preliminaryValidationFailed: false
},(response) => { },(response) => {
res.end(s.prettyPrint(response)) res.end(s.prettyPrint(response))
}) })
@ -1084,10 +1161,21 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const userDetails = user.details
const monitorId = req.params.id
const groupKey = req.params.ke const groupKey = req.params.ke
const hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1'; const monitorId = req.params.id
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
userPermissions,
} = s.checkPermission(user)
if(
userPermissions.view_logs_disallowed ||
isRestrictedApiKey && apiKeyPermissions.get_logs_disallowed
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], logs: []});
return
}
s.sqlQueryBetweenTimesWithPermissions({ s.sqlQueryBetweenTimesWithPermissions({
table: 'Logs', table: 'Logs',
user: user, user: user,
@ -1102,9 +1190,7 @@ module.exports = function(s,config,lang,app,io){
noFormat: true, noFormat: true,
noCount: true, noCount: true,
rowName: 'logs', rowName: 'logs',
preliminaryValidationFailed: ( preliminaryValidationFailed: false
user.permissions.get_logs === "0" || userDetails.sub && userDetails.view_logs !== '1'
)
},(response) => { },(response) => {
response.forEach(function(v,n){ response.forEach(function(v,n){
v.info = JSON.parse(v.info) v.info = JSON.parse(v.info)
@ -1114,51 +1200,30 @@ module.exports = function(s,config,lang,app,io){
},res,req) },res,req)
}) })
/** /**
* API : Get Monitors Online
*/
app.get(config.webPaths.apiPrefix+':auth/smonitor/:ke', function (req,res){
var response = {ok:false};
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,(user) => {
const groupKey = req.params.ke
const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId)
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.get_monitors === "0" || monitorRestrictions.length === 0)){
s.closeJsonResponse(res,[]);
return
}
s.knexQuery({
action: "select",
columns: "*",
table: "Monitors",
where: [
['ke','=',groupKey],
monitorRestrictions
]
},(err,r) => {
const startedMonitors = []
r.forEach(function(v){
if(
s.group[groupKey] &&
s.group[groupKey].activeMonitors[v.mid] &&
s.group[groupKey].activeMonitors[v.mid].isStarted === true
){
startedMonitors.push(v)
}
})
s.closeJsonResponse(res,startedMonitors)
})
},res,req);
});
/**
* API : Monitor Mode Controller * API : Monitor Mode Controller
*/ */
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){ 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){
var response = {ok:false}; var response = {ok:false};
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ 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){ const groupKey = req.params.ke
res.end(user.lang['Not Permitted']) 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 return
} }
if(req.params.f===''){response.msg = user.lang.monitorGetText1;res.end(s.prettyPrint(response));return} if(req.params.f===''){response.msg = user.lang.monitorGetText1;res.end(s.prettyPrint(response));return}
@ -1277,12 +1342,20 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.watch_videos === "0" || monitorRestrictions.length === 0)){ monitorPermissions,
s.closeJsonResponse(res,{ monitorRestrictions,
ok: false, } = s.getMonitorsPermitted(user.details,monitorId)
msg: lang['Not Permitted'] const {
}) isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_view`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
var time = s.nameToTime(req.params.file) var time = s.nameToTime(req.params.file)
@ -1334,12 +1407,20 @@ module.exports = function(s,config,lang,app,io){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const {
if(user.details.sub && user.details.allmonitors === '0' && (user.permissions.watch_videos === "0" || monitorRestrictions.length === 0)){ monitorPermissions,
s.closeJsonResponse(res,{ monitorRestrictions,
ok: false, } = s.getMonitorsPermitted(user.details,monitorId)
msg: lang['Not Permitted'] const {
}) isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_view`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
var time = s.nameToTime(req.params.file) var time = s.nameToTime(req.params.file)
@ -1399,26 +1480,35 @@ module.exports = function(s,config,lang,app,io){
*/ */
app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){ app.get(config.webPaths.apiPrefix+':auth/motion/:ke/:id', function (req,res){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const groupKey = req.params.ke const groupKey = req.params.ke
const monitorId = req.params.id const monitorId = req.params.id
const monitorRestrictions = s.getMonitorRestrictions(user.details,monitorId) const monitorConfig = s.group[groupKey].rawMonitorConfigurations[monitorId]
const {
if(user.details.sub && user.details.allmonitors === '0' && monitorRestrictions.length === 0){ monitorPermissions,
s.closeJsonResponse(res,{ monitorRestrictions,
ok: false, } = s.getMonitorsPermitted(user.details,monitorId);
msg: lang['Not Permitted'] const {
}) isRestricted,
return isRestrictedApiKey,
} apiKeyPermissions,
} = s.checkPermission(user);
const d = { if(
!monitorConfig ||
isRestrictedApiKey && apiKeyPermissions.control_monitors_disallowed
){
s.closeJsonResponse(res,{
ok: false,
msg: !monitorConfig ? user.lang['Monitor or Key does not exist.'] : lang['Not Authorized']
});
return
}
let simulatedEvent = {
id: req.params.id, id: req.params.id,
ke: req.params.ke ke: req.params.ke
} }
if(req.query.data){ if(req.query.data){
try{ try{
Object.assign(d, {details: s.parseJSON(req.query.data)}); Object.assign(simulatedEvent, {details: s.parseJSON(req.query.data)});
}catch(err){ }catch(err){
s.closeJsonResponse(res,{ s.closeJsonResponse(res,{
ok: false, ok: false,
@ -1428,13 +1518,19 @@ module.exports = function(s,config,lang,app,io){
} }
} }
// fallback for cameras that doesn't support JSON in query parameters ( i.e Sercom ICamera1000 will fail to save HTTP_Notifications as invalid url) // fallback for cameras that doesn't support JSON in query parameters ( i.e Sercom ICamera1000 will fail to save HTTP_Notifications as invalid url)
else if( req.query.plug && req.query.name && req.query.reason && req.query.confidence) { else if(req.query.plug && req.query.name && req.query.reason && req.query.confidence) {
Object.assign(d, { const {
plug,
reason,
confidence,
name,
} = req.query;
Object.assign(simulatedEvent,{
details: { details: {
plug: req.query.plug, plug,
reason: req.query.reason, reason,
confidence: req.query.confidence, confidence,
name: req.query.name name,
} }
}); });
} }
@ -1445,51 +1541,21 @@ module.exports = function(s,config,lang,app,io){
}) })
return return
} }
if(!d.ke||!d.id||!s.group[d.ke]){
s.closeJsonResponse(res,{
ok: false,
msg: user.lang['No Group with this key exists']
})
return
}
if(!s.group[d.ke].rawMonitorConfigurations[d.id]){
s.closeJsonResponse(res,{
ok: false,
msg: user.lang['Monitor or Key does not exist.']
})
return
}
var details = s.group[d.ke].rawMonitorConfigurations[d.id].details var details = s.group[d.ke].rawMonitorConfigurations[d.id].details
var detectorHttpApi = details.detector_http_api var detectorHttpApi = details.detector_http_api
var detectorOn = (details.detector === '1') var detectorOn = (details.detector === '1')
switch(detectorHttpApi){ if(
case'0': detectorHttpApi === '0' ||
s.closeJsonResponse(res,{ detectorHttpApi === '2' && !detectorOn ||
ok: false, detectorHttpApi === '3' && detectorOn
msg: user.lang['Trigger Blocked'] ){
}) s.closeJsonResponse(res,{
return ok: false,
break; msg: user.lang['Trigger Blocked']
case'2': })
if(!detectorOn){ return;
s.closeJsonResponse(res,{
ok: false,
msg: user.lang['Trigger Blocked']
})
return
}
break;
case'2':
if(detectorOn){
s.closeJsonResponse(res,{
ok: false,
msg: user.lang['Trigger Blocked']
})
return
}
break;
} }
triggerEvent(d) triggerEvent(simulatedEvent)
s.closeJsonResponse(res,{ s.closeJsonResponse(res,{
ok: true, ok: true,
msg: user.lang['Trigger Successful'] msg: user.lang['Trigger Successful']
@ -1512,8 +1578,25 @@ module.exports = function(s,config,lang,app,io){
app.get(config.webPaths.apiPrefix+':auth/eventCountStatus/:ke/:id', function (req,res){ app.get(config.webPaths.apiPrefix+':auth/eventCountStatus/:ke/:id', function (req,res){
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ 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){ const monitorId = req.params.id
res.end(user.lang['Not Permitted']) const groupKey = req.params.ke
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], counted: 0, tags: []});
return return
} }
var selectedObject = s.group[req.params.ke].activeMonitors[req.params.id].eventsCounted var selectedObject = s.group[req.params.ke].activeMonitors[req.params.id].eventsCounted
@ -1533,10 +1616,27 @@ module.exports = function(s,config,lang,app,io){
], function (req,res){ ], function (req,res){
res.setHeader('Content-Type', 'application/json') res.setHeader('Content-Type', 'application/json')
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const userDetails = user.details
const monitorId = req.params.id const monitorId = req.params.id
const groupKey = req.params.ke const groupKey = req.params.ke
var hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1'; const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
isRestricted && (
monitorId && !monitorPermissions[`${monitorId}_video_view`] ||
monitorRestrictions.length === 0
)
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized'], videos: []});
return
}
s.sqlQueryBetweenTimesWithPermissions({ s.sqlQueryBetweenTimesWithPermissions({
table: 'Events Counts', table: 'Events Counts',
user: user, user: user,
@ -1552,11 +1652,7 @@ module.exports = function(s,config,lang,app,io){
endIsStartTo: !!req.query.endIsStartTo, endIsStartTo: !!req.query.endIsStartTo,
parseRowDetails: true, parseRowDetails: true,
rowName: 'counts', rowName: 'counts',
preliminaryValidationFailed: ( preliminaryValidationFailed: false
user.permissions.watch_videos === "0" ||
hasRestrictions &&
(!userDetails.video_view || userDetails.video_view.indexOf(monitorId)===-1)
)
},(response) => { },(response) => {
res.end(s.prettyPrint(response)) res.end(s.prettyPrint(response))
}) })
@ -1597,12 +1693,24 @@ module.exports = function(s,config,lang,app,io){
var response = {ok:false} var response = {ok:false}
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ 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){ const groupKey = req.params.ke
res.end(user.lang['Not Permitted']) const monitorId = req.params.id
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions.delete_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_delete`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
var groupKey = req.params.ke
var monitorId = req.params.id
// req.query.overwrite === '1' // req.query.overwrite === '1'
if(s.group[groupKey] && s.group[groupKey].activeMonitors && s.group[groupKey].activeMonitors[monitorId]){ if(s.group[groupKey] && s.group[groupKey].activeMonitors && s.group[groupKey].activeMonitors[monitorId]){
var monitor = s.group[groupKey].rawMonitorConfigurations[monitorId] var monitor = s.group[groupKey].rawMonitorConfigurations[monitorId]
@ -1658,8 +1766,22 @@ module.exports = function(s,config,lang,app,io){
let response = { ok: false }; let response = { ok: false };
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){ 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){ const monitorId = req.params.id
res.end(user.lang['Not Permitted']) const groupKey = req.params.ke
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user);
if(
isRestrictedApiKey && apiKeyPermissions.delete_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_delete`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return return
} }
var time = s.nameToTime(req.params.file) var time = s.nameToTime(req.params.file)
@ -1675,8 +1797,6 @@ module.exports = function(s,config,lang,app,io){
videoSet = 'Cloud Videos' videoSet = 'Cloud Videos'
break; break;
} }
const groupKey = req.params.ke
const monitorId = req.params.id
s.knexQuery({ s.knexQuery({
action: "select", action: "select",
columns: "*", columns: "*",

View File

@ -10,6 +10,24 @@ var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({}) var proxy = httpProxy.createProxyServer({})
var ejs = require('ejs'); var ejs = require('ejs');
module.exports = function(s,config,lang,app){ module.exports = function(s,config,lang,app){
function cantLiveStreamPermission(user,monitorId,permission){
const {
monitorPermissions,
monitorRestrictions,
} = s.getMonitorsPermitted(user.details,monitorId)
const {
isRestricted,
isRestrictedApiKey,
apiKeyPermissions,
} = s.checkPermission(user)
if(
isRestrictedApiKey && apiKeyPermissions[`${permission}_disallowed`] ||
isRestricted && !monitorPermissions[`${monitorId}_monitors`]
){
return true
}
return false
}
var noCache = function(res){ var noCache = function(res){
res.setHeader('Cache-Control', 'private, no-cache, no-store, must-revalidate') res.setHeader('Cache-Control', 'private, no-cache, no-store, must-revalidate')
res.setHeader('Expires', '-1') res.setHeader('Expires', '-1')
@ -21,6 +39,11 @@ module.exports = function(s,config,lang,app){
app.get([config.webPaths.apiPrefix+':auth/embed/:ke/:id',config.webPaths.apiPrefix+':auth/embed/:ke/:id/:addon'], function (req,res){ app.get([config.webPaths.apiPrefix+':auth/embed/:ke/:id',config.webPaths.apiPrefix+':auth/embed/:ke/:id/:addon'], function (req,res){
req.params.protocol=req.protocol; req.params.protocol=req.protocol;
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const monitorId = req.params.id
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
noCache(res) noCache(res)
if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){
res.end(user.lang['Not Permitted']) res.end(user.lang['Not Permitted'])
@ -44,6 +67,11 @@ module.exports = function(s,config,lang,app){
*/ */
app.get([config.webPaths.apiPrefix+':auth/mp4/:ke/:id/:channel/s.mp4',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/s.mp4',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/:channel/s.ts',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/s.ts'], function (req, res) { app.get([config.webPaths.apiPrefix+':auth/mp4/:ke/:id/:channel/s.mp4',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/s.mp4',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/:channel/s.ts',config.webPaths.apiPrefix+':auth/mp4/:ke/:id/s.ts'], function (req, res) {
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const monitorId = req.params.id
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
if(!s.group[req.params.ke] || !s.group[req.params.ke].activeMonitors[req.params.id]){ if(!s.group[req.params.ke] || !s.group[req.params.ke].activeMonitors[req.params.id]){
res.status(404); res.status(404);
res.end('404 : Monitor not found'); res.end('404 : Monitor not found');
@ -108,6 +136,11 @@ module.exports = function(s,config,lang,app){
res.end() res.end()
}else{ }else{
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const monitorId = req.params.id
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
s.checkChildProxy(req.params,function(){ s.checkChildProxy(req.params,function(){
if(s.group[req.params.ke]&&s.group[req.params.ke].activeMonitors[req.params.id]){ if(s.group[req.params.ke]&&s.group[req.params.ke].activeMonitors[req.params.id]){
if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){
@ -169,6 +202,11 @@ module.exports = function(s,config,lang,app){
*/ */
app.get([config.webPaths.apiPrefix+':auth/hls/:ke/:id/:file',config.webPaths.apiPrefix+':auth/hls/:ke/:id/:channel/:file'], function (req,res){ app.get([config.webPaths.apiPrefix+':auth/hls/:ke/:id/:file',config.webPaths.apiPrefix+':auth/hls/:ke/:id/:channel/:file'], function (req,res){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const monitorId = req.params.id
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
s.checkChildProxy(req.params,function(){ s.checkChildProxy(req.params,function(){
noCache(res) noCache(res)
if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){ if(user.permissions.watch_stream==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){
@ -195,6 +233,11 @@ module.exports = function(s,config,lang,app){
*/ */
app.get(config.webPaths.apiPrefix+':auth/jpeg/:ke/:id/s.jpg', function(req,res){ app.get(config.webPaths.apiPrefix+':auth/jpeg/:ke/:id/s.jpg', function(req,res){
s.auth(req.params,function(user){ s.auth(req.params,function(user){
const monitorId = req.params.id
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
s.checkChildProxy(req.params,function(){ s.checkChildProxy(req.params,function(){
noCache(res) noCache(res)
if(user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors&&user.details.monitors.indexOf(req.params.id)===-1){ if(user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors&&user.details.monitors.indexOf(req.params.id)===-1){
@ -221,9 +264,10 @@ module.exports = function(s,config,lang,app){
*/ */
app.get(config.webPaths.apiPrefix+':auth/icon/:ke/:id', function(req,res){ app.get(config.webPaths.apiPrefix+':auth/icon/:ke/:id', function(req,res){
s.auth(req.params,async (user) => { s.auth(req.params,async (user) => {
if(user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors&&user.details.monitors.indexOf(req.params.id)===-1){ const monitorId = req.params.id
res.end(user.lang['Not Permitted']) if(cantLiveStreamPermission(user,monitorId,'watch_snapshot')){
return s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
} }
const flags = req.query.noflags ? '' : req.query.flags || '-s 200x200' const flags = req.query.noflags ? '' : req.query.flags || '-s 200x200'
res.writeHead(200, { res.writeHead(200, {
@ -245,6 +289,10 @@ module.exports = function(s,config,lang,app){
*/ */
app.get([config.webPaths.apiPrefix+':auth/flv/:ke/:id/s.flv',config.webPaths.apiPrefix+':auth/flv/:ke/:id/:channel/s.flv'], function(req,res) { app.get([config.webPaths.apiPrefix+':auth/flv/:ke/:id/s.flv',config.webPaths.apiPrefix+':auth/flv/:ke/:id/:channel/s.flv'], function(req,res) {
s.auth(req.params,function(user){ s.auth(req.params,function(user){
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
s.checkChildProxy(req.params,function(){ s.checkChildProxy(req.params,function(){
noCache(res) noCache(res)
var Emitter,chunkChannel var Emitter,chunkChannel
@ -302,6 +350,10 @@ module.exports = function(s,config,lang,app){
config.webPaths.apiPrefix+':auth/h264/:ke/:id' config.webPaths.apiPrefix+':auth/h264/:ke/:id'
], function (req, res) { ], function (req, res) {
s.auth(req.params,function(user){ s.auth(req.params,function(user){
if(cantLiveStreamPermission(user,monitorId)){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return;
}
s.checkChildProxy(req.params,function(){ s.checkChildProxy(req.params,function(){
noCache(res) noCache(res)
if(!req.query.feed){req.query.feed='1'} if(!req.query.feed){req.query.feed='1'}

BIN
web/assets/img/splash.avif Normal file

Binary file not shown.

View File

@ -209,13 +209,18 @@ $(document).ready(function(){
permissionsSection.find('.permission-view select').each(function(n,v){ permissionsSection.find('.permission-view select').each(function(n,v){
var el = $(v) var el = $(v)
var monitorId = el.attr('monitor') var monitorId = el.attr('monitor')
var value = el.val() var value = el.val() // permissions selected
$.each(value,function(n,permissionNameSelected){ $.each(value,function(n,permissionNameSelected){
if(!foundSelected[permissionNameSelected])foundSelected[permissionNameSelected] = [] if(!foundSelected[permissionNameSelected])foundSelected[permissionNameSelected] = []
foundSelected[permissionNameSelected].push(monitorId) foundSelected[permissionNameSelected].push(monitorId)
}) })
}) })
details = Object.assign(details,foundSelected) details = Object.assign(details,{
'monitors': [],
'monitor_edit': [],
'video_view': [],
'video_delete': [],
},foundSelected)
detailsElement.val(JSON.stringify(details)) detailsElement.val(JSON.stringify(details))
} }
var getCompleteForm = function(){ var getCompleteForm = function(){

View File

@ -59,7 +59,7 @@ $(document).ready(function(){
<div class="d-block pt-4"> <div class="d-block pt-4">
<div class="btn-group btn-group-justified"> <div class="btn-group btn-group-justified">
<a class="btn btn-sm btn-success" download href="${videoUrl}"><i class="fa fa-download"></i> ${lang.Download}</a> <a class="btn btn-sm btn-success" download href="${videoUrl}"><i class="fa fa-download"></i> ${lang.Download}</a>
<a class="btn btn-sm btn-danger delete-video"><i class="fa fa-trash-o"></i> ${lang.Delete}</a> ${permissionCheck('video_delete',video.mid) ? `<a class="btn btn-sm btn-danger delete-video"><i class="fa fa-trash-o"></i> ${lang.Delete}</a>` : ''}
</div> </div>
</div> </div>
</div> </div>

View File

@ -158,7 +158,7 @@ $(document).ready(function(e){
<a class="btn btn-sm btn-primary" href="${href}" download title="${lang.Download}"><i class="fa fa-download"></i></a> <a class="btn btn-sm btn-primary" href="${href}" download title="${lang.Download}"><i class="fa fa-download"></i></a>
<a class="btn btn-sm btn-primary preview-video" href="${href}" title="${lang.Play}"><i class="fa fa-play"></i></a> <a class="btn btn-sm btn-primary preview-video" href="${href}" title="${lang.Play}"><i class="fa fa-play"></i></a>
<a class="btn btn-sm btn-default open-video" href="${href}" title="${lang.Play}"><i class="fa fa-play"></i></a> <a class="btn btn-sm btn-default open-video" href="${href}" title="${lang.Play}"><i class="fa fa-play"></i></a>
<a class="btn btn-sm btn-danger delete-video" href="${href}" title="${lang.Delete}"><i class="fa fa-trash-o"></i></a> ${permissionCheck('video_delete',file.mid) ? `<a class="btn btn-sm btn-danger delete-video" href="${href}" title="${lang.Delete}"><i class="fa fa-trash-o"></i></a>` : ''}
</div> </div>
`, `,
} }

View File

@ -291,17 +291,17 @@ a {cursor:pointer}
} */ } */
/* Slim Style */ /* Slim Style */
.form-control { .form-control {
background-color: transparent; /* background-color: transparent;
border: 1px solid #E3E3E3; border: 1px solid #E3E3E3;
border-radius: 30px; border-radius: 30px;
color: #2c2c2c; color: #2c2c2c;
line-height: normal; line-height: normal;
font-size: 0.8571em; font-size: 0.8571em;
box-shadow: none; box-shadow: none; */
} }
.btn-round { .btn-round {
border-width: 1px; /* border-width: 1px; */
border-radius: 30px !important; /* border-radius: 30px !important; */
} }
.btn, .navbar .navbar-nav>a.btn { .btn, .navbar .navbar-nav>a.btn {
font-weight: 400; font-weight: 400;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,11 +14,11 @@ $(document).ready(function(){
}else{ }else{
listElement.append(` listElement.append(`
<div class="col-md-12"> <div class="col-md-12">
<div class="card" package-name="${module.name}"> <div class="card bg-dark" package-name="${module.name}">
<div class="card-body"> <div class="card-body">
<div><h4 class="title mt-0">${humanName}</h4></div> <div><h4 class="title mt-0">${humanName}</h4></div>
<div><pre><b>${lang['Time Created']} :</b> ${module.created}</pre></div> <div class="pb-2"><b>${lang['Time Created']} :</b> ${module.created}</div>
<div><pre><b>${lang['Last Modified']} :</b> ${module.lastModified}</pre></div> <div class="pb-2"><b>${lang['Last Modified']} :</b> ${module.lastModified}</div>
<div class="mb-2"> <div class="mb-2">
${!module.isIgnitor ? ` ${!module.isIgnitor ? `
${module.hasInstaller ? ` ${module.hasInstaller ? `

View File

@ -1,12 +1,55 @@
$(document).ready(function(){ $(document).ready(function(){
var changeSuperPreferencesTab = $('#changeSuperPreferences') var changeSuperPreferencesTab = $('#changeSuperPreferences')
var tokenContainer = $('#super-tokens')
var changeSuperPreferencesForm = changeSuperPreferencesTab.find('form') var changeSuperPreferencesForm = changeSuperPreferencesTab.find('form')
function generateId(x){
if(!x){x=10};var t = "";var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < x; i++ )
t += p.charAt(Math.floor(Math.random() * p.length));
return t;
}
function drawTokenRow(tokenValue){
var html = `<div class="d-flex flex-row token-row mt-3">
<div class="flex-grow-1">
<input class="form-control form-control-sm token-row-input" value="${tokenValue || generateId(30)}">
</div>
<div>
<a class="delete-token btn btn-danger btn-sm my-0 ml-3"><i class="fa fa-trash"></i></a>
</div>
</div>`
tokenContainer.append(html)
}
function getTokenRows(){
var rowsFound = []
changeSuperPreferencesTab.find('.token-row-input').each(function(n,v){
var el = $(v)
var tokenValue = el.val().trim()
if(tokenValue)rowsFound.push(tokenValue);
})
return rowsFound
}
function loadPreferences(){
var tokens = $user.tokens
changeSuperPreferencesTab.find('[name=mail]').val($user.mail)
if(tokens instanceof Array){
tokens.forEach(function(token){
drawTokenRow(token)
})
}
}
changeSuperPreferencesTab.find('.new-token').click(function(){
drawTokenRow()
})
changeSuperPreferencesTab.on('click','.delete-token',function(){
$(this).parents('.token-row').remove()
})
changeSuperPreferencesTab.find('.submit').click(function(){ changeSuperPreferencesTab.find('.submit').click(function(){
changeSuperPreferencesForm.submit() changeSuperPreferencesForm.submit()
}) })
changeSuperPreferencesForm.submit(function(e){ changeSuperPreferencesForm.submit(function(e){
e.preventDefault() e.preventDefault()
var formValues = $(this).serializeObject() var formValues = $(this).serializeObject()
formValues.tokens = getTokenRows()
// $.ccio.cx({f:'accounts',ff:'saveSuper',form:formValues}) // $.ccio.cx({f:'accounts',ff:'saveSuper',form:formValues})
$.post(superApiPrefix + $user.sessionKey + '/accounts/saveSettings',{ $.post(superApiPrefix + $user.sessionKey + '/accounts/saveSettings',{
data: JSON.stringify(formValues) data: JSON.stringify(formValues)
@ -15,8 +58,5 @@ $(document).ready(function(){
}) })
return false return false
}) })
function loadPreferences(){
changeSuperPreferencesTab.find('[name=mail]').val($user.mail)
}
loadPreferences() loadPreferences()
}) })

File diff suppressed because one or more lines are too long

View File

@ -37,23 +37,25 @@
<ul id="pageTabLinks" class="nav flex-column nav-pills"> <ul id="pageTabLinks" class="nav flex-column nav-pills">
<div class="pb-2 px-3" id="home-collapse"> <div class="pb-2 px-3" id="home-collapse">
<% menuInfo.links.forEach((item) => { <% menuInfo.links.forEach((item) => {
if(item.divider){ %> if(!item.eval || eval(item.eval)){
<li><hr class="dropdown-divider"></li> if(item.divider){ %>
<% }else{ %> <li><hr class="dropdown-divider"></li>
<li class="nav-item" <%- item.attributes ? item.attributes : '' %> <%- item.pageOpen ? `id="side-menu-link-${item.pageOpen}"` : '' %>> <% }else{ %>
<a class="nav-link side-menu-link <%- item.class %>" aria-current="page" <%- item.pageOpen ? `page-open="${item.pageOpen}"` : '' %>> <li class="nav-item" <%- item.attributes ? item.attributes : '' %> <%- item.pageOpen ? `id="side-menu-link-${item.pageOpen}"` : '' %>>
<i class="fa fa-<%- item.icon %>"></i> &nbsp; <%- item.label %> <a class="nav-link side-menu-link <%- item.class %>" aria-current="page" <%- item.pageOpen ? `page-open="${item.pageOpen}"` : '' %>>
</a> <i class="fa fa-<%- item.icon %>"></i> &nbsp; <%- item.label %>
<% if(item.addUl){ %> </a>
<ul class="btn-default rounded btn-toggle-nav list-unstyled fw-normal ml-3 mt-2 px-2 pb-2 pt-1 <%- item.ulClass ? item.ulClass : '' %>"> <% if(item.addUl){ %>
<% if(item.ulItems){ <ul class="btn-default rounded btn-toggle-nav list-unstyled fw-normal ml-3 mt-2 px-2 pb-2 pt-1 <%- item.ulClass ? item.ulClass : '' %>">
item.ulItems.forEach((listItem) => { %> <% if(item.ulItems){
<li><a class="<%- define.Theme.isDark ? 'text-white' : 'text-dark' %> <%- listItem.class ? listItem.class : '' %>" <%- listItem.attributes ? listItem.attributes : '' %>><span class="dot dot-<%- listItem.color ? listItem.color : 'blue' %> shadow mr-2"></span><%- listItem.label ? listItem.label : 'Need Label' %></a></li> item.ulItems.forEach((listItem) => { %>
<% }) <li><a class="<%- define.Theme.isDark ? 'text-white' : 'text-dark' %> <%- listItem.class ? listItem.class : '' %>" <%- listItem.attributes ? listItem.attributes : '' %>><span class="dot dot-<%- listItem.color ? listItem.color : 'blue' %> shadow mr-2"></span><%- listItem.label ? listItem.label : 'Need Label' %></a></li>
} %> <% })
</ul> } %>
<% } %> </ul>
</li> <% } %>
</li>
<% } %>
<% } %> <% } %>
<% }) %> <% }) %>
</div> </div>

View File

@ -1,5 +1,5 @@
<% var pageTitle = lang.Shinobi %> <% var pageTitle = lang.Shinobi %>
<!-- Header -->
<% include blocks/header.ejs %> <% include blocks/header.ejs %>
<% include blocks/header-loggedIn.ejs %> <% include blocks/header-loggedIn.ejs %>
<!-- Page --> <!-- Page -->

View File

@ -1,3 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<head> <head>
<!-- Powered by Shinobi, http://shinobi.video --> <!-- Powered by Shinobi, http://shinobi.video -->
<% include blocks/header-title.ejs %> <% include blocks/header-title.ejs %>
@ -27,6 +29,7 @@
return string.replace(/'/g,"\\'") return string.replace(/'/g,"\\'")
}%> }%>
<% if(screen){screen=screen.toLowerCase()} %> <% if(screen){screen=screen.toLowerCase()} %>
<body>
<div id="page-contents" class="display-table full-height"> <div id="page-contents" class="display-table full-height">
<div class="shinobi-bg-shade bg-gradient-<%- screen === 'super' ? 'green' : 'blue' %>"> <div class="shinobi-bg-shade bg-gradient-<%- screen === 'super' ? 'green' : 'blue' %>">
<div class="d-flex flex-row full-height"> <div class="d-flex flex-row full-height">
@ -176,6 +179,7 @@
</div> </div>
</div> </div>
</div> </div>
</body>
<script> <script>
var googleSignIn = false; var googleSignIn = false;
<% var failedLogin;if(failedLogin===true){ %> <% var failedLogin;if(failedLogin===true){ %>
@ -202,3 +206,4 @@
} }
</script> </script>
<% } %> <% } %>
</html>

View File

@ -78,10 +78,10 @@
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#changeSuperPreferences" role="tab"><%-lang['Preferences']%></a> <a class="nav-link" data-bs-toggle="tab" data-bs-target="#changeSuperPreferences" role="tab"><%-lang['Preferences']%></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#customAutoLoad" role="tab"><%-lang['Custom Auto Load']%></a> <a class="nav-link" data-bs-toggle="tab" data-bs-target="#easyRemoteAccess" role="tab"><%-lang['Easy Remote Access (P2P)']%></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#easyRemoteAccess" role="tab"><%-lang['Easy Remote Access (P2P)']%></a> <a class="nav-link" data-bs-toggle="tab" data-bs-target="#customAutoLoad" role="tab"><%-lang['Custom Auto Load']%></a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" data-bs-target="#superPluginManager" role="tab"><%-lang['Plugin Manager']%></a> <a class="nav-link" data-bs-toggle="tab" data-bs-target="#superPluginManager" role="tab"><%-lang['Plugin Manager']%></a>