135 lines
3.5 KiB
JavaScript
135 lines
3.5 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const { NotFound, Forbidden, ErrorDeletingFile } = require('../../errors');
|
|
const executeAccess = require('../../auth/executeAccess');
|
|
const fileExists = require('../../uploads/fileExists');
|
|
|
|
async function deleteQuery(args) {
|
|
const {
|
|
depth,
|
|
collection: {
|
|
Model,
|
|
config: collectionConfig,
|
|
},
|
|
id,
|
|
req,
|
|
req: {
|
|
locale,
|
|
fallbackLocale,
|
|
},
|
|
overrideAccess,
|
|
} = args;
|
|
|
|
// /////////////////////////////////////
|
|
// 1. Retrieve and execute access
|
|
// /////////////////////////////////////
|
|
|
|
const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true;
|
|
const hasWhereAccess = typeof accessResults === 'object';
|
|
|
|
// /////////////////////////////////////
|
|
// 2. Execute before collection hook
|
|
// /////////////////////////////////////
|
|
|
|
collectionConfig.hooks.beforeDelete.forEach((hook) => hook({ req, id }));
|
|
|
|
// /////////////////////////////////////
|
|
// 3. Get existing document
|
|
// /////////////////////////////////////
|
|
|
|
let query = { _id: id };
|
|
|
|
if (hasWhereAccess) {
|
|
query = {
|
|
...query,
|
|
...accessResults,
|
|
};
|
|
}
|
|
|
|
let resultToDelete = await Model.findOne(query);
|
|
|
|
if (!resultToDelete && !hasWhereAccess) throw new NotFound();
|
|
if (!resultToDelete && hasWhereAccess) throw new Forbidden();
|
|
|
|
resultToDelete = resultToDelete.toJSON({ virtuals: true });
|
|
|
|
if (locale && resultToDelete.setLocale) {
|
|
resultToDelete.setLocale(locale, fallbackLocale);
|
|
}
|
|
|
|
// /////////////////////////////////////
|
|
// 4. Delete any associated files
|
|
// /////////////////////////////////////
|
|
|
|
if (collectionConfig.upload) {
|
|
const { staticDir } = collectionConfig.upload;
|
|
|
|
const staticPath = path.resolve(this.config.paths.configDir, staticDir);
|
|
|
|
const fileToDelete = `${staticPath}/${resultToDelete.filename}`;
|
|
if (await fileExists(fileToDelete)) {
|
|
fs.unlink(fileToDelete, (err) => {
|
|
if (err) {
|
|
throw new ErrorDeletingFile();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (resultToDelete.sizes) {
|
|
Object.values(resultToDelete.sizes).forEach(async (size) => {
|
|
if (await fileExists(`${staticPath}/${size.filename}`)) {
|
|
fs.unlink(`${staticPath}/${size.filename}`, (err) => {
|
|
if (err) {
|
|
throw new ErrorDeletingFile();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// /////////////////////////////////////
|
|
// 5. Delete database document
|
|
// /////////////////////////////////////
|
|
|
|
let result = await Model.findOneAndDelete({ _id: id });
|
|
|
|
result = result.toJSON({ virtuals: true });
|
|
|
|
if (locale && result.setLocale) {
|
|
result.setLocale(locale, fallbackLocale);
|
|
}
|
|
|
|
// /////////////////////////////////////
|
|
// 6. Execute field-level hooks and access
|
|
// /////////////////////////////////////
|
|
|
|
result = await this.performFieldOperations(collectionConfig, {
|
|
data: result,
|
|
hook: 'afterRead',
|
|
operation: 'read',
|
|
req,
|
|
depth,
|
|
overrideAccess,
|
|
});
|
|
|
|
// /////////////////////////////////////
|
|
// 7. Execute after collection hook
|
|
// /////////////////////////////////////
|
|
|
|
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
|
|
await priorHook;
|
|
|
|
result = await hook({ req, id, doc: result }) || result;
|
|
}, Promise.resolve());
|
|
|
|
// /////////////////////////////////////
|
|
// 8. Return results
|
|
// /////////////////////////////////////
|
|
|
|
return result;
|
|
}
|
|
|
|
module.exports = deleteQuery;
|