Fix no redirect to dashboard if user is already logged in and lands on login page (#4561)
Did not go the middleware route here because even if we properly check the logged in status in middleware and redirect - it's possible for user to get stuck in that case if for some reason the wallet never gets into "connecting" status and so the useLoggedInUser query never runs and never redirects the user to login page ( and even if it did - they would immediately get redirected to other page because they have a "valid" auth cookie )
so safest solution here is to let the user land on login page and once then redirect from there after wallet connection + sign in is done
<!-- start pr-codex -->
---
## PR-Codex overview
The focus of this PR is to refactor the login process in the dashboard app.
### Detailed summary
- Removed unused imports and functions
- Refactored `doLogin` function to handle redirect logic internally
- Added `useDashboardRouter` hook to handle navigation
- Improved error handling and redirect logic in the login process
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -3,7 +3,6 @@ import "server-only";
|
||||
|
||||
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
|
||||
import { cookies } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getAddress } from "thirdweb";
|
||||
import type {
|
||||
GenerateLoginPayloadParams,
|
||||
@@ -34,10 +33,7 @@ export async function getLoginPayload(
|
||||
return (await res.json()).payload;
|
||||
}
|
||||
|
||||
export async function doLogin(
|
||||
payload: VerifyLoginPayloadParams,
|
||||
nextPath?: string | null,
|
||||
) {
|
||||
export async function doLogin(payload: VerifyLoginPayloadParams) {
|
||||
// forward the request to the API server
|
||||
const res = await fetch(`${THIRDWEB_API_HOST}/v1/auth/login`, {
|
||||
method: "POST",
|
||||
@@ -126,25 +122,6 @@ export async function doLogin(
|
||||
// 3 days
|
||||
maxAge: 3 * 24 * 60 * 60,
|
||||
});
|
||||
|
||||
// redirect to the nextPath (if set)
|
||||
if (nextPath && isValidRedirectPath(nextPath)) {
|
||||
return redirect(nextPath);
|
||||
}
|
||||
// if we do not have a next path, redirect to dashboard home
|
||||
return redirect("/dashboard");
|
||||
}
|
||||
function isValidRedirectPath(encodedPath: string): boolean {
|
||||
try {
|
||||
// Decode the URI component
|
||||
const decodedPath = decodeURIComponent(encodedPath);
|
||||
// ensure the path always starts with a _single_ slash
|
||||
// dobule slash could be interpreted as `//example.com` which is not allowed
|
||||
return decodedPath.startsWith("/") && !decodedPath.startsWith("//");
|
||||
} catch {
|
||||
// If decoding fails, return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function doLogout() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { ColorModeToggle } from "@/components/color-mode-toggle";
|
||||
import { thirdwebClient } from "@/constants/client";
|
||||
import { useDashboardRouter } from "@/lib/DashboardRouter";
|
||||
import { useTheme } from "next-themes";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
@@ -38,14 +39,39 @@ export default function LoginPage() {
|
||||
function CustomConnectEmmbed() {
|
||||
const isLG = useMediaQuery("(min-width: 1024px)");
|
||||
const searchParams = useSearchParams();
|
||||
const router = useDashboardRouter();
|
||||
const { theme } = useTheme();
|
||||
const nextSearchParam = searchParams?.get("next");
|
||||
|
||||
function onLoginSuccessful() {
|
||||
if (nextSearchParam && isValidRedirectPath(nextSearchParam)) {
|
||||
router.replace(nextSearchParam);
|
||||
} else {
|
||||
router.replace("/dashboard");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ConnectEmbed
|
||||
auth={{
|
||||
getLoginPayload,
|
||||
doLogin: (params) => doLogin(params, searchParams?.get("next")),
|
||||
doLogin: async (params) => {
|
||||
try {
|
||||
await doLogin(params);
|
||||
onLoginSuccessful();
|
||||
} catch (e) {
|
||||
console.error("Failed to login", e);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
doLogout,
|
||||
isLoggedIn,
|
||||
isLoggedIn: async (x) => {
|
||||
const isLoggedInResult = await isLoggedIn(x);
|
||||
if (isLoggedInResult) {
|
||||
onLoginSuccessful();
|
||||
}
|
||||
return isLoggedInResult;
|
||||
},
|
||||
}}
|
||||
client={thirdwebClient}
|
||||
modalSize={isLG ? "wide" : "compact"}
|
||||
@@ -54,6 +80,19 @@ function CustomConnectEmmbed() {
|
||||
);
|
||||
}
|
||||
|
||||
function isValidRedirectPath(encodedPath: string): boolean {
|
||||
try {
|
||||
// Decode the URI component
|
||||
const decodedPath = decodeURIComponent(encodedPath);
|
||||
// ensure the path always starts with a _single_ slash
|
||||
// dobule slash could be interpreted as `//example.com` which is not allowed
|
||||
return decodedPath.startsWith("/") && !decodedPath.startsWith("//");
|
||||
} catch {
|
||||
// If decoding fails, return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function useMediaQuery(query: string) {
|
||||
const [matches, setMatches] = useState(() => {
|
||||
if (typeof window === "undefined") return false;
|
||||
|
||||
Reference in New Issue
Block a user