diff --git a/components/dashboard/src/service/json-rpc-authprovider-client.ts b/components/dashboard/src/service/json-rpc-authprovider-client.ts new file mode 100644 index 00000000000000..471f18e93623bb --- /dev/null +++ b/components/dashboard/src/service/json-rpc-authprovider-client.ts @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2023 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { PartialMessage } from "@bufbuild/protobuf"; +import { Code, ConnectError, PromiseClient } from "@connectrpc/connect"; +import { AuthProviderService } from "@gitpod/public-api/lib/gitpod/v1/authprovider_connect"; +import { + CreateAuthProviderRequest, + CreateAuthProviderResponse, + DeleteAuthProviderRequest, + DeleteAuthProviderResponse, + GetAuthProviderRequest, + GetAuthProviderResponse, + ListAuthProviderDescriptionsRequest, + ListAuthProviderDescriptionsResponse, + ListAuthProvidersRequest, + ListAuthProvidersResponse, + UpdateAuthProviderRequest, + UpdateAuthProviderResponse, +} from "@gitpod/public-api/lib/gitpod/v1/authprovider_pb"; +import { converter } from "./public-api"; +import { getGitpodService } from "./service"; + +export class JsonRpcAuthProviderClient implements PromiseClient { + async createAuthProvider(request: PartialMessage): Promise { + const ownerId = request.owner?.case === "ownerId" ? request.owner.value : undefined; + const organizationId = request.owner?.case === "organizationId" ? request.owner.value : undefined; + + if (!organizationId && !ownerId) { + throw new ConnectError("organizationId or ownerId is required", Code.InvalidArgument); + } + if (!request.type) { + throw new ConnectError("type is required", Code.InvalidArgument); + } + if (!request.host) { + throw new ConnectError("host is required", Code.InvalidArgument); + } + + if (organizationId) { + const result = await getGitpodService().server.createOrgAuthProvider({ + entry: { + organizationId, + host: request.host, + type: converter.fromAuthProviderType(request.type), + clientId: request.oauth2Config?.clientId, + clientSecret: request.oauth2Config?.clientSecret, + }, + }); + return new CreateAuthProviderResponse({ authProvider: converter.toAuthProvider(result) }); + } + if (ownerId) { + const result = await getGitpodService().server.updateOwnAuthProvider({ + entry: { + host: request.host, + ownerId, + type: converter.fromAuthProviderType(request.type), + clientId: request.oauth2Config?.clientId, + clientSecret: request.oauth2Config?.clientSecret, + }, + }); + return new CreateAuthProviderResponse({ authProvider: converter.toAuthProvider(result) }); + } + + throw new ConnectError("organizationId or ownerId is required", Code.InvalidArgument); + } + + async getAuthProvider(request: PartialMessage): Promise { + if (!request.authProviderId) { + throw new ConnectError("authProviderId is required", Code.InvalidArgument); + } + + const provider = await getGitpodService().server.getAuthProvider(request.authProviderId); + return new GetAuthProviderResponse({ + authProvider: converter.toAuthProvider(provider), + }); + } + + async listAuthProviders(request: PartialMessage): Promise { + if (!request.id?.case) { + throw new ConnectError("id is required", Code.InvalidArgument); + } + const organizationId = request.id.case === "organizationId" ? request.id.value : undefined; + const userId = request.id.case === "userId" ? request.id.value : undefined; + + if (!organizationId && !userId) { + throw new ConnectError("organizationId or userId is required", Code.InvalidArgument); + } + + const authProviders = !!organizationId + ? await getGitpodService().server.getOrgAuthProviders({ + organizationId, + }) + : await getGitpodService().server.getOwnAuthProviders(); + const response = new ListAuthProvidersResponse({ + authProviders: authProviders.map(converter.toAuthProvider), + }); + return response; + } + + async listAuthProviderDescriptions( + request: PartialMessage, + ): Promise { + const aps = await getGitpodService().server.getAuthProviders(); + return new ListAuthProviderDescriptionsResponse({ + descriptions: aps.map((ap) => converter.toAuthProviderDescription(ap)), + }); + } + + async updateAuthProvider(request: PartialMessage): Promise { + if (!request.authProviderId) { + throw new ConnectError("authProviderId is required", Code.InvalidArgument); + } + const clientId = request?.clientId; + const clientSecret = request?.clientSecret; + if (!clientId || !clientSecret) { + throw new ConnectError("clientId or clientSecret are required", Code.InvalidArgument); + } + + await getGitpodService().server.updateAuthProvider(request.authProviderId, { + clientId, + clientSecret, + }); + return new UpdateAuthProviderResponse(); + } + + async deleteAuthProvider(request: PartialMessage): Promise { + if (!request.authProviderId) { + throw new ConnectError("authProviderId is required", Code.InvalidArgument); + } + await getGitpodService().server.deleteAuthProvider(request.authProviderId); + return new DeleteAuthProviderResponse(); + } +} diff --git a/components/dashboard/src/service/public-api.ts b/components/dashboard/src/service/public-api.ts index 557d729d5d96ca..f327a89ad40b20 100644 --- a/components/dashboard/src/service/public-api.ts +++ b/components/dashboard/src/service/public-api.ts @@ -23,6 +23,8 @@ import { getMetricsInterceptor } from "@gitpod/public-api/lib/metrics"; import { getExperimentsClient } from "../experiments/client"; import { JsonRpcOrganizationClient } from "./json-rpc-organization-client"; import { JsonRpcWorkspaceClient } from "./json-rpc-workspace-client"; +import { JsonRpcAuthProviderClient } from "./json-rpc-authprovider-client"; +import { AuthProviderService } from "@gitpod/public-api/lib/gitpod/v1/authprovider_connect"; const transport = createConnectTransport({ baseUrl: `${window.location.protocol}//${window.location.host}/public-api`, @@ -49,6 +51,8 @@ export const organizationClient = createServiceClient( // No jsonrcp client for the configuration service as it's only used in new UI of the dashboard export const configurationClient = createServiceClient(ConfigurationService); +export const authProviderClient = createServiceClient(AuthProviderService, new JsonRpcAuthProviderClient()); + export async function listAllProjects(opts: { orgId: string }): Promise { let pagination = { page: 1,