mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
refactor: auth page
This commit is contained in:
parent
6bb1a5a5a0
commit
1a46cec662
@ -98,7 +98,9 @@ function Overview() {
|
|||||||
</p>
|
</p>
|
||||||
{mouted ? (
|
{mouted ? (
|
||||||
<p className="opacity-1 text-sm font-medium">{timeString}</p>
|
<p className="opacity-1 text-sm font-medium">{timeString}</p>
|
||||||
) : <Skeleton className="h-[20px] w-[50px] rounded-[5px] bg-muted-foreground/10 animate-none"></Skeleton>}
|
) : (
|
||||||
|
<Skeleton className="h-[20px] w-[50px] rounded-[5px] bg-muted-foreground/10 animate-none"></Skeleton>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Footer from "@/app/[locale]/(main)/footer";
|
import Footer from "@/app/[locale]/(main)/footer";
|
||||||
import Header from "@/app/[locale]/(main)/header";
|
import Header from "@/app/[locale]/(main)/header";
|
||||||
import { auth } from "@/auth";
|
import { auth } from "@/auth";
|
||||||
import { SignIn } from "@/components/sign-in";
|
import { SignIn } from "@/components/SignIn";
|
||||||
import getEnv from "@/lib/env-entry";
|
import getEnv from "@/lib/env-entry";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -13,12 +13,8 @@ export default async function MainLayout({ children }: DashboardProps) {
|
|||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
if (!session && getEnv("SitePassword")) {
|
if (!session && getEnv("SitePassword")) {
|
||||||
if (getEnv("CF_PAGES")) {
|
|
||||||
redirect("/api/auth/signin");
|
|
||||||
} else {
|
|
||||||
return <SignIn />;
|
return <SignIn />;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen w-full flex-col">
|
<div className="flex min-h-screen w-full flex-col">
|
||||||
|
9
auth.ts
9
auth.ts
@ -6,14 +6,15 @@ import getEnv from "./lib/env-entry";
|
|||||||
export const { handlers, signIn, signOut, auth } = NextAuth({
|
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||||
secret: "this_is_nezha_dash_web_secret",
|
secret: "this_is_nezha_dash_web_secret",
|
||||||
trustHost: true,
|
trustHost: true,
|
||||||
|
pages: {
|
||||||
|
signIn: "/",
|
||||||
|
},
|
||||||
providers: [
|
providers: [
|
||||||
Credentials({
|
Credentials({
|
||||||
credentials: {
|
credentials: { password: { label: "Password", type: "password" } },
|
||||||
password: {},
|
|
||||||
},
|
|
||||||
authorize: async (credentials) => {
|
authorize: async (credentials) => {
|
||||||
if (credentials.password === getEnv("SitePassword")) {
|
if (credentials.password === getEnv("SitePassword")) {
|
||||||
return { id: "0" };
|
return { id: "nezha-dash-auth" };
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
66
components/SignIn.tsx
Normal file
66
components/SignIn.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Footer from "@/app/[locale]/(main)/footer";
|
||||||
|
import Header from "@/app/[locale]/(main)/header";
|
||||||
|
import { getCsrfToken } from "next-auth/react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export function SignIn({}) {
|
||||||
|
const t = useTranslations("SignIn");
|
||||||
|
|
||||||
|
const [csrfToken, setCsrfToken] = useState("");
|
||||||
|
const [errorState, setErrorState] = useState(false);
|
||||||
|
|
||||||
|
const search = useSearchParams();
|
||||||
|
const error = search.get("error");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (error) {
|
||||||
|
setErrorState(true);
|
||||||
|
}
|
||||||
|
}, [error]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function loadProviders() {
|
||||||
|
const csrf = await getCsrfToken();
|
||||||
|
setCsrfToken(csrf);
|
||||||
|
}
|
||||||
|
loadProviders();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen w-full flex-col">
|
||||||
|
<main className="flex min-h-[calc(100vh_-_theme(spacing.16))] flex-1 flex-col gap-4 bg-muted/40 p-4 md:p-10 md:pt-8">
|
||||||
|
<Header />
|
||||||
|
<form
|
||||||
|
className="flex flex-col items-center justify-start gap-4 p-4 "
|
||||||
|
method="post"
|
||||||
|
action="/api/auth/callback/credentials"
|
||||||
|
>
|
||||||
|
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||||
|
<section className="flex flex-col items-start gap-2">
|
||||||
|
<label className="flex flex-col items-start gap-1 ">
|
||||||
|
{errorState && (
|
||||||
|
<p className="text-red-500 text-sm font-semibold">
|
||||||
|
{t("ErrorMessage")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<p className="text-base font-semibold">{t("SignInMessage")}</p>
|
||||||
|
<input
|
||||||
|
className="px-1 border-[1px] rounded-[5px]"
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button className=" px-1.5 py-0.5 w-fit text-sm font-semibold rounded-[8px] border bg-card hover:brightness-95 transition-all text-card-foreground shadow-lg shadow-neutral-200/40 dark:shadow-none">
|
||||||
|
{t("Submit")}
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</form>
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
import Footer from "@/app/[locale]/(main)/footer";
|
|
||||||
import Header from "@/app/[locale]/(main)/header";
|
|
||||||
import { signIn } from "@/auth";
|
|
||||||
import { useLocale } from "next-intl";
|
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
|
|
||||||
export function SignIn() {
|
|
||||||
const locale = useLocale();
|
|
||||||
|
|
||||||
async function handleSubmit(formData: FormData) {
|
|
||||||
"use server";
|
|
||||||
try {
|
|
||||||
await signIn("credentials", formData);
|
|
||||||
} catch (error) {
|
|
||||||
redirect(`/${locale}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex min-h-screen w-full flex-col">
|
|
||||||
<main className="flex min-h-[calc(100vh_-_theme(spacing.16))] flex-1 flex-col gap-4 bg-muted/40 p-4 md:p-10 md:pt-8">
|
|
||||||
<Header />
|
|
||||||
<form
|
|
||||||
className="flex flex-col items-center justify-start gap-4 p-4 "
|
|
||||||
action={handleSubmit}
|
|
||||||
>
|
|
||||||
<section className="flex flex-col items-start gap-2">
|
|
||||||
<label className="flex flex-col items-start gap-1 ">
|
|
||||||
<p className="text-base font-semibold">请输入页面密码</p>
|
|
||||||
<input
|
|
||||||
className="px-1 border-[1px] rounded-[5px]"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<button className=" px-1.5 py-0.5 w-fit text-sm font-semibold rounded-[8px] border bg-card hover:brightness-95 transition-all text-card-foreground shadow-lg shadow-neutral-200/40 dark:shadow-none">
|
|
||||||
确认
|
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
<Footer />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -23,6 +23,11 @@
|
|||||||
"Detail": "Detail",
|
"Detail": "Detail",
|
||||||
"Network": "Network"
|
"Network": "Network"
|
||||||
},
|
},
|
||||||
|
"SignIn": {
|
||||||
|
"SignInMessage": "Please enter the password",
|
||||||
|
"Submit": "Login",
|
||||||
|
"ErrorMessage": "Invalid password"
|
||||||
|
},
|
||||||
"ServerCardPopover": {
|
"ServerCardPopover": {
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"CPU": "CPU",
|
"CPU": "CPU",
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
"Detail": "詳細",
|
"Detail": "詳細",
|
||||||
"Network": "ネットワーク"
|
"Network": "ネットワーク"
|
||||||
},
|
},
|
||||||
|
"SignIn": {
|
||||||
|
"SignInMessage": "パスワードを入力してください",
|
||||||
|
"Submit": "ログイン",
|
||||||
|
"ErrorMessage": "パスワードが間違っています"
|
||||||
|
},
|
||||||
"ServerCardPopover": {
|
"ServerCardPopover": {
|
||||||
"System": "システム",
|
"System": "システム",
|
||||||
"CPU": "CPU",
|
"CPU": "CPU",
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
"Detail": "詳細",
|
"Detail": "詳細",
|
||||||
"Network": "網路"
|
"Network": "網路"
|
||||||
},
|
},
|
||||||
|
"SignIn": {
|
||||||
|
"SignInMessage": "請輸入密碼",
|
||||||
|
"Submit": "登入",
|
||||||
|
"ErrorMessage": "密碼錯誤"
|
||||||
|
},
|
||||||
"ServerCardPopover": {
|
"ServerCardPopover": {
|
||||||
"System": "系統",
|
"System": "系統",
|
||||||
"CPU": "CPU",
|
"CPU": "CPU",
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
"Detail": "详情",
|
"Detail": "详情",
|
||||||
"Network": "网络"
|
"Network": "网络"
|
||||||
},
|
},
|
||||||
|
"SignIn": {
|
||||||
|
"SignInMessage": "请输入密码",
|
||||||
|
"Submit": "登录",
|
||||||
|
"ErrorMessage": "密码错误"
|
||||||
|
},
|
||||||
"ServerCardPopover": {
|
"ServerCardPopover": {
|
||||||
"System": "系统",
|
"System": "系统",
|
||||||
"CPU": "CPU",
|
"CPU": "CPU",
|
||||||
|
@ -23,11 +23,6 @@ const withPWA = withPWAInit({
|
|||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
experimental: {
|
|
||||||
serverActions: {
|
|
||||||
allowedOrigins: ["*"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logging: {
|
logging: {
|
||||||
fetches: {
|
fetches: {
|
||||||
fullUrl: true,
|
fullUrl: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user