diff --git a/webapp/packages/core-connections/src/ConnectionInfoResource.ts b/webapp/packages/core-connections/src/ConnectionInfoResource.ts index aa64be5228..ae7a32f3fe 100644 --- a/webapp/packages/core-connections/src/ConnectionInfoResource.ts +++ b/webapp/packages/core-connections/src/ConnectionInfoResource.ts @@ -55,7 +55,6 @@ export type ConnectionInitConfig = Omit< | 'includeCredentialsSaved' | 'includeProperties' | 'includeProviderProperties' - | 'includeSharedSecrets' | 'customIncludeOptions' >; export type ConnectionInfoIncludes = Omit; @@ -595,7 +594,6 @@ export class ConnectionInfoResource extends CachedMapResource { + constructor( + private readonly graphQLService: GraphQLService, + private connectionInfoResource: ConnectionInfoResource, + ) { + super(); + this.sync(connectionInfoResource, key => { + const connectionInfoProjectKey = this.aliases.isAlias(key, ConnectionInfoProjectKey); + const connectionInfoActiveProjectKey = this.aliases.isAlias(key, ConnectionInfoActiveProjectKey); + + if (connectionInfoProjectKey) { + return resourceKeyList( + connectionInfoResource + .get(connectionInfoProjectKey as any as ResourceKeyList) + ?.filter(isDefined) + .map(createConnectionParam), + ); + } + + if (connectionInfoActiveProjectKey) { + return resourceKeyList( + connectionInfoResource + .get(connectionInfoActiveProjectKey as any as ResourceKeyList) + ?.filter(isDefined) + .map(createConnectionParam), + ); + } + + return key; + }); + this.connectionInfoResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + protected async loader(originalKey: ResourceKey): Promise> { + if (isResourceAlias(originalKey)) { + throw new Error('Aliases are not supported in this resource'); + } + + await ResourceKeyUtils.forEachAsync(originalKey, async key => { + const { connections } = await this.graphQLService.sdk.getPublicConnectionSecrets({ + projectId: key.projectId, + connectionId: key.connectionId, + }); + + if (connections.length === 0) { + throw new Error('Connection not found'); + } + const connection = connections[0]; + + this.set(key, connection.sharedSecrets); + }); + + return this.data; + } + + isKeyEqual(param: IConnectionInfoParams, second: IConnectionInfoParams): boolean { + return isConnectionInfoParamEqual(param, second); + } + + protected validateKey(key: IConnectionInfoParams): boolean { + const parse = CONNECTION_INFO_PARAM_SCHEMA.safeParse(toJS(key)); + if (!parse.success) { + this.logger.warn(`Invalid resource key ${schemaValidationError(parse.error, { prefix: null }).toString()}`); + } + return parse.success; + } +} diff --git a/webapp/packages/core-connections/src/index.ts b/webapp/packages/core-connections/src/index.ts index f00de1eb2d..9e1b444c2f 100644 --- a/webapp/packages/core-connections/src/index.ts +++ b/webapp/packages/core-connections/src/index.ts @@ -40,6 +40,7 @@ export * from './ContainerResource'; export * from './ConnectionsLocaleService'; export * from './createConnectionFolderParam'; export * from './DatabaseAuthModelsResource'; +export * from './ConnectionPublicSecretsResource'; export * from './DatabaseConnection'; export * from './DBDriverResource'; export * from './CONNECTION_INFO_PARAM_SCHEMA'; diff --git a/webapp/packages/core-connections/src/manifest.ts b/webapp/packages/core-connections/src/manifest.ts index a0ea16a88f..375e803ebf 100644 --- a/webapp/packages/core-connections/src/manifest.ts +++ b/webapp/packages/core-connections/src/manifest.ts @@ -30,5 +30,6 @@ export const manifest: PluginManifest = { () => import('./ConnectionInfoEventHandler').then(m => m.ConnectionInfoEventHandler), () => import('./ConnectionFolderEventHandler').then(m => m.ConnectionFolderEventHandler), () => import('./ConnectionsSettingsService').then(m => m.ConnectionsSettingsService), + () => import('./ConnectionPublicSecretsResource').then(m => m.ConnectionPublicSecretsResource), ], }; diff --git a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql index b0678f2f0d..7aee378640 100644 --- a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql @@ -9,7 +9,6 @@ mutation closeConnection( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: closeConnection(projectId: $projectId, id: $connectionId) { diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql index 888eb15480..9af020fc7a 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql @@ -9,7 +9,6 @@ mutation createConnection( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: createConnection(projectId: $projectId, config: $config) { diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql index 1e67270c7e..9115537615 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql @@ -10,7 +10,6 @@ mutation createConnectionFromNode( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: copyConnectionFromNode(projectId: $projectId, nodePath: $nodePath, config: $config) { diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql index b51d252f19..54dda8b0fa 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql @@ -10,7 +10,6 @@ mutation createConnectionFromTemplate( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: createConnectionFromTemplate(projectId: $projectId, templateId: $templateId, connectionName: $connectionName) { diff --git a/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql b/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql index 5ebee78f97..7d28702d00 100644 --- a/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql +++ b/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql @@ -8,7 +8,6 @@ query getTemplateConnections( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connections: templateConnections(projectId: $projectId) { diff --git a/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql b/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql index 83877443b6..a147612f7c 100644 --- a/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql +++ b/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql @@ -10,7 +10,6 @@ query getUserConnections( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connections: userConnections(projectId: $projectId, id: $connectionId, projectIds: $projectIds) { diff --git a/webapp/packages/core-sdk/src/queries/connections/initConnection.gql b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql index 360b91e7c6..98522e47a1 100644 --- a/webapp/packages/core-sdk/src/queries/connections/initConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql @@ -14,7 +14,6 @@ mutation initConnection( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: initConnection( diff --git a/webapp/packages/core-sdk/src/queries/connections/secrets/getPublicConnectionSecrets.gql b/webapp/packages/core-sdk/src/queries/connections/secrets/getPublicConnectionSecrets.gql new file mode 100644 index 0000000000..77cdd56dac --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/secrets/getPublicConnectionSecrets.gql @@ -0,0 +1,8 @@ +query getPublicConnectionSecrets($projectId: ID!, $connectionId: ID!) { + connections: userConnections(projectId: $projectId, id: $connectionId) { + sharedSecrets { + displayName + secretId + } + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql b/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql index 9b8703396d..c5cf9278ee 100644 --- a/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql +++ b/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql @@ -10,7 +10,6 @@ mutation setConnectionNavigatorSettings( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: setConnectionNavigatorSettings(projectId: $projectId, id: $connectionId, settings: $settings) { diff --git a/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql b/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql index 101fce9be2..ebabddc440 100644 --- a/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql @@ -9,7 +9,6 @@ mutation updateConnection( $includeAuthNeeded: Boolean! $includeProperties: Boolean! $includeProviderProperties: Boolean! - $includeSharedSecrets: Boolean! $customIncludeOptions: Boolean! ) { connection: updateConnection(projectId: $projectId, config: $config) { diff --git a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql index ce53eb6d70..bd0b84abee 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql @@ -40,10 +40,6 @@ fragment DatabaseConnection on ConnectionInfo { ...ObjectOriginInfo } - sharedSecrets @include(if: $includeSharedSecrets) { - displayName - secretId - } authNeeded @include(if: $includeAuthNeeded) authModel diff --git a/webapp/packages/plugin-connection-template/src/TemplateConnectionsResource.ts b/webapp/packages/plugin-connection-template/src/TemplateConnectionsResource.ts index f9fc69210e..d82f877b7d 100644 --- a/webapp/packages/plugin-connection-template/src/TemplateConnectionsResource.ts +++ b/webapp/packages/plugin-connection-template/src/TemplateConnectionsResource.ts @@ -68,7 +68,6 @@ export class TemplateConnectionsResource extends CachedDataResource = observer(function DatabaseAuthDialog({ payload, options, rejectDialog, resolveDialog }) { const connectionInfoLoader = useResource(DatabaseAuthDialog, ConnectionInfoResource, { key: payload.connection, - includes: ['includeAuthNeeded', 'includeSharedSecrets', 'includeNetworkHandlersConfig', 'includeCredentialsSaved'], + includes: ['includeAuthNeeded', 'includeNetworkHandlersConfig', 'includeCredentialsSaved'], }); const translate = useTranslate(); const driverLoader = useResource(DatabaseAuthDialog, DBDriverResource, connectionInfoLoader.data?.driverId || null); - const useSharedCredentials = (connectionInfoLoader.data?.sharedSecrets?.length || 0) > 1; + const connectionPublicSecretsLoader = useResource(DatabaseSecretAuthDialog, ConnectionPublicSecretsResource, payload.connection); + const useSharedCredentials = (connectionPublicSecretsLoader.data?.length || 0) > 1; let subtitle = connectionInfoLoader.data?.name; diff --git a/webapp/packages/plugin-connections/src/DatabaseAuthDialog/DatabaseSecretAuthDialog/DatabaseSecretAuthDialog.tsx b/webapp/packages/plugin-connections/src/DatabaseAuthDialog/DatabaseSecretAuthDialog/DatabaseSecretAuthDialog.tsx index c5c09f4125..6a6d005afe 100644 --- a/webapp/packages/plugin-connections/src/DatabaseAuthDialog/DatabaseSecretAuthDialog/DatabaseSecretAuthDialog.tsx +++ b/webapp/packages/plugin-connections/src/DatabaseAuthDialog/DatabaseSecretAuthDialog/DatabaseSecretAuthDialog.tsx @@ -20,7 +20,7 @@ import { useObservableRef, useResource, } from '@cloudbeaver/core-blocks'; -import { ConnectionInfoResource, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; +import { ConnectionInfoResource, ConnectionPublicSecretsResource, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; interface Props { connectionKey: IConnectionInfoParams; @@ -30,7 +30,7 @@ interface Props { export const DatabaseSecretAuthDialog = observer(function DatabaseSecretAuthDialog({ connectionKey, onLogin }) { const connectionInfoLoader = useResource(DatabaseSecretAuthDialog, ConnectionInfoResource, { key: connectionKey, - includes: ['includeAuthNeeded', 'includeSharedSecrets', 'includeNetworkHandlersConfig', 'includeCredentialsSaved'], + includes: ['includeAuthNeeded', 'includeNetworkHandlersConfig', 'includeCredentialsSaved'], }); const state = useObservableRef( () => ({ @@ -43,7 +43,8 @@ export const DatabaseSecretAuthDialog = observer(function DatabaseSecretA }, false, ); - const secrets = connectionInfoLoader.data?.sharedSecrets || []; + const connectionPublicSecretsLoader = useResource(DatabaseSecretAuthDialog, ConnectionPublicSecretsResource, connectionKey); + const secrets = connectionPublicSecretsLoader.data || []; async function handleSecretSelect(secretId: string) { try {