CB-4067 gets back ask credentials window and removes connectionCredentialsStateContext

This commit is contained in:
sergeyteleshev
2025-03-11 13:38:15 +01:00
parent 43a9c2c866
commit f892e5b484
8 changed files with 73 additions and 60 deletions
@@ -19,7 +19,7 @@ import type { ConnectionFormState } from './ConnectionFormState.js';
import { getFirstException } from '@cloudbeaver/core-utils';
import { ConnectionFormService } from './ConnectionFormService.js';
import { ConnectionInfoResource, createConnectionParam } from '@cloudbeaver/core-connections';
import { connectionTestContext } from './Contexts/connectionTestContext.js';
import { connectionTestContext, type IConnectionTestContext } from './Contexts/connectionTestContext.js';
export interface ConnectionFormProps {
formState: ConnectionFormState;
@@ -70,6 +70,24 @@ export const ConnectionForm = observer<ConnectionFormProps>(function ConnectionF
onCancel,
}));
function getTestMessageInfo(testContext: IConnectionTestContext) {
let message = '';
if (testContext.clientVersion) {
message += 'Client version: ' + testContext.clientVersion + '\n';
}
if (testContext.serverVersion) {
message += 'Server version: ' + testContext.serverVersion + '\n';
}
if (testContext.connectTime) {
message += 'Connection time: ' + testContext.connectTime + '\n';
}
return message;
}
useExecutor({
executor: formState.submitTask,
postHandlers: [
@@ -77,18 +95,13 @@ export const ConnectionForm = observer<ConnectionFormProps>(function ConnectionF
const validation = contexts.getContext(formValidationContext);
const state = contexts.getContext(formStatusContext);
const testContext = contexts.getContext(connectionTestContext);
const message = getTestMessageInfo(testContext);
if (data.state.submitType === 'test' && !data.isError) {
if (data.state.submitType === 'test' && !data.isError && message.length) {
notificationService.notify(
{
title: 'Connection is established',
message:
'Client version: ' +
testContext.clientVersion +
'\nServer version: ' +
testContext.serverVersion +
'\nConnection time: ' +
testContext.connectTime,
message,
},
ENotificationType.Success,
);
@@ -1,30 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
interface IConnectionCredentialsState {
authModelId: string | null;
networkHandlers: string[];
}
interface IConnectionCredentialsStateContext extends IConnectionCredentialsState {
requireAuthModel: (id: string) => void;
requireNetworkHandler: (id: string) => void;
}
export function connectionCredentialsStateContext(): IConnectionCredentialsStateContext {
return {
authModelId: null,
networkHandlers: [],
requireAuthModel(id) {
this.authModelId = id;
},
requireNetworkHandler(id) {
this.networkHandlers.push(id);
},
};
}
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
interface IConnectionTestContext {
export interface IConnectionTestContext {
clientVersion: string | null;
serverVersion: string | null;
connectTime: string | null;
@@ -20,15 +20,16 @@ import {
} from '@cloudbeaver/core-connections';
import type { ProjectInfoResource } from '@cloudbeaver/core-projects';
import { AUTH_PROVIDER_LOCAL_ID, AuthProvidersResource, UserInfoResource } from '@cloudbeaver/core-authentication';
import { toJS } from 'mobx';
import { observable, runInAction, toJS } from 'mobx';
import { getUniqueName, isNotNullDefined } from '@cloudbeaver/core-utils';
import { getDefaultConfigurationType } from './getDefaultConfigurationType.js';
import { getConnectionName } from './getConnectionName.js';
import type { LocalizationService } from '@cloudbeaver/core-localization';
import { connectionCredentialsStateContext } from '../Contexts/connectionCredentialsStateContext.js';
import type { IConnectionFormOptionsState } from './IConnectionFormOptionsState.js';
import type { IConnectionFormState } from '../IConnectionFormState.js';
import { connectionTestContext } from '../Contexts/connectionTestContext.js';
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
import { ConnectionAuthenticationDialogLoader } from '../../ConnectionAuthentication/ConnectionAuthenticationDialogLoader.js';
const MAIN_PROPERTY_DATABASE_KEY = 'database';
const MAIN_PROPERTY_HOST_KEY = 'host';
@@ -77,8 +78,11 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
private readonly connectionInfoOriginResource: ConnectionInfoOriginResource,
private readonly authProvidersResource: AuthProvidersResource,
private readonly localizationService: LocalizationService,
private readonly commonDialogService: CommonDialogService,
) {
super(formState, defaultStateGetter());
this.formState.validationTask.addPostHandler(this.askCredentials.bind(this));
}
private async formAuthState(data: IConnectionFormState, contexts: IExecutionContextProvider<IFormState<IConnectionFormState>>) {
@@ -109,6 +113,44 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
}
}
private async askCredentials(data: IFormState<IConnectionFormState>, contexts: IExecutionContextProvider<IFormState<IConnectionFormState>>) {
const authModelId = this.state.authModelId ?? this.formState.state.config.authModelId ?? null;
const networkHandlers = this.state.networkHandlersConfig ?? [];
if (data.state.submitType !== 'test' || (!authModelId && !networkHandlers.length)) {
return;
}
runInAction(() => {
if (authModelId) {
if (!this.state.credentials) {
this.state.credentials = { ...this.formState.state.config.credentials };
}
this.state.credentials = observable(this.state.credentials);
}
if (networkHandlers.length > 0) {
if (!this.state.networkHandlersConfig) {
this.state.networkHandlersConfig = toJS(this.formState.state.config.networkHandlersConfig) || [];
}
this.state.networkHandlersConfig = observable(this.state.networkHandlersConfig);
}
});
const result = await this.commonDialogService.open(ConnectionAuthenticationDialogLoader, {
config: this.state,
authModelId: authModelId,
networkHandlers: networkHandlers.map(handler => handler.id),
projectId: this.formState.state.projectId,
});
if (result === DialogueStateResult.Rejected) {
ExecutorInterrupter.interrupt(contexts);
}
}
protected override async loader(): Promise<void> {
if (this.formState.mode === 'create') {
await this.setDefaults();
@@ -224,8 +266,6 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
data: IFormState<IConnectionFormState>,
contexts: IExecutionContextProvider<IFormState<IConnectionFormState>>,
): Promise<void> {
const credentialsState = contexts.getContext(connectionCredentialsStateContext);
if (!this.state.driverId || !this.formState.state.projectId) {
return;
}
@@ -283,7 +323,7 @@ export class ConnectionFormOptionsPart extends FormPart<IConnectionFormOptionsSt
}
if (!this.state.saveCredentials) {
credentialsState.requireAuthModel(this.state.authModelId);
this.formState.state.config.authModelId = this.state.authModelId;
}
}
@@ -13,6 +13,7 @@ import { ProjectInfoResource } from '@cloudbeaver/core-projects';
import { AuthProvidersResource, UserInfoResource } from '@cloudbeaver/core-authentication';
import { LocalizationService } from '@cloudbeaver/core-localization';
import type { IConnectionFormState } from '../IConnectionFormState.js';
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
const DATA_CONTEXT_CONNECTION_FORM_OPTIONS_PART = createDataContext<ConnectionFormOptionsPart>('Connection Form Options Part');
@@ -27,6 +28,7 @@ export function getConnectionFormOptionsPart(formState: IFormState<IConnectionFo
const authProvidersResource = di.getService(AuthProvidersResource);
const localizationService = di.getService(LocalizationService);
const connectionInfoOriginResource = di.getService(ConnectionInfoOriginResource);
const commonDialogService = di.getService(CommonDialogService);
return new ConnectionFormOptionsPart(
formState,
@@ -38,6 +40,7 @@ export function getConnectionFormOptionsPart(formState: IFormState<IConnectionFo
connectionInfoOriginResource,
authProvidersResource,
localizationService,
commonDialogService,
);
});
}
@@ -11,7 +11,6 @@ import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { DriverConfigurationType, NetworkHandlerAuthType, type NetworkHandlerConfigInput } from '@cloudbeaver/core-sdk';
import { ConnectionInfoResource, createConnectionParam, SSH_TUNNEL_ID } from '@cloudbeaver/core-connections';
import { toJS } from 'mobx';
import { connectionCredentialsStateContext } from '../Contexts/connectionCredentialsStateContext.js';
import type { IConnectionFormState } from '../IConnectionFormState.js';
import type { INetworkHandlerConfig } from '../Options/IConnectionNetworkHanler.js';
import { getConnectionFormOptionsPart } from '../Options/getConnectionFormOptionsPart.js';
@@ -63,7 +62,6 @@ export class ConnectionFormSSHPart extends FormPart<INetworkHandlerConfig, IConn
data: IFormState<IConnectionFormState>,
contexts: IExecutionContextProvider<IFormState<IConnectionFormState>>,
): void | Promise<void> {
const credentialsState = contexts.getContext(connectionCredentialsStateContext);
const optionsPart = getConnectionFormOptionsPart(this.formState);
const urlType = optionsPart.state.configurationType === DriverConfigurationType.Url;
@@ -87,11 +85,7 @@ export class ConnectionFormSSHPart extends FormPart<INetworkHandlerConfig, IConn
delete handlerConfig.secureProperties;
}
if (this.state.enabled && !this.state.savePassword) {
credentialsState.requireNetworkHandler(this.state.id);
}
if (handlerConfig) {
if (handlerConfig && this.state.enabled && !this.state.savePassword) {
this.state = getTrimmedSSHConfig(handlerConfig);
const sshConfigIndex = optionsPart.state.networkHandlersConfig?.findIndex(h => h.id === SSH_TUNNEL_ID);
@@ -20,7 +20,6 @@ import {
} from '@cloudbeaver/core-connections';
import { CachedMapAllKey } from '@cloudbeaver/core-resource';
import { toJS } from 'mobx';
import { connectionCredentialsStateContext } from '../Contexts/connectionCredentialsStateContext.js';
import { PROPERTY_FEATURE_SECURED } from './PROPERTY_FEATURE_SECURED.js';
import { SSL_CODE_NAME } from './SSL_CODE_NAME.js';
import type { INetworkHandlerConfig } from '../Options/IConnectionNetworkHanler.js';
@@ -79,7 +78,6 @@ export class ConnectionFormSSLPart extends FormPart<INetworkHandlerConfig, IConn
data: IFormState<IConnectionFormState>,
contexts: IExecutionContextProvider<IFormState<IConnectionFormState>>,
): Promise<void> {
const credentialsState = contexts.getContext(connectionCredentialsStateContext);
const optionsPart = getConnectionFormOptionsPart(this.formState);
if (!this.isChanged || !this.formState.state.config.driverId) {
@@ -138,11 +136,7 @@ export class ConnectionFormSSLPart extends FormPart<INetworkHandlerConfig, IConn
}
}
if (handler.enabled && !handler.savePassword) {
credentialsState.requireNetworkHandler(handler.id);
}
if (this.isChanged) {
if (this.isChanged && handler.enabled && !handler.savePassword) {
this.state = trimSSLConfig(handlerConfig);
const sslConfigIndex = optionsPart.state.networkHandlersConfig?.findIndex(h => (handlerConfig.id || SSL_CODE_NAME) === h.id);
@@ -13,7 +13,6 @@ export * from './ConnectionForm/Options/ConnectionOptionsTabService.js';
export * from './ConnectionForm/DriverProperties/ConnectionDriverPropertiesTabService.js';
export * from './ConnectionForm/SSH/ConnectionSSHTabService.js';
export * from './ConnectionForm/OriginInfo/ConnectionOriginInfoTabService.js';
export * from './ConnectionForm/Contexts/connectionCredentialsStateContext.js';
export * from './ConnectionForm/ConnectionFormBaseActionsLoader.js';
export * from './ConnectionForm/ConnectionFormLoader.js';
export * from './ConnectionForm/IConnectionFormState.js';