Home > Net >  how to find a nested object in passport?
how to find a nested object in passport?

Time:11-18

I have a JSON that looks like this :

{
  _id: new ObjectId("6374633c7cf80673ee9a22c9"),
  consultant_name: 'Jackson',
  consultantUsername: 'paul',
  consultant_Password: '123',
  clients: [
    {
      client_name: 'Amine Bouabou',
      client_Username: 'amine',
      client_Password: '123',
      documents: [Array],
      _id: new ObjectId("6374633c7cf80673ee9a22ca")
    },
    {
      client_name: 'Latifa Alaoui',
      client_Username: 'latifa',
      client_Password: '1234',
      documents: [Array],
      _id: new ObjectId("6374633c7cf80673ee9a22cd")
    }
  ],
  createdAt: 2022-11-16T04:12:44.645Z,
  updatedAt: 2022-11-16T04:12:44.645Z,
  __v: 0
}

What I want to do is 1)find the object that has a client_Username when user is trying to log in (for ex "amine" or "latifa", that I can do for now) AND compare that specific password of that specific client_Username ("123" or "1234", this I can't). I use passeport for auth, here's how my code looks like :

const User = require('./models/user');

const localStrategy = require("passport-local").Strategy;

module.exports = function (passport) {
  passport.use(
    new localStrategy((username, password, done) => {
      User.findOne({ "clients.client_Username": username }, (err, user) => {
        if (err) throw err;
        if (!user) return done(null, false);
        if (user) console.log("we have a user");

// the user answer that I get here is the exact json posted above
        if (user) console.log(user);

// line underneath doesn't work, I want to compare the password that user is using for login with // the proper specific password of that client_username (so either 123 or 1234)

        if (password === user.clients.client_Password) {
           console.log("password match");
            return done(null, user);
        }else {
          console.log("no password match");
            return done(null, false);     
        }
      });
    })
  );

  passport.serializeUser((user, cb) => {
    cb(null, user.id);
  });
  passport.deserializeUser((id, cb) => {
    User.findOne({ _id: id }, (err, user) => {
      const userInformation = {
        username: user.username,
        password: user.password,
        documents: user.documents,
      };
      cb(err, userInformation);
    });
  });
};

I did try to run this just as a test and it works :

module.exports = function (passport) {
  passport.use(
    new localStrategy((username, password, done) => {
      console.log("this is my "   username);
      console.log("this is my "   password);
      User.findOne({ "clients.client_Username": username }, (err, user) => {
        if (err) throw err;
        if (!user) return done(null, false);

// change here

        if (password === user.clients[0].client_Password) {
           console.log("password match");
            return done(null, user);
        }else {
          console.log("no password match");
            return done(null, false);     
        }
      });
    })
  );

Obviously when I specify the index of that user it works. Basically what I am seeking is the same results but without having to hard code the index.

CodePudding user response:

Before you match the password with the provided one, you must get the correct entry from the clients array. It would look something like this:

const client = user.clients.filter((el) => el.client_Username === username)[0]
if (password === client.client_Password) {
...

Another option is to use aggregate functions on the Mongo query to get an already filtered list. I'm not sure however if the library you use for Mongo supports that. You would have to check for yourself. (Here's the documentation for Mongo's $filter aggregation: https://www.mongodb.com/docs/manual/reference/operator/aggregation/filter/). Using a mongo filter, theoretically, should have better performance, as you wouldn't have to then filter the array in the JS code.

  • Related