strapi-plugin-do-not-delete
Version:
A plugin for Strapi CMS that protects certain entries from being deleted.
150 lines (149 loc) • 5.03 kB
JavaScript
const utils = require("@strapi/utils");
const PLUGIN_ID = "do-not-delete";
const getService = (name) => global.strapi.plugin(PLUGIN_ID).service(name);
const COMPARATOR_ACTIONS = {
// Equality.
is: (value, attr) => value === attr,
isNot: (value, attr) => value !== attr,
// Contains.
has: (value, attr) => attr.includes(value),
hasNot: (value, attr) => !attr.includes(value),
in: (value, attr) => value.includes(attr),
notIn: (value, attr) => !value.includes(attr),
// Greater than or equal to.
between: (value, attr) => attr >= value[0] && attr <= value[1],
gt: (value, attr) => attr > value,
gte: (value, attr) => attr >= value,
lt: (value, attr) => attr < value,
lte: (value, attr) => attr <= value,
// Dates.
after: (value, attr) => new Date(attr) > new Date(value),
before: (value, attr) => new Date(attr) < new Date(value),
day: (value, attr) => {
const d1 = new Date(attr);
const d2 = new Date(value);
return d1.getUTCDate() === d2.getUTCDate() && d1.getUTCMonth() === d2.getUTCMonth() && d1.getUTCFullYear() === d2.getUTCFullYear();
},
month: (value, attr) => {
const d1 = new Date(attr);
const d2 = new Date(value);
return d1.getUTCMonth() === d2.getUTCMonth() && d1.getUTCFullYear() === d2.getUTCFullYear();
},
year: (value, attr) => new Date(attr).getUTCFullYear() === new Date(value).getUTCFullYear(),
// Regular expression.
matches: (value, attr) => RegExp(value).test(attr)
};
const isProtectedEntry = (entity, rules) => rules.some((rule) => {
const [attr, comparator, value] = rule;
const entityAttr = entity[attr];
const comparatorAction = COMPARATOR_ACTIONS[comparator];
return !!(comparatorAction && comparatorAction(value, entityAttr));
});
const bootstrap = ({ strapi }) => {
const validateService = getService("validation");
Object.keys(strapi.contentTypes).forEach((uid) => {
const contentType = strapi.contentTypes[uid];
const pluginOptions = contentType.pluginOptions ? contentType.pluginOptions[PLUGIN_ID] : null;
if (pluginOptions) {
validateService.validatePluginOptions(uid, pluginOptions);
}
});
};
const register = async ({ strapi }) => {
const validateService = getService("validation");
strapi.documents.use(async (context, next) => {
const { action, contentType, params, uid } = context;
const { documentId } = params;
const pluginOptions = contentType.pluginOptions[PLUGIN_ID];
if (!["delete"].includes(action) || !pluginOptions) {
return next();
}
const entity = await strapi.documents(uid).findOne({ documentId });
if (!entity) {
return;
}
validateService.validateDeleteAction(entity, pluginOptions.rules);
return next();
});
};
const validationService = () => ({
validateDeleteAction(entry, rules) {
if (!rules || !rules.length) {
return;
}
if (isProtectedEntry(entry, rules)) {
throw new utils.errors.ValidationError("This entry is protected and cannot be deleted.");
}
},
validatePluginOptions(uid, options) {
if (!Array.isArray(options.rules)) {
throw new utils.errors.ValidationError(
`Must define delete protection rules as an array for ${uid}.`
);
}
options.rules.forEach((rule) => {
if (!Array.isArray(rule)) {
throw new utils.errors.ValidationError(
`Must define delete protection rules as an array for ${uid}.`
);
}
if (rule.length !== 3) {
throw new utils.errors.ValidationError(
`Must define delete protection rules with all arguments for ${uid}.`
);
}
const comparator = rule[1];
const value = rule[2];
const comparators = [
"after",
"before",
"between",
"has",
"hasNot",
"in",
"notIn",
"is",
"isNot",
"gt",
"gte",
"lt",
"lte",
"day",
"month",
"year",
"matches"
];
if (!comparators.includes(comparator)) {
throw new utils.errors.ValidationError(
`Unknown comparator ${comparator} used for ${uid} protection rules.`
);
}
if (["in", "notIn", "between"].includes(comparator) && !Array.isArray(value)) {
throw new utils.errors.ValidationError(
`Invalid ${comparator} value for ${uid} protection rules.`
);
}
if (comparator === "between" && value.length !== 2) {
throw new utils.errors.ValidationError(
`Invalid number of array values for between comparators for ${uid} protection rules.`
);
}
if (["day", "month", "year"].includes(comparator)) {
throw new utils.errors.ValidationError(
`Invalid date string for ${comparator} value for ${uid} protection rules.`
);
}
});
}
});
const services = {
validation: validationService
};
const index = {
bootstrap,
register,
services
};
module.exports = index;
//# sourceMappingURL=index.js.map
;