Loopback: Overriding validation

Created on 28 Nov 2014  Â·  9Comments  Â·  Source: strongloop/loopback

I have a class MyUser which extends built-in User.
How can I remove default validation (like the one on email and password)?

Most helpful comment

How can I remove default validation (like the one on email and password)?

In the sample below, I remove everything from the custom MyModel which extends User:

  1. the validations on username and email are removed
  2. the password field is removed
  3. the username and email fields are removed
{
  "name": "MyModel",
  "base": "User",
  "properties": {
    "email": false,
    "username": false,
    "password": false
  }
}
...
module.exports = function(MyModel) {
  MyModel.disableRemoteMethod("login", true);
  MyModel.disableRemoteMethod("logout", true);
  MyModel.on('dataSourceAttached', function() {
    console.log('MyModel', 'on.dataSourceAttached()');
    delete MyModel.validations.email; //delete MyModel.app.models.User.validations.email;
    delete MyModel.validations.username; //delete MyModel.app.models.User.validations.username;
  });
};

Some ideas came from: issue #1137

How can this be helpful? Well what if you're trying to experiment with a multi-tenant setup where MyModel is actually OrgModel? It may help.

All 9 comments

I have the same question.
I have resolved it by setting default value in beforecreate hook.

2014-11-28 16:46 GMT+08:00 Salvatore [email protected]:

I have a class MyUser which extends built-in User.
How can I remove default validation (like the one on email and password)?

—
Reply to this email directly or view it on GitHub
https://github.com/strongloop/loopback/issues/879.

Ok, it could be a workaround for the password, but what about email uniqueness? I would allow multiple accounts with same email.

It is not possible to drop the uniqueness constraint on User email. User.login supports both username and email, and if email was not unique, it would not be possible to tell which user is logging in.

But @bajtos , the mere fact that User.login supports both methods implies there are two use-cases it handles: one is where username is unique, and the other is where email is unique. It should be straightforward to choose which use-case you want, and be assured of the semantics only in that one.

So, can I really not override the uniqueness of email if I never log my users in using email? My derived model (e.g. MyUser) would not offer an email-based login, only realm + username.

Please can you confirm that it's still true there's no solution for me? It's really hard to believe I would have to build my own User class from the ground up just to do what otherwise seems very straightforward override behavior.

(And before you ask -- of course it makes sense to have multiple or even no email addresses associated with User. There are many examples, among them: (1) migrating accounts from an old system where username was unique and not email address, and (2) using the passport plugin to link users' accounts to other services, i.e. where there is no email-based login provided at all.)

Email as pseudo-primary key to login is mostly a thing of the past. It would actually be smart to consider dropping email altogether in the User model and if people want to add a relationship between Users and emails, let them add it in themselves in their derived model. I will never use any of Loopback's built-in User email confirmation dialog, for example -- again, because I won't require email at all in many cases.

So for my use-case, am I forced to either build my own User model from the ground up, or to finagle fake email addresses that are unique just to satisfy this constraint?

Am I really in the minority wanting this functionality?

Thanks.

Steve

Ah hah -- man, sometimes it's really hard piecing together what's what from a Google search given how active development is on this (though, that's a good thing of course).

Anyway, I think I figured out that in fact you do correctly support this dichotomy of uses in the current implementation of the built-in User model (as of 2016, anyway). I see in the code, all I needed to do was add "realmRequired": true to the options object in my derived user model, e.g.:

{
  "name": "MyUser",
  "base": "User",
  "idInjection": true,
  "options": {
    "validateUpsert": true,
    "realmRequired": true
  },
 ...
}

With realmRequired: true, email is not required to be unique. Excellent!

So that's pretty much just what I needed in my case (I am fine requiring realm, as I said above, it makes total sense that realm+username would replace email as the primary-ish key.

Thanks a lot -- I'm good to go. Though as usual, maybe there's something I can do to help improve the docs, will look at it again later and update this if so with proposed improvement (or not :-) ).

Steve

How can I remove default validation (like the one on email and password)?

In the sample below, I remove everything from the custom MyModel which extends User:

  1. the validations on username and email are removed
  2. the password field is removed
  3. the username and email fields are removed
{
  "name": "MyModel",
  "base": "User",
  "properties": {
    "email": false,
    "username": false,
    "password": false
  }
}
...
module.exports = function(MyModel) {
  MyModel.disableRemoteMethod("login", true);
  MyModel.disableRemoteMethod("logout", true);
  MyModel.on('dataSourceAttached', function() {
    console.log('MyModel', 'on.dataSourceAttached()');
    delete MyModel.validations.email; //delete MyModel.app.models.User.validations.email;
    delete MyModel.validations.username; //delete MyModel.app.models.User.validations.username;
  });
};

Some ideas came from: issue #1137

How can this be helpful? Well what if you're trying to experiment with a multi-tenant setup where MyModel is actually OrgModel? It may help.

In your built-in user model inside, a lot of places to use the mailbox this thing, so can not simply delete this thing. Delete will influence to reset the password, and even affect the secret key generation, I think we should provide an optional project, configuration into the phone number or e-mail address, user name is to make configuration options for unique personality, but need to choose a as a unique ID.
Of course, if you replace the mailbox with a phone number, a lot of places need to change, first of all, you may not need to change the token, but the certification section has to make a lot of changes.

In your built-in user model inside, a lot of places to use the mailbox this thing, so can not simply delete this thing. Delete will influence to reset the password, and even affect the secret key generation, I think we should provide an optional project, configuration into the phone number or e-mail address, user name is to make configuration options for unique personality, but need to choose a as a unique ID.
Of course, if you replace the mailbox with a phone number, a lot of places need to change, first of all, you may not need to change the token, but the certification section has to make a lot of changes.

In my example code in my previous comment, I am not changing the built-in user model, I'm changing MyModel which inherited from user model. So no harm done, I hope you agree @buzai? Unless I'm nuking a shared prototype unknowingly? Let me know.

@pulkitsinghal , I'm not saying you destroy something, I think if you do not use it's own mailbox, then how to generate the user's token it, then you have to write your own method of generating token, there is a lot of built-in methods you can not use the fact, I think if we do so, not as a direct write a model, rather than inherited user. I look at the code inside the user's login and also implements several methods to create a similar, but those methods and mailbox properties coupled together.

Was this page helpful?
0 / 5 - 0 ratings