mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 10:55:37 +00:00
skip unique validation if the attribute is unchanged
This commit is contained in:
parent
d3de1ca7be
commit
2b625210d7
@ -202,10 +202,14 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
|
||||
|
||||
const isDraft = contentTypesUtils.isDraft(entityToUpdate, model);
|
||||
|
||||
const validData = await entityValidator.validateEntityUpdate(model, data, {
|
||||
isDraft,
|
||||
entityId,
|
||||
});
|
||||
const validData = await entityValidator.validateEntityUpdate(
|
||||
model,
|
||||
data,
|
||||
{
|
||||
isDraft,
|
||||
},
|
||||
entityToUpdate
|
||||
);
|
||||
|
||||
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
||||
|
||||
|
||||
@ -120,12 +120,13 @@ const createRelationValidator = createOrUpdate => (attr, data, { isDraft }) => {
|
||||
|
||||
const createScalarAttributeValidator = createOrUpdate => (
|
||||
attr,
|
||||
{ isDraft, uid, attributeName, entityId }
|
||||
data,
|
||||
{ isDraft, model, attributeName, entity }
|
||||
) => {
|
||||
let validator;
|
||||
|
||||
if (has(attr.type, validators)) {
|
||||
validator = validators[attr.type](attr, { isDraft, uid, attributeName, entityId });
|
||||
validator = validators[attr.type](attr, { isDraft, model, attributeName, entity, data });
|
||||
} else {
|
||||
// No validators specified - fall back to mixed
|
||||
validator = yup.mixed();
|
||||
@ -139,18 +140,18 @@ const createScalarAttributeValidator = createOrUpdate => (
|
||||
const createAttributeValidator = createOrUpdate => (
|
||||
attr,
|
||||
data,
|
||||
{ isDraft, uid, attributeName, entityId }
|
||||
{ isDraft, model, attributeName, entity }
|
||||
) => {
|
||||
let validator;
|
||||
|
||||
if (isMediaAttribute(attr)) {
|
||||
validator = yup.mixed();
|
||||
} else if (isScalarAttribute(attr)) {
|
||||
validator = createScalarAttributeValidator(createOrUpdate)(attr, {
|
||||
validator = createScalarAttributeValidator(createOrUpdate)(attr, data, {
|
||||
isDraft,
|
||||
uid,
|
||||
model,
|
||||
attributeName,
|
||||
entityId,
|
||||
entity,
|
||||
});
|
||||
} else {
|
||||
if (attr.type === 'component') {
|
||||
@ -169,14 +170,14 @@ const createAttributeValidator = createOrUpdate => (
|
||||
return validator;
|
||||
};
|
||||
|
||||
const createModelValidator = createOrUpdate => (model, data, { isDraft, entityId }) => {
|
||||
const createModelValidator = createOrUpdate => (model, data, { isDraft }, entity) => {
|
||||
const writableAttributes = model ? getWritableAttributes(model) : [];
|
||||
|
||||
const schema = writableAttributes.reduce((validators, attributeName) => {
|
||||
const validator = createAttributeValidator(createOrUpdate)(
|
||||
model.attributes[attributeName],
|
||||
prop(attributeName, data),
|
||||
{ isDraft, uid: model.uid, attributeName, entityId }
|
||||
{ isDraft, model, attributeName, entity }
|
||||
);
|
||||
|
||||
return assoc(attributeName, validator)(validators);
|
||||
@ -188,7 +189,8 @@ const createModelValidator = createOrUpdate => (model, data, { isDraft, entityId
|
||||
const createValidateEntity = createOrUpdate => async (
|
||||
model,
|
||||
data,
|
||||
{ isDraft = false, entityId } = {}
|
||||
{ isDraft = false } = {},
|
||||
entity = null
|
||||
) => {
|
||||
if (!isObject(data)) {
|
||||
const { displayName } = model.info;
|
||||
@ -198,10 +200,14 @@ const createValidateEntity = createOrUpdate => async (
|
||||
);
|
||||
}
|
||||
|
||||
const validator = createModelValidator(createOrUpdate)(model, data, {
|
||||
isDraft,
|
||||
entityId,
|
||||
}).required();
|
||||
const validator = createModelValidator(createOrUpdate)(
|
||||
model,
|
||||
data,
|
||||
{
|
||||
isDraft,
|
||||
},
|
||||
entity
|
||||
).required();
|
||||
return validateYupSchema(validator, { strict: false, abortEarly: false })(data);
|
||||
};
|
||||
|
||||
|
||||
@ -7,9 +7,9 @@ const { yup } = require('@strapi/utils');
|
||||
/**
|
||||
* Utility function to compose validators
|
||||
*/
|
||||
const composeValidators = (...fns) => (attr, { isDraft, uid, attributeName, entityId }) => {
|
||||
const composeValidators = (...fns) => (attr, { isDraft, model, attributeName, entity, data }) => {
|
||||
return fns.reduce((validator, fn) => {
|
||||
return fn(attr, validator, { isDraft, uid, attributeName, entityId });
|
||||
return fn(attr, validator, { isDraft, model, attributeName, entity, data });
|
||||
}, yup.mixed());
|
||||
};
|
||||
|
||||
@ -71,14 +71,24 @@ const addMaxFloatValidator = ({ max }, validator) =>
|
||||
const addStringRegexValidator = ({ regex }, validator) =>
|
||||
_.isUndefined(regex) ? validator : validator.matches(new RegExp(regex));
|
||||
|
||||
const addUniqueValidator = (attr, validator, { uid, attributeName, entityId }) => {
|
||||
if (attr.unique) {
|
||||
const addUniqueValidator = (attr, validator, { model, attributeName, entity, data }) => {
|
||||
/**
|
||||
* If the attribute is unchanged we skip the unique verification. This will
|
||||
* prevent the validator to be triggered in case the user activated the
|
||||
* unique constraint after already creating multiple entries with
|
||||
* the same attribute value for that field.
|
||||
*/
|
||||
if (entity && data === entity[attributeName]) {
|
||||
return validator;
|
||||
}
|
||||
|
||||
if (attr.unique || attr.type === 'uid') {
|
||||
return validator.test('unique', 'This attribute must be unique', async value => {
|
||||
let whereParams = entityId
|
||||
? { $and: [{ [attributeName]: value }, { $not: { id: entityId } }] }
|
||||
let whereParams = entity
|
||||
? { $and: [{ [attributeName]: value }, { $not: { id: entity.id } }] }
|
||||
: { [attributeName]: value };
|
||||
|
||||
const record = await strapi.db.query(uid).findOne({
|
||||
const record = await strapi.db.query(model.uid).findOne({
|
||||
select: ['id'],
|
||||
where: whereParams,
|
||||
});
|
||||
@ -131,7 +141,7 @@ module.exports = {
|
||||
password: stringValidator,
|
||||
email: emailValidator,
|
||||
enumeration: enumerationValidator,
|
||||
boolean: () => () => yup.mixed(),
|
||||
boolean: () => yup.boolean(),
|
||||
uid: uidValidator,
|
||||
json: () => yup.mixed(),
|
||||
integer: integerValidator,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user