Skip to content

Commit

Permalink
feat(ui): add gitlab sso support (#2219)
Browse files Browse the repository at this point in the history
* feat(ui): add gitlab sso support

* format

* format

* add icon

* [autofix.ci] apply automated fixes

* styling

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
liangfung and autofix-ci[bot] authored May 22, 2024
1 parent 8b073ce commit 8924998
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,13 @@ export const PROVIDER_METAS: Array<{
domain: 'google.com',
displayName: 'Google'
}
},
{
name: 'gitlab',
enum: OAuthProvider.Gitlab,
meta: {
domain: 'gitlab.com',
displayName: 'GitLab'
}
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ import {
FormLabel,
FormMessage
} from '@/components/ui/form'
import { IconSpinner } from '@/components/ui/icons'
import {
IconGitHub,
IconGitLab,
IconGoogle,
IconSpinner
} from '@/components/ui/icons'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
Expand Down Expand Up @@ -157,6 +162,12 @@ export default function OAuthCredentialForm({
variables: { provider: providerValue }
})

const accessTokenPlaceholder = React.useMemo(() => {
if (!isNew) return new Array(36).fill('*').join('')

return 'e.g. e363c08d7e9ca4e66e723a53f38a21f6a54c1b83'
}, [isNew])

return (
<Form {...form}>
<div className={cn('grid gap-2', className)} {...props}>
Expand All @@ -181,7 +192,7 @@ export default function OAuthCredentialForm({
<FormLabel>Provider</FormLabel>
<FormControl>
<RadioGroup
className="flex gap-6"
className="flex gap-8"
orientation="horizontal"
onValueChange={onChange}
{...rest}
Expand All @@ -192,7 +203,11 @@ export default function OAuthCredentialForm({
id="r_github"
disabled={!isNew}
/>
<Label className="cursor-pointer" htmlFor="r_github">
<Label
className="flex cursor-pointer items-center gap-2"
htmlFor="r_github"
>
<IconGitHub className="h-5 w-5" />
GitHub
</Label>
</div>
Expand All @@ -202,10 +217,28 @@ export default function OAuthCredentialForm({
id="r_google"
disabled={!isNew}
/>
<Label className="cursor-pointer" htmlFor="r_google">
<Label
className="flex cursor-pointer items-center gap-2"
htmlFor="r_google"
>
<IconGoogle className="h-5 w-5" />
Google
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem
value={OAuthProvider.Gitlab}
id="r_gitlab"
disabled={!isNew}
/>
<Label
className="flex cursor-pointer items-center gap-2"
htmlFor="r_gitlab"
>
<IconGitLab className="h-5 w-5" />
GitLab
</Label>
</div>
</RadioGroup>
</FormControl>
<FormMessage />
Expand Down Expand Up @@ -265,19 +298,19 @@ export default function OAuthCredentialForm({
name="clientSecret"
render={({ field }) => (
<FormItem>
<FormLabel required>Client Secret</FormLabel>
<FormLabel required={isNew}>Client Secret</FormLabel>
<FormControl>
<Input
{...field}
placeholder={
isNew
? 'e.g. e363c08d7e9ca4e66e723a53f38a21f6a54c1b83'
: '*****'
}
className={cn({
'placeholder:translate-y-[10%] !placeholder-foreground':
!isNew
})}
placeholder={accessTokenPlaceholder}
autoCapitalize="none"
autoComplete="off"
autoCorrect="off"
type="password"
{...field}
/>
</FormControl>
<FormMessage />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import LoadingWrapper from '@/components/loading-wrapper'

import { PROVIDER_METAS } from './constant'
import { SSOHeader } from './sso-header'
import { IconGitHub, IconGitLab, IconGoogle } from '@/components/ui/icons'

export const oauthCredential = graphql(/* GraphQL */ `
query OAuthCredential($provider: OAuthProvider!) {
Expand All @@ -41,11 +42,19 @@ const OAuthCredentialList = () => {
query: oauthCredential,
variables: { provider: OAuthProvider.Google }
})
const [{ data: gitlabData, fetching: fetchingGitlab }] = useQuery({
query: oauthCredential,
variables: { provider: OAuthProvider.Gitlab }
})

const isLoading = fetchingGithub || fetchingGoogle
const isLoading = fetchingGithub || fetchingGoogle || fetchingGitlab
const credentialList = React.useMemo(() => {
return compact([githubData?.oauthCredential, googleData?.oauthCredential])
}, [githubData, googleData])
return compact([
githubData?.oauthCredential,
googleData?.oauthCredential,
gitlabData?.oauthCredential
])
}, [githubData, googleData, gitlabData])

const router = useRouter()
const createButton = (
Expand Down Expand Up @@ -100,7 +109,7 @@ const OAuthCredentialList = () => {
)
})}
</div>
{credentialList.length < 2 && (
{credentialList.length < 3 && (
<div className="mt-4 flex justify-end">{createButton}</div>
)}
</div>
Expand All @@ -115,15 +124,19 @@ const OauthCredentialCard = ({
const meta = React.useMemo(() => {
return find(PROVIDER_METAS, { enum: data?.provider })?.meta
}, [data])

if (!data) return null

return (
<Card>
<CardHeader className="border-b p-4">
<div className="flex items-center justify-between">
<CardTitle className="text-xl">
{meta?.displayName || data?.provider}
<CardTitle className="flex items-center gap-2 text-xl">
<OAuthProviderIcon provider={data.provider} />
{meta?.displayName || data.provider}
</CardTitle>
<Link
href={`/settings/sso/detail/${data?.provider.toLowerCase()}`}
href={`/settings/sso/detail/${data.provider.toLowerCase()}`}
className={buttonVariants({ variant: 'secondary' })}
>
View
Expand All @@ -144,4 +157,17 @@ const OauthCredentialCard = ({
)
}

export { OAuthCredentialList as OauthCredentialList }
function OAuthProviderIcon({ provider }: { provider: OAuthProvider }) {
switch (provider) {
case OAuthProvider.Github:
return <IconGitHub className="h-6 w-6" />
case OAuthProvider.Google:
return <IconGoogle className="h-6 w-6" />
case OAuthProvider.Gitlab:
return <IconGitLab className="h-6 w-6" />
default:
return null
}
}

export { OAuthCredentialList }
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Metadata } from 'next'

import { OauthCredentialList } from './components/oauth-credential-list'
import { OAuthCredentialList } from './components/oauth-credential-list'

export const metadata: Metadata = {
title: 'SSO'
}

export default function IndexPage() {
return <OauthCredentialList />
return <OAuthCredentialList />
}
14 changes: 12 additions & 2 deletions ee/tabby-ui/app/auth/signin/components/signin-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import useRouterStuff from '@/lib/hooks/use-router-stuff'
import { useAllowSelfSignup } from '@/lib/hooks/use-server-info'
import { useSession, useSignIn } from '@/lib/tabby/auth'
import fetcher from '@/lib/tabby/fetcher'
import { IconGithub, IconGoogle, IconSpinner } from '@/components/ui/icons'
import {
IconGitLab,
IconGithub,
IconGoogle,
IconSpinner
} from '@/components/ui/icons'

import UserSignInForm from './user-signin-form'

Expand Down Expand Up @@ -78,7 +83,7 @@ export default function SigninSection() {
<div className="grow border-t "></div>
</div>
)}
<div className="mx-auto flex items-center gap-6">
<div className="mx-auto flex items-center gap-8">
{data?.includes('github') && (
<a href={`/oauth/signin?provider=github`}>
<IconGithub className="h-8 w-8" />
Expand All @@ -89,6 +94,11 @@ export default function SigninSection() {
<IconGoogle className="h-8 w-8" />
</a>
)}
{data?.includes('gitlab') && (
<a href={`/oauth/signin?provider=gitlab`}>
<IconGitLab className="h-8 w-8" />
</a>
)}
</div>
{!!errorMessage && (
<div className="mt-4 text-destructive">{errorMessage}</div>
Expand Down
6 changes: 5 additions & 1 deletion ee/tabby-webserver/src/routes/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ async fn has_provider(auth: &Arc<dyn AuthenticationService>, x: &OAuthProvider)
}

async fn providers_handler(state: State<OAuthState>) -> Json<Vec<OAuthProvider>> {
let candidates = vec![OAuthProvider::Google, OAuthProvider::Github];
let candidates = vec![
OAuthProvider::Google,
OAuthProvider::Github,
OAuthProvider::Gitlab,
];
let mut providers = vec![];

for x in candidates {
Expand Down

0 comments on commit 8924998

Please sign in to comment.