Openstatus www.openstatus.dev

fix: middleware redirect (#513)

authored by

Maximilian Kaske and committed by
GitHub
4e25fce3 a2bdd705

+49 -87
+3 -1
apps/web/src/app/app/[workspaceSlug]/onboarding/page.tsx
··· 35 35 const { id: monitorId } = search.data; 36 36 37 37 const allMonitors = await api.monitor.getMonitorsByWorkspace.query(); 38 + const allNotifications = 39 + await api.notification.getNotificationsByWorkspace.query(); 38 40 39 41 if (!monitorId) { 40 42 return ( ··· 50 52 /> 51 53 <div className="grid h-full w-full gap-6 md:grid-cols-3 md:gap-8"> 52 54 <div className="md:col-span-2"> 53 - <MonitorForm /> 55 + <MonitorForm notifications={allNotifications} /> 54 56 </div> 55 57 <div className="hidden h-full md:col-span-1 md:block"> 56 58 <Description step="monitor" />
+46 -86
apps/web/src/middleware.ts
··· 92 92 return redirectToSignIn({ returnBackUrl: req.url }); 93 93 } 94 94 95 - // redirect them to organization selection page 96 - if ( 97 - auth.userId && 98 - (req.nextUrl.pathname === "/app" || req.nextUrl.pathname === "/app/") 99 - ) { 100 - console.log('>>> Redirecting to "/app/workspace"'); 101 - // improve on sign-up if the webhook has not been triggered yet 102 - const userQuery = db 103 - .select() 104 - .from(user) 105 - .where(eq(user.tenantId, auth.userId)) 106 - .as("userQuery"); 107 - const result = await db 108 - .select() 109 - .from(usersToWorkspaces) 110 - .innerJoin(userQuery, eq(userQuery.id, usersToWorkspaces.userId)) 111 - .all(); 112 - if (result.length > 0) { 113 - console.log(">>> User has workspace"); 114 - const currentWorkspace = await db 115 - .select() 116 - .from(workspace) 117 - .where(eq(workspace.id, result[0].users_to_workspaces.workspaceId)) 118 - .get(); 119 - if (currentWorkspace) { 120 - const firstMonitor = await db 121 - .select() 122 - .from(monitor) 123 - .where(eq(monitor.workspaceId, currentWorkspace.id)) 124 - .get(); 95 + if (auth.userId) { 96 + const pathname = req.nextUrl.pathname; 97 + if (pathname.startsWith("/app") && !pathname.startsWith("/app/invite")) { 98 + const workspaceSlug = req.nextUrl.pathname.split("/")?.[2]; 99 + const hasWorkspaceSlug = !!workspaceSlug && workspaceSlug.trim() !== ""; 125 100 126 - if (!firstMonitor) { 127 - console.log(`>>> Redirecting to onboarding`); 128 - const onboarding = new URL( 129 - `/app/${currentWorkspace.slug}/onboarding`, 130 - req.url, 131 - ); 132 - return NextResponse.redirect(onboarding); 133 - } 101 + const allowedWorkspaces = await db 102 + .select() 103 + .from(usersToWorkspaces) 104 + .innerJoin(user, eq(user.id, usersToWorkspaces.userId)) 105 + .innerJoin(workspace, eq(workspace.id, usersToWorkspaces.workspaceId)) 106 + .where(eq(user.tenantId, auth.userId)) 107 + .all(); 134 108 135 - const orgSelection = new URL( 136 - `/app/${currentWorkspace.slug}/monitors`, 137 - req.url, 109 + // means, we are "not only on `/app` or `/app/`" 110 + if (hasWorkspaceSlug) { 111 + console.log(">>> Workspace slug", workspaceSlug); 112 + const hasAccessToWorkspace = allowedWorkspaces.find( 113 + ({ workspace }) => workspace.slug === workspaceSlug, 138 114 ); 139 - console.log(`>>> Redirecting to ${orgSelection}`); 140 - return NextResponse.redirect(orgSelection); 141 - } 142 - } else { 143 - console.log("redirecting to onboarding"); 144 - // return NextResponse.redirect(new URL("/app/onboarding", req.url)); 145 - // probably redirect to onboarding 146 - // or find a way to wait for the webhook 147 - } 148 - console.log("redirecting to onboarding"); 149 - return; 150 - } 115 + if (hasAccessToWorkspace) { 116 + console.log(">>> Allowed! Attaching to cookie", workspaceSlug); 117 + req.cookies.set("workspace-slug", workspaceSlug); 118 + } else { 119 + console.log(">>> Not allowed, redirecting to /app", workspaceSlug); 120 + const appURL = new URL("/app", req.url); 121 + return NextResponse.redirect(appURL); 122 + } 123 + } else { 124 + console.log(">>> No workspace slug available"); 125 + if (allowedWorkspaces.length > 0) { 126 + const firstWorkspace = allowedWorkspaces[0].workspace; 127 + const { id, slug } = firstWorkspace; 128 + console.log(">>> Redirecting to first related workspace", slug); 129 + const firstMonitor = await db 130 + .select() 131 + .from(monitor) 132 + .where(eq(monitor.workspaceId, firstWorkspace.id)) 133 + .get(); 151 134 152 - if (auth.userId && req.nextUrl.pathname.startsWith("/app")) { 153 - const workspaceSlug = req.nextUrl.pathname.split("/")?.[2]; 154 - // overrides the document.cookie set on the client 155 - if (workspaceSlug) req.cookies.set("workspace-slug", workspaceSlug); 156 - } 135 + if (!firstMonitor) { 136 + console.log(`>>> Redirecting to onboarding`, slug); 137 + const onboardingURL = new URL(`/app/${slug}/onboarding`, req.url); 138 + return NextResponse.redirect(onboardingURL); 139 + } 157 140 158 - // TODO: remove 159 - if ( 160 - auth.userId && 161 - req.nextUrl.pathname === "/app/integrations/vercel/configure" 162 - ) { 163 - const userQuery = db 164 - .select() 165 - .from(user) 166 - .where(eq(user.tenantId, auth.userId)) 167 - .as("userQuery"); 168 - const result = await db 169 - .select() 170 - .from(usersToWorkspaces) 171 - .innerJoin(userQuery, eq(userQuery.id, usersToWorkspaces.userId)) 172 - .all(); 173 - if (result.length > 0) { 174 - const currentWorkspace = await db 175 - .select() 176 - .from(workspace) 177 - .where(eq(workspace.id, result[0].users_to_workspaces.workspaceId)) 178 - .get(); 179 - if (currentWorkspace) { 180 - const configure = new URL( 181 - `/app/${currentWorkspace.slug}/integrations/vercel/configure`, 182 - req.url, 183 - ); 184 - return NextResponse.redirect(configure); 141 + console.log(">>> Redirecting to workspace", slug); 142 + const monitorURL = new URL(`/app/${slug}/monitors`, req.url); 143 + return NextResponse.redirect(monitorURL); 144 + } 145 + console.log(">>> No action taken"); 185 146 } 186 147 } 187 148 } ··· 192 153 matcher: [ 193 154 "/((?!api|assets|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", 194 155 "/", 195 - "/app/integrations/vercel/configure", 196 156 "/(api/webhook|api/trpc)(.*)", 197 157 "/(!api/checker/:path*|!api/og|!api/ping)", 198 158 "/api/analytics", // used for tracking vercel beta integration click events