S3 for other controolers

This commit is contained in:
2026-06-19 15:47:02 +03:30
parent c73027540a
commit e95883eb6a
32 changed files with 1073 additions and 650 deletions
+1 -1
View File
@@ -36,7 +36,7 @@
v-for="(item, i) in items"
:key="i"
class="item">
<img :src="`/uploads/images/category/shafafiat/${item.icon}`" alt="شفافیت" />
<img :src="item.icon" alt="شفافیت" />
<div class="parent">
<div class="right"></div>
<div class="left"></div>
+81 -133
View File
@@ -8,13 +8,19 @@ const {
checkValidations,
} = require("../plugins/controllersHelperFunctions");
const News = require("../models/News");
const sharp = require("sharp");
const fs = require("fs");
const { extname } = require("path");
const {
deleteCategoryImage,
deleteShafafiatIcon,
uploadProcessedImage,
uploadShafafiatIcon,
uploadTermsFile,
deleteTermsFile,
getStoredImageName,
} = require("../plugins/categoryImageStorage");
// variables
const titleFilterRegex = new RegExp("/", "g");
const noCover = "/img/no-cover.jpg";
const coverNewsWidth = 400;
const coverNewsHeight = 400;
const coverQuality = 100;
@@ -411,34 +417,13 @@ module.exports.addCategory = [
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
.jpeg({ quality: coverQuality })
.toFile(`./static/uploads/images/category/${imageName}`);
/**
* if exist old pic delete it from file
*/
// if (targetNews.cover !== noCover && !targetNews.imported) {
// let oldPic = `./static${targetNews.cover}`;
//
// if (await fs.existsSync(oldPic)) {
// fs.unlink(oldPic, (err) => {
// if (err) return res500(res, err?.message);
// });
// }
// }
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
// let oldPic = `./static${targetNews.thumbCover}`;
//
// if (await fs.existsSync(oldPic)) {
// fs.unlink(oldPic, (err) => {
// if (err) return res500(res, err?.message);
// });
// }
// }
await uploadProcessedImage(
image.data,
imageName,
coverNewsWidth,
coverNewsHeight,
coverQuality
);
create.managerCover = imageName;
await create.save();
@@ -461,33 +446,12 @@ module.exports.addCategory = [
const ext = extname(image.name);
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
try {
await image.mv(
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
await uploadShafafiatIcon(
image.data,
imageName,
image.mimetype
);
/**
* if exist old pic delete it from file
*/
// if (targetNews.cover !== noCover && !targetNews.imported) {
// let oldPic = `./static${targetNews.cover}`;
//
// if (await fs.existsSync(oldPic)) {
// fs.unlink(oldPic, (err) => {
// if (err) return res500(res, err?.message);
// });
// }
// }
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
// let oldPic = `./static${targetNews.thumbCover}`;
//
// if (await fs.existsSync(oldPic)) {
// fs.unlink(oldPic, (err) => {
// if (err) return res500(res, err?.message);
// });
// }
// }
create.icon = imageName;
await create.save();
} catch (e) {
@@ -812,24 +776,15 @@ module.exports.updateCategory = [
image.mimetype.split("/")[1]
}`;
try {
const target = sharp(image.data);
await target
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
.jpeg({ quality: coverQuality })
.toFile(`./static/uploads/images/category/${imageName}`);
await deleteCategoryImage(targetCategory, "managerCover");
/**
* if exist old pic delete it from file
*/
if (targetCategory.managerCover !== noCover) {
let oldPic = `./static${targetCategory.managerCover}`;
if (await fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
coverNewsWidth,
coverNewsHeight,
coverQuality
);
targetCategory.managerCover = imageName;
} catch (e) {
@@ -839,7 +794,6 @@ module.exports.updateCategory = [
if (req.files?.icon) {
const image = req.files.icon;
console.log(image);
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
return res.status(422).json({
validation: {
@@ -852,30 +806,17 @@ module.exports.updateCategory = [
const ext = extname(image.name);
const imageName = `shafafiat_icon_${Date.now()}${ext}`;
try {
await image.mv(
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
await deleteShafafiatIcon(
getStoredImageName(targetCategory, "icon")
);
// const target = sharp(image.data)
// await target
// .resize(coverNewsWidth, coverNewsHeight, {fit: 'cover'})
// .jpeg({quality: coverQuality})
// .toFile(`./static/uploads/images/category/shafafiat/${imageName}`);
/**
* if exist old pic delete it from file
*/
if (targetCategory.icon !== noCover) {
let oldPic = `./static${targetCategory.icon}`;
if (await fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadShafafiatIcon(
image.data,
imageName,
image.mimetype
);
targetCategory.icon = imageName;
console.log(targetCategory);
} catch (e) {
return res500(res, e?.message);
}
@@ -1223,52 +1164,59 @@ module.exports.getParent = [
module.exports.addTermsFileToCategory = [
[body("termsTitle").notEmpty().withMessage(_sr["fa"].required.title)],
checkValidations(validationResult),
(req, res) => {
if (!req.files?.file)
return res
.status(422)
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
if (req.files?.file.mimetype.split("/")[1] !== "pdf")
return res
.status(422)
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
async (req, res) => {
try {
if (!req.files?.file)
return res
.status(422)
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
if (req.files?.file.mimetype.split("/")[1] !== "pdf")
return res
.status(422)
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
const data = { title: req.body.termsTitle };
const file = req.files.file;
const fileName =
req.body.termsTitle.replace(titleFilterRegex, "-") +
"_" +
Date.now() +
".pdf";
file.mv(`./static/uploads/files/terms/${fileName}`);
data.file = fileName;
const category = await Category.findById(req.params.categoryId);
if (!category) return res404(res, "category not found");
Category.findById(req.params.categoryId, (err, category) => {
if (err || !category) return res404(res, err);
category.terms.push(data);
category.save((err) => {
if (err) return res500(res, err);
else return res.json({ message: _sr["fa"].response.success_save });
const fileName =
req.body.termsTitle.replace(titleFilterRegex, "-") +
"_" +
Date.now() +
".pdf";
await uploadTermsFile(req.files.file.data, fileName);
category.terms.push({
title: req.body.termsTitle,
file: fileName,
});
});
await category.save();
return res.json({ message: _sr["fa"].response.success_save });
} catch (err) {
return res500(res, err);
}
},
];
module.exports.removeTermsFileFromCategory = [
(req, res) => {
Category.findOne({ "terms._id": req.params.fileId }, (err, category) => {
if (err || !category) return res404(res, err);
const file = category.terms.id(req.params.fileId);
if (!file) return res404(res, "not found");
file.remove();
fs.unlink(`./static/${file.file}`, (err) => {
if (err) console.log(err);
});
category.save((err) => {
if (err) return res500(res, err);
else return res.json({ message: _sr["fa"].response.success_remove });
});
});
async (req, res) => {
try {
const category = await Category.findOne({ "terms._id": req.params.fileId });
if (!category) return res404(res, "not found");
const termsFile = category.terms.id(req.params.fileId);
if (!termsFile) return res404(res, "not found");
const fileName = getStoredImageName(termsFile, "file");
termsFile.remove();
await deleteTermsFile(fileName);
await category.save();
return res.json({ message: _sr["fa"].response.success_remove });
} catch (err) {
return res500(res, err);
}
},
];
+34 -55
View File
@@ -1,9 +1,11 @@
const {body, validationResult} = require('express-validator');
const sharp = require('sharp');
const {_sr} = require('../plugins/serverResponses');
const {res404, res500, hasWhiteSpaces, isLatinCharactersWithSymbol, generateRandomDigits} = require('../plugins/controllersHelperFunctions');
const Content = require('../models/Content');
const fs = require('fs');
const {
deleteContentImages,
uploadProcessedImage,
} = require('../plugins/contentImageStorage');
////// variables
@@ -85,26 +87,23 @@ module.exports.addContent = [
const imageName = `manager_${Date.now()}_${create._id}.${image.mimetype.split('/')[1]}`;
const thumbName = 'thumb_' + imageName
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/content/${imageName}`)
await target
.resize(profileThumbWidth, profileThumbHeight, {
fit: 'cover'
})
.jpeg({
quality: profileThumbQuality
})
.toFile(`./static/uploads/images/content/${thumbName}`)
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
await uploadProcessedImage(
image.data,
thumbName,
profileThumbWidth,
profileThumbHeight,
profileThumbQuality
);
create.cover = imageName;
create.thumb = imageName;
create.thumb = thumbName;
await create.save();
} catch (e) {
@@ -180,42 +179,22 @@ module.exports.updateContent = [
const imageName = `manager_${Date.now()}_${targetContent._id}.${image.mimetype.split('/')[1]}`;
const thumbName = 'thumb_' + imageName
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/content/${imageName}`)
await target
.resize(profileThumbWidth, profileThumbHeight, {
fit: 'cover'
})
.jpeg({
quality: profileThumbQuality
})
.toFile(`./static/uploads/images/content/${thumbName}`)
await deleteContentImages(targetContent);
/**
* if exist old pic delete it from file
*/
if (targetContent.cover) {
const oldPic = `./static${targetContent.cover}`
const oldThumb = `./static${targetContent.thumb}`
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
if (fs.existsSync(oldThumb)) {
fs.unlink(oldThumb, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
await uploadProcessedImage(
image.data,
thumbName,
profileThumbWidth,
profileThumbHeight,
profileThumbQuality
);
targetContent.cover = imageName;
targetContent.thumb = thumbName;
+63 -63
View File
@@ -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})
+22 -53
View File
@@ -10,8 +10,11 @@ const {
hasWhiteSpaces,
isLatinCharactersWithSymbol
} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const sharp = require('sharp');
const {
deleteCandidateImage,
deleteElectionCandidateImages,
uploadProcessedImage,
} = require('../plugins/electionImageStorage');
////// variables
const profileWidth = 300;
@@ -292,17 +295,7 @@ module.exports.deletOneElection = [
}
if (deleteElection.candidates.length) {
const targetDir = `./static/uploads/images/election/`;
const getFiles = fs.readdirSync(targetDir);
for (const file of getFiles) {
if (file.includes(deleteElection._id)) {
fs.unlink(`./static/uploads/images/election/${file}`, (err) => {
if (err) console.log(err)
});
}
}
await deleteElectionCandidateImages(deleteElection);
}
await deleteElection.deleteOne();
@@ -457,16 +450,13 @@ module.exports.addCandidate = [
}
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
data.profilePic = imageName;
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.toFormat('jpg')
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/election/${imageName}`)
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
targetElection.candidates.push(data);
@@ -528,29 +518,16 @@ module.exports.updateCandidate = [
return res.status(422).json({validation: {profilePic: {msg: _sr['fa'].format.image}}});
}
const imageName = 'candidate_' + Date.now() + '_' + targetElection._id + '.jpg';
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.toFormat('jpg')
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/election/${imageName}`)
await deleteCandidateImage(candidate);
/**
* if exist old pic delete it from file
*/
if (candidate.profilePic) {
const oldPic = `./static${candidate.profilePic}`;
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
candidate.profilePic = imageName;
}
@@ -586,15 +563,7 @@ module.exports.deleteCandidate = [
if (!candidate) return res404(res, `کاندید مورد نظر پیدا نشد`);
if (candidate.profilePic) {
const oldPic = `./static${candidate.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await deleteCandidateImage(candidate);
await targetElection.candidates.id(candidateId).remove();
+20 -41
View File
@@ -3,7 +3,6 @@ const {
body,
validationResult
} = require('express-validator');
const sharp = require('sharp');
const {
_sr
} = require('../plugins/serverResponses');
@@ -14,7 +13,10 @@ const {
isLatinCharactersWithSymbol,
generateRandomDigits
} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const {
deleteLinksImage,
uploadProcessedImage,
} = require('../plugins/linksImageStorage');
////// variables
const profileWidth = 50;
@@ -108,15 +110,13 @@ module.exports.addLinks = [
}
const imageName = `links_${Date.now()}_${createLinks._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/links/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
createLinks.icon = imageName;
@@ -243,28 +243,15 @@ module.exports.updateLinks = [
}
const imageName = `links_${Date.now()}_${targetLinks._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/links/${imageName}`);
await deleteLinksImage(targetLinks, 'icon');
/**
* if exist old pic delete it from file
*/
if (targetLinks.icon) {
var oldPic = `./static${targetLinks.icon}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
targetLinks.icon = imageName;
targetLinks.linksStatus = true;
@@ -312,15 +299,7 @@ module.exports.deletOneLinks = [
return res500(res, `شما اجازه حذف این پیوند را ندارید`);
}
if (targetLinks.icon) {
var oldPic = `./static${targetLinks.icon}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (error) => {
if (error) return res500(res, error?.message);
});
}
}
await deleteLinksImage(targetLinks, 'icon');
/** delete links */
await targetLinks.deleteOne();
+20 -40
View File
@@ -2,8 +2,10 @@ const Occasion = require('../models/Occasion');
const {body, validationResult} = require('express-validator');
const {_sr} = require('../plugins/serverResponses');
const {res404, res500} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const sharp = require('sharp');
const {
deleteOccasionImage,
uploadProcessedImage,
} = require('../plugins/occasionImageStorage');
const moment = require('moment-jalaali');
////// variables
@@ -63,16 +65,13 @@ module.exports.addOccasion = [
}
const imageName = `occasion_${addOccasion._id}_${Date.now()}.jpg`;
const target = sharp(image.data)
await target
.resize(occasionWidth, occasionHeight, {
fit: 'cover'
})
.toFormat('jpg')
.jpeg({
quality: occasionQuality
})
.toFile(`./static/uploads/images/occasion/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
occasionWidth,
occasionHeight,
occasionQuality
);
addOccasion.status = true;
addOccasion.mainCover = imageName;
@@ -132,26 +131,15 @@ module.exports.updateOccasion = [
}
const imageName = `occasion_${targetOccasion._id}_${Date.now()}.jpg`;
const target = sharp(image.data)
await target
.resize(occasionWidth, occasionHeight, {
fit: 'cover'
})
.toFormat('jpg')
.jpeg({
quality: occasionQuality
})
.toFile(`./static/uploads/images/occasion/${imageName}`);
await deleteOccasionImage(targetOccasion, 'mainCover');
if (targetOccasion.mainCover) {
var oldPic = `./static${targetOccasion.mainCover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
occasionWidth,
occasionHeight,
occasionQuality
);
targetOccasion.status = true;
targetOccasion.mainCover = imageName;
@@ -184,15 +172,7 @@ module.exports.deleteOccasion = [
return res404(res, `مناسبت مورد نظر پیدا نشد`);
}
if (targetOccasion.mainCover) {
var oldPic = `./static${targetOccasion.mainCover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await deleteOccasionImage(targetOccasion, 'mainCover');
await targetOccasion.deleteOne();
+130 -91
View File
@@ -1,109 +1,148 @@
const fs = require("fs/promises");
const os = require("os");
const path = require("path");
const axios = require("axios");
const { body, validationResult } = require("express-validator");
const { _sr } = require("../plugins/serverResponses");
const { checkValidations } = require("../plugins/controllersHelperFunctions");
const Book = require("../models/Book");
var convertapi = require('convertapi')('6zZB0nquI5V3P3Vg');
const {
uploadPdf,
uploadBookSlide,
deletePdf,
deleteBookSlide,
} = require("../plugins/bookImageStorage");
const convertapi = require("convertapi")("6zZB0nquI5V3P3Vg");
module.exports.AddPDF = [
[
body('title')
.notEmpty().withMessage(_sr['fa'].required.title)
],
checkValidations(validationResult),
async (req, res) => {
try {
const firstbook = [];
if (!req.files?.file) {
return res.status(422).json({ validation: { file: { msg: _sr['fa'].required.file } } });
}
if (req.files?.file.mimetype.split('/')[1] !== 'pdf') {
return res.status(422).json({ validation: { file: { msg: 'فقط فرمت PDF قابل قبول است' } } });
}
const book = await Book.findById(req.body.bookId);
const bookId = book ? book._id : null;
const data = { title: req.body.title };
const file = req.files.file;
const fileName = req.body.title.replace(Date.now(), '-') + '_' + Date.now() + '.pdf';
const imageName = req.body.title.replace(Date.now(), '-') + '_' + Date.now();
const filePath = `./static/uploads/pdf/${fileName}`;
await file.mv(filePath);
data.file = fileName;
const convertPromise = convertapi.convert('jpg', {
File: filePath
}, 'pdf');
const result = await convertPromise;
const savedFiles = await result.saveFiles(`./static/uploads/books/${imageName}.jpeg`);
const imagePath = `https://ostan-mr.ir/uploads/books/${imageName}.jpeg`;
firstbook.push(imagePath);
if (bookId) {
const update = await Book.findByIdAndUpdate(
{_id:bookId},
{ $push: { slides: imagePath } },
{ upsert: true }
);
return res.status(201).json({ msg: "اسلاید کتاب اضافه شد", Data: update });
} else {
const newBook = new Book({
title: req.body.title,
uri: `https://ostan-mr.ir/uploads/pdf/${fileName}`,
slides: firstbook
});
await newBook.save();
return res.status(201).json({ msg: "کتاب ایجاد شد", Data: newBook });
}
} catch (error) {
console.error(error);
return res.status(500).json({ msg: "خطایی در پردازش فایل رخ داد", error: error.message });
}
[body("title").notEmpty().withMessage(_sr["fa"].required.title)],
checkValidations(validationResult),
async (req, res) => {
let tmpDir;
try {
const firstbook = [];
if (!req.files?.file) {
return res
.status(422)
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
}
if (req.files?.file.mimetype.split("/")[1] !== "pdf") {
return res
.status(422)
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
}
const book = await Book.findById(req.body.bookId);
const bookId = book ? book._id : null;
const file = req.files.file;
const fileName =
req.body.title.replace(Date.now(), "-") + "_" + Date.now() + ".pdf";
const imageName =
req.body.title.replace(Date.now(), "-") + "_" + Date.now();
const { url: pdfUrl } = await uploadPdf(file.data, fileName);
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "book-"));
const tmpPdfPath = path.join(tmpDir, fileName);
await fs.writeFile(tmpPdfPath, file.data);
const result = await convertapi.convert(
"jpg",
{ File: tmpPdfPath },
"pdf"
);
const convertedResponse = await axios.get(result.files[0].url, {
responseType: "arraybuffer",
});
const imagePath = await uploadBookSlide(
Buffer.from(convertedResponse.data),
imageName
);
firstbook.push(imagePath);
if (bookId) {
const update = await Book.findByIdAndUpdate(
{ _id: bookId },
{ $push: { slides: imagePath } },
{ upsert: true }
);
return res
.status(201)
.json({ msg: "اسلاید کتاب اضافه شد", Data: update });
}
const newBook = new Book({
title: req.body.title,
uri: pdfUrl,
slides: firstbook,
});
await newBook.save();
return res.status(201).json({ msg: "کتاب ایجاد شد", Data: newBook });
} catch (error) {
console.error(error);
return res.status(500).json({
msg: "خطایی در پردازش فایل رخ داد",
error: error.message,
});
} finally {
if (tmpDir) {
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});
}
}
},
];
module.exports.GetAll = [
async (req, res,next) => {
try {
const Books = await Book.find({});
return res.status(200).json({ Books });
} catch (error) {
next(error)
}
async (req, res, next) => {
try {
const Books = await Book.find({});
return res.status(200).json({ Books });
} catch (error) {
next(error);
}
},
];
module.exports.GetOne = [
async (req, res,next) => {
try {
const id = req.params.id
const book = await Book.findById(id);
return res.status(200).json({ msg: book });
} catch (error) {
next(error)
}
async (req, res, next) => {
try {
const id = req.params.id;
const book = await Book.findById(id);
return res.status(200).json({ msg: book });
} catch (error) {
next(error);
}
},
];
module.exports.DeleteOne = [
async(req,res,next)=>{
try {
const book = await Book.deleteOne({_id:req.params.id})
if(!book){
return res.status(200).json({ msg: 'کتاب وجود ندارد ' });
}
return res.status(200).json({ msg: 'کتاب حذف شد' });
} catch (error) {
next(error)
}
async (req, res, next) => {
try {
const book = await Book.findById(req.params.id);
if (!book) {
return res.status(200).json({ msg: "کتاب وجود ندارد " });
}
const uri = book.get("uri", null, { getters: false });
if (uri) {
await deletePdf(uri.split("/").pop());
}
const slides = book.get("slides", [], { getters: false }) || [];
for (const slide of slides) {
const imageName = slide.split("/").pop().replace(/\.jpeg$/i, "");
await deleteBookSlide(imageName);
}
await book.deleteOne();
return res.status(200).json({ msg: "کتاب حذف شد" });
} catch (error) {
next(error);
}
]
},
];
+20 -41
View File
@@ -3,7 +3,6 @@ const {
body,
validationResult
} = require('express-validator');
const sharp = require('sharp');
const {
_sr
} = require('../plugins/serverResponses');
@@ -14,7 +13,10 @@ const {
isLatinCharactersWithSymbol,
generateRandomDigits
} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const {
deleteSliderImage,
uploadProcessedImage,
} = require('../plugins/sliderImageStorage');
////// variables
const profileWidth = 600;
@@ -113,15 +115,13 @@ module.exports.addSlider = [
}
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/slider/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
createSlider.cover = imageName;
@@ -253,28 +253,15 @@ module.exports.updateSlider = [
}
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/slider/${imageName}`);
await deleteSliderImage(targetSlider, "cover");
/**
* if exist old pic delete it from file
*/
if (targetSlider.cover) {
var oldPic = `./static${targetSlider.cover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
targetSlider.cover = imageName;
} catch (e) {
@@ -322,15 +309,7 @@ module.exports.deletOneSlider = [
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
}
if (targetSlider.cover) {
var oldPic = `./static${targetSlider.cover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (error) => {
if (error) return res500(res, error?.message);
});
}
}
await deleteSliderImage(targetSlider, "cover");
/** delete slider */
await targetSlider.deleteOne();
+20 -41
View File
@@ -3,7 +3,6 @@ const {
body,
validationResult
} = require('express-validator');
const sharp = require('sharp');
const {
_sr
} = require('../plugins/serverResponses');
@@ -14,7 +13,10 @@ const {
isLatinCharactersWithSymbol,
generateRandomDigits
} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const {
deleteSliderImage,
uploadProcessedImage,
} = require('../plugins/sliderImageStorage');
////// variables
const profileWidth = 880;
@@ -113,15 +115,13 @@ module.exports.addSlider = [
}
const imageName = `slider_${Date.now()}_${createSlider._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/slider/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
createSlider.cover = imageName;
@@ -253,28 +253,15 @@ module.exports.updateSlider = [
}
const imageName = `slider_${Date.now()}_${targetSlider._id}.${image.mimetype.split('/')[1]}`;
try {
const target = sharp(image.data)
await target
.resize(profileWidth, profileHeight, {
fit: 'cover'
})
.jpeg({
quality: profileQuality
})
.toFile(`./static/uploads/images/slider/${imageName}`);
await deleteSliderImage(targetSlider, "cover");
/**
* if exist old pic delete it from file
*/
if (targetSlider.cover) {
var oldPic = `./static${targetSlider.cover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
targetSlider.cover = imageName;
} catch (e) {
@@ -322,15 +309,7 @@ module.exports.deletOneSlider = [
return res500(res, `شما اجازه حذف این اسلایدر را ندارید`);
}
if (targetSlider.cover) {
var oldPic = `./static${targetSlider.cover}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (error) => {
if (error) return res500(res, error?.message);
});
}
}
await deleteSliderImage(targetSlider, "cover");
/** delete slider */
await targetSlider.deleteOne();
+28 -65
View File
@@ -4,7 +4,6 @@ const { rateLimit } = require("express-rate-limit");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const sharp = require("sharp");
const { secretKey } = require("./../authentication");
const { _sr } = require("../plugins/serverResponses");
const {
@@ -14,7 +13,10 @@ const {
isLatinCharactersWithSymbol,
generateRandomDigits,
} = require("../plugins/controllersHelperFunctions");
const fs = require("fs");
const {
deleteUserImage,
uploadProcessedImage,
} = require("../plugins/userImageStorage");
const nodemailer = require("nodemailer");
const Category = require("../models/Category");
const Logger = require("../models/Logger");
@@ -566,15 +568,13 @@ module.exports.registerAdmin = [
image.mimetype.split("/")[1];
data.profilePic = imageName;
try {
const target = sharp(image.data);
await target
.resize(profileWidth, profileHeight, {
fit: "cover",
})
.jpeg({
quality: profileQuality,
})
.toFile(`./static/uploads/images/users/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
} catch (e) {
return res500(res, e?.message);
}
@@ -713,18 +713,7 @@ module.exports.deleteOneUser = [
.json({ message: `شما نمیتوانید این کاربر را حذف کنید` });
}
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await deleteUserImage(user, "profilePic");
/** delete user */
await user.deleteOne();
@@ -922,28 +911,15 @@ module.exports.updateUser = [
image.mimetype.split("/")[1];
try {
const target = sharp(image.data);
await target
.resize(profileWidth, profileHeight, {
fit: "cover",
})
.jpeg({
quality: profileQuality,
})
.toFile(`./static/uploads/images/users/${imageName}`);
await deleteUserImage(user, "profilePic");
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
} catch (e) {
return res500(res, e?.message);
}
@@ -1129,28 +1105,15 @@ module.exports.updateProfile = [
image.mimetype.split("/")[1];
try {
const target = sharp(image.data);
await target
.resize(profileWidth, profileHeight, {
fit: "cover",
})
.jpeg({
quality: profileQuality,
})
.toFile(`./static/uploads/images/users/${imageName}`);
await deleteUserImage(user, "profilePic");
/**
* if exist old pic delete it from file
*/
if (user.profilePic) {
var oldPic = `./static${user.profilePic}`;
if (fs.existsSync(oldPic)) {
fs.unlink(oldPic, (err) => {
if (err) return res500(res, err?.message);
});
}
}
await uploadProcessedImage(
image.data,
imageName,
profileWidth,
profileHeight,
profileQuality
);
} catch (e) {
return res500(res, e?.message);
}
+8 -8
View File
@@ -2,8 +2,7 @@ const YearBanner = require('../models/YearBanner');
const {body, validationResult, checkSchema} = require('express-validator');
const {_sr} = require('../plugins/serverResponses');
const {res404, res500} = require('../plugins/controllersHelperFunctions');
const fs = require('fs');
const sharp = require('sharp');
const {uploadProcessedImage} = require('../plugins/yearBannerImageStorage');
////// variables
const yearBannerWidth = 1920
@@ -51,12 +50,13 @@ module.exports.updateYearBanner = [
imageName = `mainPage_cover.jpg`;
const target = sharp(image.data)
await target
.resize(yearBannerWidth, yearBannerHeight, {fit: 'cover'})
.toFormat('jpg')
.jpeg({quality: yearBannerQuality})
.toFile(`./static/uploads/images/mainCover/${imageName}`);
await uploadProcessedImage(
image.data,
imageName,
yearBannerWidth,
yearBannerHeight,
yearBannerQuality
);
}
if (yearBanner) {
+22 -7
View File
@@ -1,16 +1,31 @@
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const s3Storage = require('../plugins/s3Storage');
function PDF(pdf) {
if (pdf) return '/uploads/files/ReadOnly-PDF' + pdf
function pdfUri(uri) {
if (!uri) return null;
if (uri.startsWith('http://') || uri.startsWith('https://')) return uri;
const fileName = uri.startsWith('/') ? uri.split('/').pop() : uri;
return s3Storage.getPublicUrl(`uploads/pdf/${fileName}`);
}
function slideUrl(slide) {
if (!slide) return null;
if (slide.startsWith('http://') || slide.startsWith('https://')) return slide;
const imageName = slide.startsWith('/') ? slide.split('/').pop() : slide;
const key = imageName.endsWith('.jpeg')
? `uploads/books/${imageName}`
: `uploads/books/${imageName}.jpeg`;
return s3Storage.getPublicUrl(key);
}
const BookSchema = mongoose.Schema({
title: String,
uri: String,
slides:{
default:[],
type:Array
uri: { type: String, get: pdfUri, default: null },
slides: {
default: [],
type: [String],
get: (slides) => (slides || []).map(slideUrl),
}
});
+14 -4
View File
@@ -1,4 +1,5 @@
const mongoose = require("mongoose");
const s3Storage = require("../plugins/s3Storage");
function autoPopulateSubs(next) {
this.populate({
@@ -14,12 +15,21 @@ function autoPopulateSubs(next) {
}
function file(file) {
return "/uploads/files/terms/" + file;
if (!file) return null;
if (file.startsWith("http://") || file.startsWith("https://")) return file;
return s3Storage.getPublicUrl(`uploads/files/terms/${file}`);
}
function image(img) {
if (img) return "/uploads/images/category/" + img;
else return "/img/no-cover.jpg";
if (!img) return "/img/no-cover.jpg";
if (img.startsWith("http://") || img.startsWith("https://")) return img;
return s3Storage.getPublicUrl(`uploads/images/category/${img}`);
}
function shafafiatIcon(icon) {
if (!icon) return null;
if (icon.startsWith("http://") || icon.startsWith("https://")) return icon;
return s3Storage.getPublicUrl(`uploads/images/category/shafafiat/${icon}`);
}
const CategoryTermsFile = mongoose.Schema({
@@ -71,7 +81,7 @@ const CategorySchema = mongoose.Schema({
managerName: String,
managerDescription: String,
/** if category was shafafiat this icon is for that */
icon: String,
icon: { type: String, get: shafafiatIcon, default: null },
});
CategorySchema.index({ parent: 1, childs: 1 });
+4 -1
View File
@@ -1,7 +1,10 @@
const mongoose = require('mongoose');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/content/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/content/${img}`);
}
+4 -1
View File
@@ -1,8 +1,11 @@
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/election/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/election/${img}`);
}
const CandidatesSchema = mongoose.Schema({
+4 -1
View File
@@ -1,7 +1,10 @@
const mongoose = require('mongoose');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/links/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/links/${img}`);
}
const LinksSchema = mongoose.Schema({
+4 -1
View File
@@ -1,8 +1,11 @@
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/occasion/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/occasion/${img}`);
}
const OccasionSchema = mongoose.Schema({
+4 -1
View File
@@ -1,8 +1,11 @@
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/slider/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/slider/${img}`);
}
const SliderSchema = mongoose.Schema({
+4 -1
View File
@@ -1,8 +1,11 @@
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/users/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/users/${img}`);
}
const AdminSchema = mongoose.Schema({
+4 -1
View File
@@ -1,7 +1,10 @@
const mongoose = require('mongoose');
const s3Storage = require('../plugins/s3Storage');
function image(img) {
if (img) return '/uploads/images/mainCover/' + img
if (!img) return null;
if (img.startsWith('http://') || img.startsWith('https://')) return img;
return s3Storage.getPublicUrl(`uploads/images/mainCover/${img}`);
}
const YearBannerSchema = mongoose.Schema({
+33
View File
@@ -0,0 +1,33 @@
const s3Storage = require("./s3Storage");
const BACKUP_PREFIX = "backup";
const UPLOADS_PREFIX = "uploads";
const appendS3UploadsToArchive = async (archive) => {
const keys = await s3Storage.listObjects(UPLOADS_PREFIX);
for (const key of keys) {
const buffer = await s3Storage.getObjectBuffer(key);
archive.append(buffer, { name: key });
}
};
const uploadBackupArchive = async (buffer, fileName) => {
await s3Storage.uploadBuffer(
`${BACKUP_PREFIX}/${fileName}`,
buffer,
"application/zip"
);
};
const deleteOldBackups = async () => {
await s3Storage.deleteObjectsByPrefix(BACKUP_PREFIX);
};
module.exports = {
BACKUP_PREFIX,
UPLOADS_PREFIX,
appendS3UploadsToArchive,
uploadBackupArchive,
deleteOldBackups,
};
+48
View File
@@ -0,0 +1,48 @@
const s3Storage = require("./s3Storage");
const PDF_PREFIX = "uploads/pdf";
const BOOK_SLIDE_PREFIX = "uploads/books";
const uploadPdf = async (fileData, fileName) => {
const key = `${PDF_PREFIX}/${fileName}`;
await s3Storage.uploadBuffer(key, fileData, "application/pdf");
return {
fileName,
url: s3Storage.getPublicUrl(key),
};
};
const uploadBookSlide = async (buffer, imageName) => {
const key = `${BOOK_SLIDE_PREFIX}/${imageName}.jpeg`;
await s3Storage.uploadBuffer(key, buffer, "image/jpeg");
return s3Storage.getPublicUrl(key);
};
const deletePdf = async (fileName) => {
if (!fileName) return;
try {
await s3Storage.deleteObject(`${PDF_PREFIX}/${fileName}`);
} catch (error) {
console.log("Failed to delete PDF from S3:", error?.message);
}
};
const deleteBookSlide = async (imageName) => {
if (!imageName) return;
try {
await s3Storage.deleteObject(`${BOOK_SLIDE_PREFIX}/${imageName}.jpeg`);
} catch (error) {
console.log("Failed to delete book slide from S3:", error?.message);
}
};
module.exports = {
PDF_PREFIX,
BOOK_SLIDE_PREFIX,
uploadPdf,
uploadBookSlide,
deletePdf,
deleteBookSlide,
};
+94
View File
@@ -0,0 +1,94 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const CATEGORY_IMAGE_PREFIX = "uploads/images/category";
const CATEGORY_SHAFAFIAT_PREFIX = "uploads/images/category/shafafiat";
const TERMS_FILE_PREFIX = "uploads/files/terms";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteCategoryImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${CATEGORY_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const deleteShafafiatIcon = async (fileName) => {
if (!fileName) return;
try {
await s3Storage.deleteObject(`${CATEGORY_SHAFAFIAT_PREFIX}/${fileName}`);
} catch (error) {
console.log("Failed to delete shafafiat icon from S3:", error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${CATEGORY_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
const uploadShafafiatIcon = async (fileData, fileName, contentType) => {
await s3Storage.uploadBuffer(
`${CATEGORY_SHAFAFIAT_PREFIX}/${fileName}`,
fileData,
contentType
);
return fileName;
};
const uploadTermsFile = async (fileData, fileName) => {
await s3Storage.uploadBuffer(
`${TERMS_FILE_PREFIX}/${fileName}`,
fileData,
"application/pdf"
);
return fileName;
};
const deleteTermsFile = async (fileName) => {
if (!fileName) return;
try {
await s3Storage.deleteObject(`${TERMS_FILE_PREFIX}/${fileName}`);
} catch (error) {
console.log("Failed to delete terms file from S3:", error?.message);
}
};
module.exports = {
CATEGORY_IMAGE_PREFIX,
CATEGORY_SHAFAFIAT_PREFIX,
TERMS_FILE_PREFIX,
getStoredImageName,
deleteCategoryImage,
deleteShafafiatIcon,
uploadProcessedImage,
uploadShafafiatIcon,
uploadTermsFile,
deleteTermsFile,
};
+52
View File
@@ -0,0 +1,52 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const CONTENT_IMAGE_PREFIX = "uploads/images/content";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteContentImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${CONTENT_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const deleteContentImages = async (doc) => {
await deleteContentImage(doc, "cover");
await deleteContentImage(doc, "thumb");
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${CONTENT_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
CONTENT_IMAGE_PREFIX,
getStoredImageName,
deleteContentImage,
deleteContentImages,
uploadProcessedImage,
};
+58
View File
@@ -0,0 +1,58 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const ELECTION_IMAGE_PREFIX = "uploads/images/election";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteElectionImage = async (fileName) => {
if (!fileName) return;
try {
await s3Storage.deleteObject(`${ELECTION_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete election image from S3:`, error?.message);
}
};
const deleteCandidateImage = async (candidate) => {
const fileName = getStoredImageName(candidate, "profilePic");
await deleteElectionImage(fileName);
};
const deleteElectionCandidateImages = async (election) => {
for (const candidate of election.candidates) {
await deleteCandidateImage(candidate);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${ELECTION_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
ELECTION_IMAGE_PREFIX,
getStoredImageName,
deleteElectionImage,
deleteCandidateImage,
deleteElectionCandidateImages,
uploadProcessedImage,
};
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const LINKS_IMAGE_PREFIX = "uploads/images/links";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteLinksImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${LINKS_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${LINKS_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
LINKS_IMAGE_PREFIX,
getStoredImageName,
deleteLinksImage,
uploadProcessedImage,
};
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const OCCASION_IMAGE_PREFIX = "uploads/images/occasion";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteOccasionImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${OCCASION_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${OCCASION_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
OCCASION_IMAGE_PREFIX,
getStoredImageName,
deleteOccasionImage,
uploadProcessedImage,
};
+47
View File
@@ -2,6 +2,8 @@ const {
S3Client,
PutObjectCommand,
DeleteObjectCommand,
ListObjectsV2Command,
GetObjectCommand,
} = require("@aws-sdk/client-s3");
const config = {
@@ -85,9 +87,54 @@ const deleteObject = async (key) => {
);
};
const listObjects = async (prefix = "") => {
const keys = [];
let continuationToken;
do {
const response = await getClient().send(
new ListObjectsV2Command({
Bucket: config.bucket,
Prefix: normalizeKey(prefix),
ContinuationToken: continuationToken,
})
);
for (const item of response.Contents || []) {
if (item.Key) keys.push(item.Key);
}
continuationToken = response.IsTruncated
? response.NextContinuationToken
: undefined;
} while (continuationToken);
return keys;
};
const getObjectBuffer = async (key) => {
const response = await getClient().send(
new GetObjectCommand({
Bucket: config.bucket,
Key: normalizeKey(key),
})
);
return Buffer.from(await response.Body.transformToByteArray());
};
const deleteObjectsByPrefix = async (prefix) => {
const keys = await listObjects(prefix);
await Promise.all(keys.map((key) => deleteObject(key)));
};
module.exports = {
isConfigured,
getPublicUrl,
uploadBuffer,
deleteObject,
listObjects,
getObjectBuffer,
deleteObjectsByPrefix,
};
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const SLIDER_IMAGE_PREFIX = "uploads/images/slider";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteSliderImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${SLIDER_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${SLIDER_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
SLIDER_IMAGE_PREFIX,
getStoredImageName,
deleteSliderImage,
uploadProcessedImage,
};
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const USER_IMAGE_PREFIX = "uploads/images/users";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteUserImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${USER_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${USER_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
USER_IMAGE_PREFIX,
getStoredImageName,
deleteUserImage,
uploadProcessedImage,
};
+46
View File
@@ -0,0 +1,46 @@
const sharp = require("sharp");
const s3Storage = require("./s3Storage");
const YEAR_BANNER_IMAGE_PREFIX = "uploads/images/mainCover";
const getStoredImageName = (doc, field) =>
doc.get(field, null, { getters: false });
const deleteYearBannerImage = async (doc, field) => {
const fileName = getStoredImageName(doc, field);
if (!fileName) return;
try {
await s3Storage.deleteObject(`${YEAR_BANNER_IMAGE_PREFIX}/${fileName}`);
} catch (error) {
console.log(`Failed to delete ${field} from S3:`, error?.message);
}
};
const uploadProcessedImage = async (
imageData,
imageName,
width,
height,
quality
) => {
const buffer = await sharp(imageData)
.resize(width, height, { fit: "cover" })
.jpeg({ quality })
.toBuffer();
await s3Storage.uploadBuffer(
`${YEAR_BANNER_IMAGE_PREFIX}/${imageName}`,
buffer,
"image/jpeg"
);
return imageName;
};
module.exports = {
YEAR_BANNER_IMAGE_PREFIX,
getStoredImageName,
deleteYearBannerImage,
uploadProcessedImage,
};