CB-4067 fixes SSL part

This commit is contained in:
sergeyteleshev
2025-03-05 22:26:12 +01:00
parent 625c490243
commit 6f4d696ad4
3 changed files with 62 additions and 95 deletions
@@ -9,8 +9,8 @@ import { FormPart, type IFormState } from '@cloudbeaver/core-ui';
import type { IExecutionContextProvider } from '@cloudbeaver/core-executor';
import type { IConnectionFormStateRefactored } from '../IConnectionFormStateRefactored.js';
import type { NetworkHandlerConfigInput } from '@cloudbeaver/core-sdk';
import { isNotNullDefined, isObjectsEqual } from '@cloudbeaver/core-utils';
import { type NetworkHandlerConfigInput } from '@cloudbeaver/core-sdk';
import { isNotNullDefined } from '@cloudbeaver/core-utils';
import { getSSLDriverHandler } from './getSSLDriverHandler.js';
import {
createConnectionParam,
@@ -19,21 +19,28 @@ import {
type NetworkHandlerResource,
} from '@cloudbeaver/core-connections';
import { CachedMapAllKey } from '@cloudbeaver/core-resource';
import { getSSLDefaultConfig } from './getSSLDefaultConfig.js';
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';
import { getSSLDefaultConfig } from './getSSLDefaultConfig.js';
// TODO should I have networkHandler state here?
export class ConnectionFormSSLPart extends FormPart<void, IConnectionFormStateRefactored> {
const DEFAULT_SSL_NETWORK_HANDLER: INetworkHandlerConfig = {
id: SSL_CODE_NAME,
enabled: false,
properties: {},
secureProperties: {},
};
export class ConnectionFormSSLPart extends FormPart<INetworkHandlerConfig, IConnectionFormStateRefactored> {
constructor(
formState: IFormState<IConnectionFormStateRefactored>,
private readonly dbDriverResource: DBDriverResource,
private readonly networkHandlerResource: NetworkHandlerResource,
private readonly connectionInfoResource: ConnectionInfoResource,
) {
super(formState);
super(formState, DEFAULT_SSL_NETWORK_HANDLER);
}
protected override async loader(): Promise<void> {
@@ -43,70 +50,54 @@ export class ConnectionFormSSLPart extends FormPart<void, IConnectionFormStateRe
const driver = await this.dbDriverResource.load(this.formState.state.config.driverId);
const handlers = await this.networkHandlerResource.load(CachedMapAllKey);
const handler = getSSLDriverHandler(handlers, driver?.applicableNetworkHandlers ?? []);
const info = this.connectionInfoResource.get(
createConnectionParam({
id: this.formState.state.config.connectionId!,
projectId: this.formState.state.projectId,
}),
);
if (!handler) {
return;
}
const info = this.connectionInfoResource.get(createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId!));
const initialConfig = info?.networkHandlersConfig?.find(h => h.id === handler.id);
if (!this.formState.state.config.networkHandlersConfig) {
this.formState.state.config.networkHandlersConfig = [];
}
if (!this.formState.state.config.networkHandlersConfig.some(state => state.id === handler.id)) {
if (!this.formState.state.config.networkHandlersConfig?.some(state => state.id === handler.id)) {
const config: NetworkHandlerConfigInput = initialConfig ? toJS(initialConfig) : getSSLDefaultConfig(handler.id);
if (config.secureProperties) {
config.properties = { ...config.properties, ...config.secureProperties };
}
this.formState.state.config.networkHandlersConfig.push(config);
this.setInitialState(config);
return;
}
this.setInitialState(initialConfig ?? DEFAULT_SSL_NETWORK_HANDLER);
}
protected override async format(
data: IFormState<IConnectionFormStateRefactored>,
contexts: IExecutionContextProvider<IFormState<IConnectionFormStateRefactored>>,
): Promise<void> {
const config = this.formState.state.config;
const credentialsState = contexts.getContext(connectionCredentialsStateContext);
const info = this.connectionInfoResource.get(
createConnectionParam({
id: data.state.config.connectionId!,
projectId: data.state.projectId,
}),
);
if (!config.networkHandlersConfig || config.networkHandlersConfig.length === 0 || !config.driverId) {
if (!this.isChanged || !this.formState.state.config.driverId) {
return;
}
const driver = await this.dbDriverResource.load(config.driverId);
const driver = await this.dbDriverResource.load(this.formState.state.config.driverId);
const handlers = await this.networkHandlerResource.load(CachedMapAllKey);
const handler = config.networkHandlersConfig.find(
handler => driver?.applicableNetworkHandlers.includes(handler.id) && handlers.some(h => h.id === handler.id && h.codeName === SSL_CODE_NAME),
);
const handler = driver?.applicableNetworkHandlers.includes(this.state.id) ? this.state : undefined;
const descriptor = handlers.find(h => h.id === handler?.id);
if (!handler) {
return;
}
const initial = info?.networkHandlersConfig?.find(h => h.id === handler.id);
const handlerConfig: NetworkHandlerConfigInput = toJS(handler);
handlerConfig.savePassword = handler.savePassword || config.sharedCredentials;
// TODO should I have formstate.config here?
handlerConfig.savePassword = handler.savePassword || this.formState.state.config.sharedCredentials;
const changed = isChanged(handlerConfig, initial);
if (changed && descriptor) {
if (this.isChanged && descriptor) {
for (const descriptorProperty of descriptor.properties) {
if (!descriptorProperty.id) {
continue;
@@ -123,7 +114,7 @@ export class ConnectionFormSSLPart extends FormPart<void, IConnectionFormStateRe
if (secured) {
const value = handlerConfig.properties[key];
const propertyChanged = initial?.secureProperties?.[key] !== value;
const propertyChanged = this.initialState?.secureProperties?.[key] !== value;
if (propertyChanged) {
handlerConfig.secureProperties[key] = toJS(value);
@@ -150,33 +141,39 @@ export class ConnectionFormSSLPart extends FormPart<void, IConnectionFormStateRe
credentialsState.requireNetworkHandler(handler.id);
}
if (changed) {
if (!config.networkHandlersConfig) {
config.networkHandlersConfig = [];
}
trimSSLConfig(handlerConfig);
config.networkHandlersConfig.push(handlerConfig);
if (this.isChanged) {
this.state = trimSSLConfig(handlerConfig);
}
}
protected override saveChanges(
protected override async saveChanges(
data: IFormState<IConnectionFormStateRefactored>,
contexts: IExecutionContextProvider<IFormState<IConnectionFormStateRefactored>>,
): Promise<void> {
return Promise.resolve();
const info = this.connectionInfoResource.get(createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId!));
await this.connectionInfoResource.update(createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId!), {
connectionId: this.formState.state.config.connectionId,
networkHandlersConfig: [
...(info?.networkHandlersConfig ?? []),
{
...this.state,
id: this.state.id,
},
],
});
}
}
function trimSSLConfig(input: NetworkHandlerConfigInput) {
function trimSSLConfig(input: INetworkHandlerConfig): INetworkHandlerConfig {
const { secureProperties } = input;
if (!secureProperties) {
return;
return input;
}
if (!Object.keys(secureProperties).length) {
return;
return input;
}
for (const key in secureProperties) {
@@ -184,22 +181,6 @@ function trimSSLConfig(input: NetworkHandlerConfigInput) {
secureProperties[key] = secureProperties[key]?.trim();
}
}
}
function isChanged(handler: NetworkHandlerConfigInput, initial?: NetworkHandlerConfigInput) {
if (!initial && !handler.enabled) {
return false;
}
const initialProperties = { ...(initial?.properties ?? {}), ...(initial?.secureProperties ?? {}) };
if (
handler.enabled !== initial?.enabled ||
handler.savePassword !== initial?.savePassword ||
!isObjectsEqual(handler.properties, initialProperties)
) {
return true;
}
return false;
return input;
}
@@ -27,23 +27,20 @@ import { useService } from '@cloudbeaver/core-di';
import { ProjectInfoResource } from '@cloudbeaver/core-projects';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import type { NetworkHandlerConfigInput, NetworkHandlerDescriptor } from '@cloudbeaver/core-sdk';
import type { IFormState, TabContainerPanelComponent } from '@cloudbeaver/core-ui';
import type { TabContainerPanelComponent } from '@cloudbeaver/core-ui';
import { isSafari } from '@cloudbeaver/core-utils';
import { SAVED_VALUE_INDICATOR } from './SAVED_VALUE_INDICATOR.js';
import styles from './SSL.module.css';
import type { IConnectionFormStateRefactored } from '../IConnectionFormStateRefactored.js';
import type { IConnectionFormPropsRefactored } from '../IConnectionFormStateRefactored.js';
import { ConnectionInfoResource, createConnectionParam } from '@cloudbeaver/core-connections';
interface Props {
interface Props extends IConnectionFormPropsRefactored {
handler: NetworkHandlerDescriptor;
handlerState: NetworkHandlerConfigInput;
formState: IFormState<IConnectionFormStateRefactored>;
sharedCredentials: boolean;
template: boolean;
}
export const SSL: TabContainerPanelComponent<Props> = observer(function SSL({ formState, sharedCredentials, template, handler, handlerState }) {
export const SSL: TabContainerPanelComponent<Props> = observer(function SSL({ formState, handler, handlerState }) {
const translate = useTranslate();
const style = useS(styles);
@@ -73,7 +70,7 @@ export const SSL: TabContainerPanelComponent<Props> = observer(function SSL({ fo
properties={handler.properties}
category={null}
disabled={disabled || !enabled}
isSaved={p => !!p.id && initialHandler?.secureProperties?.[p.id] === SAVED_VALUE_INDICATOR}
isSaved={p => !!p.id && initialHandler?.secureProperties[p.id] === SAVED_VALUE_INDICATOR}
autofillToken={autofillToken}
hideEmptyPlaceholder
showRememberTip
@@ -89,7 +86,7 @@ export const SSL: TabContainerPanelComponent<Props> = observer(function SSL({ fo
properties={handler.properties}
category={category}
disabled={disabled || !enabled}
isSaved={p => !!p.id && initialHandler?.secureProperties?.[p.id] === SAVED_VALUE_INDICATOR}
isSaved={p => !!p.id && initialHandler?.secureProperties[p.id] === SAVED_VALUE_INDICATOR}
autofillToken={autofillToken}
hideEmptyPlaceholder
showRememberTip
@@ -98,12 +95,14 @@ export const SSL: TabContainerPanelComponent<Props> = observer(function SSL({ fo
</React.Fragment>
))}
{credentialsSavingEnabled && !template && !sharedCredentials && (
{/* TODO use formState.state.config??? */}
{credentialsSavingEnabled && !formState.state.config.template && !formState.state.config.sharedCredentials && (
<FieldCheckbox
id={handler.id + '_savePassword'}
name="savePassword"
state={handlerState}
disabled={disabled || !enabled || sharedCredentials}
// TODO use formState.config???
disabled={disabled || !enabled || formState.state.config.sharedCredentials}
title={translate(
!isSharedProject || serverConfigResource.data?.distributed
? 'connections_connection_authentication_save_credentials_for_user_tooltip'
@@ -12,38 +12,25 @@ import { DBDriverResource, NetworkHandlerResource } from '@cloudbeaver/core-conn
import { CachedMapAllKey } from '@cloudbeaver/core-resource';
import type { TabContainerTabComponent } from '@cloudbeaver/core-ui';
import { getSSLDefaultConfig } from './getSSLDefaultConfig.js';
import { getSSLDriverHandler } from './getSSLDriverHandler.js';
import { SSL } from './SSL.js';
import type { ConnectionFormRefactoredProps } from '../ConnectionFormServiceRefactored.js';
import { getConnectionFormSSLPart } from './getConnectionFormSSLPart.js';
import type { IConnectionFormPropsRefactored } from '../IConnectionFormStateRefactored.js';
export const SSLPanel: TabContainerTabComponent<ConnectionFormRefactoredProps> = observer(function SSLPanel(props) {
export const SSLPanel: TabContainerTabComponent<IConnectionFormPropsRefactored> = observer(function SSLPanel(props) {
const networkHandlerResource = useResource(SSLPanel, NetworkHandlerResource, CachedMapAllKey);
const dbDriverResource = useResource(SSLPanel, DBDriverResource, props.formState.state.config.driverId ?? null);
const SSLPart = getConnectionFormSSLPart(props.formState);
const handler = getSSLDriverHandler(networkHandlerResource.resource.values, dbDriverResource.data?.applicableNetworkHandlers ?? []);
const SSLPart = getConnectionFormSSLPart(props.formState);
if (SSLPart.isLoaded() && handler && !props.formState.state.config.networkHandlersConfig?.some(state => state.id === handler?.id)) {
props.formState.state.config.networkHandlersConfig?.push(getSSLDefaultConfig(handler.id));
}
const handlerState = SSLPart.state;
const handlerState = props.formState.state.config.networkHandlersConfig?.find(h => h.id === handler?.id);
useAutoLoad(SSLPanel, [SSLPart]);
useAutoLoad(SSLPanel, SSLPart);
if (!handler || !handlerState) {
return null;
}
return (
<SSL
{...props}
sharedCredentials={Boolean(props.formState.state.config.sharedCredentials)}
template={Boolean(props.formState.state.config.template)}
handler={handler}
handlerState={handlerState}
/>
);
return <SSL {...props} handler={handler} handlerState={handlerState} />;
});