Merge branch 'auth' into cloudflare-dev

This commit is contained in:
hamster1963 2024-10-21 00:26:26 +08:00
commit 410c04d946
14 changed files with 107 additions and 7 deletions

View File

@ -20,6 +20,7 @@ function Header() {
const router = useRouter(); const router = useRouter();
const locale = useLocale(); const locale = useLocale();
return ( return (
<div className="mx-auto w-full max-w-5xl"> <div className="mx-auto w-full max-w-5xl">
<section className="flex items-center justify-between"> <section className="flex items-center justify-between">

View File

@ -1,11 +1,17 @@
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 { SignIn } from "@/components/sign-in";
import getEnv from "@/lib/env-entry";
import React from "react"; import React from "react";
type DashboardProps = { type DashboardProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
export default function MainLayout({ children }: DashboardProps) { export default async function MainLayout({ children }: DashboardProps) {
const session = await auth()
if (!session && getEnv("SITE_PASSWORD")) return <SignIn />
return ( return (
<div className="flex min-h-screen w-full flex-col"> <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"> <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">

View File

@ -10,6 +10,7 @@ export default function Home({
params: { locale: string }; params: { locale: string };
}) { }) {
unstable_setRequestLocale(locale); unstable_setRequestLocale(locale);
return ( return (
<div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6"> <div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6">
<ServerOverview /> <ServerOverview />

View File

@ -13,6 +13,7 @@ import { Inter as FontSans } from "next/font/google";
import React from "react"; import React from "react";
import "/node_modules/flag-icons/css/flag-icons.min.css"; import "/node_modules/flag-icons/css/flag-icons.min.css";
import { auth } from "@/auth";
const fontSans = FontSans({ const fontSans = FontSans({
subsets: ["latin"], subsets: ["latin"],
@ -54,6 +55,7 @@ export default function LocaleLayout({
unstable_setRequestLocale(locale); unstable_setRequestLocale(locale);
const messages = useMessages(); const messages = useMessages();
return ( return (
<html lang={locale} suppressHydrationWarning> <html lang={locale} suppressHydrationWarning>
<head> <head>

View File

@ -0,0 +1,2 @@
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers

View File

@ -1,6 +1,8 @@
import { NezhaAPISafe } from "@/app/[locale]/types/nezha-api"; import { NezhaAPISafe } from "@/app/[locale]/types/nezha-api";
import { GetServerDetail } from "@/lib/serverFetch"; import { GetServerDetail } from "@/lib/serverFetch";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { auth } from "@/auth"
import getEnv from "@/lib/env-entry";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export const runtime = 'edge'; export const runtime = 'edge';
@ -10,7 +12,12 @@ interface NezhaDataResponse {
data?: NezhaAPISafe; data?: NezhaAPISafe;
} }
export async function GET(req: Request) { export const GET = auth(async function GET(req) {
if (!req.auth && getEnv("SITE_PASSWORD")) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
}
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
const server_id = searchParams.get("server_id"); const server_id = searchParams.get("server_id");
if (!server_id) { if (!server_id) {
@ -27,4 +34,4 @@ export async function GET(req: Request) {
return NextResponse.json({ error: response.error }, { status: 400 }); return NextResponse.json({ error: response.error }, { status: 400 });
} }
return NextResponse.json(response, { status: 200 }); return NextResponse.json(response, { status: 200 });
} });

View File

@ -1,4 +1,6 @@
import { ServerMonitorChart } from "@/app/[locale]/types/nezha-api"; import { ServerMonitorChart } from "@/app/[locale]/types/nezha-api";
import { auth } from "@/auth";
import getEnv from "@/lib/env-entry";
import { GetServerMonitor } from "@/lib/serverFetch"; import { GetServerMonitor } from "@/lib/serverFetch";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
@ -10,7 +12,12 @@ interface NezhaDataResponse {
data?: ServerMonitorChart; data?: ServerMonitorChart;
} }
export async function GET(req: Request) { export const GET = auth(async function GET(req) {
if (!req.auth && getEnv("SITE_PASSWORD")) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
}
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
const server_id = searchParams.get("server_id"); const server_id = searchParams.get("server_id");
if (!server_id) { if (!server_id) {
@ -27,4 +34,4 @@ export async function GET(req: Request) {
return NextResponse.json({ error: response.error }, { status: 400 }); return NextResponse.json({ error: response.error }, { status: 400 });
} }
return NextResponse.json(response, { status: 200 }); return NextResponse.json(response, { status: 200 });
} });

View File

@ -1,5 +1,6 @@
import { NezhaAPI, ServerApi } from "@/app/[locale]/types/nezha-api"; import { NezhaAPI, ServerApi } from "@/app/[locale]/types/nezha-api";
import { auth } from "@/auth";
import { MakeOptional } from "@/app/[locale]/types/utils"; import { MakeOptional } from "@/app/[locale]/types/utils";
import getEnv from "@/lib/env-entry"; import getEnv from "@/lib/env-entry";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
@ -13,14 +14,19 @@ interface NezhaDataResponse {
data?: ServerApi; data?: ServerApi;
} }
export async function GET(_: Request) { export const GET = auth(async function GET(req) {
if (!req.auth && getEnv("SITE_PASSWORD")) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
}
const response = (await GetNezhaData()) as NezhaDataResponse; const response = (await GetNezhaData()) as NezhaDataResponse;
if (response.error) { if (response.error) {
console.log(response.error); console.log(response.error);
return NextResponse.json({ error: response.error }, { status: 400 }); return NextResponse.json({ error: response.error }, { status: 400 });
} }
return NextResponse.json(response, { status: 200 }); return NextResponse.json(response, { status: 200 });
} });
async function GetNezhaData() { async function GetNezhaData() {

20
auth.ts Normal file
View File

@ -0,0 +1,20 @@
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
import getEnv from "./lib/env-entry"
export const { handlers, signIn, signOut, auth } = NextAuth({
secret:"this_is_nezha_dash_web_secret",
providers: [
Credentials({
credentials: {
password: {},
},
authorize: async (credentials) => {
if (credentials.password === getEnv("SITE_PASSWORD")) {
return { id: "0" }
}
return null
},
}),
],
})

BIN
bun.lockb

Binary file not shown.

40
components/sign-in.tsx Normal file
View File

@ -0,0 +1,40 @@
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>
)
}

View File

@ -3,6 +3,8 @@ import createMiddleware from "next-intl/middleware";
import { defaultLocale, locales } from "./i18n-metadata"; import { defaultLocale, locales } from "./i18n-metadata";
// export { auth as middleware } from "@/auth"
export default createMiddleware({ export default createMiddleware({
// A list of all locales that are supported // A list of all locales that are supported
locales: locales, locales: locales,

View File

@ -23,6 +23,11 @@ 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,

View File

@ -33,6 +33,7 @@
"lucide-react": "^0.451.0", "lucide-react": "^0.451.0",
"luxon": "^3.5.0", "luxon": "^3.5.0",
"next": "^14.2.15", "next": "^14.2.15",
"next-auth": "^5.0.0-beta.25",
"next-intl": "^3.21.1", "next-intl": "^3.21.1",
"next-runtime-env": "^3.2.2", "next-runtime-env": "^3.2.2",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",