Подтвердить что ты не робот

Что такое функция User.findOrCreate и когда она называется в паспорте?

Я не могу найти документацию по этой функции, и поэтому я не могу заставить ее работать правильно. Когда вызывается эта функция, что она делает и что она принимает в качестве первых параметров? Я пытаюсь получить токен доступа из паспорта, но никак не могу связаться с ним.

passport.use(new FacebookStrategy({
    clientID:   APP_ID,
    clientSecret:   APP_SECRET,
    callbackURL: "http://localhost:3000/",
  },
  function(accessToken, refreshToken, profile, done) {
    User.findOrCreate({// what are these parameters?}, function (err, user) {
        // when is this function called and what is it doing? 
       });

  }
));

Как я могу получить токен доступа из паспорта?

4b9b3361

Ответ 1

User.findOrCreate - это созданная функция, которая представляет любую функцию, которую вы должны найти для пользователя по идентификатору Facebook, или создать ее, если пользователь не существует. Я думаю, что ваша первая проблема заключается в том, что ваш обратный URL-адрес просто подходит к вашему корню, поэтому вы, вероятно, никогда не доберетесь до этой функции.

Ваш URL-адрес обратного вызова должен быть как http://localhost:3000/auth/facebook/callback.

И затем обработайте этот URL:

app.get('/auth/facebook/callback', 
  passport.authenticate('facebook', { failureRedirect: '/login' }),
  function(req, res) {
    res.redirect('/');
  });

В этот момент завершена аутентификация. accessToken вам возвращается - "это необходимо в любое время, когда приложение вызывает API для чтения, изменения или записи данных конкретного человека Facebook от их имени". Вы должны сохранить это в той таблице, где вы храните токены доступа для пользователя. profile - это другая ключевая переменная, потому что это информация о пользователе (какая информация зависит от службы).

Что вы делаете внутри этой функции, зависит от вас. Итак, сделайте свой собственный User.findOrCreate. Вот код из паспорта для Facebook с некоторыми комментариями, чтобы объяснить это. Предполагается, что вы используете что-то вроде MongoDB и имеете таблицу User. User В этом случае любая переменная, которую вы указали, может взаимодействовать с таблицей User.

//Use facebook strategy
passport.use(new FacebookStrategy({
        clientID: config.facebook.clientID,
        clientSecret: config.facebook.clientSecret,
        callbackURL: config.facebook.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
        //check user table for anyone with a facebook ID of profile.id
        User.findOne({
            'facebook.id': profile.id 
        }, function(err, user) {
            if (err) {
                return done(err);
            }
            //No user was found... so create a new user with values from Facebook (all the profile. stuff)
            if (!user) {
                user = new User({
                    name: profile.displayName,
                    email: profile.emails[0].value,
                    username: profile.username,
                    provider: 'facebook',
                    //now in the future searching on User.findOne({'facebook.id': profile.id } will match because of this next line
                    facebook: profile._json
                });
                user.save(function(err) {
                    if (err) console.log(err);
                    return done(err, user);
                });
            } else {
                //found user. Return
                return done(err, user);
            }
        });
    }
));

Лично я также использую таблицу "членства" для отслеживания нескольких учетных записей для каждого пользователя (чтобы они могли выполнять аутентификацию с несколькими учетными записями), поскольку я настраивал ее через mongoose. На самом деле я храню этот токен доступа. Я предпочитаю, чтобы это имело столбец facebook в таблице пользователя... но это зависит от вас.

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

var membershipSchema = new Schema({
    provider:  String,
    providerUserId:  String,
    accessToken: String,
    userId: {type: ObjectId, ref: 'User'},
    dateAdded: {type: Date, default: Date.now}
});

module.exports = mongoose.model('Membership', membershipSchema);

и как таковая моя версия User.findOrCreate начинается следующим образом:

function(accessToken, refreshToken, profile, done) {
    Membership.findOne({
        providerUserId: profile.id
    }, function(err,membershipData) {
            //blah blah blah

где членство является указанной выше моделью и определяется как переменная:

var Membership =  require('./models/membership.js')

Ответ 2

Если вы хотите использовать findOrCreate, попробуйте пакет npm mongoose-findorcreate или supergoose

например. mongoose-findorcreate

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');

var findOrCreate = require('mongoose-findorcreate')
var Schema = mongoose.Schema;
var UserSchema = new Schema({ facebookId: Number});
UserSchema.plugin(findOrCreate);
var User = mongoose.model('User', UserSchema);

passport.use(new FacebookStrategy({
        clientID: 'clientID',
        clientSecret: 'clientSecret',
        callbackURL: "/auth/facebook/callback"
    },
    function(accessToken, refreshToken, profile, cb) {
        User.findOrCreate({ facebookId: profile.id }, function (err, user) {
          console.log('A new uxer from "%s" was inserted', user.facebookId);
          return cb(err, user);
        });
    }
));