mongoose-findorcreate 在使用 passport-facebook 时写入重复的用户
mongoose-findorcreate writing duplicated users when using passport-facebook
我正在尝试使用 passportJS 设置用户身份验证。我决定使用这个名为 mongoose-findorcreate 的 npm 包,而不是自己编写 findOrCreate 函数来处理护照。
所以现在我正在测试我的应用程序,我可以按预期使用我的 facebook 凭据登录,但问题是我在我的数据库中为同一个 facebook 登录获取多个条目。
这是我的用户模型:
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let findOrCreate = require('mongoose-findorcreate');
// User schema definition
let UserSchema = new Schema(
{
provider: { type: String, required: true },
id: { type: String, default: 'unknown' },
displayName: { type: String, default: 'unknown' },
name: { type: Object },
emails: { type: Array },
photos: { type: Array },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
}
);
UserSchema.plugin(findOrCreate);
// Sets the updatedAt parameter equal to the current time
UserSchema.pre('save', (next) => {
now = new Date();
if(!this.updatedAt) {
this.updatedAt = now;
}
next();
});
module.exports = mongoose.model('user', UserSchema);
这些是我的路线:
let passport = require('passport');
let FacebookStrategy = require('passport-facebook').Strategy;
let User = require('../models/user');
passport.use(new FacebookStrategy({
clientID: 12345,
clientSecret: 'supersecretsecret',
callbackURL: 'http://localhost:1337/auth/facebook/callback'
},
(accessToken, refreshToken, profile, done) => {
User.findOrCreate( profile, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
function redirectFB() {
return passport.authenticate('facebook');
}
function callbackFB() {
return passport.authenticate('facebook', {
successRedirect: '/word',
failureRedirect: '/'
})
}
module.exports = { redirectFB, callbackFB };
重复用户示例:
{
"_id":ObjectId("584ade8915644f1186fa8a96"),
"provider":"facebook",
"updatedAt": ISODate("2016-12-09T16:40:41.921 Z"),
"createdAt": ISODate("2016-12-09T16:40:41.921 Z"),
"photos":[ ],
"emails":[ ],
"displayName":"Miha Šušteršič",
"id":"10154914634234238",
"__v":0
}{
"_id":ObjectId("584adea3b8adfb11948ed1d6"),
"provider":"facebook",
"updatedAt": ISODate("2016-12-09T16:41:07.626 Z"),
"createdAt": ISODate("2016-12-09T16:41:07.625 Z"),
"photos":[ ],
"emails":[ ],
"displayName":"Miha Šušteršič",
"id":"10154914634234238",
"__v":0
}
我不知道这是否是我的代码的问题(是否将配置文件传递给 findOrCreate
函数。
发现问题 - 我需要以正确的格式将用户数据传递给 findOrCreate 函数。
User.findOrCreate( profile._json, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
findOrCreate
不起作用的原因是因为 findOrCreate
查询将整个 profile
对象传递到查询条件中。
如果你看这里:https://github.com/drudge/mongoose-findorcreate/blob/master/index.js#L22
根据您从 Facebook 返回的数据类型,您的查询将始终 return 为空,除非配置文件对象与您的架构完全匹配。
你可以在这里做的是:
User.findOrCreate({ provider: profile.provider, id: profile.id, .... }, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
而不是 profile
传入 { provider: profile.provider, id: profile.id, .... }
当然,修复 { provider: profile.provider, id: profile.id, .... }
以与您的架构定义相匹配。
我正在尝试使用 passportJS 设置用户身份验证。我决定使用这个名为 mongoose-findorcreate 的 npm 包,而不是自己编写 findOrCreate 函数来处理护照。
所以现在我正在测试我的应用程序,我可以按预期使用我的 facebook 凭据登录,但问题是我在我的数据库中为同一个 facebook 登录获取多个条目。
这是我的用户模型:
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let findOrCreate = require('mongoose-findorcreate');
// User schema definition
let UserSchema = new Schema(
{
provider: { type: String, required: true },
id: { type: String, default: 'unknown' },
displayName: { type: String, default: 'unknown' },
name: { type: Object },
emails: { type: Array },
photos: { type: Array },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
}
);
UserSchema.plugin(findOrCreate);
// Sets the updatedAt parameter equal to the current time
UserSchema.pre('save', (next) => {
now = new Date();
if(!this.updatedAt) {
this.updatedAt = now;
}
next();
});
module.exports = mongoose.model('user', UserSchema);
这些是我的路线:
let passport = require('passport');
let FacebookStrategy = require('passport-facebook').Strategy;
let User = require('../models/user');
passport.use(new FacebookStrategy({
clientID: 12345,
clientSecret: 'supersecretsecret',
callbackURL: 'http://localhost:1337/auth/facebook/callback'
},
(accessToken, refreshToken, profile, done) => {
User.findOrCreate( profile, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
function redirectFB() {
return passport.authenticate('facebook');
}
function callbackFB() {
return passport.authenticate('facebook', {
successRedirect: '/word',
failureRedirect: '/'
})
}
module.exports = { redirectFB, callbackFB };
重复用户示例:
{
"_id":ObjectId("584ade8915644f1186fa8a96"),
"provider":"facebook",
"updatedAt": ISODate("2016-12-09T16:40:41.921 Z"),
"createdAt": ISODate("2016-12-09T16:40:41.921 Z"),
"photos":[ ],
"emails":[ ],
"displayName":"Miha Šušteršič",
"id":"10154914634234238",
"__v":0
}{
"_id":ObjectId("584adea3b8adfb11948ed1d6"),
"provider":"facebook",
"updatedAt": ISODate("2016-12-09T16:41:07.626 Z"),
"createdAt": ISODate("2016-12-09T16:41:07.625 Z"),
"photos":[ ],
"emails":[ ],
"displayName":"Miha Šušteršič",
"id":"10154914634234238",
"__v":0
}
我不知道这是否是我的代码的问题(是否将配置文件传递给 findOrCreate
函数。
发现问题 - 我需要以正确的格式将用户数据传递给 findOrCreate 函数。
User.findOrCreate( profile._json, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
findOrCreate
不起作用的原因是因为 findOrCreate
查询将整个 profile
对象传递到查询条件中。
如果你看这里:https://github.com/drudge/mongoose-findorcreate/blob/master/index.js#L22
根据您从 Facebook 返回的数据类型,您的查询将始终 return 为空,除非配置文件对象与您的架构完全匹配。
你可以在这里做的是:
User.findOrCreate({ provider: profile.provider, id: profile.id, .... }, (err, user) => {
if (err) {
return done(err);
}
done(null, user);
})
而不是 profile
传入 { provider: profile.provider, id: profile.id, .... }
当然,修复 { provider: profile.provider, id: profile.id, .... }
以与您的架构定义相匹配。