mirror of
https://github.com/strapi/strapi.git
synced 2025-11-08 06:07:41 +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 isDraft = contentTypesUtils.isDraft(entityToUpdate, model);
|
||||||
|
|
||||||
const validData = await entityValidator.validateEntityUpdate(model, data, {
|
const validData = await entityValidator.validateEntityUpdate(
|
||||||
isDraft,
|
model,
|
||||||
entityId,
|
data,
|
||||||
});
|
{
|
||||||
|
isDraft,
|
||||||
|
},
|
||||||
|
entityToUpdate
|
||||||
|
);
|
||||||
|
|
||||||
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
|
||||||
|
|
||||||
|
|||||||
@ -120,12 +120,13 @@ const createRelationValidator = createOrUpdate => (attr, data, { isDraft }) => {
|
|||||||
|
|
||||||
const createScalarAttributeValidator = createOrUpdate => (
|
const createScalarAttributeValidator = createOrUpdate => (
|
||||||
attr,
|
attr,
|
||||||
{ isDraft, uid, attributeName, entityId }
|
data,
|
||||||
|
{ isDraft, model, attributeName, entity }
|
||||||
) => {
|
) => {
|
||||||
let validator;
|
let validator;
|
||||||
|
|
||||||
if (has(attr.type, validators)) {
|
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 {
|
} else {
|
||||||
// No validators specified - fall back to mixed
|
// No validators specified - fall back to mixed
|
||||||
validator = yup.mixed();
|
validator = yup.mixed();
|
||||||
@ -139,18 +140,18 @@ const createScalarAttributeValidator = createOrUpdate => (
|
|||||||
const createAttributeValidator = createOrUpdate => (
|
const createAttributeValidator = createOrUpdate => (
|
||||||
attr,
|
attr,
|
||||||
data,
|
data,
|
||||||
{ isDraft, uid, attributeName, entityId }
|
{ isDraft, model, attributeName, entity }
|
||||||
) => {
|
) => {
|
||||||
let validator;
|
let validator;
|
||||||
|
|
||||||
if (isMediaAttribute(attr)) {
|
if (isMediaAttribute(attr)) {
|
||||||
validator = yup.mixed();
|
validator = yup.mixed();
|
||||||
} else if (isScalarAttribute(attr)) {
|
} else if (isScalarAttribute(attr)) {
|
||||||
validator = createScalarAttributeValidator(createOrUpdate)(attr, {
|
validator = createScalarAttributeValidator(createOrUpdate)(attr, data, {
|
||||||
isDraft,
|
isDraft,
|
||||||
uid,
|
model,
|
||||||
attributeName,
|
attributeName,
|
||||||
entityId,
|
entity,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (attr.type === 'component') {
|
if (attr.type === 'component') {
|
||||||
@ -169,14 +170,14 @@ const createAttributeValidator = createOrUpdate => (
|
|||||||
return validator;
|
return validator;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createModelValidator = createOrUpdate => (model, data, { isDraft, entityId }) => {
|
const createModelValidator = createOrUpdate => (model, data, { isDraft }, entity) => {
|
||||||
const writableAttributes = model ? getWritableAttributes(model) : [];
|
const writableAttributes = model ? getWritableAttributes(model) : [];
|
||||||
|
|
||||||
const schema = writableAttributes.reduce((validators, attributeName) => {
|
const schema = writableAttributes.reduce((validators, attributeName) => {
|
||||||
const validator = createAttributeValidator(createOrUpdate)(
|
const validator = createAttributeValidator(createOrUpdate)(
|
||||||
model.attributes[attributeName],
|
model.attributes[attributeName],
|
||||||
prop(attributeName, data),
|
prop(attributeName, data),
|
||||||
{ isDraft, uid: model.uid, attributeName, entityId }
|
{ isDraft, model, attributeName, entity }
|
||||||
);
|
);
|
||||||
|
|
||||||
return assoc(attributeName, validator)(validators);
|
return assoc(attributeName, validator)(validators);
|
||||||
@ -188,7 +189,8 @@ const createModelValidator = createOrUpdate => (model, data, { isDraft, entityId
|
|||||||
const createValidateEntity = createOrUpdate => async (
|
const createValidateEntity = createOrUpdate => async (
|
||||||
model,
|
model,
|
||||||
data,
|
data,
|
||||||
{ isDraft = false, entityId } = {}
|
{ isDraft = false } = {},
|
||||||
|
entity = null
|
||||||
) => {
|
) => {
|
||||||
if (!isObject(data)) {
|
if (!isObject(data)) {
|
||||||
const { displayName } = model.info;
|
const { displayName } = model.info;
|
||||||
@ -198,10 +200,14 @@ const createValidateEntity = createOrUpdate => async (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const validator = createModelValidator(createOrUpdate)(model, data, {
|
const validator = createModelValidator(createOrUpdate)(
|
||||||
isDraft,
|
model,
|
||||||
entityId,
|
data,
|
||||||
}).required();
|
{
|
||||||
|
isDraft,
|
||||||
|
},
|
||||||
|
entity
|
||||||
|
).required();
|
||||||
return validateYupSchema(validator, { strict: false, abortEarly: false })(data);
|
return validateYupSchema(validator, { strict: false, abortEarly: false })(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,9 @@ const { yup } = require('@strapi/utils');
|
|||||||
/**
|
/**
|
||||||
* Utility function to compose validators
|
* 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 fns.reduce((validator, fn) => {
|
||||||
return fn(attr, validator, { isDraft, uid, attributeName, entityId });
|
return fn(attr, validator, { isDraft, model, attributeName, entity, data });
|
||||||
}, yup.mixed());
|
}, yup.mixed());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,14 +71,24 @@ const addMaxFloatValidator = ({ max }, validator) =>
|
|||||||
const addStringRegexValidator = ({ regex }, validator) =>
|
const addStringRegexValidator = ({ regex }, validator) =>
|
||||||
_.isUndefined(regex) ? validator : validator.matches(new RegExp(regex));
|
_.isUndefined(regex) ? validator : validator.matches(new RegExp(regex));
|
||||||
|
|
||||||
const addUniqueValidator = (attr, validator, { uid, attributeName, entityId }) => {
|
const addUniqueValidator = (attr, validator, { model, attributeName, entity, data }) => {
|
||||||
if (attr.unique) {
|
/**
|
||||||
|
* 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 => {
|
return validator.test('unique', 'This attribute must be unique', async value => {
|
||||||
let whereParams = entityId
|
let whereParams = entity
|
||||||
? { $and: [{ [attributeName]: value }, { $not: { id: entityId } }] }
|
? { $and: [{ [attributeName]: value }, { $not: { id: entity.id } }] }
|
||||||
: { [attributeName]: value };
|
: { [attributeName]: value };
|
||||||
|
|
||||||
const record = await strapi.db.query(uid).findOne({
|
const record = await strapi.db.query(model.uid).findOne({
|
||||||
select: ['id'],
|
select: ['id'],
|
||||||
where: whereParams,
|
where: whereParams,
|
||||||
});
|
});
|
||||||
@ -131,7 +141,7 @@ module.exports = {
|
|||||||
password: stringValidator,
|
password: stringValidator,
|
||||||
email: emailValidator,
|
email: emailValidator,
|
||||||
enumeration: enumerationValidator,
|
enumeration: enumerationValidator,
|
||||||
boolean: () => () => yup.mixed(),
|
boolean: () => yup.boolean(),
|
||||||
uid: uidValidator,
|
uid: uidValidator,
|
||||||
json: () => yup.mixed(),
|
json: () => yup.mixed(),
|
||||||
integer: integerValidator,
|
integer: integerValidator,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user