I don't know what is wrong here.... im getting this error when i am trying to run my passport config for Google SignIn. This is my schema, i tried almost every solution and now, i am here.
interface userInterface{
name : string,
userHandle : string,
profilePic? : string,
following : Schema.Types.ObjectId[],
followers : Schema.Types.ObjectId[],
auth : {
signInType :string,
sessionInfo : {
password : string
},
googleInfo : {
googleId : string,
}
}
}
const userSchema = new Schema<userInterface>({
name : {
type : String,
required : [true, 'Name is required.'],
maxlength : [50 , 'Name must not exceed 50 charecters.']
},
userHandle : {
type : String,
required : [true , 'User handle is required.'],
unique : [true, 'Please enter a unique user handle.']
},
profilePic : {
type : String,
},
following : {
type: [Schema.Types.ObjectId],
ref : 'User'
},
followers : {
type : [Schema.Types.ObjectId],
ref : 'User'
},
auth : {
select: false,
signInType : {
type : String,
enum : ["Google" , "Session"]
},
sessionInfo : {
password : {
type : String,
required : [function(this : any){
return this.auth.signInType === "Session";
} , "Please enter a password."],
}
},
googleInfo : {
googleId : {
type : String,
required : [function(this : any){
return this.auth.signInType === "Google";
}, "Please enter a google id."]
}
},
},
}, {timestamps : true})
export default model<userInterface>('User' , userSchema);
This following is my passport config
import passport from "passport";
import passportGoogle from "passport-google-oauth2";
import User from "../model/UserSchema";
import {userHandleGenerater} from "../utils/utils";
const GoogleStrategy = passportGoogle.Strategy;
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
callbackURL: `${process.env.FRONTEND_URI as string}/home`,
},
async (accessToken , refreshToken, profile , done) => {
try{
let user = await User.findOne({"googleInfo.googleId" : profile.id});
if(!user){
let userHandle = "";
let found = true;
while (found) {
userHandle = userHandleGenerater(profile.name.givenName);
let existingUser = await User.findOne({ userHandle });
if (existingUser) {
found = true;
} else {
found = false;
}
}
const newUser = {
name : profile.displayName,
userHandle : userHandle,
auth : {
signInType : "Google",
googleInfo : {
googleId : profile.id
},
}
}
user = await User.create(newUser);
}
return done(null , user);
}catch(e){
return done(e , null);
}
}
)
);
passport.serializeUser((user : any , done) => {
done(null , user._id);
});
passport.deserializeUser(async (id , done) => {
try {
const user = await User.findById(id);
return done(null , user);
}catch(e){
return done(e, null);
}
});
I am getting this error: TypeError: Invalid schema configuration: false
is not a valid type at path select
.I am using typescript with mern stack and i have the following packages:
"dependencies": {
"@types/express-session": "^1.18.1",
"@types/node-cron": "^3.0.11",
"@types/passport-google-oauth2": "^0.1.10",
"backend": "file:",
"cors": "^2.8.5",
"express": "^4.21.2",
"express-session": "^1.18.1",
"mongoose": "^8.9.5",
"node-cron": "^3.0.3",
"passport": "^0.7.0",
"passport-google-oauth2": "^0.2.0",
"passport-google-oidc": "^0.1.0"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
"@types/node": "^22.10.7",
"@types/passport": "^1.0.17",
"dotenv": "^16.4.7",
"nodemon": "^3.1.9",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"typescript": "^5.7.3"
}
I somehow found a working solution, i changed the auth object to its own schema and it somehow worked and if it works, i am not touching it. I am dropping this to help someone else who has this issue in the future.
Here is the code:
import { model, Schema, Document, Types } from 'mongoose';
interface Auth {
signInType: 'Google' | 'Session';
sessionInfo?: {
password: string;
};
googleInfo?: {
googleId: string;
};
}
interface UserInterface extends Document {
name: string;
userHandle: string;
profilePic?: string;
following: Types.ObjectId[];
followers: Types.ObjectId[];
auth: Auth;
}
const SessionInfoSchema = new Schema({
password: {
type: String,
required: [true, 'Please enter a password.'],
},
}, {_id : false});
const GoogleInfoSchema = new Schema({
googleId: {
type: String,
required: [true, 'Please enter a Google ID.'],
},
}, {_id : false});
const AuthSchema = new Schema({
signInType: {
type: String,
enum: ['Google', 'Session'],
required: true,
},
sessionInfo: {
type: SessionInfoSchema,
required: function (this: any) {
return this.signInType === 'Session';
},
},
googleInfo: {
type: GoogleInfoSchema,
required: function (this: any) {
return this.signInType === 'Google';
},
},
}, {_id : false});
const userSchema = new Schema<UserInterface>(
{
name: {
type: String,
required: [true, 'Name is required.'],
maxlength: [50, 'Name must not exceed 50 characters.'],
},
userHandle: {
type: String,
required: [true, 'User handle is required.'],
unique: true,
},
profilePic: {
type: String,
},
following: [
{
type: Schema.Types.ObjectId,
ref: 'User',
},
],
followers: [
{
type: Schema.Types.ObjectId,
ref: 'User',
},
],
auth: {
type: AuthSchema,
required: true,
select: true,
},
},
{ timestamps: true }
);
export default model<UserInterface>('User', userSchema);