Player Josu
Player Josu

Reputation: 1253

Yup schema validation password and confirmPassword doesn't work

import * as Yup from 'yup';
import User from '../models/User';

class UserController {
async store(req, res) {
const schema = Yup.object().shape({
  name: Yup.string().required(),
  email: Yup.string()
    .email()
    .required(),
  password: Yup.string()
    .required()
    .min(6),
});

if (!(await schema.isValid(req.body))) {
  return res.status(400).json({ error: 'Validation fails' });
}

const userExists = await User.findOne({ where: { email: req.body.email } });
if (userExists) {
  return res.status(400).json({ error: 'User already exists.' });
}
const { id, name, email, provider } = await User.create(req.body);
return res.json({ id, name, email, provider });
}

async update(req, res) {
const schema = Yup.object().shape({
  name: Yup.string(),
  email: Yup.string().email(),
  oldPassword: Yup.string().min(6),
  password: Yup.string()
    .min(6)
    .when('oldPassword', (oldPassword, field) =>
      oldPassword ? field.required() : field
    ),
  confirmPassword: Yup.string().when('password', (password, field) =>
    password ? field.required().oneOf([Yup.ref('password')]) : field
  ),
});

if (!(await schema.isValid(req.body))) {
  return res.status(400).json({ error: 'Validation fails' });
}

const { email, oldPassword } = req.body;
const user = await User.findByPk(req.userId);
if (user.email !== email) {
  const userExists = await User.findOne({
    where: { email },
  });
  if (userExists) {
    return res.status(400).json({ error: 'User already exists.' });
  }
}

if (oldPassword && !(await user.checkPassword(oldPassword))) {
  return res.status(401).json({ error: 'Password does not match.' });
}

const { id, name, provider } = await user.update(req.body);

return res.json({ id, name, email, provider });
  }  
}
export default new UserController();

Here it creates a normal user with the password 123456:

Here it should work, since the old password is the same as the password of the created user, and it should update the new password:

I want to try to understand how to make him understand the current password as oldpassword and update the password.

Upvotes: 114

Views: 129948

Answers (6)

Bahaa Samoudi
Bahaa Samoudi

Reputation: 183

Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
yup.string().when('password', ([password], schema, options) => {
  if (password!= '') {
     // if the password filled but passwordConfirmation not then return 
     required message
    if (options.value == '') {
      return schema.required();
    } else {
 // if the password filled and passwordConfirmation then return mismatch 
  message
      return schema.oneOf([password], 'validations.mismatch');
    }
  } else {
    return schema;
  }
})
})

Upvotes: 0

leinad
leinad

Reputation: 420

Based on Harshal's answer above, but the API is a little different.

import * as Yup from 'yup';

validationSchema: Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password'), undefined], 'Passwords must match')
});

Notice it's undefined instead of null.

Alternatively you can skip the undefined all together:

import * as Yup from 'yup';

validationSchema: Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password')], 'Passwords must match')
});

Upvotes: 1

Benji
Benji

Reputation: 59

It seems in the latest version of Yup. Yup ^1.0.0

You no longer need to pass null as the second argument to yup.ref where the options arguments go: docs.

Here's how I would test the confirm password:

import * as Yup from 'yup';

validationSchema: Yup.object({
  password: Yup.string().required('Password is required').matches(
      /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*[\]{}()?"\\,><':;|_~`=+-])[a-zA-Z\d!@#$%^&*[\]{}()?"\\,><':;|_~`=+-]{12,99}$/,
      'Must contain at least 12 Characters, 1 Uppercase, 1 Lowercase, 1 Special Character, and 1 Number'
    ),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password')], 'Passwords must match')
});

Note: I have added an extra .matches() regex in to the solution as for security most sites use some form of password validation.

Upvotes: 0

aprilmintacpineda
aprilmintacpineda

Reputation: 1274

This is how I did it.

yup.object({
  password: yup
    .string()
    .required('Please enter your password.')
    .min(8, 'Your password is too short.'),
  retypePassword: yup
    .string()
    .required('Please retype your password.')
    .oneOf([yup.ref('password')], 'Your passwords do not match.')
});

Upvotes: 39

Hammed Oyedele
Hammed Oyedele

Reputation: 1225

Based on @anoNewb answer and the request made by @Renan,

Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
    .test('passwords-match', 'Passwords must match', function(value){
      return this.parent.password === value
    })
})

Upvotes: 89

Harshal
Harshal

Reputation: 8308

Try this out:

import * as Yup from 'yup';

validationSchema: Yup.object({
  password: Yup.string().required('Password is required'),
  passwordConfirmation: Yup.string()
     .oneOf([Yup.ref('password'), null], 'Passwords must match')
});

Upvotes: 282

Related Questions