如何在visa.authenticate与社会服务后签署承诺。 KeystoneJS + Passport

时间:2016-12-07 17:18:48

标签: authentication express mongoose keystonejs passport.js

除了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}}

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);
            });
        }
    }
};