diff --git a/app/app/(admin)/components/sidebar.tsx b/app/app/(admin)/components/sidebar.tsx index 0287214ba..b3081cb2a 100644 --- a/app/app/(admin)/components/sidebar.tsx +++ b/app/app/(admin)/components/sidebar.tsx @@ -36,21 +36,16 @@ const items: MenuItem[] = [ getItem("使用分析", "/admin/ana"), ]), - getItem("Navigation Two", "sub2", , [ - getItem("Option 5", "5"), - getItem("Option 6", "6"), - getItem("Submenu", "sub3", null, [ - getItem("Option 7", "7"), - getItem("Option 8", "8"), - ]), + getItem("管理", "manage", , [ + getItem("用户管理", "/admin/users"), ]), - getItem("Navigation Three", "sub4", , [ - getItem("Option 9", "9"), - getItem("Option 10", "10"), - getItem("Option 11", "11"), - getItem("Option 12", "12"), - ]), + // getItem("Navigation Three", "sub4", , [ + // getItem("Option 9", "9"), + // getItem("Option 10", "10"), + // getItem("Option 11", "11"), + // getItem("Option 12", "12"), + // ]), ]; const SideBar: React.FC = () => { @@ -68,12 +63,12 @@ const SideBar: React.FC = () => { setCurrent(e.key); router.push(e.key); }; - // useEffect(() => { - // // 如果按钮和路径不相等,那其实应该跳转到按钮的网址 - // if (current != pathname) { - // router.push(current); - // } - // }, [current, pathname, router]); + useEffect(() => { + // 如果按钮和路径不相等,那其实应该跳转到按钮的网址 + if (current != pathname) { + router.push(current); + } + }, [current, pathname, router]); return ( <> diff --git a/lib/auth.ts b/lib/auth.ts index 37dc4c525..60750fcca 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -1,10 +1,11 @@ -import { getServerSession, type NextAuthOptions } from "next-auth"; +import {getServerSession, type NextAuthOptions, Theme} from "next-auth"; import GitHubProvider from "next-auth/providers/github"; import EmailProvider from "next-auth/providers/email"; import CredentialsProvider from "next-auth/providers/credentials"; import { PrismaAdapter } from "@next-auth/prisma-adapter"; import prisma from "@/lib/prisma"; import { isEmail, isName } from "@/lib/auth_list"; +import { createTransport } from "nodemailer"; const SECURE_COOKIES:boolean = !!process.env.SECURE_COOKIES; @@ -31,13 +32,36 @@ export const authOptions: NextAuthOptions = { EmailProvider({ server: { host: process.env.EMAIL_SERVER_HOST, - port: process.env.EMAIL_SERVER_PORT, + port: parseInt(process.env.EMAIL_SERVER_PORT ?? "0"), auth: { user: process.env.EMAIL_SERVER_USER, pass: process.env.EMAIL_SERVER_PASSWORD, }, }, from: process.env.EMAIL_FROM, + async sendVerificationRequest({ + identifier: email, + url, + provider: { server, from, name }, + theme, + }) { + /* your function */ + console.log('send mail,', email, url, server, from, ) + const { host } = new URL(url) + const transport = createTransport(server) + const result = await transport.sendMail({ + to: email, + from: from, + subject: `Sign in to ${host}`, + html: email_html({ url, host, theme }), + }) + const failed = result.rejected.concat(result.pending).filter(Boolean) + console.log('[result],', result) + if (failed.length) { + throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) + } + + }, }), CredentialsProvider({ // The name to display on the sign in form (e.g. "Sign in with...") @@ -232,3 +256,62 @@ function cleanUpString(input: string): string { return ''; } } + + + + +/** + * Email HTML body + * Insert invisible space into domains from being turned into a hyperlink by email + * clients like Outlook and Apple mail, as this is confusing because it seems + * like they are supposed to click on it to sign in. + * + * @note We don't add the email address to avoid needing to escape it, if you do, remember to sanitize it! + */ +function email_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 ` + + + + + + + + + + + +
+ Sign in to ${escapedHost} +
+ + + + +
Sign + in
+
+ If you did not request this email you can safely ignore it. +
+ +` +} diff --git a/package.json b/package.json index 91d625e44..36135c250 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "@types/bcryptjs": "^2.4.6", "@types/cookie": "^0.6.0", "@types/node": "^20.11.10", + "@types/nodemailer": "^6.4.14", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.7", "@types/react-highlight-words": "^0.16.7",