Path: blob/main/components/dashboard/src/teams/sso/OIDCClients.tsx
2501 views
/**1* Copyright (c) 2023 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { OIDCClientConfig } from "@gitpod/public-api/lib/gitpod/experimental/v1/oidc_pb";7import { FC, useCallback, useState } from "react";8import { Button } from "@podkit/buttons/Button";9import { EmptyMessage } from "../../components/EmptyMessage";10import { Item, ItemField, ItemFieldIcon, ItemsList } from "../../components/ItemsList";11import { SpinnerLoader } from "../../components/Loader";12import { Heading2, Subheading } from "../../components/typography/headings";13import { useOIDCClientsQuery } from "../../data/oidc-clients/oidc-clients-query";14import { OIDCClientConfigModal } from "./OIDCClientConfigModal";15import { OIDCClientListItem } from "./OIDCClientListItem";16import { useToast } from "../../components/toasts/Toasts";17import { LinkButton } from "../../components/LinkButton";18import { ActivateConfigModal } from "./ActivateConfigModal";19import { useVerifyClient } from "./use-verify-client";2021export const OIDCClients: FC = () => {22const { data, isLoading } = useOIDCClientsQuery();2324if (isLoading) {25return <SpinnerLoader />;26}2728return <OIDCClientsList clientConfigs={data || []} />;29};3031type OIDCClientsListProps = {32clientConfigs: OIDCClientConfig[];33};34const OIDCClientsList: FC<OIDCClientsListProps> = ({ clientConfigs }) => {35const { toast } = useToast();36const [showCreateModal, setShowCreateModal] = useState(false);37const [activateModalConfigId, setActivateModalConfigID] = useState("");3839const verifyClient = useVerifyClient({40onSuccess: (configId: string) => {41toast(42<span>43Single sign-on configuration was successfully verified.{" "}44<LinkButton inverted onClick={() => setActivateModalConfigID(configId)}>45Activate configuration46</LinkButton>47</span>,48);49},50onError: (errorMessage) => {51toast(errorMessage);52},53});5455const onCreate = useCallback(() => setShowCreateModal(true), []);56const hideModal = useCallback(() => setShowCreateModal(false), []);5758const handleSaved = useCallback(59(configId: string) => {60toast(61<span>62Single sign-on configuration was successfully saved.{" "}63<LinkButton inverted onClick={() => verifyClient(configId)}>64Verify configuration65</LinkButton>66</span>,67);68},69[toast, verifyClient],70);7172const hasActiveConfig = clientConfigs.some((config) => config.active);7374return (75<>76{showCreateModal && <OIDCClientConfigModal onSaved={handleSaved} onClose={hideModal} />}7778<div className="flex flex-col space-y-2 md:flex-row md:items-start md:justify-between md:space-y-0">79<div>80<Heading2>SSO Configurations</Heading2>81<Subheading>Configure OpenID Connect single sign-on for your organization.</Subheading>82</div>8384{clientConfigs.length !== 0 ? (85<div>86<Button className="whitespace-nowrap" onClick={onCreate}>87New Configuration88</Button>89</div>90) : null}91</div>9293{clientConfigs.length === 0 ? (94<EmptyMessage95subtitle="Enable single sign-on for your organization using an external identity provider (IdP) service that supports the OpenID Connect (OIDC) standard, such as Google or Okta."96buttonText="New Configuration"97onClick={onCreate}98/>99) : (100<ItemsList className="pt-6">101<Item header={true}>102<ItemFieldIcon />103<ItemField>Issuer URL</ItemField>104</Item>105{clientConfigs.map((cc) => (106<OIDCClientListItem107key={cc.id}108clientConfig={cc}109hasActiveConfig={hasActiveConfig}110onVerify={verifyClient}111onActivate={setActivateModalConfigID}112onSaved={handleSaved}113/>114))}115</ItemsList>116)}117118{!!activateModalConfigId && (119<ActivateConfigModal120configId={activateModalConfigId}121hasActiveConfig={hasActiveConfig}122onClose={() => setActivateModalConfigID("")}123/>124)}125</>126);127};128129130