diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/Connection.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/Connection.tsx index bf2b80ffb8..87c8b4a207 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/Connection.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/Connection.tsx @@ -49,7 +49,7 @@ export const Connection = observer(function Connection({ connection }: Props) { {connection.name} {connection.host} {connection.port} - + ); diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionForm/ConnectionForm.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionForm/ConnectionForm.tsx index 58e05d5803..c6ca725a78 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionForm/ConnectionForm.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionForm/ConnectionForm.tsx @@ -39,10 +39,10 @@ export const ConnectionForm = observer(function ConnectionForm({ controller.onChange('template', !value)} - disabled={controller.isSaving} + checkboxLabel={translate('connections_connection_template')} + checked={controller.config.template} + onChange={value => controller.onChange('template', value)} + disabled={!controller.isNew || controller.isSaving} mod='surface' /> diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx index 554c1bccc0..4e54f68a24 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx @@ -46,7 +46,7 @@ export const ConnectionsTable = observer(function ConnectionsTable({ {translate('connections_connection_name')} {translate('connections_connection_host')} {translate('connections_connection_port')} - {translate('connections_connection_in_tree')} + {translate('connections_connection_template')} diff --git a/webapp/packages/core-connections/src/ConnectionInfoResource.ts b/webapp/packages/core-connections/src/ConnectionInfoResource.ts index 0840271a96..7402e06d2a 100644 --- a/webapp/packages/core-connections/src/ConnectionInfoResource.ts +++ b/webapp/packages/core-connections/src/ConnectionInfoResource.ts @@ -22,8 +22,15 @@ export class ConnectionInfoResource extends CachedMapResource { + const { connection } = await this.graphQLService.gql.createConnectionFromTemplate({ templateId }); + this.set(connection.id, connection); + + return this.get(connection.id)!; + } + async init(id: string, credentials?: any): Promise { - const connection = await this.performUpdate(id, async () => { + await this.performUpdate(id, async () => { const connection = await this.setActivePromise(id, this.initConnection(id, credentials)); this.set(id, connection); return connection; @@ -64,7 +71,7 @@ export class ConnectionInfoResource extends CachedMapResource> { - const { connection } = await this.graphQLService.gql.connectionState({ id: connectionId }); + const { connection } = await this.graphQLService.gql.connectionInfo({ id: connectionId }); const oldConnection = this.get(connectionId) || {}; this.set(connectionId, { ...oldConnection, ...connection }); diff --git a/webapp/packages/core-connections/src/locales/en.ts b/webapp/packages/core-connections/src/locales/en.ts index d37fe37951..a3cd06207a 100644 --- a/webapp/packages/core-connections/src/locales/en.ts +++ b/webapp/packages/core-connections/src/locales/en.ts @@ -9,5 +9,5 @@ export default [ ['connections_connection_driver', 'Driver'], ['connections_connection_host', 'Host'], ['connections_connection_port', 'Port'], - ['connections_connection_in_tree', 'Show in navigation tree'], + ['connections_connection_template', 'Template'], ]; diff --git a/webapp/packages/core-connections/src/locales/ru.ts b/webapp/packages/core-connections/src/locales/ru.ts index 2a23bc24f0..9ecef14a53 100644 --- a/webapp/packages/core-connections/src/locales/ru.ts +++ b/webapp/packages/core-connections/src/locales/ru.ts @@ -9,5 +9,5 @@ export default [ ['connections_connection_driver', 'Driver'], ['connections_connection_host', 'Хост'], ['connections_connection_port', 'Порт'], - ['connections_connection_in_tree', 'Показывать в дереве навигации'], + ['connections_connection_template', 'Шаблон'], ]; diff --git a/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql b/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql index 4c90426abb..45a36cef72 100644 --- a/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql +++ b/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql @@ -1,5 +1,5 @@ query connectionAuthProperties($id: ID!) { - connection: connectionState(id: $id) { + connection: connectionInfo(id: $id) { authProperties { id displayName diff --git a/webapp/packages/core-sdk/src/queries/connections/connectionState.gql b/webapp/packages/core-sdk/src/queries/connections/connectionInfo.gql similarity index 61% rename from webapp/packages/core-sdk/src/queries/connections/connectionState.gql rename to webapp/packages/core-sdk/src/queries/connections/connectionInfo.gql index 1868cd6087..ac40bea7f8 100644 --- a/webapp/packages/core-sdk/src/queries/connections/connectionState.gql +++ b/webapp/packages/core-sdk/src/queries/connections/connectionInfo.gql @@ -1,5 +1,5 @@ -query connectionState($id: ID!) { - connection: connectionState(id: $id) { +query connectionInfo($id: ID!) { + connection: connectionInfo(id: $id) { id name description diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql new file mode 100644 index 0000000000..0aea2c8b81 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql @@ -0,0 +1,15 @@ +mutation createConnectionFromTemplate($templateId: ID!) { + connection: createConnectionFromTemplate(templateId: $templateId) { + id + name + description + driverId + connected + readOnly + + features + + authNeeded + authModel + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/openConnection.gql b/webapp/packages/core-sdk/src/queries/connections/openConnection.gql deleted file mode 100644 index 8c58130a77..0000000000 --- a/webapp/packages/core-sdk/src/queries/connections/openConnection.gql +++ /dev/null @@ -1,15 +0,0 @@ -mutation openConnection($config: ConnectionConfig!) { - connection: openConnection(config: $config) { - id - name - description - driverId - connected - readOnly - - features - - authNeeded - authModel - } -} diff --git a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql index 689b4f38e9..f79600e364 100644 --- a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql +++ b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql @@ -3,8 +3,6 @@ query serverConfig { name version productConfiguration - supportsPredefinedConnections - supportsProvidedConnections supportsCustomConnections supportsConnectionBrowser supportsWorkspaces diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index ee5e8431f3..7353c1d054 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -35,6 +35,8 @@ export type Query = { deleteRole?: Maybe; deleteUser?: Maybe; driverList: Array; + getConnectionAccess: Array; + getSubjectAccess: Array; grantUserRole?: Maybe; listPermissions: Array>; listRoles: Array>; @@ -51,6 +53,7 @@ export type Query = { sessionState: SessionInfo; sessionUser?: Maybe; setConnectionAccess?: Maybe; + setSubjectAccess?: Maybe; setSubjectPermissions?: Maybe; setUserCredentials?: Maybe; sqlCompletionProposals?: Maybe>>; @@ -118,6 +121,14 @@ export type QueryDriverListArgs = { id?: Maybe; }; +export type QueryGetConnectionAccessArgs = { + connectionId?: Maybe; +}; + +export type QueryGetSubjectAccessArgs = { + subject?: Maybe; +}; + export type QueryGrantUserRoleArgs = { userId: Scalars['ID']; roleId: Scalars['ID']; @@ -171,6 +182,11 @@ export type QuerySetConnectionAccessArgs = { subjects: Array; }; +export type QuerySetSubjectAccessArgs = { + subjectId: Scalars['ID']; + connections: Array; +}; + export type QuerySetSubjectPermissionsArgs = { roleId: Scalars['ID']; permissions: Array; @@ -214,6 +230,7 @@ export type Mutation = { closeConnection: ConnectionInfo; closeSession?: Maybe; createConnection: ConnectionInfo; + createConnectionFromTemplate: ConnectionInfo; deleteConnection: Scalars['Boolean']; initConnection: ConnectionInfo; /** @deprecated Field no longer supported */ @@ -269,6 +286,10 @@ export type MutationCreateConnectionArgs = { config: ConnectionConfig; }; +export type MutationCreateConnectionFromTemplateArgs = { + templateId: Scalars['ID']; +}; + export type MutationDeleteConnectionArgs = { id: Scalars['ID']; }; @@ -675,6 +696,16 @@ export type SqlResultRow = { updateValues?: Maybe; }; +export enum AdminSubjectType { + User = 'user', + Role = 'role' +} + +export type AdminSubjectInfo = { + subjectId: Scalars['ID']; + subjectType: AdminSubjectType; +}; + export type AdminUserInfo = { userId: Scalars['ID']; metaParameters: Scalars['Object']; @@ -858,11 +889,11 @@ export type ConnectionAuthPropertiesQueryVariables = Exact<{ export type ConnectionAuthPropertiesQuery = { connection: { authProperties: Array> } }; -export type ConnectionStateQueryVariables = Exact<{ +export type ConnectionInfoQueryVariables = Exact<{ id: Scalars['ID']; }>; -export type ConnectionStateQuery = { connection: Pick }; +export type ConnectionInfoQuery = { connection: Pick }; export type CreateConnectionMutationVariables = Exact<{ config: ConnectionConfig; @@ -870,6 +901,12 @@ export type CreateConnectionMutationVariables = Exact<{ export type CreateConnectionMutation = { createConnection: Pick }; +export type CreateConnectionFromTemplateMutationVariables = Exact<{ + templateId: Scalars['ID']; +}>; + +export type CreateConnectionFromTemplateMutation = { connection: Pick }; + export type DeleteConnectionMutationVariables = Exact<{ id: Scalars['ID']; }>; @@ -909,12 +946,6 @@ export type InitConnectionMutationVariables = Exact<{ export type InitConnectionMutation = { connection: Pick }; -export type OpenConnectionMutationVariables = Exact<{ - config: ConnectionConfig; -}>; - -export type OpenConnectionMutation = { connection: Pick }; - export type GetTemplateConnectionsQueryVariables = Exact<{ [key: string]: never }>; export type GetTemplateConnectionsQuery = { connections: Array> }; @@ -1151,7 +1182,7 @@ export type ReadSessionLogQuery = { log: Array; export type ServerConfigQuery = { serverConfig: ( - Pick + Pick & { supportedLanguages: Array>; defaultNavigatorSettings: Pick } ); }; @@ -1389,7 +1420,7 @@ export const CloseConnectionDocument = ` `; export const ConnectionAuthPropertiesDocument = ` query connectionAuthProperties($id: ID!) { - connection: connectionState(id: $id) { + connection: connectionInfo(id: $id) { authProperties { id displayName @@ -1404,9 +1435,9 @@ export const ConnectionAuthPropertiesDocument = ` } } `; -export const ConnectionStateDocument = ` - query connectionState($id: ID!) { - connection: connectionState(id: $id) { +export const ConnectionInfoDocument = ` + query connectionInfo($id: ID!) { + connection: connectionInfo(id: $id) { id name description @@ -1434,6 +1465,21 @@ export const CreateConnectionDocument = ` } } `; +export const CreateConnectionFromTemplateDocument = ` + mutation createConnectionFromTemplate($templateId: ID!) { + connection: createConnectionFromTemplate(templateId: $templateId) { + id + name + description + driverId + connected + readOnly + features + authNeeded + authModel + } +} + `; export const DeleteConnectionDocument = ` mutation deleteConnection($id: ID!) { deleteConnection(id: $id) @@ -1516,21 +1562,6 @@ export const InitConnectionDocument = ` } } `; -export const OpenConnectionDocument = ` - mutation openConnection($config: ConnectionConfig!) { - connection: openConnection(config: $config) { - id - name - description - driverId - connected - readOnly - features - authNeeded - authModel - } -} - `; export const GetTemplateConnectionsDocument = ` query getTemplateConnections { connections: templateConnections { @@ -1921,8 +1952,6 @@ export const ServerConfigDocument = ` name version productConfiguration - supportsPredefinedConnections - supportsProvidedConnections supportsCustomConnections supportsConnectionBrowser supportsWorkspaces @@ -2059,12 +2088,15 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = connectionAuthProperties(variables: ConnectionAuthPropertiesQueryVariables): Promise { return withWrapper(() => client.request(ConnectionAuthPropertiesDocument, variables)); }, - connectionState(variables: ConnectionStateQueryVariables): Promise { - return withWrapper(() => client.request(ConnectionStateDocument, variables)); + connectionInfo(variables: ConnectionInfoQueryVariables): Promise { + return withWrapper(() => client.request(ConnectionInfoDocument, variables)); }, createConnection(variables: CreateConnectionMutationVariables): Promise { return withWrapper(() => client.request(CreateConnectionDocument, variables)); }, + createConnectionFromTemplate(variables: CreateConnectionFromTemplateMutationVariables): Promise { + return withWrapper(() => client.request(CreateConnectionFromTemplateDocument, variables)); + }, deleteConnection(variables: DeleteConnectionMutationVariables): Promise { return withWrapper(() => client.request(DeleteConnectionDocument, variables)); }, @@ -2083,9 +2115,6 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = initConnection(variables: InitConnectionMutationVariables): Promise { return withWrapper(() => client.request(InitConnectionDocument, variables)); }, - openConnection(variables: OpenConnectionMutationVariables): Promise { - return withWrapper(() => client.request(OpenConnectionDocument, variables)); - }, getTemplateConnections(variables?: GetTemplateConnectionsQueryVariables): Promise { return withWrapper(() => client.request(GetTemplateConnectionsDocument, variables)); }, diff --git a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionController.ts b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionController.ts index 9508f15052..1153935c79 100644 --- a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionController.ts +++ b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionController.ts @@ -6,18 +6,17 @@ * you may not use this file except in compliance with the License. */ -import { observable, action } from 'mobx'; +import { observable } from 'mobx'; import { - DBDriverResource, Connection, DatabaseAuthModelsResource + DBDriverResource, Connection, DatabaseAuthModelsResource, ConnectionInfoResource } from '@cloudbeaver/core-connections'; import { injectable, IInitializableController, IDestructibleController } from '@cloudbeaver/core-di'; import { CommonDialogService } from '@cloudbeaver/core-dialogs'; import { NotificationService } from '@cloudbeaver/core-events'; import { ErrorDetailsDialog } from '@cloudbeaver/core-notifications'; -import { ConnectionConfig, GQLError, DatabaseAuthModel } from '@cloudbeaver/core-sdk'; +import { GQLError, DatabaseAuthModel } from '@cloudbeaver/core-sdk'; -import { TemplateConnectionService } from '../TemplateConnectionService'; import { TemplateConnectionsResource } from '../TemplateConnectionsResource'; export enum ConnectionStep { @@ -27,7 +26,7 @@ export enum ConnectionStep { export interface IConnectionController { template: Connection | null; - config: ConnectionConfig; + credentials: any; isConnecting: boolean; onConnect(): void; } @@ -40,9 +39,7 @@ implements IInitializableController, IDestructibleController, IConnectionControl @observable isConnecting = false; @observable template: Connection | null = null @observable authModel?: DatabaseAuthModel; - @observable config: ConnectionConfig = { - credentials: {}, - } + @observable credentials: any = { } @observable hasDetails = false @observable responseMessage: string | null = null @@ -67,8 +64,8 @@ implements IInitializableController, IDestructibleController, IConnectionControl constructor( private dbDriverResource: DBDriverResource, + private connectionInfoResource: ConnectionInfoResource, private templateConnectionsResource: TemplateConnectionsResource, - private templateConnectionService: TemplateConnectionService, private notificationService: NotificationService, private commonDialogService: CommonDialogService, private dbAuthModelsResource: DatabaseAuthModelsResource @@ -93,13 +90,24 @@ implements IInitializableController, IDestructibleController, IConnectionControl } onConnect = async () => { + if (!this.template) { + return; + } + this.isConnecting = true; this.clearError(); try { - const connection = await this.templateConnectionService.openConnectionAsync(this.getConnectionConfig()); + const connection = await this.connectionInfoResource.createFromTemplate(this.template.id); - this.notificationService.logInfo({ title: `Connection ${connection.name} established` }); - this.onClose(); + try { + await this.connectionInfoResource.init(connection.id, this.credentials); + + this.notificationService.logInfo({ title: `Connection ${connection.name} established` }); + this.onClose(); + } catch (exception) { + this.showError(exception, 'Failed to establish connection'); + await this.connectionInfoResource.delete(connection.id); + } } catch (exception) { this.showError(exception, 'Failed to establish connection'); } finally { @@ -112,7 +120,7 @@ implements IInitializableController, IDestructibleController, IConnectionControl await this.loadAuthModel(); this.clearError(); - this.seTemplateDefaults(); + this.credentials = {}; this.step = ConnectionStep.Connection; if (!this.authModel) { @@ -126,22 +134,6 @@ implements IInitializableController, IDestructibleController, IConnectionControl } } - private getConnectionConfig(): ConnectionConfig { - const config: ConnectionConfig = {}; - config.templateId = this.config.templateId; - config.authModelId = this.config.authModelId; - config.credentials = this.config.credentials; - - return config; - } - - @action - private seTemplateDefaults() { - this.config.templateId = this.template?.id; - this.config.authModelId = this.dbDriver?.defaultAuthModel; - this.config.credentials = {}; - } - private clearError() { this.responseMessage = null; this.hasDetails = false; diff --git a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx index 0a1a20327f..355bbf6a47 100644 --- a/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx +++ b/webapp/packages/plugin-connection-template/src/ConnectionDialog/ConnectionDialog.tsx @@ -86,7 +86,7 @@ export const ConnectionDialog = observer(function ConnectionDialog({ prefix={`auth_${controller.template?.id || ''}`} autofillToken={`section-${controller.template?.id || ''} section-auth`} properties={controller.authModel.properties} - credentials={controller.config.credentials} + credentials={controller.credentials} processing={controller.isConnecting} /> diff --git a/webapp/packages/plugin-connection-template/src/TemplateConnectionService.ts b/webapp/packages/plugin-connection-template/src/TemplateConnectionService.ts deleted file mode 100644 index c6ad9ba2ca..0000000000 --- a/webapp/packages/plugin-connection-template/src/TemplateConnectionService.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * cloudbeaver - Cloud Database Manager - * Copyright (C) 2020 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ - -import { Connection, ConnectionsManagerService } from '@cloudbeaver/core-connections'; -import { injectable } from '@cloudbeaver/core-di'; -import { ConnectionConfig, GraphQLService } from '@cloudbeaver/core-sdk'; - -@injectable() -export class TemplateConnectionService { - - constructor( - private graphQLService: GraphQLService, - private connectionsManagerService: ConnectionsManagerService - ) { - } - - async openConnectionAsync(config: ConnectionConfig): Promise { - const { connection } = await this.graphQLService.gql.openConnection({ config }); - this.connectionsManagerService.addOpenedConnection(connection); - return connection; - } -} diff --git a/webapp/packages/plugin-connection-template/src/manifest.ts b/webapp/packages/plugin-connection-template/src/manifest.ts index 4ad4bf0000..adbe4910cd 100644 --- a/webapp/packages/plugin-connection-template/src/manifest.ts +++ b/webapp/packages/plugin-connection-template/src/manifest.ts @@ -10,7 +10,6 @@ import { PluginManifest } from '@cloudbeaver/core-di'; import { LocaleService } from './LocaleService'; import { TemplateConnectionPluginBootstrap } from './TemplateConnectionPluginBootstrap'; -import { TemplateConnectionService } from './TemplateConnectionService'; import { TemplateConnectionsResource } from './TemplateConnectionsResource'; export const connectionTemplate: PluginManifest = { @@ -19,7 +18,6 @@ export const connectionTemplate: PluginManifest = { }, providers: [ - TemplateConnectionService, TemplateConnectionsResource, LocaleService, ],