mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-03 00:26:40 +08:00
整体优化认证
This commit is contained in:
parent
f686fe09ce
commit
20871f7e50
@ -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();
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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>>;
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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];
|
||||||
|
|
||||||
|
@ -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";
|
||||||
|
@ -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
|
||||||
|
16
app/page.tsx
16
app/page.tsx
@ -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
13
lib/auth_client.ts
Normal 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));
|
||||||
|
}
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user