TypeError:User.findById 不是反序列化用户的函数

Posted

技术标签:

【中文标题】TypeError:User.findById 不是反序列化用户的函数【英文标题】:TypeError: User.findById is not a function on deserializeUser 【发布时间】:2017-09-22 13:06:33 【问题描述】:

我正在使用护照身份验证(本地和谷歌策略),现在它在“deserializeUser”函​​数上告诉我“User.findById 不是函数”。

passport.js

const passport = require('passport');
const request = require('request');
const LocalStrategy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth').

const OAuthStrategy = require('passport-oauth').OAuthStrategy;
const OAuth2Strategy = require('passport-oauth').OAuth2Strategy;

const User = require('../routes/user');

passport.serializeUser((user, done) => 
    done(null, user.id);
);

passport.deserializeUser(function(id, done) 
    User.findById(id, function(err, user) 
        done(err, user);
    );
);

/**
 * Sign in using Email and Password.
 */
passport.use(new LocalStrategy( usernameField: 'email' , (email, password, done) => 
    User.findOne( email: email.toLowerCase() , (err, user) => 
        if (err)  return done(err); 
        if (!user) 
            return done(null, false,  msg: `Email $email not found.` );
        
        user.comparePassword(password, (err, isMatch) => 
            if (err)  return done(err); 
            if (isMatch) 
                return done(null, user);
            
            return done(null, false,  msg: 'Invalid email or password.' );
        );
    );
));

/**
 * OAuth Strategy Overview
 *
 * - User is already logged in.
 *   - Check if there is an existing account with a provider id.
 *     - If there is, return an error message. (Account merging not supported)
 *     - Else link new OAuth account with currently logged-in user.
 * - User is not logged in.
 *   - Check if it's a returning user.
 *     - If returning user, sign in and we are done.
 *     - Else check if there is an existing account with user's email.
 *       - If there is, return an error message.
 *       - Else create a new account.
 */


/**
 * Sign in with Google.
 */
passport.use(new GoogleStrategy(
    clientID: process.env.GOOGLE_ID,
    clientSecret: process.env.GOOGLE_SECRET,
    callbackURL: '/auth/google/callback',
    passReqToCallback: true
, (req, accessToken, refreshToken, profile, done) => 
    if (req.user) 
        User.findOne( google: profile.id , (err, existingUser) => 
            if (err)  return done(err); 
            if (existingUser) 
                req.flash('errors',  msg: 'There is already a Google account that belongs to you. Sign in with that account or delete it' );
                done(err);
             else 
                User.findById(req.user.id, (err, user) => 
                    if (err)  return done(err); 
                    user.google = profile.id;
                    user.tokens.push( kind: 'google', accessToken );
                    user.profile.name = user.profile.name || profile.displayName;
                    user.profile.gender = user.profile.gender || profile._json.gender;
                    user.profile.picture = user.profile.picture || profile._json.image.url;
                    user.save((err) => 
                        req.flash('info',  msg: 'Google account has been linked.' );
                        done(err, user);
                    );
                );
            
        );
     else 
        User.findOne( google: profile.id , (err, existingUser) => 
            if (err)  return done(err); 
            if (existingUser) 
                return done(null, existingUser);
            
            User.findOne( email: profile.emails[0].value , (err, existingEmailUser) => 
                if (err)  return done(err); 
                if (existingEmailUser) 
                    req.flash('errors',  msg: 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' );
                    done(err);
                 else 
                    const user = new User();
                    user.email = profile.emails[0].value;
                    user.google = profile.id;
                    user.tokens.push( kind: 'google', accessToken );
                    user.profile.name = profile.displayName;
                    user.profile.gender = profile._json.gender;
                    user.profile.picture = profile._json.image.url;
                    user.save((err) => 
                        done(err, user);
                    );
                
            );
        );
    
));

exports.isAuthenticated = (req, res, next) => 
    if (req.isAuthenticated()) 
        return next();
    
    res.redirect('/login');
;

/**
 * Authorization Required middleware.
 */
exports.isAuthorized = (req, res, next) => 
    const provider = req.path.split('/').slice(-1)[0];
    const token = req.user.tokens.find(token => token.kind === provider);
    if (token) 
        next();
     else 
        res.redirect(`/auth/$provider`);
    
;

在我将粘贴复制到另一个目录之前它正在工作,什么都没有。

【问题讨论】:

'../routes/user' 对于应该导出模型的文件来说似乎是一个奇怪的位置。 我正在使用我的合作伙伴代码,我告诉了他,但我们还没有更改它(还) 所以文件导出了一个(大概)Mongoose 模型?导入后试试console.log-ing。 这不是问题,而是它的结构方式,所以感谢您指出这一点 在我的例子中,我使用了“than”而不是“then”:passport.deserializeUser((id, done) => User.findById(id).than((user) => 完成(空,用户););); passport.deserializeUser((id, done) => User.findById(id).then((user) => done(null, user); ); ); 【参考方案1】:

所以,这是一个结构问题,找到并修复了。

【讨论】:

以上是关于TypeError:User.findById 不是反序列化用户的函数的主要内容,如果未能解决你的问题,请参考以下文章

mongoose FindbyId和数组匹配的字符串

grails中不区分大小写的搜索

❤️‍Spring全家桶从入门到大神--spring mvc 参数绑定

如何在 Playframework 中更新模型的某个字段?

hibernate dynamic-update="true" 的一点应用

如何使用猫鼬过滤函数中的对象?