diff --git a/frontend/src/routes/(root)/(logged)/user/(user)/onboarding/+page.svelte b/frontend/src/routes/(root)/(logged)/user/(user)/onboarding/+page.svelte index b2cbb1685f..0428e61fbb 100644 --- a/frontend/src/routes/(root)/(logged)/user/(user)/onboarding/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/user/(user)/onboarding/+page.svelte @@ -2,6 +2,7 @@ import { ArrowLeft } from 'lucide-svelte' import { UserService } from '$lib/gen/services.gen' import { goto } from '$lib/navigation' + import { page } from '$app/state' import CenteredModal from '$lib/components/CenteredModal.svelte' import { Button } from '$lib/components/common' import Popover from '$lib/components/meltComponents/Popover.svelte' @@ -16,7 +17,7 @@ Building2, Twitter, Youtube, - Bot, + Bot, MessageCircleCode } from 'lucide-svelte' import { sendUserToast } from '$lib/toast' @@ -96,10 +97,21 @@ sendUserToast('Failed to save information: ' + (error?.body || error?.message || error), true) } finally { // do not block users from accessing windmill even if there is an error - goto('/user/workspaces') + goto(onboardingDestination()) } } + /** + * Where to go once onboarding is done. `/user/workspaces` unless the sign-in carried a + * destination — a hub project import, say — in which case that is what the user came for. + * Same-origin relative paths only, so a crafted `?rd=` cannot bounce them off-site. + */ + function onboardingDestination(): string { + const rd = page.url.searchParams.get('rd') + if (rd && rd.startsWith('/') && !rd.startsWith('//')) return rd + return '/user/workspaces' + } + async function skip() { isSubmitting = true try { @@ -110,7 +122,7 @@ console.error('Error skipping onboarding:', error) } finally { // do not block users from accessing windmill even if there is an error - goto('/user/workspaces') + goto(onboardingDestination()) } } diff --git a/frontend/src/routes/user/login_callback/[client_name]/+page.svelte b/frontend/src/routes/user/login_callback/[client_name]/+page.svelte index 1aeb57f223..3d4a4adf7a 100644 --- a/frontend/src/routes/user/login_callback/[client_name]/+page.svelte +++ b/frontend/src/routes/user/login_callback/[client_name]/+page.svelte @@ -64,7 +64,10 @@ try { const globalUserInfo = await UserService.globalWhoami() if (globalUserInfo.first_time_user) { - goto('/user/onboarding') + // `rd` rides along: someone arriving from a shared hub project signs up with a + // destination already in hand, and dropping it here strands them in an empty + // workspace with no sign of what they came to import. + goto(`/user/onboarding${rd ? `?rd=${encodeURIComponent(rd)}` : ''}`) return } } catch (err) {