fix: validation message shape

This commit is contained in:
Ben Irvin 2025-01-29 16:54:15 +01:00
parent 1f8e39868e
commit e07a466901
7 changed files with 46 additions and 37 deletions

View File

@ -47,7 +47,7 @@ const REGISTER_USER_SCHEMA = yup.object().shape({
id: 'components.Input.error.contain.maxBytes', id: 'components.Input.error.contain.maxBytes',
defaultMessage: 'Password must be less than 73 bytes', defaultMessage: 'Password must be less than 73 bytes',
}, },
(value) => { function (value) {
if (!value) return true; if (!value) return true;
return new TextEncoder().encode(value).length <= 72; return new TextEncoder().encode(value).length <= 72;
} }
@ -115,7 +115,7 @@ const REGISTER_ADMIN_SCHEMA = yup.object().shape({
id: 'components.Input.error.contain.maxBytes', id: 'components.Input.error.contain.maxBytes',
defaultMessage: 'Password must be less than 73 bytes', defaultMessage: 'Password must be less than 73 bytes',
}, },
(value) => { function (value) {
if (!value) return true; if (!value) return true;
return new TextEncoder().encode(value).length <= 72; return new TextEncoder().encode(value).length <= 72;
} }

View File

@ -30,11 +30,20 @@ const RESET_PASSWORD_SCHEMA = yup.object().shape({
values: { min: 8 }, values: { min: 8 },
}) })
// bcrypt has a max length of 72 bytes (not characters!) // bcrypt has a max length of 72 bytes (not characters!)
.test('required-byte-size', 'Password must be less than 73 bytes', (value) => { .test(
if (!value) return true; 'required-byte-size',
const byteSize = new TextEncoder().encode(value).length; {
return byteSize <= 72; message: {
}) id: 'components.Input.error.contain.maxBytes',
defaultMessage: 'Password must be less than 73 bytes',
},
},
function (value) {
if (!value) return true;
const byteSize = new TextEncoder().encode(value).length;
return byteSize <= 72;
}
)
.matches(/[a-z]/, { .matches(/[a-z]/, {
message: { message: {
id: 'components.Input.error.contain.lowercase', id: 'components.Input.error.contain.lowercase',

View File

@ -33,7 +33,7 @@ const COMMON_USER_SCHEMA = {
id: 'components.Input.error.contain.maxBytes', id: 'components.Input.error.contain.maxBytes',
defaultMessage: 'Password must be less than 73 bytes', defaultMessage: 'Password must be less than 73 bytes',
}, },
(value) => { function (value) {
if (!value) return true; if (!value) return true;
return new TextEncoder().encode(value).length <= 72; return new TextEncoder().encode(value).length <= 72;
} }

View File

@ -23,7 +23,7 @@ export const username = yup.string().min(1);
export const password = yup export const password = yup
.string() .string()
.min(8) .min(8)
.test('required-byte-size', '${path} must be less than 73 bytes', (value) => { .test('required-byte-size', '${path} must be less than 73 bytes', function (value) {
if (!value) return true; if (!value) return true;
const byteSize = new TextEncoder().encode(value).length; const byteSize = new TextEncoder().encode(value).length;
return byteSize <= 72; return byteSize <= 72;

View File

@ -477,7 +477,12 @@ describe('user-permissions auth', () => {
const authorization = auth({ strapi: global.strapi }); const authorization = auth({ strapi: global.strapi });
if (expectedMessage) { if (expectedMessage) {
await expect(authorization.resetPassword(ctx)).rejects.toThrow(expectedMessage); await expect(authorization.resetPassword(ctx)).rejects.toThrowError(
expect.objectContaining({
name: 'ValidationError',
message: expectedMessage,
})
);
expect(ctx.send).toHaveBeenCalledTimes(0); expect(ctx.send).toHaveBeenCalledTimes(0);
} else { } else {
await authorization.resetPassword(ctx); await authorization.resetPassword(ctx);

View File

@ -14,16 +14,14 @@ const createRegisterSchema = (config) =>
password: yup password: yup
.string() .string()
.required() .required()
.test( .test(function (value) {
'max-bytes', if (!value) return true;
{ const isValid = new TextEncoder().encode(value).length <= 72;
message: 'Password must be less than 73 bytes', if (!isValid) {
}, return this.createError({ message: 'Password must be less than 73 bytes' });
(value) => {
if (!value) return true;
return new TextEncoder().encode(value).length <= 72;
} }
) return true;
})
.test(async function (value) { .test(async function (value) {
if (typeof config?.validatePassword === 'function') { if (typeof config?.validatePassword === 'function') {
try { try {
@ -59,16 +57,14 @@ const createResetPasswordSchema = (config) =>
password: yup password: yup
.string() .string()
.required() .required()
.test( .test(function (value) {
'max-bytes', if (!value) return true;
{ const isValid = new TextEncoder().encode(value).length <= 72;
message: 'Password must be less than 73 bytes', if (!isValid) {
}, return this.createError({ message: 'Password must be less than 73 bytes' });
(value) => {
if (!value) return true;
return new TextEncoder().encode(value).length <= 72;
} }
) return true;
})
.test(async function (value) { .test(async function (value) {
if (typeof config?.validatePassword === 'function') { if (typeof config?.validatePassword === 'function') {
try { try {
@ -97,16 +93,14 @@ const createChangePasswordSchema = (config) =>
password: yup password: yup
.string() .string()
.required() .required()
.test( .test(function (value) {
'max-bytes', if (!value) return true;
{ const isValid = new TextEncoder().encode(value).length <= 72;
message: 'Password must be less than 73 bytes', if (!isValid) {
}, return this.createError({ message: 'Password must be less than 73 bytes' });
(value) => {
if (!value) return true;
return new TextEncoder().encode(value).length <= 72;
} }
) return true;
})
.test(async function (value) { .test(async function (value) {
if (typeof config?.validatePassword === 'function') { if (typeof config?.validatePassword === 'function') {
try { try {

View File

@ -34,6 +34,7 @@ describe('Auth API', () => {
}); });
afterAll(async () => { afterAll(async () => {
await strapi.db.query('plugin::users-permissions.user').deleteMany();
await strapi.destroy(); await strapi.destroy();
}); });