New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique validations with custom error message being overwritten #4920

Closed
corbanb opened this Issue Nov 24, 2015 · 3 comments

Comments

2 participants
@corbanb

corbanb commented Nov 24, 2015

Hey guys! Long time Sequelize user, love the product and hope to contribute one day.

In the meantime I have been trying to understand a bug I have run into. Basically the scenario is you have a User model that needs unique usernames and emails being saved to the db. Obviously these should be case insensitive so 'Foo' and 'foo' are the same user and fail if a new user tries to create 'foO' or any of the other possibilities in the future a unique error is thrown.

Info

Sequelize Version: 3.14.1
Dialect: postgres
Github Repo: https://github.com/corbanb/sequelize-demos
Heroku App: https://sequelize-demos.herokuapp.com

Questions

Right now the demo does know it failed on uniques but in the case of the username it sends back the emails custom error message (see here).

  1. Why am I getting the email custom error message for username? (see below)
  2. Is this the proper usage of the fields lower case for unique or is there a more 'sequelize' way of doing this? (See User Model below)

Issue Details

Error response

{
  name: "SequelizeUniqueConstraintError",
  message: "Oops. Looks like you already have an account with this email address. Please try to login.",
  errors: [
    {
      message: "Oops. Looks like you already have an account with this email address. Please try to login.",
      type: "unique violation",
      path: "username",
      value: "foo"
  },
  {
    message: "Oops. Looks like you already have an account with this email address. Please try to login.",
    type: "unique violation",
    path: "email",
    value: "foo@bar.com"
  }
  ],
  fields: {
    username: "foo",
    email: "foo@bar.com"
  }
}

Example User Model

var Instance = require('sequelize/lib/instance');

module.exports = function(sequelize, DataTypes) {
    var User = sequelize.define('User', {
        username: {
            type: DataTypes.STRING,
            unique: {
                args: true,
                message: 'Username must be unique.',
                fields: [sequelize.fn('lower', sequelize.col('username'))]
            },
            validate: {
                min: {
                    args: 3,
                    msg: 'Username must start with a letter, have no spaces, and be at least 3 characters.'
                },
                max: {
                    args: 40,
                    msg: 'Username must start with a letter, have no spaces, and be at less than 40 characters.'
                },
                is: {
                    args: /^[A-Za-z][A-Za-z0-9-]+$/i, // must start with letter and only have letters, numbers, dashes
                    msg: 'Username must start with a letter, have no spaces, and be 3 - 40 characters.'
                }
            },
        },

        email: {
            type: DataTypes.STRING,
            unique: {
                args: true,
                msg: 'Oops. Looks like you already have an account with this email address. Please try to login.',
                fields: [sequelize.fn('lower', sequelize.col('email'))]
            },
            validate: {
                isEmail: {
                    args: true,
                    msg: 'The email you entered is invalid or is already in our system.'
                },
                max: {
                    args: 254,
                    msg: 'The email you entered is invalid or longer than 254 characters.'
                }
            }
        },

        name: {
            type: DataTypes.STRING,
            validate: {
                max: {
                    args: 254,
                    msg: 'Your full name can only be 254 caracters.'
                }
            }
        }
    }, {
        indexes: [
            {
                unique: true,
                fields: ['username', 'email']
            }
        ]
    });

    return User;
};
@mickhansen

This comment has been minimized.

Contributor

mickhansen commented Nov 25, 2015

It's a composite unique so sequelize is probably just finding the first field.

@mickhansen mickhansen added the bug label Nov 25, 2015

@corbanb

This comment has been minimized.

corbanb commented Nov 30, 2015

I would be happy to take a look to offer up a PR if you have some input for me on where to head with it @mickhansen

@mickhansen

This comment has been minimized.

Contributor

mickhansen commented Nov 30, 2015

@corbanb each dialect has it's own method like: https://github.com/sequelize/sequelize/blob/master/lib/dialects/postgres/query.js#L264

Generally it should be dialects/[dialect]/query.js#formatError

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment