fix(frontend): login/signup pages away redirects (#11430)

## Changes 🏗️

When the user is logged in and tries to navigate to `/login` or
`/signup` manually, redirect them away to `/marketplace`.

### Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  - [x] Login
  - [x] Go to `/login` or `/signup`
  - [x] You are redirected back into `/marketplace`
This commit is contained in:
Ubbe
2025-11-25 15:47:29 +07:00
committed by GitHub
parent 126d5838a0
commit 1ab66eaed4
3 changed files with 61 additions and 8 deletions

View File

@@ -4,21 +4,28 @@ import { environment } from "@/services/environment";
import { loginFormSchema, LoginProvider } from "@/types/auth";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import z from "zod";
import { login as loginAction } from "./actions";
export function useLoginPage() {
const { supabase, user, isUserLoading } = useSupabase();
const { supabase, user, isUserLoading, isLoggedIn } = useSupabase();
const [feedback, setFeedback] = useState<string | null>(null);
const router = useRouter();
const { toast } = useToast();
const [isLoading, setIsLoading] = useState(false);
const [isLoggingIn, setIsLoggingIn] = useState(false);
const [isGoogleLoading, setIsGoogleLoading] = useState(false);
const [showNotAllowedModal, setShowNotAllowedModal] = useState(false);
const isCloudEnv = environment.isCloud();
useEffect(() => {
if (isLoggedIn && !isLoggingIn) {
router.push("/marketplace");
}
}, [isLoggedIn, isLoggingIn]);
const form = useForm<z.infer<typeof loginFormSchema>>({
resolver: zodResolver(loginFormSchema),
defaultValues: {
@@ -29,6 +36,7 @@ export function useLoginPage() {
async function handleProviderLogin(provider: LoginProvider) {
setIsGoogleLoading(true);
setIsLoggingIn(true);
try {
const response = await fetch("/api/auth/provider", {
@@ -46,6 +54,7 @@ export function useLoginPage() {
if (url) window.location.href = url as string;
} catch (error) {
setIsGoogleLoading(false);
setIsLoggingIn(false);
setFeedback(
error instanceof Error ? error.message : "Failed to start OAuth flow",
);
@@ -53,8 +62,6 @@ export function useLoginPage() {
}
async function handleLogin(data: z.infer<typeof loginFormSchema>) {
setIsLoading(true);
if (data.email.includes("@agpt.co")) {
toast({
title: "Please use Google SSO to login using an AutoGPT email.",
@@ -62,9 +69,12 @@ export function useLoginPage() {
});
setIsLoading(false);
setIsLoggingIn(false);
return;
}
setIsLoggingIn(true);
try {
const result = await loginAction(data.email, data.password);
@@ -86,6 +96,7 @@ export function useLoginPage() {
variant: "destructive",
});
setIsLoading(false);
setIsLoggingIn(false);
}
}

View File

@@ -4,21 +4,28 @@ import { environment } from "@/services/environment";
import { LoginProvider, signupFormSchema } from "@/types/auth";
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import z from "zod";
import { signup as signupAction } from "./actions";
export function useSignupPage() {
const { supabase, user, isUserLoading } = useSupabase();
const { supabase, user, isUserLoading, isLoggedIn } = useSupabase();
const [feedback, setFeedback] = useState<string | null>(null);
const { toast } = useToast();
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const [isSigningUp, setIsSigningUp] = useState(false);
const [isGoogleLoading, setIsGoogleLoading] = useState(false);
const [showNotAllowedModal, setShowNotAllowedModal] = useState(false);
const isCloudEnv = environment.isCloud();
useEffect(() => {
if (isLoggedIn && !isSigningUp) {
router.push("/marketplace");
}
}, [isLoggedIn, isSigningUp]);
const form = useForm<z.infer<typeof signupFormSchema>>({
resolver: zodResolver(signupFormSchema),
defaultValues: {
@@ -31,6 +38,7 @@ export function useSignupPage() {
async function handleProviderSignup(provider: LoginProvider) {
setIsGoogleLoading(true);
setIsSigningUp(true);
try {
const response = await fetch("/api/auth/provider", {
@@ -44,6 +52,7 @@ export function useSignupPage() {
if (error === "not_allowed") {
setShowNotAllowedModal(true);
setIsSigningUp(false);
return;
}
@@ -54,6 +63,7 @@ export function useSignupPage() {
if (url) window.location.href = url as string;
} catch (error) {
setIsGoogleLoading(false);
setIsSigningUp(false);
toast({
title:
error instanceof Error ? error.message : "Failed to start OAuth flow",
@@ -76,6 +86,8 @@ export function useSignupPage() {
return;
}
setIsSigningUp(true);
try {
const result = await signupAction(
data.email,
@@ -89,10 +101,12 @@ export function useSignupPage() {
if (!result.success) {
if (result.error === "user_already_exists") {
setFeedback("User with this email already exists");
setIsSigningUp(false);
return;
}
if (result.error === "not_allowed") {
setShowNotAllowedModal(true);
setIsSigningUp(false);
return;
}
@@ -100,6 +114,7 @@ export function useSignupPage() {
title: result.error || "Signup failed",
variant: "destructive",
});
setIsSigningUp(false);
return;
}
@@ -107,6 +122,7 @@ export function useSignupPage() {
if (next) router.replace(next);
} catch (error) {
setIsLoading(false);
setIsSigningUp(false);
toast({
title:
error instanceof Error

View File

@@ -1,11 +1,11 @@
// auth.spec.ts
import test from "@playwright/test";
import { getTestUser } from "./utils/auth";
import { BuildPage } from "./pages/build.page";
import { LoginPage } from "./pages/login.page";
import { hasUrl, isHidden, isVisible } from "./utils/assertion";
import { getTestUser } from "./utils/auth";
import { getSelectors } from "./utils/selectors";
import { BuildPage } from "./pages/build.page";
test.beforeEach(async ({ page }) => {
await page.goto("/login");
@@ -171,3 +171,29 @@ test("multi-tab logout with WebSocket cleanup", async ({ context }) => {
await page1.close();
await page2.close();
});
test("logged in user is redirected from /login to /marketplace", async ({
page,
}) => {
const testUser = await getTestUser();
const loginPage = new LoginPage(page);
await loginPage.login(testUser.email, testUser.password);
await hasUrl(page, "/marketplace");
await page.goto("/login");
await hasUrl(page, "/marketplace");
});
test("logged in user is redirected from /signup to /marketplace", async ({
page,
}) => {
const testUser = await getTestUser();
const loginPage = new LoginPage(page);
await loginPage.login(testUser.email, testUser.password);
await hasUrl(page, "/marketplace");
await page.goto("/signup");
await hasUrl(page, "/marketplace");
});