我试图在nextJs 13应用程序中创建一个基于角色的谷歌登录,该应用程序使用next-auth,以便调用2个不同的表来创建基于他们的角色的用户。
我使用mongodb/mongoose作为数据库。用户型号为:
import mongoose, { Schema, model, models } from "mongoose";
const userSchema = new Schema({
email: {
type: String,
required: [true, "Email is required"],
unique: [true, "Email already exists"],
index: true,
},
username: {
type: String,
required: [true, "Username is required"],
match: [/^[a-zA-Z0-9]+$/, "Username is invalid"],
index: true,
},
image: {
type: String,
},
userType: {
type: String,
enum: ["typeA", "typeB"],
required: [true, "User type is required"],
},
});
const typeASchema = new Schema({
typeA: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
other1: [{
type: mongoose.Schema.Types.ObjectId,
ref: "other_table1",
}],
});
const typeBSchema = new Schema({
typeB: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
other2: [{
type: mongoose.Schema.Types.ObjectId,
ref: "other_table2",
}],
});
const User = models.User || model("User", userSchema);
const TypeA= models.TypeA || User.discriminator("TypeA", typeASchema);
const TypeB= models.TypeB || User.discriminator("TypeB", typeBSchema);
export { User, TypeA, TypeB};
然后在我的/app/API/auth/[... nextauth]/route.js中,我定义:
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import { connectToDB } from '@/utils/database';
import {User, TypeA, TypeB} from '@/models/user';
function getRandomAvatarURL() {
}
const handler = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
})
],
callbacks: {
async session({ session }) {
const sessionUser = await User.findOne({
email: session.user.email
})
session.user.id = sessionUser._id.toString();
session.user.image = sessionUser.image;
return session;
},
async signIn({ profile, userType}) {
try {
await connectToDB();
// check if a user already exists
const userExists = await User.findOne({
email: profile.email
});
// if not, create user and add to db
if(!userExists) {
const name = profile.name.split(" ");
const firstName = name[0] || ".";
const lastName = name.slice(1).join(" ") || ".";
const username = `${firstName}${lastName}`.replace(/\s/g, "");
if (userType === "typeA"){
await TypeA.create({
email: profile.email,
username: username,
image: getRandomAvatarURL(),
userType: "typeA",
})
} else if (userType === "typeB"){
await TypeB.create({
email: profile.email,
username: username,
image: getRandomAvatarURL(),
userType: "typeB",
})
}
}
return true;
} catch (error) {
console.log(error)
if (error.code === 11000){
console.log("Unique constraint violation error! Username already Exists!")
}
return false;
}
}
},
})
export { handler as GET, handler as POST };
在我的Nav组件中,我调用如下函数:
//imports
const Nav = () => {
// other code ...
const handleSignin = async(providerId, userType) => {
console.log('provider.id:', providerId); // returns correctly
console.log('userType:', userType); //returns correctly
await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:{userType: userType}});
}
//...
return(
//....
{providers &&
Object.values(providers).map((provider) => (
<button
type="button"
key={provider.name}
onClick={() => handleSignin(provider.id, "refree")}
>
<Image src="/assets/icons/signin.svg" width={20} height={20} className="rounded-none" alt="signin" />
</button>
))}
);
};
export default Nav;
我尝试了所有可能的前端和后端组合,其中一些是:
Frontend:
const handleSignin = async(providerId, userType) => {
await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:{userType: userType}});
}
const handleSignin = async(providerId, userType) => {
await signIn(providerId, { callbackUrl: "/dashboard"}, {credentials:userType});
const handleSignin = async(providerId, userType) => {
await signIn(providerId, { callbackUrl: "/dashboard"}, {userType: userType});
}
const handleSignin = async(providerId, userType) => {
await signIn(providerId, {userType: userType, callbackUrl: "/dashboard"});
}
Backend:
async signIn({ profile, userType}) {
try {
await connectToDB();
console.log(userType)
async signIn({ profile, credentials}) {
try {
await connectToDB();
console.log(credentials)
它总是返回undefined。我似乎无法捕获从前端传递到后端的参数。任何帮助或指针都非常感谢。当我不传递userType参数,而只是尝试在登录时创建任何一种类型的用户时,该流就可以工作。
1条答案
按热度按时间kyxcudwk1#
nextauth中
signIn
的第三个参数authorizationParams
被传递给提供者(google),而不是signIn
回调。您可以创建一个自定义提供程序,并从signIn
回调的user
中获取userType
,如下所示:前端会像……