Как изменить маршрут Express для входа в систему пользователя после его создания в Mongodb? - PullRequest
0 голосов
/ 23 марта 2020

У меня есть маршрут ниже. Это работает, если я вручную добавляю документы в MongoDB. Однако я бы хотел обработать случай, когда пользователь не найден, создан, а затем авторизован автоматически.

Как лучше всего изменить этот маршрут?

router.post("/loginViaFacebook", (req, res) => {
  const userEmail = req.body.email;
  const errors = {};

  User.findOne({ email: userEmail }).then(user => {
    if (!user) {
      new User({
        facebookId: req.body.facebookId,
        name: req.body.name,
        email: req.body.email,
        pictureUrl: req.body.picture
      }).save();
    } else {
      const payload = {
        facebookId: user.id,
        name: user.name,
        email: user.email,
        pictureUrl: user.picture
      };

      jwt.sign(payload, secretOrKey, { expiresIn: 3600 }, (err, token) => {
        res.json({ success: true, token: "Bearer " + token });
      });

      console.log("success!");
    }
  });
});

Ответы [ 2 ]

1 голос
/ 23 марта 2020

После сохранения нового объекта User в базе данных вы можете получить идентификатор из возвращенного результата. Я не знаю mon go слишком хорошо, поэтому вам придется посмотреть на результат, полученный из .save(), и получить идентификатор оттуда. Вот общая структура:

const promisify = require('util').promisify;
const jwt.signPromise = promisify(jwt.sign);

/**
 * @route POST api/auth/loginViaFacebook
 * @desc Login User via Facebook/
 * @access public
 */
router.post("/loginViaFacebook", async (req, res) => {
    const userEmail = req.body.email;
    const errors = {};

    try {
        let user = await User.findOne({
            email: userEmail
        });
        if (!user) {
            user = new User({
                facebookId: req.body.facebookId,
                name: req.body.name,
                email: req.body.email,
                pictureUrl: req.body.picture
            });
            user = await user.save();
        }
        const payload = {
            facebookId: user.facebookId,
            name: user.name,
            email: user.email,
            pictureUrl: user.picture
        };

        let token = await jwt.signPromise(payload, secretOrKey, {expiresIn: 3600});
        res.json({success: true, token: "Bearer " + token});

    } catch (e) {
        // send some sort of error response here
        console.log(e);
        res.sendStatus(500);
    }
});

Если вы хотите придерживаться своей исходной структуры без использования await, вы можете просто переместить дублированный код в общую функцию.

/**
 * @route POST api/auth/loginViaFacebook
 * @desc Login User via Facebook/
 * @access public
 */
router.post("/loginViaFacebook", (req, res) => {
  const userEmail = req.body.email;
  const facebookId = req.body.facebookId;

  function finish(user) {
    const payload = {
      facebookId: user.facebookId,
      name: user.name,
      email: user.email,
      pictureUrl: user.picture
    };

    jwt.sign(payload, secretOrKey, { expiresIn: 3600 }, (err, token) => {
      if (err) {
          console.log(err);
          res.sendStatus(500);
          return;
      }
      res.json({ success: true, token: "Bearer " + token });
    });
    return;
  }

  // Find user by email. ( Down below { email } in ES6 is same as { email: email }
  User.findOne({ email: userEmail }).then(user => {
    if (!user) {
      new User({
        facebookId: facebookId,
        name: req.body.name,
        email: userEmail,
        pictureUrl: req.body.picture
      }).save(function(err, user) {
        if (err) {
            res.send({ errors: err });
            return;
        }
        finish(user);        
      });
    } else {
      finish(user);
    }
  }).catch(err => {
      console.log(err);
      res.sendStatus(500);
  });
});
0 голосов
/ 23 марта 2020

Я закончил тем, что модифицировал код следующим образом, и он работает:

/**
 * @route POST api/auth/loginViaFacebook
 * @desc Login User via Facebook/
 * @access public
 */
router.post("/loginViaFacebook", (req, res) => {
  const userEmail = req.body.email;
  const facebookId = req.body.facebookId;

  // Find user by email. ( Down below { email } in ES6 is same as { email: email }
  User.findOne({ email: userEmail }).then(user => {
    if (!user) {
      new User({
        facebookId: facebookId,
        name: req.body.name,
        email: userEmail,
        pictureUrl: req.body.picture
      }).save(function(err, user) {
        if (err) res.send({ errors: err });

        const payload = {
          facebookId: user.facebookId,
          name: user.name,
          email: user.email,
          pictureUrl: user.picture
        };

        jwt.sign(payload, secretOrKey, { expiresIn: 3600 }, (err, token) => {
          res.json({ success: true, token: "Bearer " + token });
        });
        return;
      });
    }

    const payload = {
      facebookId: user.facebookId,
      name: user.name,
      email: user.email,
      pictureUrl: user.picture
    };

    jwt.sign(payload, secretOrKey, { expiresIn: 3600 }, (err, token) => {
      res.json({ success: true, token: "Bearer " + token });
    });
  });
});

Я абсолютно ненавижу тот факт, что мне пришлось использовать код аутентификации дважды, но он работает. Я был бы признателен, если бы кто-то мог предложить переработанную версию этого кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...