除了my question in repository我需要在这里发布,可能有人会帮助我,我会很感激。
我需要在我的应用中取消阻止代码的帮助。
我有几个服务,它们在会话中获取回调存储用户信息并重定向到名为/ auth / confirm /的页面。
以下是twitter auth的示例,非常适合我。
const keystone = require('keystone');
const User = keystone.list('User');
module.exports = (req, res, next) => {
const locals = res.locals;
locals.authUser = req.session.auth;
// Set existing user if already logged in
locals.existingUser = req.user || false;
// Reject request if no auth data is stored in session
if (!locals.authUser) {
console.log('[auth.confirm] - No auth data detected, redirecting to signin.');
console.log('------------------------------------------------------------');
return res.redirect('/');
}
const authenticateUser = new Promise((resolve, reject) => {
if (locals.existingUser) resolve(true);
console.log('[auth.confirm] - Searching for existing users via [' + locals.authUser.type + '] profile id...');
console.log('------------------------------------------------------------');
User.model.findOne()
.where('services.' + locals.authUser.type + '.profileId', locals.authUser.profileId)
.exec((err, user) => {
if (err) {
console.log('[auth.confirm] - Error finding existing user via profile id.', err);
console.log('------------------------------------------------------------');
reject(err);
}
if (user) {
console.log('[auth.confirm] - Found existing user via [' + locals.authUser.type + '] profile id...');
console.log('------------------------------------------------------------');
locals.existingUser = user;
resolve(true);
}
resolve(false);
});
});
authenticateUser
.then(result => {
if (result) return result;
User.model.findOne()
.where('email', locals.authUser.email)
.exec((err, user) => {
if (err) {
throw err;
}
if (user) {
locals.existingUser = user;
}
return false;
});
})
.then(result => {
if (result) return result;
if (locals.existingUser) {
const userData = {
email: locals.authUser.email,
services: locals.existingUser.services || {}
};
userData.services[locals.authUser.type] = {
isConfigured: true,
profileId: locals.authUser.profileId,
username: locals.authUser.username,
avatar: locals.authUser.avatar,
accessToken: locals.authUser.accessToken,
refreshToken: locals.authUser.refreshToken
};
locals.existingUser.set(userData);
locals.existingUser.save(err => {
if (err) throw err;
return true;
});
} else {
const userData = {
name: {
first: locals.authUser.name.first,
last: locals.authUser.name.last
},
email: locals.authUser.email,
password: Math.random().toString(36).slice(-8),
services: {}
};
userData.services[locals.authUser.type] = {
isConfigured: true,
profileId: locals.authUser.profileId,
username: locals.authUser.username,
avatar: locals.authUser.avatar,
accessToken: locals.authUser.accessToken,
refreshToken: locals.authUser.refreshToken
};
locals.existingUser = new User.model(userData);
locals.existingUser.save(err => {
if (err) throw err;
return true;
});
}
})
.then(result => {
console.log('[auth.confirm] - Signing in user...');
console.log('------------------------------------------------------------');
const onSuccess = user => {
console.log('[auth.confirm] - Successfully signed in.');
console.log('------------------------------------------------------------');
return res.redirect(req.cookies.target || '/keystone');
};
const onFail = err => {
console.log('[auth.confirm] - Failed signing in.', err);
console.log('------------------------------------------------------------');
if (err) throw err;
return res.redirect('/');
};
keystone.session.signin(String(locals.existingUser._id), req, res, onSuccess, onFail);
});
return authenticateUser;
};
如果我们从用户那里获得访问权限,现在我们将twitter用户存储在req.session.auth中。但现在我有一个大问题。 Mongoose User模型也像我所知的那样工作异步,当我尝试通过twitter profileID检查现有用户时,我无法获得正确的结果,因为它首先进行回调。然后回调并且不等待检查结果。我不想使这个异步但避免异步库,因为对于一个功能它对我来说太大了。我更喜欢使用Node新版本中的原生Promises。我不确定这一切并且不知道如何以最佳性能制作它并且非常期待,有人会帮助我。无论如何 - 感谢阅读...
{{1}}
答案 0 :(得分:1)
此时我的代码如下。这是工作和异步,但无论如何,我很乐意得到某人的评论。
const keystone = require('keystone');
const User = keystone.list('User');
module.exports = (req, res, next) => {
const authUser = req.session.auth;
// Reject request if no auth data is stored in session
if (!authUser) {
return res.redirect('/');
}
// Set existing user if already logged in
if (req.user) return doSignIn(req.user);
User.model.findOne()
.where('services.' + authUser.type + '.profileId', authUser.profileId)
.exec()
.then(user => {
if (user) return doSignIn(user);
User.model.findOne()
.where('email', authUser.email)
.exec()
.then(user => {
return createOrUpdateUser(user);
}, err => {
if (err) {
throw err;
}
});
}, err => {
throw err;
});
function doSignIn(user) {
const onSuccess = user => {
return res.redirect(req.cookies.target || '/keystone');
};
const onFail = err => {
if (err) throw err;
return res.redirect('/');
};
keystone.session.signin(String(user._id), req, res, onSuccess, onFail);
}
function createOrUpdateUser(user) {
if (user) {
const userData = {
email: authUser.email,
services: user.services || {}
};
userData.services[authUser.type] = {
isConfigured: true,
profileId: authUser.profileId,
username: authUser.username,
avatar: authUser.avatar,
accessToken: authUser.accessToken,
refreshToken: authUser.refreshToken
};
user.set(userData);
user.save((err, user) => {
if (err) throw err;
return doSignIn(user);
});
} else {
const userData = {
name: {
first: authUser.name.first,
last: authUser.name.last
},
email: authUser.email,
password: Math.random().toString(36).slice(-8),
services: {}
};
userData.services[authUser.type] = {
isConfigured: true,
profileId: authUser.profileId,
username: authUser.username,
avatar: authUser.avatar,
accessToken: authUser.accessToken,
refreshToken: authUser.refreshToken
};
const newUser = new User.model(userData);
newUser.save((err, user) => {
if (err) throw err;
return doSignIn(user);
});
}
}
};