S3 for other controolers
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
const fs = require('fs')
|
||||
const {PassThrough} = require('stream')
|
||||
const archiver = require('archiver')
|
||||
const moment = require('moment')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const {secretKey} = require('../authentication')
|
||||
const {_sr} = require('../plugins/serverResponses')
|
||||
const {
|
||||
appendS3UploadsToArchive,
|
||||
uploadBackupArchive,
|
||||
deleteOldBackups,
|
||||
} = require('../plugins/backupStorage')
|
||||
// models
|
||||
const Category = require('../models/Category')
|
||||
const Comment = require('../models/Comment')
|
||||
@@ -21,6 +27,8 @@ const Slider = require('../models/Slider')
|
||||
const User = require('../models/User')
|
||||
const YearBanner = require('../models/YearBanner')
|
||||
|
||||
const hostFullError = '<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>'
|
||||
|
||||
module.exports.createBackUp = [
|
||||
// check user token and permission to backup
|
||||
async (req, res, next) => {
|
||||
@@ -85,86 +93,72 @@ module.exports.createBackUp = [
|
||||
|
||||
const [categories, comments, contactus, contents, galleries, homepage, links, meetings, news, newsFiles, services, sliders, users, yearBanner, occasion] = await Promise.all(dataBaseQueries)
|
||||
|
||||
if (await !fs.existsSync('./backup/database')) await fs.mkdirSync('./backup/database')
|
||||
|
||||
await Promise.all([
|
||||
fs.writeFileSync(`./backup/database/categories_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(categories)),
|
||||
fs.writeFileSync(`./backup/database/comments_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(comments)),
|
||||
fs.writeFileSync(`./backup/database/contactus_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(contactus)),
|
||||
fs.writeFileSync(`./backup/database/contents_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(contents)),
|
||||
fs.writeFileSync(`./backup/database/galleries_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(galleries)),
|
||||
fs.writeFileSync(`./backup/database/homepage_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(homepage)),
|
||||
fs.writeFileSync(`./backup/database/links_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(links)),
|
||||
fs.writeFileSync(`./backup/database/meetings_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(meetings)),
|
||||
fs.writeFileSync(`./backup/database/news_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(news)),
|
||||
fs.writeFileSync(`./backup/database/newsFiles_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(newsFiles)),
|
||||
fs.writeFileSync(`./backup/database/services_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(services)),
|
||||
fs.writeFileSync(`./backup/database/sliders_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(sliders)),
|
||||
fs.writeFileSync(`./backup/database/users_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(users)),
|
||||
fs.writeFileSync(`./backup/database/yearBanner_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(yearBanner)),
|
||||
fs.writeFileSync(`./backup/database/occasion_${moment(Date.now()).format('YYYY-MM-DD')}.json`, JSON.stringify(occasion))
|
||||
])
|
||||
|
||||
/////////////////// create backup zip file
|
||||
|
||||
const backupName = 'backup_' + moment(Date.now()).format('YYYY-MM-DD') + '.zip'
|
||||
// create a file to stream archive data to.
|
||||
const output = fs.createWriteStream(`./backup/${backupName}`)
|
||||
const dateStr = moment(Date.now()).format('YYYY-MM-DD')
|
||||
const backupName = `backup_${dateStr}.zip`
|
||||
const archive = archiver('zip', {
|
||||
zlib: {level: 9} // Sets the compression level.
|
||||
zlib: {level: 9}
|
||||
})
|
||||
const output = new PassThrough()
|
||||
const chunks = []
|
||||
|
||||
output.on('data', (chunk) => chunks.push(chunk))
|
||||
|
||||
// listen for all archive data to be written
|
||||
// 'close' event is fired only when a file descriptor is involved
|
||||
output.on('close', function () {
|
||||
console.log(archive.pointer() + ' total bytes')
|
||||
console.log('archiver has been finalized and the output file descriptor has closed.')
|
||||
return res.download(`./backup/${backupName}`)
|
||||
})
|
||||
|
||||
// This event is fired when the data source is drained no matter what was the data source.
|
||||
// It is not part of this library but rather from the NodeJS Stream API.
|
||||
// @see: https://nodejs.org/api/stream.html#stream_event_end
|
||||
output.on('end', function () {
|
||||
console.log('Data has been drained')
|
||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
||||
})
|
||||
|
||||
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
||||
archive.on('warning', function (err) {
|
||||
|
||||
if (err.code === 'ENOENT') {
|
||||
// log warning
|
||||
console.log('On archiver warning -- ENOENT error code', err)
|
||||
} else {
|
||||
// throw error
|
||||
console.log('On archiver warning -- other error codes ', err)
|
||||
}
|
||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
||||
return res.status(500).send(hostFullError)
|
||||
})
|
||||
|
||||
// good practice to catch this error explicitly
|
||||
archive.on('error', function (err) {
|
||||
// throw err
|
||||
console.log(err)
|
||||
return res.status(500).json({message: 'مشکلی پیش آمده'})
|
||||
})
|
||||
|
||||
// pipe archive data to the file
|
||||
await archive.pipe(output)
|
||||
archive.pipe(output)
|
||||
|
||||
// append files from a sub-directory and naming it `new-subdir` within the archive
|
||||
await archive.directory(`./static/uploads/`, 'uploads')
|
||||
await archive.directory(`./backup/database/`, 'database')
|
||||
const databaseExports = [
|
||||
['categories', categories],
|
||||
['comments', comments],
|
||||
['contactus', contactus],
|
||||
['contents', contents],
|
||||
['galleries', galleries],
|
||||
['homepage', homepage],
|
||||
['links', links],
|
||||
['meetings', meetings],
|
||||
['news', news],
|
||||
['newsFiles', newsFiles],
|
||||
['services', services],
|
||||
['sliders', sliders],
|
||||
['users', users],
|
||||
['yearBanner', yearBanner],
|
||||
['occasion', occasion],
|
||||
]
|
||||
|
||||
for (const [name, data] of databaseExports) {
|
||||
archive.append(JSON.stringify(data), {name: `database/${name}_${dateStr}.json`})
|
||||
}
|
||||
|
||||
await appendS3UploadsToArchive(archive)
|
||||
|
||||
// finalize the archive (ie we are done appending files but streams have to finish yet)
|
||||
// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
|
||||
await archive.finalize()
|
||||
|
||||
await fs.rmdirSync('./backup/database', {recursive: true})
|
||||
await new Promise((resolve, reject) => {
|
||||
output.on('end', resolve)
|
||||
output.on('error', reject)
|
||||
})
|
||||
|
||||
const buffer = Buffer.concat(chunks)
|
||||
|
||||
await uploadBackupArchive(buffer, backupName)
|
||||
|
||||
res.setHeader('Content-Type', 'application/zip')
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${backupName}"`)
|
||||
return res.send(buffer)
|
||||
} catch (e) {
|
||||
return res.status(500).send('<h1 style="margin-top: 150px;text-align: center;direction: rtl;color: red;">فضای هاست پر میباشد.لطفا نسبت به پاک کردن بکاپ های قبلی یا افزایش فضای هاست اقدام فرمایید.</h1>')
|
||||
return res.status(500).send(hostFullError)
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -173,12 +167,18 @@ module.exports.createBackUp = [
|
||||
module.exports.removeOldBackups = [
|
||||
async (req, res) => {
|
||||
try {
|
||||
const files = await fs.readdirSync('./backup')
|
||||
for await (const file of files) {
|
||||
const isDirectory = await fs.statSync(`./backup/${file}`).isDirectory()
|
||||
if (isDirectory) await fs.rmdirSync(`./backup/${file}`, {recursive: true})
|
||||
else await fs.unlinkSync(`./backup/${file}`)
|
||||
await deleteOldBackups()
|
||||
|
||||
if (fs.existsSync('./backup')) {
|
||||
const files = fs.readdirSync('./backup')
|
||||
for (const file of files) {
|
||||
const filePath = `./backup/${file}`
|
||||
const isDirectory = fs.statSync(filePath).isDirectory()
|
||||
if (isDirectory) fs.rmdirSync(filePath, {recursive: true})
|
||||
else fs.unlinkSync(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({message: _sr['fa'].response.success_remove})
|
||||
} catch (e) {
|
||||
return res.status(500).json({message: e})
|
||||
|
||||
Reference in New Issue
Block a user