From 7889ecb0d250f0f1571feb7dafbe6f9e1633073e Mon Sep 17 00:00:00 2001 From: mlogclub Date: Fri, 24 Apr 2026 11:35:29 +0800 Subject: [PATCH] feat(auth): update login routes and add WxWork login callback handling --- dashboard/app/dashboard/layout.tsx | 14 ++++++++++---- dashboard/app/{ => dashboard}/login/page.tsx | 4 ++-- .../login/wxwork/callback/page.tsx | 4 ++-- dashboard/app/favicon.ico | Bin 25931 -> 17548 bytes dashboard/app/page.tsx | 2 +- dashboard/components/auth-provider.tsx | 9 +++++---- docs | 2 +- internal/controllers/api/auth_controller.go | 2 +- 8 files changed, 22 insertions(+), 15 deletions(-) rename dashboard/app/{ => dashboard}/login/page.tsx (94%) rename dashboard/app/{ => dashboard}/login/wxwork/callback/page.tsx (95%) diff --git a/dashboard/app/dashboard/layout.tsx b/dashboard/app/dashboard/layout.tsx index 7b15445..d2ce9a4 100644 --- a/dashboard/app/dashboard/layout.tsx +++ b/dashboard/app/dashboard/layout.tsx @@ -1,7 +1,7 @@ "use client" import { Loader2Icon } from "lucide-react" -import { useRouter } from "next/navigation" +import { usePathname, useRouter } from "next/navigation" import type { CSSProperties, ReactNode } from "react" import { useEffect } from "react" @@ -16,13 +16,19 @@ export default function DashboardLayout({ children: ReactNode }) { const { ready, session } = useAuth() + const pathname = usePathname() const router = useRouter() + const isLoginRoute = pathname?.startsWith("/dashboard/login") ?? false useEffect(() => { - if (ready && !session) { - router.replace("/login") + if (ready && !session && !isLoginRoute) { + router.replace("/dashboard/login") } - }, [ready, router, session]) + }, [isLoginRoute, ready, router, session]) + + if (isLoginRoute) { + return <>{children} + } if (!ready || !session) { return ( diff --git a/dashboard/app/login/page.tsx b/dashboard/app/dashboard/login/page.tsx similarity index 94% rename from dashboard/app/login/page.tsx rename to dashboard/app/dashboard/login/page.tsx index bcf63ef..d9e56a7 100644 --- a/dashboard/app/login/page.tsx +++ b/dashboard/app/dashboard/login/page.tsx @@ -1,5 +1,5 @@ import { LoginForm } from "@/components/login-form" -import { BotMessageSquareIcon, ShieldCheckIcon, UsersIcon, KeyRoundIcon } from "lucide-react" +import { BotMessageSquareIcon, ShieldCheckIcon } from "lucide-react" import Link from "next/link" import { Suspense } from "react" @@ -47,7 +47,7 @@ export default function LoginPage() {
- +
diff --git a/dashboard/app/login/wxwork/callback/page.tsx b/dashboard/app/dashboard/login/wxwork/callback/page.tsx similarity index 95% rename from dashboard/app/login/wxwork/callback/page.tsx rename to dashboard/app/dashboard/login/wxwork/callback/page.tsx index 7a74be7..1f6cc61 100644 --- a/dashboard/app/login/wxwork/callback/page.tsx +++ b/dashboard/app/dashboard/login/wxwork/callback/page.tsx @@ -31,7 +31,7 @@ function WxWorkLoginCallbackContent() { if (!ticket) { toast.error("企业微信登录票据不存在") - router.replace("/login") + router.replace("/dashboard/login") return } @@ -42,7 +42,7 @@ function WxWorkLoginCallbackContent() { }) .catch((error) => { toast.error(error instanceof Error ? error.message : "企业微信登录失败") - router.replace("/login") + router.replace("/dashboard/login") }) }, [router, searchParams]) diff --git a/dashboard/app/favicon.ico b/dashboard/app/favicon.ico index 718d6fea4835ec2d246af9800eddb7ffb276240c..432e26d980b0241556ecd451077f6dcbabea89b6 100644 GIT binary patch literal 17548 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 LrJugUA?W`A8`#=m diff --git a/dashboard/app/page.tsx b/dashboard/app/page.tsx index ab0660d..f45a1dd 100644 --- a/dashboard/app/page.tsx +++ b/dashboard/app/page.tsx @@ -15,7 +15,7 @@ export default function HomePage() { 进入控制台 - + 登录后台
diff --git a/dashboard/components/auth-provider.tsx b/dashboard/components/auth-provider.tsx index 43591d6..aaa0f43 100644 --- a/dashboard/components/auth-provider.tsx +++ b/dashboard/components/auth-provider.tsx @@ -33,7 +33,8 @@ export function AuthProvider({ children }: { children: ReactNode }) { const router = useRouter() const [session, setSession] = useState(null) const [ready, setReady] = useState(false) - const requiresAuth = pathname?.startsWith("/dashboard") ?? false + const isDashboardLoginRoute = pathname?.startsWith("/dashboard/login") ?? false + const requiresAuth = (pathname?.startsWith("/dashboard") ?? false) && !isDashboardLoginRoute const refreshProfile = useCallback(async () => { const stored = readSession() @@ -58,7 +59,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { setSession(null) if (requiresAuth) { startTransition(() => { - router.replace("/login") + router.replace("/dashboard/login") }) } } finally { @@ -71,7 +72,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { await logout(current?.refreshToken) setSession(null) startTransition(() => { - router.replace("/login") + router.replace("/dashboard/login") }) } @@ -86,7 +87,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { setReady(true) if (requiresAuth) { startTransition(() => { - router.replace("/login") + router.replace("/dashboard/login") }) } }, [requiresAuth, refreshProfile, router]) diff --git a/docs b/docs index 688d3b0..2c06261 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 688d3b061856055a2e19da8ec6733155eb13fb64 +Subproject commit 2c062610c432b096b2ae984fda45923ca7de04ce diff --git a/internal/controllers/api/auth_controller.go b/internal/controllers/api/auth_controller.go index 84af987..5166aac 100644 --- a/internal/controllers/api/auth_controller.go +++ b/internal/controllers/api/auth_controller.go @@ -75,7 +75,7 @@ func (c *AuthController) GetWxwork_callback() { c.redirectWxWorkError(err.Error()) return } - c.Ctx.Redirect("/login/wxwork/callback?ticket="+url.QueryEscape(ticket)+"&next="+url.QueryEscape(next), iris.StatusFound) + c.Ctx.Redirect("/dashboard/login/wxwork/callback?ticket="+url.QueryEscape(ticket)+"&next="+url.QueryEscape(next), iris.StatusFound) } func (c *AuthController) PostWxwork_exchange() *web.JsonResult {