mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
refactor(ui): remove backward-compat redirect for legacy invitation links (#10797)
Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
8d48c26c1e
commit
390bbdd1a6
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
All notable changes to the **Prowler UI** are documented in this file.
|
All notable changes to the **Prowler UI** are documented in this file.
|
||||||
|
|
||||||
|
## [1.25.0] (Prowler UNRELEASED)
|
||||||
|
|
||||||
|
### ❌ Removed
|
||||||
|
|
||||||
|
- Backward-compatibility middleware redirect from `/sign-up?invitation_token=…` to `/invitation/accept?invitation_token=…`; new invitation emails use `/invitation/accept` directly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.24.1] (Prowler v5.24.1)
|
## [1.24.1] (Prowler v5.24.1)
|
||||||
|
|
||||||
### 🐞 Fixed
|
### 🐞 Fixed
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
|
|
||||||
import { acceptInvitation } from "@/actions/invitations";
|
import { acceptInvitation } from "@/actions/invitations";
|
||||||
import { Button } from "@/components/shadcn";
|
import { Button } from "@/components/shadcn";
|
||||||
import {
|
|
||||||
INVITATION_ACTION_PARAM,
|
|
||||||
INVITATION_SIGNUP_ACTION,
|
|
||||||
} from "@/lib/invitation-routing";
|
|
||||||
|
|
||||||
type AcceptState =
|
type AcceptState =
|
||||||
| { kind: "no-token" }
|
| { kind: "no-token" }
|
||||||
@@ -204,7 +200,7 @@ export function AcceptInvitationClient({
|
|||||||
className="w-full"
|
className="w-full"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/sign-up?invitation_token=${encodeURIComponent(token!)}&${INVITATION_ACTION_PARAM}=${INVITATION_SIGNUP_ACTION}`,
|
`/sign-up?invitation_token=${encodeURIComponent(token!)}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
* Query param name + value used to bypass the backward-compat redirect
|
|
||||||
* in proxy.ts when the user explicitly chose "Create an account"
|
|
||||||
* from the invitation smart router.
|
|
||||||
*
|
|
||||||
* Client sends: /sign-up?invitation_token=…&action=signup
|
|
||||||
* Proxy skips redirect when "action" param is present.
|
|
||||||
*/
|
|
||||||
export const INVITATION_ACTION_PARAM = "action";
|
|
||||||
export const INVITATION_SIGNUP_ACTION = "signup";
|
|
||||||
+3
-18
@@ -1,7 +1,7 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
import type { NextAuthRequest } from "next-auth";
|
||||||
|
|
||||||
import { auth } from "@/auth.config";
|
import { auth } from "@/auth.config";
|
||||||
import { INVITATION_ACTION_PARAM } from "@/lib/invitation-routing";
|
|
||||||
|
|
||||||
const publicRoutes = [
|
const publicRoutes = [
|
||||||
"/sign-in",
|
"/sign-in",
|
||||||
@@ -18,24 +18,9 @@ const isPublicRoute = (pathname: string): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// NextAuth's auth() wrapper - renamed from middleware to proxy
|
// NextAuth's auth() wrapper - renamed from middleware to proxy
|
||||||
export default auth((req: NextRequest & { auth: any }) => {
|
export default auth((req: NextAuthRequest) => {
|
||||||
const { pathname } = req.nextUrl;
|
const { pathname } = req.nextUrl;
|
||||||
|
|
||||||
// Backward compatibility: redirect old invitation links to new smart router
|
|
||||||
// Skip redirect when the user explicitly chose "Create an account" from the smart router
|
|
||||||
if (
|
|
||||||
pathname === "/sign-up" &&
|
|
||||||
req.nextUrl.searchParams.has("invitation_token") &&
|
|
||||||
!req.nextUrl.searchParams.has(INVITATION_ACTION_PARAM)
|
|
||||||
) {
|
|
||||||
const acceptUrl = new URL("/invitation/accept", req.url);
|
|
||||||
acceptUrl.searchParams.set(
|
|
||||||
"invitation_token",
|
|
||||||
req.nextUrl.searchParams.get("invitation_token")!,
|
|
||||||
);
|
|
||||||
return NextResponse.redirect(acceptUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = req.auth?.user;
|
const user = req.auth?.user;
|
||||||
const sessionError = req.auth?.error;
|
const sessionError = req.auth?.error;
|
||||||
|
|
||||||
|
|||||||
@@ -76,4 +76,28 @@ test.describe("Middleware Error Handling", () => {
|
|||||||
|
|
||||||
// Note: Billing and integrations permission tests removed
|
// Note: Billing and integrations permission tests removed
|
||||||
// These features only exist in Prowler Cloud, not in the open-source version
|
// These features only exist in Prowler Cloud, not in the open-source version
|
||||||
|
|
||||||
|
test(
|
||||||
|
"should not redirect /sign-up?invitation_token=... to /invitation/accept",
|
||||||
|
{ tag: ["@e2e", "@auth", "@middleware", "@AUTH-MW-E2E-003"] },
|
||||||
|
async ({ page, context }) => {
|
||||||
|
const signUpPage = new SignUpPage(page);
|
||||||
|
await context.clearCookies();
|
||||||
|
|
||||||
|
const token = "test-token-regression";
|
||||||
|
const response = await page.goto(
|
||||||
|
`/sign-up?invitation_token=${token}`,
|
||||||
|
{ waitUntil: "commit" },
|
||||||
|
);
|
||||||
|
|
||||||
|
// The middleware must not rewrite the URL any more. Assert the final
|
||||||
|
// URL stayed on /sign-up with the token intact, and that the sign-up
|
||||||
|
// form actually rendered (guards against "URL stayed but page broke").
|
||||||
|
expect(response?.status()).toBe(200);
|
||||||
|
await expect(page).toHaveURL(
|
||||||
|
`/sign-up?invitation_token=${token}`,
|
||||||
|
);
|
||||||
|
await signUpPage.verifyPageLoaded();
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ export class SignUpPage extends BasePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async verifyPageLoaded(): Promise<void> {
|
async verifyPageLoaded(): Promise<void> {
|
||||||
await expect(this.page).toHaveURL("/sign-up");
|
|
||||||
await expect(this.emailInput).toBeVisible();
|
await expect(this.emailInput).toBeVisible();
|
||||||
await expect(this.submitButton).toBeVisible();
|
await expect(this.submitButton).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user