From b66c3f3452024b6576dd437474b8d00e20773a2d Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Tue, 14 Nov 2023 03:20:54 +0530 Subject: [PATCH] fix: Org: Any team URL with slug starting with `d` is 404 (#12302) --- apps/web/pagesAndRewritePaths.js | 35 ++++++++++++++++++--------- apps/web/test/lib/next-config.test.ts | 32 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/apps/web/pagesAndRewritePaths.js b/apps/web/pagesAndRewritePaths.js index 784e638e63..96f8b48083 100644 --- a/apps/web/pagesAndRewritePaths.js +++ b/apps/web/pagesAndRewritePaths.js @@ -11,10 +11,6 @@ let pages = (exports.pages = glob ) .filter((v, i, self) => self.indexOf(v) === i && !v.startsWith("[user]"))); -// Following routes don't exist but they work by doing rewrite. Thus they need to be excluded from matching the orgRewrite patterns -// Make sure to keep it upto date as more nonExistingRouteRewrites are added. -const otherNonExistingRoutePrefixes = ["forms", "router", "success", "cancel"]; - // .* matches / as well(Note: *(i.e wildcard) doesn't match / but .*(i.e. RegExp) does) // It would match /free/30min but not /bookings/upcoming because 'bookings' is an item in pages // It would also not match /free/30min/embed because we are ensuring just two slashes @@ -27,11 +23,26 @@ let subdomainRegExp = (exports.subdomainRegExp = getSubdomainRegExp( )); exports.orgHostPath = `^(?${subdomainRegExp})\\.(?!vercel\.app).*`; -let beforeRewriteExcludePages = pages.concat(otherNonExistingRoutePrefixes); -exports.orgUserRoutePath = `/:user((?!${beforeRewriteExcludePages.join("|")}|_next|public)[a-zA-Z0-9\-_]+)`; -exports.orgUserTypeRoutePath = `/:user((?!${beforeRewriteExcludePages.join( - "/|" -)}|_next/|public/)[^/]+)/:type((?!avatar\.png)[^/]+)`; -exports.orgUserTypeEmbedRoutePath = `/:user((?!${beforeRewriteExcludePages.join( - "/|" -)}|_next/|public/)[^/]+)/:type/embed`; +/** + * Returns a regex that matches all existing routes, virtual routes (like /forms, /router, /success etc) and nextjs special paths (_next, public) + */ +function getRegExpMatchingAllReservedRoutes(suffix) { + // Following routes don't exist but they work by doing rewrite. Thus they need to be excluded from matching the orgRewrite patterns + // Make sure to keep it upto date as more nonExistingRouteRewrites are added. + const otherNonExistingRoutePrefixes = ["forms", "router", "success", "cancel"]; + const nextJsSpecialPaths = ["_next", "public"]; + + let beforeRewriteExcludePages = pages.concat(otherNonExistingRoutePrefixes).concat(nextJsSpecialPaths); + return beforeRewriteExcludePages.join(`${suffix}|`) + suffix; +} + +// To handle /something +exports.orgUserRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/?$")})[a-zA-Z0-9\-_]+)`; + +// To handle /something/somethingelse +exports.orgUserTypeRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes( + "/" +)})[^/]+)/:type((?!avatar\.png)[^/]+)`; + +// To handle /something/somethingelse/embed +exports.orgUserTypeEmbedRoutePath = `/:user((?!${getRegExpMatchingAllReservedRoutes("/")})[^/]+)/:type/embed`; diff --git a/apps/web/test/lib/next-config.test.ts b/apps/web/test/lib/next-config.test.ts index 8c70bb66d0..dbcd93faaf 100644 --- a/apps/web/test/lib/next-config.test.ts +++ b/apps/web/test/lib/next-config.test.ts @@ -99,15 +99,47 @@ describe("next.config.js - Org Rewrite", () => { expect(orgUserRouteMatch("/abc")?.params).toContain({ user: "abc", }); + + // Tests that something that starts with 'd' which could accidentally match /d route is correctly identified as a booking page + expect(orgUserRouteMatch("/designer")?.params).toContain({ + user: "designer", + }); + + // Tests that something that starts with 'apps' which could accidentally match /apps route is correctly identified as a booking page + expect(orgUserRouteMatch("/apps-conflict-possibility")?.params).toContain({ + user: "apps-conflict-possibility", + }); + + // Tests that something that starts with '_next' which could accidentally match /_next route is correctly identified as a booking page + expect(orgUserRouteMatch("/_next-candidate")?.params).toContain({ + user: "_next-candidate", + }); + + // Tests that something that starts with 'public' which could accidentally match /public route is correctly identified as a booking page + expect(orgUserRouteMatch("/public-person")?.params).toContain({ + user: "public-person", + }); }); it("Non booking pages", () => { expect(orgUserTypeRouteMatch("/_next/def")).toEqual(false); expect(orgUserTypeRouteMatch("/public/def")).toEqual(false); + expect(orgUserRouteMatch("/_next/")).toEqual(false); expect(orgUserRouteMatch("/public/")).toEqual(false); + + expect(orgUserRouteMatch("/event-types/")).toEqual(false); + expect(orgUserTypeRouteMatch("/event-types/")).toEqual(false); + + expect(orgUserRouteMatch("/event-types/?abc=1")).toEqual(false); + expect(orgUserTypeRouteMatch("/event-types/?abc=1")).toEqual(false); + expect(orgUserRouteMatch("/event-types")).toEqual(false); expect(orgUserTypeRouteMatch("/event-types")).toEqual(false); + + expect(orgUserRouteMatch("/event-types?abc=1")).toEqual(false); + expect(orgUserTypeRouteMatch("/event-types?abc=1")).toEqual(false); + expect(orgUserTypeRouteMatch("/john/avatar.png")).toEqual(false); expect(orgUserTypeRouteMatch("/cancel/abcd")).toEqual(false); expect(orgUserTypeRouteMatch("/success/abcd")).toEqual(false);