我是node.js,sequelize,Bluebird promises和FB身份验证的新手。
我想通过一些身份验证详细信息来保留我的FB身份验证用户。
在我的模型中,一个用户可以同时进行多次身份验证(一个用于浏览器,另一个用于移动设备等)。 我需要处理这些身份验证,所以我有下一个关系:
User.hasMany(AUTH); Auth.belongsTo(用户);
我编写的这段代码有效,但我仍在寻找更智能的解决方案。
主要目标是将身份验证信息添加到用户。 因此,在保存身份验证信息之前,我会寻找一个持久的用户。
function(accessToken, refreshToken, profile, done) {
console.log("FacebookStrategy_function:\naccessToken: " + accessToken);
var thatUser=null;
User.find({
where: {
username: profile.username
},
include: [{model: Auth}]
}).then(function(user) {
console.log("USER IS #1: %j", user);
if(user!= null){ // User found in database
console.log("User " + profile.id + "found in database");
return user;
}else{ // First time that user authenticate in app
var user = User.build({
username: profile.username,
givenName: profile.name.givenName,
familyName: profile.name.familyName
});
return user.save();
}
}).then(function(user) {
console.log("USER IS #2: %j", user);
thatUser=user;
var auth= Auth.build({
provider: 'facebook',
providerId: profile.id,
accessToken: accessToken
});
return user.addAuth(auth);
}).then(function(auth){
user=thatUser;
console.log("USER IS #3: %j", user);
console.log("done. user and association saved. auth is: %j", auth);
done(null, user); // Call FacebookEstrategy's done
}, function(err) {
console.log("\nsomething happened persisting user/auth " + err);
done(err, null); // Propagate error to FacebookEstrategy
});
}
有下一个日志:
FacebookStrategy_function: accessToken: CAACO...
Executing (default): SELECT "Users".*, "Auths"."id" AS "Auths.id", ... WHERE "Users"."username"='john.doe'...
INSERT INTO "Users" ("id","username","givenName","familyName","createdAt","updatedAt") VALUES (DEFAULT,'john.doe',...)
USER IS #1: null
Executing (default): INSERT INTO "Users" ("id","username","givenName","familyName","createdAt","updatedAt") VALUES (DEFAULT,'john.doe',...)
USER IS #2: {"username":"john.doe","givenName":"John","familyName":"Doe","id":2,"updatedAt":"2014-11-09T19:12:23.250Z","createdAt":"2014-11-09T19:12:23.250Z"}
Executing (default): SELECT * FROM "Auths" WHERE "UserId" = 2;
Executing (default): INSERT INTO "Auths" ("id","provider","providerId","accessToken","createdAt","updatedAt","UserId") VALUES (DEFAULT,'facebook','...','CAACO...','2014-11-09 19:12:23.278 +00:00','2014-11-09 19:12:23.278 +00:00',2) RETURNING *;
USER IS #3: {"username":"john.doe","givenName":"John","familyName":"Doe","id":2,"updatedAt":"2014-11-09T19:12:23.250Z","createdAt":"2014-11-09T19:12:23.250Z"}
done. user and association saved. auth is: {"provider":"facebook","providerId":"...","accessToken":"CAACO...","id":2,"UserId":2,"updatedAt":"2014-11-09T19:12:23.278Z","createdAt":"2014-11-09T19:12:23.278Z"}
对于我来说很难处理,user.addAuth(auth)返回一个auth对象。 在接下来的方法中,我希望收到一个用户对象(而不是auth) 作为解决方法,我在主函数范围中使用了一个糟糕的.User变量。 有没有更聪明的方法呢?
在日志中,跟踪"用户是#3:"显示没有其身份验证对象的用户。 为什么呢?
任何改正或改善都会得到很好的支持
由于
答案 0 :(得分:1)
如果您正在使用promises - 您可以放弃done
回调 - 您只需返回承诺即可。如果您真的想要完成回调 - 您可以调用.nodeify
而不是显式调用它,尽管返回承诺还有其他好处,例如未处理的拒绝跟踪。
您也可以使用聚合方法而不是显式闭包范围:
function(accessToken, refreshToken, profile) {
console.log("FacebookStrategy_function:\naccessToken: " + accessToken);
return User.find({
where: { username: profile.username }, include: [{model: Auth}]
}).then(function(user) {
console.log("USER IS #1: %j", user);
if(user!= null){ // User found in database
console.log("User " + profile.id + "found in database");
return user;
}
return User.build({ // first time
username: profile.username,
givenName: profile.name.givenName,
familyName: profile.name.familyName
}).save();
}).then(function(user) {
console.log("USER IS #2: %j", user);
var auth= Auth.build({
provider: 'facebook',
providerId: profile.id,
accessToken: accessToken
});
return [user, user.addAuth(auth)]; // note the array
}).spread(function(user, auth){ // note the spread
console.log("USER IS #3: %j", user);
console.log("done. user and association saved. auth is: %j", auth);
return user;
});
}
现在,如果我被允许放弃所有console.log
s,这会变得更短:
function(accessToken, refreshToken, profile) {
return User.find({
where: { username: profile.username }, include: [{model: Auth}]
}).then(function(user) {
return user || User.build({ // first time
username: profile.username,
givenName: profile.name.givenName,
familyName: profile.name.familyName
}).save();
}).then(function(user) {
return Auth.build({
provider: 'facebook',
providerId: profile.id,
accessToken: accessToken
}).return(user);
});
}