重构鉴权逻辑,新增中间件刷新令牌,授权接口统一后处理无授权跳转

This commit is contained in:
2025-04-26 14:18:08 +08:00
parent 5c88cd7f32
commit 6db037204c
20 changed files with 303 additions and 318 deletions

View File

@@ -3,8 +3,6 @@ import Image from 'next/image'
import banner from './_assets/banner.webp'
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'
import {Button} from '@/components/ui/button'
import {getProfile} from '@/actions/auth/auth'
import {redirect} from 'next/navigation'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs'
export type DashboardPageProps = {}
@@ -65,7 +63,7 @@ export default async function DashboardPage(props: DashboardPageProps) {
</Card>
{/* 图表 */}
<section className={`col-start-1 row-start-3 col-span-3 row-span-2`}>
<section className={`col-start-1 row-start-3 col-span-3 row-span-2 bg-card p-4 rounded-lg`}>
<Tabs defaultValue={`dynamic`}>
<TabsList>
<TabsTrigger value={`dynamic`} className={`data-[state=active]:text-primary`}> IP </TabsTrigger>

View File

@@ -17,7 +17,7 @@ export default function Navbar(props: NavbarProps) {
<nav data-expand={navbar} className={merge(
`transition-[flex-basis] duration-200 ease-in-out`,
`flex flex-col overflow-hidden group`,
`flex-none ${navbar ? `expand basis-52` : `noexpand basis-16`}`,
`data-[expand=true]:basis-52 data-[expand=false]:basis-16`,
)}>
{/* logo */}
<Logo mini={!navbar}/>
@@ -25,22 +25,23 @@ export default function Navbar(props: NavbarProps) {
{/* routes */}
<section className={merge(
`transition-[padding] duration-200 ease-in-out`,
`flex-auto overflow-auto ${navbar ? `px-4` : `px-3`}`,
`flex-auto overflow-auto`,
`data-[expand=true]:px-4 data-[expand=false]:px-3`,
)}>
<NavItem href={'/admin'} icon={`🏠`} label={`账户总览`} expand={navbar}/>
<NavItem href={'/admin'} icon={`🏠`} label={`账户总览`}/>
<NavTitle label={`个人信息`}/>
<NavItem href={`/admin/profile`} icon={`📝`} label={`个人中心`} expand={navbar}/>
<NavItem href={`/admin/identify`} icon={`🆔`} label={`实名认证`} expand={navbar}/>
<NavItem href={`/admin/whitelist`} icon={`🔒`} label={`白名单`} expand={navbar}/>
<NavItem href={`/admin/bills`} icon={`💰`} label={`我的账单`} expand={navbar}/>
<NavItem href={`/admin/profile`} icon={`📝`} label={`个人中心`}/>
<NavItem href={`/admin/identify`} icon={`🆔`} label={`实名认证`}/>
<NavItem href={`/admin/whitelist`} icon={`🔒`} label={`白名单`}/>
<NavItem href={`/admin/bills`} icon={`💰`} label={`我的账单`}/>
<NavTitle label={`套餐管理`}/>
<NavItem href={`/admin/purchase`} icon={`🛒`} label={`购买套餐`} expand={navbar}/>
<NavItem href={`/admin/resources`} icon={`📦`} label={`套餐管理`} expand={navbar}/>
<NavItem href={`/admin/purchase`} icon={`🛒`} label={`购买套餐`}/>
<NavItem href={`/admin/resources`} icon={`📦`} label={`套餐管理`}/>
<NavTitle label={`IP 管理`}/>
<NavItem href={`/admin/extract`} icon={`📤`} label={`提取 IP`} expand={navbar}/>
<NavItem href={`/admin`} icon={`👁️`} label={`IP 管理`} expand={navbar}/>
<NavItem href={`/admin`} icon={`📜`} label={`提取记录`} expand={navbar}/>
<NavItem href={`/admin`} icon={`🗂️`} label={`使用记录`} expand={navbar}/>
<NavItem href={`/admin/extract`} icon={`📤`} label={`提取 IP`}/>
<NavItem href={`/admin`} icon={`👁️`} label={`IP 管理`}/>
<NavItem href={`/admin`} icon={`📜`} label={`提取记录`}/>
<NavItem href={`/admin`} icon={`🗂️`} label={`使用记录`}/>
</section>
</nav>
)
@@ -75,10 +76,10 @@ function NavTitle(props: {
`transition-[opacity] duration-150 ease-in-out absolute mx-4`,
`group-data-[expand=true]:delay-[50ms] group-data-[expand=true]:opacity-100 group-data-[expand=false]:opacity-0`,
)}>{props.label}</span>
<div className={merge(
`transition-[opacity] duration-150 ease-in-out absolute w-full border-b`,
<span className={merge(
`transition-[opacity] duration-150 ease-in-out absolute w-full border-b block`,
`group-data-[expand=false]:delay-[50ms] group-data-[expand=false]:opacity-100 group-data-[expand=true]:opacity-0`,
)}></div>
)}></span>
</p>
)
}
@@ -87,7 +88,6 @@ function NavItem(props: {
href: string
icon?: ReactNode
label: string
expand: boolean
}) {
return (
<Link className={merge(

View File

@@ -1,6 +1,6 @@
'use client'
import {Button} from '@/components/ui/button'
import {logout} from '@/actions/auth/auth'
import {logout} from '@/actions/auth'
import {useProfileStore} from '@/components/providers/StoreProvider'
import {useRouter} from 'next/navigation'
import {toast} from 'sonner'

View File

@@ -9,7 +9,7 @@ import {Form, FormField} from '@/components/ui/form'
import {useForm} from 'react-hook-form'
import zod from 'zod'
import {zodResolver} from '@hookform/resolvers/zod'
import {Identify} from '@/actions/auth/identify'
import {Identify} from '@/actions/user'
import {toast} from 'sonner'
import {useContext, useEffect, useRef, useState} from 'react'
import * as qrcode from 'qrcode'

View File

@@ -1,29 +1,13 @@
import {ReactNode} from 'react'
import {merge} from '@/lib/utils'
import {redirect} from 'next/navigation'
import {getProfile} from '@/actions/auth/auth'
import Header from './_client/header'
import Navbar from '@/app/admin/_client/navbar'
export type DashboardLayoutProps = {
export type AdminLayoutProps = {
children: ReactNode
}
export default async function DashboardLayout(props: DashboardLayoutProps) {
// ======================
// profile
// ======================
const user = await getProfile()
if (!user) {
return redirect(`/login?redirect=${encodeURIComponent('/admin')}`)
}
// ======================
// render
// ======================
export default async function AdminLayout(props: AdminLayoutProps) {
return (
<div className={merge(
`h-screen bg-card overflow-hidden min-w-7xl overflow-y-hidden`,