0

I started to run a simple hello world project using lb4. I created a basic mongodb datasource, and a repository and a simple model (username, password and id) for users with cli command provided by loopback. I also created a user controller, with a built in crud choice provided by loopback.
as you may know, this is a very basic setup but if anyone needs details, I will provide, just comment.
the problem is that, when I try to make new users using explorer, I encounter with duplicate same username models. means that:

{
"_id" : ObjectId("5def4581f7f9d508b0da2d4c"),
"username" : "string",
"password" : "string"
}

and:

{
"_id" : ObjectId("5def4584f7f9d508b0da2d4d"),
"username" : "string",
"password" : "string"
}

the client should enter unique username for signup. that's obvious.
how can I specify uniqueness of a property of a model in loopback 4 (without declaring it as id)?

Ali Bahrami
  • 910
  • 9
  • 21

2 Answers2

1

Due to this issue on github, lb4 already checks for duplicates inside of its context using indexes and 11000 error code of mongoDB (I am talking about shopping example, not a simple lb4 app so BE AWARE! If you want you can implement uniqueness using description below). What I forgot to do was database migration ‍.
you can do database migration with this command:
npm run migrate
so the complete answer should be like this:
1- inside the model add this: (change uniqueEmail and email to property name you want to be unique)

@model({
    settings: {
        indexes: {
          uniqueEmail: {
            keys: {
              email: 1,
            },
            options: {
              unique: true,
            },
         },
    },
  },
})

2- check inside of the controller, the endpoint you want to check uniqueness, and add a try catch to catch error of uniqueness which came from your mongoDB datasource:

try {
  // In my case create the new user, but can be anything you want
  const savedUser = await this.userRepository.create(
    _.omit(newUserRequest, 'password'),
  );

  // do stuff and return

} catch (error) {
  // MongoError 11000 duplicate key
  if (error.code === 11000 && error.errmsg.includes('index: uniqueEmail')) {
    throw new HttpErrors.Conflict('Email value is already taken');
  } else {
    throw error;
  }
}

3- run npm run migrate

This answer now is a general answer which can be used for any property of any model. Hope this helps.

Ali Bahrami
  • 910
  • 9
  • 21
  • 1
    Well, you said you would define uniqueness in your `model`. And here you have done `filtering` and nothing else! – Akif Hussain Dec 10 '19 at 08:26
  • Exactly! what I wanted to do is to declare property as "unique" not filter the results and check them. But I found nothing. If any answer shows the solution inside of models declaration, accepted as the correct answer and I will remove mine. – Ali Bahrami Dec 10 '19 at 09:06
0

So basically what i found out that Loopback4 has a property called name which a unique identifier for the authentication strategy ( for example : ‘basic’, ‘jwt’, etc). You can look into more detailed manner here AND here

You should change the username to name so as to fulfill your requirement. Because that's how it works in loopback4

Akif Hussain
  • 475
  • 5
  • 22
  • this solution will work fine for usernames. but what about a model that is not part of the authentication? how can restrict "any" property of a model not to be duplicate? – Ali Bahrami Dec 10 '19 at 08:00