整体优化认证

This commit is contained in:
sijinhui 2024-04-02 00:00:51 +08:00
parent f686fe09ce
commit 20871f7e50
13 changed files with 46 additions and 98 deletions

View File

@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import { VerifiedUser } from "@/lib/auth"; // import { VerifiedUser } from "@/lib/auth";
import { getServerSideConfig } from "@/app/config/server"; import { getServerSideConfig } from "@/app/config/server";
const serverConfig = getServerSideConfig(); const serverConfig = getServerSideConfig();
// Gets an access token. // Gets an access token.
@ -21,8 +21,8 @@ async function handle(
) { ) {
// 认证 // 认证
const isUser = await VerifiedUser(); // const isUser = await VerifiedUser();
if (!isUser) return NextResponse.json({ error: "未认证" }, { status: 401 }); // if (!isUser) return NextResponse.json({ error: "未认证" }, { status: 401 });
const get_access_token = await getAccessToken(); const get_access_token = await getAccessToken();

View File

@ -9,7 +9,7 @@ async function handle(
) { ) {
try { try {
const request_data = await req.json(); const request_data = await req.json();
console.log("log", request_data); // console.log("log", request_data);
// if (request_data?.userName) { // if (request_data?.userName) {
// await insertUser({ // await insertUser({
// name: request_data?.userName, // name: request_data?.userName,

View File

@ -1,18 +1,9 @@
import UsageByModel from "./usage-by-model-chart"; import UsageByModel from "./usage-by-model-chart";
import UserByMap from "./user-by-map"; import UserByMap from "./user-by-map";
// import { getSession } from "@/lib/auth";
// import { isName, ADMIN_LIST } from "@/lib/auth_list";
// import { redirect } from "next/navigation";
import { Flex } from "antd"; import { Flex } from "antd";
export default async function AdminPage() { export default async function AdminPage() {
// const session = await getSession();
// const name = session?.user?.email || session?.user?.name;
// if (!(name && ADMIN_LIST.includes(name))) {
// // Replace '/dashboard' with the desired redirect path
// redirect("/");
// }
return ( return (
<> <>
<Flex gap="middle" vertical> <Flex gap="middle" vertical>

View File

@ -9,9 +9,8 @@ import React, {
} from "react"; } from "react";
import * as echarts from "echarts"; import * as echarts from "echarts";
// import { DatePicker } from "@tremor/react";
import { DatePicker } from "antd"; import { DatePicker } from "antd";
import { Col, Row } from "antd"; import { Row } from "antd";
import locale from "antd/es/date-picker/locale/zh_CN"; import locale from "antd/es/date-picker/locale/zh_CN";
import "dayjs/locale/zh-cn"; import "dayjs/locale/zh-cn";
@ -21,10 +20,6 @@ import { EChartsOption } from "echarts";
import { essos } from "@/lib/charts_theme"; import { essos } from "@/lib/charts_theme";
import { subDays, addDays } from "date-fns"; import { subDays, addDays } from "date-fns";
// import customParseFormat from 'dayjs/plugin/customParseFormat';
// dayjs.extend(customParseFormat);
// const dateFormat = 'YYYY-MM-DD';
interface ComponentProps { interface ComponentProps {
currentDate: Date; currentDate: Date;
setCurrentDate: Dispatch<SetStateAction<Date>>; setCurrentDate: Dispatch<SetStateAction<Date>>;

View File

@ -11,10 +11,7 @@ import React, {
import Script from "next/script"; import Script from "next/script";
import * as echarts from "echarts"; import * as echarts from "echarts";
// var echarts = require('echarts');
import "echarts/extension/bmap/bmap"; import "echarts/extension/bmap/bmap";
// require("echarts");
// require("echarts/extension/bmap/bmap");
interface DataItem { interface DataItem {
name: string; name: string;

View File

@ -4,13 +4,7 @@ import { useSession } from "next-auth/react";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import { ADMIN_LIST } from "@/lib/auth_list"; import { ADMIN_LIST } from "@/lib/auth_list";
import React, { ReactNode, useEffect, useState } from "react"; import React, { ReactNode, useEffect, useState } from "react";
import { import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
MenuFoldOutlined,
MenuUnfoldOutlined,
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from "@ant-design/icons";
import { Layout, Menu, Button, theme, ConfigProvider, ThemeConfig } from "antd"; import { Layout, Menu, Button, theme, ConfigProvider, ThemeConfig } from "antd";
import SideBar from "../components/sidebar"; import SideBar from "../components/sidebar";

View File

@ -1,20 +1,7 @@
import { Flex } from "antd"; import { Flex } from "antd";
import prisma from "@/lib/prisma";
import { User } from "@prisma/client";
import UsersTablePart from "../../components/users-table"; import UsersTablePart from "../../components/users-table";
// async function getData() {
// return await prisma.user.findMany({
// orderBy: {
// createdAt: "desc",
// },
// });
// }
export default async function UsersPage() { export default async function UsersPage() {
// const users: User[] = await getData();
// console.log("data", data);
return ( return (
<> <>
<Flex gap="middle" vertical> <Flex gap="middle" vertical>

View File

@ -1,17 +1,17 @@
"use client"; "use client";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Link from "next/link"; // import Link from "next/link";
import { useRouter, usePathname } from "next/navigation"; import { useRouter, usePathname } from "next/navigation";
import { import {
AppstoreOutlined, AppstoreOutlined,
MailOutlined, // MailOutlined,
SettingOutlined, // SettingOutlined,
DashboardTwoTone, // DashboardTwoTone,
} from "@ant-design/icons"; } from "@ant-design/icons";
import type { MenuProps, MenuTheme } from "antd"; import type { MenuProps, MenuTheme } from "antd";
import { Menu, Switch } from "antd"; import { Menu } from "antd";
type MenuItem = Required<MenuProps>["items"][number]; type MenuItem = Required<MenuProps>["items"][number];

View File

@ -1,12 +1,6 @@
"use client"; "use client";
import React, { import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
Dispatch,
SetStateAction,
useEffect,
useRef,
useState,
} from "react";
import { User } from "@prisma/client"; import { User } from "@prisma/client";
import { Space, Table, Tag, Input, Button, notification } from "antd"; import { Space, Table, Tag, Input, Button, notification } from "antd";
import type { GetRef, TableColumnsType } from "antd"; import type { GetRef, TableColumnsType } from "antd";

View File

@ -3,20 +3,13 @@
import LoadingDots from "@/app/components/icons/loading-dots"; import LoadingDots from "@/app/components/icons/loading-dots";
import { signIn } from "next-auth/react"; import { signIn } from "next-auth/react";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { useState, useEffect } from "react"; import { useState } from "react";
// import { toast } from "sonner";
export default function LoginButton() { export default function LoginButton() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
// Get error message added by next/auth in URL. // Get error message added by next/auth in URL.
const searchParams = useSearchParams(); const searchParams = useSearchParams();
// const error = searchParams?.get("error");
//
// useEffect(() => {
// const errorMessage = Array.isArray(error) ? error.pop() : error;
// errorMessage && toast.error(errorMessage);
// }, [error]);
return ( return (
<button <button

View File

@ -4,18 +4,18 @@ import { Home } from "./components/home";
import { getServerSideConfig } from "./config/server"; import { getServerSideConfig } from "./config/server";
import { getSession } from "@/lib/auth"; // import { getSession } from "@/lib/auth";
import { isName } from "@/lib/auth_list"; // import { isName } from "@/lib/auth_list";
import { redirect } from "next/navigation"; // import { redirect } from "next/navigation";
const serverConfig = getServerSideConfig(); const serverConfig = getServerSideConfig();
export default async function App() { export default async function App() {
const session = await getSession(); // const session = await getSession();
const name = session?.user?.email || session?.user?.name; // const name = session?.user?.email || session?.user?.name;
if (!(name && isName(name))) { // if (!(name && isName(name))) {
redirect("/login"); // redirect("/login");
} // }
return ( return (
<> <>

13
lib/auth_client.ts Normal file
View File

@ -0,0 +1,13 @@
import {ADMIN_LIST, isName} from "@/lib/auth_list";
import { JWT } from "next-auth/jwt";
export async function VerifiedUser(session: JWT |null) {
const userId = session?.sub
const name = session?.email || session?.name
return !!(name && isName(name) && userId);
}
export async function VerifiedAdminUser(session: JWT |null) {
const name = session?.email || session?.name
return !!(name && ADMIN_LIST.includes(name));
}

View File

@ -1,8 +1,8 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server"; import type { NextRequest } from "next/server";
import { getToken } from "next-auth/jwt"; import { getToken } from "next-auth/jwt";
import { isName, ADMIN_LIST } from "@/lib/auth_list"; // import { isName, ADMIN_LIST } from "@/lib/auth_list";
import { VerifiedUser, getSessionName } from "@/lib/auth"; import { VerifiedUser, VerifiedAdminUser } from "@/lib/auth_client";
export default async function middleware(req: NextRequest) { export default async function middleware(req: NextRequest) {
const url = req.nextUrl; const url = req.nextUrl;
@ -16,38 +16,22 @@ export default async function middleware(req: NextRequest) {
} }
const session = await getToken({ req }); const session = await getToken({ req });
// const {session} = await getSessionName(); const isUser = await VerifiedUser(session);
const isAdminUser = await VerifiedAdminUser(session);
// 管理员页面的api接口还是要认证的 // 管理员页面的api接口还是要认证的
if (path.startsWith('/api/admin/')) { if (path.startsWith('/api/admin/')) {
let is_admin_user = false;
// 需要确认是管理员 // 需要确认是管理员
if (session && session?.user) { if (!isAdminUser) return NextResponse.json({error: '无管理员授权'}, { status: 401 });
if (ADMIN_LIST.includes(session?.name ?? "")) {
is_admin_user = true
}
}
if (!is_admin_user) return NextResponse.json({error: '无管理员授权'}, { status: 401 });
} }
const userName = session?.name || session?.email // 不是用户且页面不是登录页
if (!isName(userName ?? "") && path !== "/login" ) { if (!isUser && path !== "/login" ) {
// 用处不大,避免漏网之鱼
return NextResponse.redirect(new URL("/login", req.url)); return NextResponse.redirect(new URL("/login", req.url));
} }
// 认证有点多此一举,页面中的认证应该已经够了 // 如果登录了且页面是登录页面
// if (!session && path !== "/login") { if (isUser && path == "/login") {
// // 给关键请求特殊待遇 return NextResponse.redirect(new URL("/", req.url))
// if (path.startsWith('/api/openai/')) { }
// return NextResponse.json(false, {
// status: 401,
// });
// }
// return NextResponse.redirect(new URL("/login", req.url));
// } else if (session) {
// // console.log('referer=====', DENY_LIST.includes(session?.name ?? ""))
// if (isName(session?.name ?? "") && path.startsWith("/login"))
// return NextResponse.redirect(new URL("/", req.url));
// }
if (path == '/login') { if (path == '/login') {
return NextResponse.rewrite( return NextResponse.rewrite(