Skip to content
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

schemas and validations with optional fields #724

Closed
rhadaway14 opened this issue Jun 12, 2023 · 8 comments
Closed

schemas and validations with optional fields #724

rhadaway14 opened this issue Jun 12, 2023 · 8 comments

Comments

@rhadaway14
Copy link

rhadaway14 commented Jun 12, 2023

I have a customer who is trying to have an optional field in his schema(altEmail) that still must pass a validator when present.
When saving a document with a correct email and correct alt email, the doc is written.
When attempting to save a document with a correct email and no altEmail, it fails, as the value undefined becomes the string 'undefined' and fails the email validation.
Here is some sample code(you will need to update the username, password, scope, collection, bucket, and connection endpoints):

const { Ottoman, Schema, set, addValidators } = require('ottoman');
const { config } = require('dotenv');
const { faker } = require('@faker-js/faker');
const { validate } = require('email-validator');
const { nanoid } = import('nanoid');

config();

const main = async () => {
    const { nanoid } = await import('nanoid');

const connectionObj = {
    connectionString: 'your own machine', //use your own
    bucketName: 'your bucket name', //use your own
    username: 'your username', //use your own
    password: 'your password' //use your own
  };

const ottoman = new Ottoman({
    collectionName: 'your collection name', //use your own
    scopeName: 'your scope name', //use your own
    timeout: 10000,
    ottoman: {
      idKey: 'id'
    }
  });

  const connection = await ottoman.connect(connectionObj);
  console.log('connected to couchbase')
  set('DEBUG', true);


  const res = await ottoman.start();
  console.log('ottoman started')

const email = (val) => {
    console.log(typeof val)
    if (val && !validate(val)) {
      throw new Error('Value is not a valid email address.');
    }
    return true;
  };

  addValidators({ email });

  const UserSchema = new Schema({
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
    email: { type: String, required: true, validator: 'email' },
    altEmail: { type: String, validator: 'email' },
  });

  const User = ottoman.model('User', UserSchema);

// user with alt email >> should write to db
  function emailUser(alt = undefined){
    const user = {
      firstName: faker.person.firstName(),
      lastName: faker.person.lastName(),
      email: user@user.com,
      altEmail: user@user.com
    };

// user without alt email >> should write to db
    function emailUser(alt = undefined){
    const user = {
      firstName: faker.person.firstName(),
      lastName: faker.person.lastName(),
      email: fuser@user.com,
    };

//user with incorrect email and no alt email >> should fail to write
function emailUser(alt = undefined){
    const user = {
      firstName: faker.person.firstName(),
      lastName: faker.person.lastName(),
      email: user@sdfdfsg,
    };

//user with incorrect email and correct alt email >> should fail to write
function emailUser(alt = undefined){
    const user = {
      firstName: faker.person.firstName(),
      lastName: faker.person.lastName(),
      email: user@ertret
      altEmail: user@user.com
    };

//user with correct email and incorrect alt email >> should fail to write
function emailUser(alt = undefined){
    const user = {
      firstName: faker.person.firstName(),
      lastName: faker.person.lastName(),
      email: user@user.com
      altEmail: user@dfsgdfsgs
    };
@avsej
Copy link
Member

avsej commented Jun 13, 2023

@rhadaway14, does this fixes your problem?

const email = (val) => {
    const emailRegex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

    if (!emailRegex.test(val.email)) {
        // email is not correct
        return false;
    }

    if (val.altEmail) {
      // altEmail is not correct
      return emailRegex.test(val.altEmail);
    }

    return true;
  };

@rhadaway14
Copy link
Author

No that doesn't work. The value being passed to the email validator is a String.
I think this is because the schema casts it as a String before it is sent to the validator.
So val.email or val.altEmail doesn't exist.

@rhadaway14
Copy link
Author

here is the index.js and the package.json
I've simplified the code to help demo the issue
index.txt
package.txt

@avsej
Copy link
Member

avsej commented Jun 15, 2023

then, maybe all you need is to parse string as JSON if it is stringified document body

@rhadaway14
Copy link
Author

I don't think that that is how it was designed to be used.
From my understanding,
if I create a new object using the schema, it casts each attribute as whatever type is defined in the schema.
<type: String>
Then it runs that value, and that value alone through the validator. So the value that is passed to the validator is just a string that was defined when the class was created.
And since the attribute altEmail is defined in the schema, when it is left out when I create a new object, it becomes the value undefined, which is then cast as a string.

const UserSchema = new Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true, validator: 'email' },
altEmail: { type: String, validator: 'email' },
});

@gsi-alejandro
Copy link
Collaborator

hi @rhadaway14

I created a PR already to solve this issue.

When merged and released your code should work as expected.

This was a bug due to we didn't exclude undefined, then it was being parsed as string, the above PR fix it.

Also, a couple of tests were added to ensure the correct behavior.

Thank you for your feedbacks

@rhadaway14
Copy link
Author

did that PR ever get released? it looks like it is still pending merge? I'm not trying to be irritating.

@ejscribner
Copy link
Collaborator

ejscribner commented Aug 1, 2023

Hey @rhadaway14 apologies for the delay. We've released v2.3.4 that includes this change.

Thanks so much for your patience, and for being a part of the Ottoman community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants