mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
Auth flow fixes (#35)
This commit is contained in:
parent
9662d16669
commit
cfc93622f8
19 changed files with 258 additions and 97 deletions
|
|
@ -11,7 +11,7 @@ export default async function AuthenticatedLayout({
|
|||
const { orgId } = await auth();
|
||||
|
||||
if (!orgId) {
|
||||
redirect('/onboarding/select-org');
|
||||
redirect('/select-org');
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export const Org = () => {
|
|||
<OrganizationProfile
|
||||
routing="path"
|
||||
path="/org"
|
||||
afterLeaveOrganizationUrl="/onboarding/select-org"
|
||||
afterLeaveOrganizationUrl="/select-org"
|
||||
>
|
||||
<OrganizationProfile.Page
|
||||
label={t('provider_whitelist')}
|
||||
|
|
|
|||
36
src/app/(centered)/extension/sign-in/CursorLogo.tsx
Normal file
36
src/app/(centered)/extension/sign-in/CursorLogo.tsx
Normal file
File diff suppressed because one or more lines are too long
45
src/app/(centered)/extension/sign-in/DeepLink.tsx
Normal file
45
src/app/(centered)/extension/sign-in/DeepLink.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
import { Card, CardContent, CardFooter } from '@/components/ui';
|
||||
import { VSCodeLogo } from './VSCodeLogo';
|
||||
import { CursorLogo } from './CursorLogo';
|
||||
|
||||
interface DeepLinkProps {
|
||||
vsCodeUrl: string;
|
||||
cursorUrl: string;
|
||||
}
|
||||
|
||||
export const DeepLink = ({ vsCodeUrl, cursorUrl }: DeepLinkProps) => {
|
||||
const [redirectAttempted, setRedirectAttempted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
window.location.href = vsCodeUrl;
|
||||
const timer = setTimeout(() => setRedirectAttempted(true), 2000);
|
||||
return () => clearTimeout(timer);
|
||||
}, [vsCodeUrl]);
|
||||
|
||||
return (
|
||||
<Card className="max-w-md mx-auto">
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div>You've successfully authenticated.</div>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<div>Open in your IDE:</div>
|
||||
<Link href={vsCodeUrl}>
|
||||
<VSCodeLogo />
|
||||
</Link>
|
||||
<Link href={cursorUrl}>
|
||||
<CursorLogo />
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="text-sm text-muted-foreground">
|
||||
{redirectAttempted
|
||||
? 'You can close this window after your IDE opens.'
|
||||
: 'Redirecting automatically...'}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
140
src/app/(centered)/extension/sign-in/VSCodeLogo.tsx
Normal file
140
src/app/(centered)/extension/sign-in/VSCodeLogo.tsx
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
import type { SVGProps } from 'react';
|
||||
|
||||
type VSCodeLogoProps = SVGProps<SVGSVGElement>;
|
||||
|
||||
export const VSCodeLogo = ({
|
||||
width = '36',
|
||||
height = '36',
|
||||
...props
|
||||
}: VSCodeLogoProps) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 100 100"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<mask
|
||||
id="mask0"
|
||||
type="alpha"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100"
|
||||
height="100"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M70.9119 99.3171C72.4869 99.9307 74.2828 99.8914 75.8725 99.1264L96.4608 89.2197C98.6242 88.1787 100 85.9892 100 83.5872V16.4133C100 14.0113 98.6243 11.8218 96.4609 10.7808L75.8725 0.873756C73.7862 -0.130129 71.3446 0.11576 69.5135 1.44695C69.252 1.63711 69.0028 1.84943 68.769 2.08341L29.3551 38.0415L12.1872 25.0096C10.589 23.7965 8.35363 23.8959 6.86933 25.2461L1.36303 30.2549C-0.452552 31.9064 -0.454633 34.7627 1.35853 36.417L16.2471 50.0001L1.35853 63.5832C-0.454633 65.2374 -0.452552 68.0938 1.36303 69.7453L6.86933 74.7541C8.35363 76.1043 10.589 76.2037 12.1872 74.9905L29.3551 61.9587L68.769 97.9167C69.3925 98.5406 70.1246 99.0104 70.9119 99.3171ZM75.0152 27.2989L45.1091 50.0001L75.0152 72.7012V27.2989Z"
|
||||
fill="white"
|
||||
/>
|
||||
</mask>
|
||||
<g mask="url(#mask0)">
|
||||
<path
|
||||
d="M96.4614 10.7962L75.8569 0.875542C73.4719 -0.272773 70.6217 0.211611 68.75 2.08333L1.29858 63.5832C-0.515693 65.2373 -0.513607 68.0937 1.30308 69.7452L6.81272 74.754C8.29793 76.1042 10.5347 76.2036 12.1338 74.9905L93.3609 13.3699C96.086 11.3026 100 13.2462 100 16.6667V16.4275C100 14.0265 98.6246 11.8378 96.4614 10.7962Z"
|
||||
fill="#0065A9"
|
||||
/>
|
||||
<g filter="url(#filter0_d)">
|
||||
<path
|
||||
d="M96.4614 89.2038L75.8569 99.1245C73.4719 100.273 70.6217 99.7884 68.75 97.9167L1.29858 36.4169C-0.515693 34.7627 -0.513607 31.9063 1.30308 30.2548L6.81272 25.246C8.29793 23.8958 10.5347 23.7964 12.1338 25.0095L93.3609 86.6301C96.086 88.6974 100 86.7538 100 83.3334V83.5726C100 85.9735 98.6246 88.1622 96.4614 89.2038Z"
|
||||
fill="#007ACC"
|
||||
/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d)">
|
||||
<path
|
||||
d="M75.8578 99.1263C73.4721 100.274 70.6219 99.7885 68.75 97.9166C71.0564 100.223 75 98.5895 75 95.3278V4.67213C75 1.41039 71.0564 -0.223106 68.75 2.08329C70.6219 0.211402 73.4721 -0.273666 75.8578 0.873633L96.4587 10.7807C98.6234 11.8217 100 14.0112 100 16.4132V83.5871C100 85.9891 98.6234 88.1786 96.4586 89.2196L75.8578 99.1263Z"
|
||||
fill="#1F9CF0"
|
||||
/>
|
||||
</g>
|
||||
<g style={{ mixBlendMode: 'overlay' }} opacity="0.25">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M70.8511 99.3171C72.4261 99.9306 74.2221 99.8913 75.8117 99.1264L96.4 89.2197C98.5634 88.1787 99.9392 85.9892 99.9392 83.5871V16.4133C99.9392 14.0112 98.5635 11.8217 96.4001 10.7807L75.8117 0.873695C73.7255 -0.13019 71.2838 0.115699 69.4527 1.44688C69.1912 1.63705 68.942 1.84937 68.7082 2.08335L29.2943 38.0414L12.1264 25.0096C10.5283 23.7964 8.29285 23.8959 6.80855 25.246L1.30225 30.2548C-0.513334 31.9064 -0.515415 34.7627 1.29775 36.4169L16.1863 50L1.29775 63.5832C-0.515415 65.2374 -0.513334 68.0937 1.30225 69.7452L6.80855 74.754C8.29285 76.1042 10.5283 76.2036 12.1264 74.9905L29.2943 61.9586L68.7082 97.9167C69.3317 98.5405 70.0638 99.0104 70.8511 99.3171ZM74.9544 27.2989L45.0483 50L74.9544 72.7012V27.2989Z"
|
||||
fill="url(#paint0_linear)"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter
|
||||
id="filter0_d"
|
||||
x="-8.39411"
|
||||
y="15.8291"
|
||||
width="116.727"
|
||||
height="92.2456"
|
||||
filterUnits="userSpaceOnUse"
|
||||
colorInterpolationFilters="sRGB"
|
||||
>
|
||||
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix
|
||||
in="SourceAlpha"
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
/>
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="4.16667" />
|
||||
<feColorMatrix
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
/>
|
||||
<feBlend
|
||||
mode="overlay"
|
||||
in2="BackgroundImageFix"
|
||||
result="effect1_dropShadow"
|
||||
/>
|
||||
<feBlend
|
||||
mode="normal"
|
||||
in="SourceGraphic"
|
||||
in2="effect1_dropShadow"
|
||||
result="shape"
|
||||
/>
|
||||
</filter>
|
||||
<filter
|
||||
id="filter1_d"
|
||||
x="60.4167"
|
||||
y="-8.07558"
|
||||
width="47.9167"
|
||||
height="116.151"
|
||||
filterUnits="userSpaceOnUse"
|
||||
colorInterpolationFilters="sRGB"
|
||||
>
|
||||
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix
|
||||
in="SourceAlpha"
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
/>
|
||||
<feOffset />
|
||||
<feGaussianBlur stdDeviation="4.16667" />
|
||||
<feColorMatrix
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
|
||||
/>
|
||||
<feBlend
|
||||
mode="overlay"
|
||||
in2="BackgroundImageFix"
|
||||
result="effect1_dropShadow"
|
||||
/>
|
||||
<feBlend
|
||||
mode="normal"
|
||||
in="SourceGraphic"
|
||||
in2="effect1_dropShadow"
|
||||
result="shape"
|
||||
/>
|
||||
</filter>
|
||||
<linearGradient
|
||||
id="paint0_linear"
|
||||
x1="49.9392"
|
||||
y1="0.257812"
|
||||
x2="49.9392"
|
||||
y2="99.7423"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="white" />
|
||||
<stop offset="1" stopColor="white" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
|
|
@ -17,13 +17,17 @@ export default async function Page(props: Props) {
|
|||
redirect(`/sign-in`);
|
||||
}
|
||||
|
||||
const { userId } = await auth();
|
||||
const { userId, orgId } = await auth();
|
||||
const code = userId ? await getSignInToken(userId) : undefined;
|
||||
|
||||
if (!code) {
|
||||
redirect(`/sign-in?state=${state}`);
|
||||
}
|
||||
|
||||
if (!orgId) {
|
||||
redirect(`/select-org?state=${state}`);
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams({ state, code });
|
||||
const path = `/auth/clerk/callback?${searchParams.toString()}`;
|
||||
const vsCodeUrl = new URL(path, Env.VSCODE_EXTENSION_BASE_URL);
|
||||
22
src/app/(centered)/select-org/SelectOrg.tsx
Normal file
22
src/app/(centered)/select-org/SelectOrg.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { OrganizationList } from '@clerk/nextjs';
|
||||
|
||||
export const SelectOrg = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const afterSelectOrganizationUrl = useMemo(() => {
|
||||
const state = searchParams.get('state');
|
||||
return state ? `/extension/sign-in?state=${state}` : '/dashboard';
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<OrganizationList
|
||||
afterSelectOrganizationUrl={afterSelectOrganizationUrl}
|
||||
afterCreateOrganizationUrl={afterSelectOrganizationUrl}
|
||||
hidePersonal
|
||||
/>
|
||||
);
|
||||
};
|
||||
5
src/app/(centered)/select-org/page.tsx
Normal file
5
src/app/(centered)/select-org/page.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { SelectOrg } from './SelectOrg';
|
||||
|
||||
export default async function Page() {
|
||||
return <SelectOrg />;
|
||||
}
|
||||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import { SignIn as ClerkSignIn } from '@clerk/nextjs';
|
||||
|
||||
import { Logo } from '@/components/layout';
|
||||
|
||||
export const SignIn = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
|
|
@ -15,12 +12,5 @@ export const SignIn = () => {
|
|||
return state ? `/extension/sign-in?state=${state}` : undefined;
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-8 h-screen w-full items-center justify-center">
|
||||
<Link href="/">
|
||||
<Logo />
|
||||
</Link>
|
||||
<ClerkSignIn forceRedirectUrl={forceRedirectUrl} />
|
||||
</div>
|
||||
);
|
||||
return <ClerkSignIn forceRedirectUrl={forceRedirectUrl} />;
|
||||
};
|
||||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import { SignUp as ClerkSignUp } from '@clerk/nextjs';
|
||||
|
||||
import { Logo } from '@/components/layout';
|
||||
|
||||
export const SignUp = () => {
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
|
|
@ -15,12 +12,5 @@ export const SignUp = () => {
|
|||
return state ? `/extension/sign-in?state=${state}` : undefined;
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-8 h-screen w-full items-center justify-center">
|
||||
<Link href="/">
|
||||
<Logo />
|
||||
</Link>
|
||||
<ClerkSignUp forceRedirectUrl={forceRedirectUrl} />
|
||||
</div>
|
||||
);
|
||||
return <ClerkSignUp forceRedirectUrl={forceRedirectUrl} />;
|
||||
};
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import { CreateOrganization } from '@clerk/nextjs';
|
||||
|
||||
export default async function Page() {
|
||||
return <CreateOrganization afterCreateOrganizationUrl="/dashboard" />;
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import { OrganizationList } from '@clerk/nextjs';
|
||||
|
||||
export default async function Page() {
|
||||
return (
|
||||
<OrganizationList
|
||||
afterSelectOrganizationUrl="/dashboard"
|
||||
afterCreateOrganizationUrl="/dashboard"
|
||||
hidePersonal
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
import { UserProfile } from '@clerk/nextjs';
|
||||
|
||||
export default function Page() {
|
||||
return <UserProfile routing="path" path="/user" />;
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
import { Button, Card, CardContent, CardFooter } from '@/components/ui';
|
||||
import { Logo } from '@/components/layout';
|
||||
|
||||
interface DeepLinkProps {
|
||||
vsCodeUrl: string;
|
||||
cursorUrl: string;
|
||||
}
|
||||
|
||||
export const DeepLink = ({ vsCodeUrl, cursorUrl }: DeepLinkProps) => {
|
||||
const [redirectAttempted, setRedirectAttempted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
window.location.href = vsCodeUrl;
|
||||
const timer = setTimeout(() => setRedirectAttempted(true), 2000);
|
||||
return () => clearTimeout(timer);
|
||||
}, [vsCodeUrl]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col justify-center gap-4 max-w-md h-screen mx-auto">
|
||||
<Link href="/" className="text-center">
|
||||
<Logo />
|
||||
</Link>
|
||||
<Card>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div>
|
||||
You've successfully authenticated. We're attempting to
|
||||
open VSCode with your credentials.
|
||||
</div>
|
||||
<div className="flex flex-row justify-between gap-4">
|
||||
<Button variant="secondary" className="flex-1" asChild>
|
||||
<Link href={vsCodeUrl}>Open in VSCode</Link>
|
||||
</Button>
|
||||
<Button variant="secondary" className="flex-1" asChild>
|
||||
<Link href={cursorUrl}>Open in Cursor</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="text-sm text-muted-foreground">
|
||||
{redirectAttempted
|
||||
? 'You can close this window after VSCode opens.'
|
||||
: 'Redirecting automatically...'}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -3,6 +3,7 @@ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
|
|||
const isUnprotectedRoute = createRouteMatcher([
|
||||
'/sign-in(.*)',
|
||||
'/sign-up(.*)',
|
||||
'/extension/sign-in(.*)',
|
||||
'/',
|
||||
]);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue