Shinobi/libs/fileBin.js

365 lines
13 KiB
JavaScript

var fs = require('fs')
var moment = require('moment')
module.exports = function(s,config,lang,app,io){
const getFileBinDirectory = function(monitor){
return s.dir.fileBin + monitor.ke + '/' + monitor.mid + '/'
}
const getFileBinEntry = (options) => {
return new Promise((resolve, reject) => {
s.knexQuery({
action: "select",
columns: "*",
table: "Files",
where: options
},(err,rows) => {
if(rows[0]){
resolve(rows[0])
}else{
resolve()
}
})
})
}
const getFileBinBuffer = (file) => {
const filePath = getFileBinPath(file);
return fs.promises.readFile(filePath)
}
const getFileBinPath = (file) => {
return getFileBinDirectory(file) + file.name;
}
const getFileBinEntries = (options) => {
return new Promise((resolve, reject) => {
s.knexQuery({
action: "select",
columns: "*",
table: "Files",
where: options
},(err,rows) => {
if(rows){
resolve(rows)
}else{
resolve([])
}
})
})
}
const updateFileBinEntry = (options) => {
return new Promise((resolve, reject) => {
const groupKey = options.ke
const monitorId = options.mid
const filename = options.name
const update = options.update
if(!filename){
resolve('No Filename')
return
}
if(!update){
resolve('No Update Options')
return
}
s.knexQuery({
action: "select",
columns: "size",
table: "Files",
where: {
ke: groupKey,
mid: monitorId,
name: filename,
}
},(err,rows) => {
if(rows[0]){
const fileSize = rows[0].size
s.knexQuery({
action: "update",
table: "Files",
where: {
ke: groupKey,
mid: monitorId,
name: filename,
},
update: update
},(err) => {
resolve()
if(update.size){
s.setDiskUsedForGroup(groupKey,-(fileSize/1048576),'fileBin')
s.setDiskUsedForGroup(groupKey,(update.size/1048576),'fileBin')
s.purgeDiskForGroup(groupKey)
}
})
}else{
resolve()
}
})
})
}
const deleteFileBinEntry = (options) => {
return new Promise((resolve, reject) => {
const groupKey = options.ke
const monitorId = options.mid
const filename = options.name
const whereQuery = {
ke: groupKey,
mid: monitorId,
name: filename,
}
if(!filename){
resolve('No Filename')
return
}
const deleteRow = (fileSize) => {
s.knexQuery({
action: "delete",
table: "Files",
where: whereQuery
},(err,r) => {
resolve()
s.file('delete',getFileBinDirectory(whereQuery) + filename)
s.setDiskUsedForGroup(groupKey,-(fileSize/1048576),'fileBin')
s.purgeDiskForGroup(groupKey)
})
}
if(options.size){
deleteRow(options.size)
}else{
s.knexQuery({
action: "select",
columns: "size",
table: "Files",
where: whereQuery
},(err,rows) => {
if(rows[0]){
const fileSize = rows[0].size
deleteRow(fileSize)
}else{
resolve()
}
})
}
})
}
const insertFileBinEntry = (options) => {
return new Promise((resolve, reject) => {
const groupKey = options.ke
const monitorId = options.mid
const filename = options.name
if(!filename){
resolve('No Filename')
return
}
const monitorFileBinDirectory = getFileBinDirectory({ke: groupKey,mid: monitorId,})
const fileSize = options.size || fs.lstatSync(monitorFileBinDirectory + filename).size
const details = options.details instanceof Object ? JSON.stringify(options.details) : options.details
const status = options.status || 0
const time = options.time || new Date()
s.knexQuery({
action: "insert",
table: "Files",
insert: {
ke: groupKey,
mid: monitorId,
name: filename,
size: fileSize,
details: details,
status: status,
time: time,
}
},(err) => {
resolve()
s.setDiskUsedForGroup(groupKey,(fileSize/1048576),'fileBin')
s.purgeDiskForGroup(groupKey)
})
})
}
function archiveFileBinEntry(file,unarchive){
return new Promise((resolve) => {
s.knexQuery({
action: "update",
table: 'Files',
update: {
archive: unarchive ? '0' : 1
},
where: {
ke: file.ke,
mid: file.mid,
name: file.name,
}
},function(err){
resolve({
ok: !err,
err: err,
archived: !unarchive
})
})
})
}
s.getFileBinDirectory = getFileBinDirectory
s.getFileBinEntry = getFileBinEntry
s.getFileBinBuffer = getFileBinBuffer
s.getFileBinPath = getFileBinPath
s.insertFileBinEntry = insertFileBinEntry
s.updateFileBinEntry = updateFileBinEntry
s.deleteFileBinEntry = deleteFileBinEntry
s.archiveFileBinEntry = archiveFileBinEntry
/**
* API : Get fileBin file rows
*/
app.get([config.webPaths.apiPrefix+':auth/fileBin/:ke',config.webPaths.apiPrefix+':auth/fileBin/:ke/:id'],async (req,res) => {
s.auth(req.params,(user) => {
const userDetails = user.details
const monitorId = req.params.id
const groupKey = req.params.ke
const hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1';
s.sqlQueryBetweenTimesWithPermissions({
table: 'Files',
user: user,
groupKey: req.params.ke,
monitorId: req.params.id,
startTime: req.query.start,
endTime: req.query.end,
startTimeOperator: req.query.startOperator,
endTimeOperator: req.query.endOperator,
limit: req.query.limit,
archived: req.query.archived,
endIsStartTo: true,
noFormat: true,
noCount: true,
preliminaryValidationFailed: (
user.permissions.get_monitors === "0"
)
},(response) => {
response.forEach(function(v){
v.details = s.parseJSON(v.details)
v.href = '/'+req.params.auth+'/fileBin/'+req.params.ke+'/'+req.params.id+'/'+v.name;
})
s.closeJsonResponse(res,{
ok: true,
files: response
})
})
},res,req);
});
/**
* API : Get fileBin file
*/
app.get(config.webPaths.apiPrefix+':auth/fileBin/:ke/:id/:file', async (req,res) => {
s.auth(req.params,function(user){
var failed = function(){
res.end(user.lang['File Not Found'])
}
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.watch_videos_disallowed ||
isRestricted && !monitorPermissions[`${monitorId}_video_view`]
){
s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
return
}
s.knexQuery({
action: "select",
columns: "*",
table: "Files",
where: [
['ke','=',groupKey],
['mid','=',req.params.id],
['name','=',req.params.file],
monitorRestrictions
]
},(err,r) => {
if(r && r[0]){
r = r[0]
r.details = JSON.parse(r.details)
const filename = req.params.file
const filePath = s.dir.fileBin + req.params.ke + '/' + req.params.id + (r.details.year && r.details.month && r.details.day ? '/' + r.details.year + '/' + r.details.month + '/' + r.details.day : '') + '/' + filename;
fs.stat(filePath,function(err,stats){
if(!err){
if(filename.endsWith('.mp4')){
s.streamMp4FileOverHttp(filePath,req,res,!!req.query.pureStream)
}else{
res.on('finish',function(){res.end()})
fs.createReadStream(filePath).pipe(res)
}
}else{
failed()
}
})
}else{
failed()
}
})
},res,req);
});
/**
* API : Modify fileBin File
*/
app.get(config.webPaths.apiPrefix+':auth/fileBin/:ke/:id/:file/:mode', function (req,res){
let response = { ok: false };
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
const monitorId = req.params.id
const groupKey = req.params.ke
const filename = req.params.file
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
}
s.knexQuery({
action: "select",
columns: "*",
table: 'Files',
where: [
['ke','=',groupKey],
['mid','=',monitorId],
['name','=',filename]
],
limit: 1
},async (err,r) => {
if(r && r[0]){
const file = r[0];
var details = s.parseJSON(r.details) || {}
switch(req.params.mode){
case'archive':
response.ok = true
const unarchive = s.getPostData(req,'unarchive') == '1';
const archiveResponse = await archiveFileBinEntry(file,unarchive)
response.ok = archiveResponse.ok
response.archived = archiveResponse.archived
break;
case'delete':
response.ok = true;
await deleteFileBinEntry(file)
break;
default:
response.msg = user.lang.modifyVideoText1;
break;
}
}else{
response.msg = user.lang['No such file'];
}
s.closeJsonResponse(res,response);
})
},res,req);
})
}