我在迁移我的js文件jo-tsx时遇到了一个问题,我正在做的是使用凭据登录并将会话用户自定义为我的用户数据
// api/auth/[...nextauth].js
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import { ConnectDatabase } from "../../../lib/db";
import { VertifyPassword } from "../../../lib/password";
import { getSelectedUser } from "../../../helpers/database";
import { MongoClient } from "mongodb";
import { NextApiRequest } from "next";
interface credentialsData {
data: string | number;
password: string;
}
export default NextAuth({
session: {
jwt: true,
},
callbacks: {
async session(session) {
const data = await getSelectedUser(session.user.email);
session.user = data.userData;
// inside data.userdata is a object
// {
// _id: '60a92f328dc04f58207388d1',
// email: 'user@user.com',
// phone: '087864810221',
// point: 0,
// role: 'user',
// accountstatus: 'false'
// }
return Promise.resolve(session);
},
},
providers: [
Providers.Credentials({
async authorize(credentials: credentialsData, req: NextApiRequest) {
let client;
try {
client = await ConnectDatabase();
} catch (error) {
throw new Error("Failed connet to database.");
}
const checkEmail = await client
.db()
.collection("users")
.findOne({ email: credentials.data });
const checkPhone = await client
.db()
.collection("users")
.findOne({ phone: credentials.data });
let validData = {
password: "",
email: "",
};
if (!checkEmail && !checkPhone) {
client.close();
throw new Error("Email atau No HP tidak terdaftar.");
} else if (checkEmail) {
validData = checkEmail;
} else if (checkPhone) {
validData = checkPhone;
}
const checkPassword = await VertifyPassword(
credentials.password,
validData.password
);
if (!checkPassword) {
client.close();
throw new Error("Password Salah.");
}
client.close();
// inside validData is a object
// {
// _id: '60a92f328dc04f58207388d1',
// email: 'user@user.com',
// phone: '087864810221',
// point: 0,
// role: 'user',
// accountstatus: 'false'
// }
return validData;
},
}),
],
});
// as default provider just return session.user just return email,name, and image, but I want custom the session.user to user data what I got from dababase
这在客户端中
// index.tsx
export const getServerSideProps: GetServerSideProps<{
session: Session | null;
}> = async (context) => {
const session = await getSession({ req: context.req });
if (session) {
if (session.user?.role === "admin") {
return {
redirect: {
destination: "/admin/home",
permanent: false,
},
};
}
}
return {
props: {
session,
},
};
};
但在客户端,我收到了的警告
Property 'role' does not exist on type '{ name?: string; email?: string; image?: string;
事实上,我的文件仍然运行良好,但当我的文件为js
格式时,它不会像那样发出警告
有人能帮我修一下吗?
不确定是否找到了解决方法,但也需要配置jwt回调!下面是我的一个项目的例子:
callbacks: {
async session(session, token) {
session.accessToken = token.accessToken;
session.user = token.user;
return session;
},
async jwt(token, user, account, profile, isNewUser) {
if (user) {
token.accessToken = user._id;
token.user = user;
}
return token;
},
},
解释事物。jwt函数总是在会话之前运行,所以你传递给jwt令牌的任何数据都可以在会话函数上使用,你可以用它做任何你想做的事情。在jwt函数中,我检查是否有用户,因为这只会在你登录时返回数据。
我想现在你已经解决了这个问题,但由于我在这个页面上遇到了同样的问题,我想我会发布我的解决方案。以防其他人碰到它。我是typescript/nextjs的新手,没有意识到我只需要创建一个类型定义文件就可以将角色字段添加到会话中。user
我创建了/types/next-auth.d.ts
import NextAuth from "next-auth";
declare module "next-auth" {
interface Session {
user: {
id: string;
username: string;
email: string;
role: string;
[key: string]: string;
};
}
}
然后我不得不把它添加到我的tsconfig.json 中
"include": ["next-env.d.ts", "types/**/*.ts", "**/*.ts", "**/*.tsx"],
我喜欢@klc3rd的答案,但您可以更精确地使用类型扩展,而不是完全覆盖DefaultSession
中定义的属性:
import { type DefaultSession } from 'next-auth';
declare module 'next-auth' {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user?: {
id: string;
role?: string;
username?: string;
someExoticUserProperty?: string;
} & DefaultSession['user'];
}
}
此外,请注意,user
被标记为可选。这是因为默认情况下,useSession
在客户端上工作并获取用户的会话。在提取过程完成之前,user
属性可以是undefined