Without modifying the Prisma adapter itself, I can't figure out how I could add a required String "handler" that would be saved when the user creates an account.
When they sign in, I need to generate a random unique handler for the user. Is it possible?
I tried to add info in createUser Event without success.
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
handler String @unique <-------
accounts Account[]
sessions Session[]
}
import GithubProvider from 'next-auth/providers/github'
import EmailProvider from 'next-auth/providers/email'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import { PrismaClient } from '@prisma/client'
import { NuxtAuthHandler } from '#auth'
import { generateFromEmail } from "unique-username-generator";
const prisma = new PrismaClient()
export default NuxtAuthHandler({
adapter: PrismaAdapter(prisma),
session: {
strategy: 'database',
maxAge: 30 * 24 * 60 * 60,
updateAge: 24 * 60 * 60
},
pages: {
// Change the default behavior to use custom login page /auth/login as the path for the sign-in page
signIn: '/auth/login'
},
secret: process.env.AUTH_SECRET,
providers: [
// @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point
GithubProvider.default({
clientId: process.env.AUTH_GITHUB_CLIENT_ID,
clientSecret: process.env.AUTH_GITHUB_CLIENT_SECRET,
allowDangerousEmailAccountLinking: true,
}),
// @ts-expect-error
EmailProvider.default({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD
}
},
from: process.env.EMAIL_FROM,
allowDangerousEmailAccountLinking: true,
})
],
events: {
createUser: async (user) => {
console.log(user)
try {
if (!user.handler && user.email) {
console.log('creating handler')
const handler = generateFromEmail(user.email, 4)
console.log({handler})
const existingUser = await prisma.user.findUnique({
where: {
email: user.email
}
})
if (existingUser) {
console.log({existingUser})
await prisma.user.update({
where: {
id: user.id
},
data: {
handler
}
})
}
}
} catch (err) {
console.log(err)
}
}
}
})
Thank you!
Struggled with this for a while too. As far as I know there is no way to implement that other than modifying the Adapter.
Here is my implementation, the relevant parts:
function CustomPrismaAdapter(p: typeof prisma): Adapter {
return {
...PrismaAdapter(p),
async createUser(user: Omit<AdapterUser, "id">) {
const created = await p.user.create({
data: {
...user,
folders: {
create: { name: "all" },
},
},
});
return created as AdapterUser;
},
};
}
export const authOptions: NextAuthOptions = {
adapter: CustomPrismaAdapter(prisma),
session: { strategy: "jwt" },
secret: process.env.NEXTAUTH_SECRET,
pages: {
signIn: "/login",
},
providers: [
GitHub({
clientId: process.env.GITHUB_ID ?? "",
clientSecret: process.env.GITHUB_SECRET ?? "",
}),
Google({
clientId: process.env.GOOGLE_ID ?? "",
clientSecret: process.env.GOOGLE_SECRET ?? "",
}),
],
...
}
You have to fight TypeScript a bit, but besides that it works as expected.