1
0
Code Issues Pull Requests Packages Projects Releases Wiki Activity GitHub Gitee
Files
inke/apps/web/app/api/auth/[...nextauth]/route.ts
2023-11-10 14:59:47 +08:00

107 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import NextAuth, { NextAuthOptions, Theme } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/lib/db/prisma";
import EmailProvider from "next-auth/providers/email";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";
import { createTransport } from "nodemailer";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID as string,
clientSecret: process.env.GITHUB_SECRET as string,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}),
EmailProvider({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
maxAge: 10 * 60, // 10min, 邮箱链接失效时间默认24小时
async sendVerificationRequest({
identifier: email,
url,
provider,
theme,
}) {
const { host } = new URL(url);
const transport = createTransport(provider.server);
const result = await transport.sendMail({
to: email,
from: provider.from,
subject: `You are logging in to Inke`,
text: text({ url, host }),
html: html({ url, host, theme }),
});
const failed = result.rejected.concat(result.pending).filter(Boolean);
if (failed.length) {
throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
}
},
}),
],
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
/**
*使用HTML body 代替正文内容
*/
function html(params: { url: string; host: string; theme: Theme }) {
const { url, host, theme } = params;
const escapedHost = host.replace(/\./g, "​.");
const brandColor = theme.brandColor || "#346df1";
const color = {
background: "#f9f9f9",
text: "#444",
mainBackground: "#fff",
buttonBackground: brandColor,
buttonBorder: brandColor,
buttonText: theme.buttonText || "#fff",
};
return `
<body style="background: ${color.background};">
<table width="100%" border="0" cellspacing="10" cellpadding="0"
style="background: ${color.mainBackground}; max-width: 600px; margin: auto; border-radius: 10px;">
<tr>
<td align="center"
style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
<strong>Welcome to Inke</strong> 🎉
</td>
</tr>
<tr>
<td align="center" style="padding: 5px 0;">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" style="border-radius: 5px;" bgcolor="${color.buttonBackground}"><a href="${url}"
target="_blank"
style="font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: ${color.buttonText}; text-decoration: none; border-radius: 5px; padding: 10px 20px; border: 1px solid ${color.buttonBorder}; display: inline-block; font-weight: bold;">Sign
in now</a></td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left"
style="padding: 0px 0px 10px 0px; font-size: 16px; line-height: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
Button click without response? Try open this <a href="${url}" target="_blank">link</a> in your browser. If you did not request this email you can safely ignore it.
</td>
</tr>
</table>
</body>
`;
}
/** 不支持HTML 的邮件客户端会显示下面的文本信息 */
function text({ url, host }: { url: string; host: string }) {
return `Welcome to Inke! This is a magic link, click on it to log in ${url}\n`;
}