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:
MananTank
2024-09-12 18:37:42 +00:00
parent 2d2e6cb380
commit a24de21f00
2 changed files with 42 additions and 26 deletions
+1 -24
View File
@@ -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() {
+41 -2
View File
@@ -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;