diff --git a/webapp/packages/core-authentication/src/TeamInfoMetaParametersResource.ts b/webapp/packages/core-authentication/src/TeamInfoMetaParametersResource.ts new file mode 100644 index 0000000000..f1e213544d --- /dev/null +++ b/webapp/packages/core-authentication/src/TeamInfoMetaParametersResource.ts @@ -0,0 +1,78 @@ +/* + * 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. + */ +import { injectable } from '@cloudbeaver/core-di'; +import { CachedMapAllKey, CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource'; +import { GraphQLService } from '@cloudbeaver/core-sdk'; + +import type { TeamMetaParameter } from './TeamMetaParametersResource.js'; +import { TeamsResource } from './TeamsResource.js'; + +@injectable() +export class TeamInfoMetaParametersResource extends CachedMapResource { + constructor( + private readonly graphQLService: GraphQLService, + private readonly teamsResource: TeamsResource, + ) { + super(); + + this.sync(this.teamsResource); + this.teamsResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + protected async loader(param: ResourceKey): Promise> { + const all = this.aliases.isAlias(param, CachedMapAllKey); + const teamsList: [string, TeamMetaParameter][] = []; + + await ResourceKeyUtils.forEachAsync(param, async key => { + let teamId: string | undefined; + + if (!isResourceAlias(key)) { + teamId = key; + } + + const { teams } = await this.graphQLService.sdk.getTeamsListMetaParameters({ + teamId, + }); + + if (!teams.length) { + throw new Error(`Team ${teamId} not found`); + } + + const metaParameters = teams[0]?.metaParameters; + + if (teamId) { + teamsList.push([teamId, metaParameters]); + } + }); + + const key = resourceKeyList(teamsList.map(([teamId]) => teamId)); + const value = teamsList.map(([_, metaParameters]) => metaParameters); + + if (all) { + this.replace(key, value); + } else { + this.set(key, value); + } + + return this.data; + } + + async setMetaParameters(teamId: string, parameters: Record): Promise { + await this.performUpdate(teamId, [], async () => { + await this.graphQLService.sdk.saveTeamMetaParameters({ teamId, parameters }); + + if (this.data) { + this.data.set(teamId, parameters as TeamMetaParameter); + } + }); + } + + protected validateKey(key: string): boolean { + return typeof key === 'string'; + } +} diff --git a/webapp/packages/core-authentication/src/TeamsResource.ts b/webapp/packages/core-authentication/src/TeamsResource.ts index d32ec4bb07..832c1d880c 100644 --- a/webapp/packages/core-authentication/src/TeamsResource.ts +++ b/webapp/packages/core-authentication/src/TeamsResource.ts @@ -38,12 +38,11 @@ export class TeamsResource extends CachedMapResource { + async createTeam({ teamId, teamPermissions, teamName, description }: TeamInfo): Promise { const response = await this.graphQLService.sdk.createTeam({ teamId, teamName, description, - ...this.getDefaultIncludes(), ...this.getIncludesMap(teamId), }); @@ -55,24 +54,21 @@ export class TeamsResource extends CachedMapResource { + async updateTeam({ teamId, teamPermissions, teamName, description }: TeamInfo): Promise { const { team } = await this.graphQLService.sdk.updateTeam({ teamId, teamName, description, - ...this.getDefaultIncludes(), ...this.getIncludesMap(teamId), }); this.set(team.teamId, team); - await this.setMetaParameters(team.teamId, metaParameters); await this.setSubjectPermissions(team.teamId, teamPermissions); this.markOutdated(team.teamId); @@ -123,10 +119,6 @@ export class TeamsResource extends CachedMapResource): Promise { - await this.graphQLService.sdk.saveTeamMetaParameters({ teamId, parameters }); - } - protected async loader(originalKey: ResourceKey, includes?: string[]): Promise> { const all = this.aliases.isAlias(originalKey, CachedMapAllKey); const teamsList: TeamInfo[] = []; @@ -140,7 +132,6 @@ export class TeamsResource extends CachedMapResource { + constructor( + private readonly graphQLService: GraphQLService, + private readonly userInfoResource: UserInfoResource, + ) { + super(() => undefined, undefined); + + this.sync(this.userInfoResource); + } + + protected async loader(param: ResourceKey): Promise { + const { user } = await this.graphQLService.sdk.getActiveUserMetaParameters(); + + return user?.metaParameters; + } +} diff --git a/webapp/packages/core-authentication/src/UserInfoResource.ts b/webapp/packages/core-authentication/src/UserInfoResource.ts index bcf1b0e525..61d4c0bec7 100644 --- a/webapp/packages/core-authentication/src/UserInfoResource.ts +++ b/webapp/packages/core-authentication/src/UserInfoResource.ts @@ -60,7 +60,7 @@ export class UserInfoResource extends CachedDataResource null, undefined, ['customIncludeOriginDetails', 'includeConfigurationParameters']); + super(() => null, undefined, ['includeConfigurationParameters']); this.onUserChange = new SyncExecutor(); this.onException = new SyncExecutor(); @@ -110,7 +110,6 @@ export class UserInfoResource extends CachedDataResource { + constructor( + private readonly graphQLService: GraphQLService, + private readonly usersResource: UsersResource, + ) { + super(); + + this.sync(this.usersResource); + this.usersResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + async setMetaParameters(userId: string, parameters: Record): Promise { + await this.performUpdate(userId, undefined, async () => { + await this.graphQLService.sdk.saveUserMetaParameters({ userId, parameters }); + + if (this.data) { + this.data.set(userId, parameters as UserMetaParameter); + } + }); + } + + protected async loader(originalKey: ResourceKey): Promise> { + const all = this.aliases.isAlias(originalKey, CachedMapAllKey); + const keys = resourceKeyList([]); + + if (all) { + throw new Error('Loading all users is prohibited'); + } + + const userMetaParametersList: UserMetaParameter[] = []; + + await ResourceKeyUtils.forEachAsync(originalKey, async key => { + let userId: string | undefined; + + if (!isResourceAlias(key)) { + userId = key; + } + + if (userId !== undefined) { + const { user } = await this.graphQLService.sdk.getAdminUserMetaParameters({ + userId, + }); + + keys.push(userId); + userMetaParametersList.push(user.metaParameters); + } + }); + + this.set(keys, userMetaParametersList); + + return this.data; + } + + protected validateKey(key: string): boolean { + return typeof key === 'string'; + } +} diff --git a/webapp/packages/core-authentication/src/UsersOriginDetailsResource.ts b/webapp/packages/core-authentication/src/UsersOriginDetailsResource.ts new file mode 100644 index 0000000000..8ab8d596f6 --- /dev/null +++ b/webapp/packages/core-authentication/src/UsersOriginDetailsResource.ts @@ -0,0 +1,61 @@ +/* + * 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. + */ +import { injectable } from '@cloudbeaver/core-di'; +import { CachedMapAllKey, CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource'; +import { type AdminOriginDetailsFragment, GraphQLService } from '@cloudbeaver/core-sdk'; + +import { UsersResource } from './UsersResource.js'; + +@injectable() +export class UsersOriginDetailsResource extends CachedMapResource { + constructor( + private readonly graphQLService: GraphQLService, + private readonly usersResource: UsersResource, + ) { + super(); + + this.sync(this.usersResource); + this.usersResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + protected async loader(originalKey: ResourceKey): Promise> { + const all = this.aliases.isAlias(originalKey, CachedMapAllKey); + const keys = resourceKeyList([]); + + if (all) { + throw new Error('Loading all users is prohibited'); + } + + const userMetaParametersList: AdminOriginDetailsFragment[] = []; + + await ResourceKeyUtils.forEachAsync(originalKey, async key => { + let userId: string | undefined; + + if (!isResourceAlias(key)) { + userId = key; + } + + if (userId !== undefined) { + const { user } = await this.graphQLService.sdk.getAdminUserOriginDetails({ + userId, + }); + + keys.push(userId); + userMetaParametersList.push(user); + } + }); + + this.set(keys, userMetaParametersList); + + return this.data; + } + + protected validateKey(key: string): boolean { + return typeof key === 'string'; + } +} diff --git a/webapp/packages/core-authentication/src/UsersResource.ts b/webapp/packages/core-authentication/src/UsersResource.ts index 7597bedc00..09e3a23008 100644 --- a/webapp/packages/core-authentication/src/UsersResource.ts +++ b/webapp/packages/core-authentication/src/UsersResource.ts @@ -137,16 +137,11 @@ export class UsersResource extends CachedMapResource): Promise { - await this.graphQLService.sdk.saveUserMetaParameters({ userId, parameters }); - } - async create({ userId, authRole }: UserCreateOptions): Promise { const { user } = await this.graphQLService.sdk.createUser({ userId, authRole, enabled: false, - ...this.getDefaultIncludes(), ...this.getIncludesMap(userId), }); @@ -259,7 +254,6 @@ export class UsersResource extends CachedMapResource import('./TeamsResource.js').then(m => m.TeamsResource), () => import('./TeamRolesResource.js').then(m => m.TeamRolesResource), () => import('./UserConfigurationBootstrap.js').then(m => m.UserConfigurationBootstrap), + () => import('./UserInfoMetaParametersResource.js').then(m => m.UserInfoMetaParametersResource), () => import('./UserDataService.js').then(m => m.UserDataService), () => import('./UserInfoResource.js').then(m => m.UserInfoResource), + () => import('./UsersOriginDetailsResource.js').then(m => m.UsersOriginDetailsResource), () => import('./UserMetaParametersResource.js').then(m => m.UserMetaParametersResource), + () => import('./UsersMetaParametersResource.js').then(m => m.UsersMetaParametersResource), + () => import('./TeamInfoMetaParametersResource.js').then(m => m.TeamInfoMetaParametersResource), () => import('./UsersResource.js').then(m => m.UsersResource), ], }; diff --git a/webapp/packages/core-connections/src/ConnectionInfoOriginDetailsResource.ts b/webapp/packages/core-connections/src/ConnectionInfoOriginDetailsResource.ts new file mode 100644 index 0000000000..023b483e01 --- /dev/null +++ b/webapp/packages/core-connections/src/ConnectionInfoOriginDetailsResource.ts @@ -0,0 +1,99 @@ +/* + * 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. + */ +import { runInAction, toJS } from 'mobx'; + +import { injectable } from '@cloudbeaver/core-di'; +import { ProjectsService } from '@cloudbeaver/core-projects'; +import { CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource'; +import { type DatabaseConnectionOriginDetailsFragment, GraphQLService } from '@cloudbeaver/core-sdk'; +import { schemaValidationError } from '@cloudbeaver/core-utils'; + +import { CONNECTION_INFO_PARAM_SCHEMA, type IConnectionInfoParams } from './CONNECTION_INFO_PARAM_SCHEMA.js'; +import { ConnectionInfoResource, createConnectionParam, isConnectionInfoParamEqual } from './ConnectionInfoResource.js'; +import { parseConnectionKey } from './parseConnectionKey.js'; + +export type ConnectionInfoOriginDetails = DatabaseConnectionOriginDetailsFragment; + +@injectable() +export class ConnectionInfoOriginDetailsResource extends CachedMapResource { + constructor( + private readonly projectsService: ProjectsService, + private readonly graphQLService: GraphQLService, + private readonly connectionInfoResource: ConnectionInfoResource, + ) { + super(); + + this.sync(this.connectionInfoResource); + this.connectionInfoResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + protected async loader( + originalKey: ResourceKey, + _: any, + refresh?: boolean, + ): Promise> { + const connectionsList: ConnectionInfoOriginDetails[] = []; + let removedConnections: IConnectionInfoParams[] = []; + const parsed = parseConnectionKey({ + originalKey, + aliases: this.aliases, + isOutdated: this.isOutdated.bind(this), + activeProjects: this.projectsService.activeProjects, + refresh, + }); + + let { projectId } = parsed; + const { projectIds, key } = parsed; + + await ResourceKeyUtils.forEachAsync(key, async connectionKey => { + let connectionId: string | undefined; + if (!isResourceAlias(connectionKey)) { + projectId = connectionKey.projectId; + connectionId = connectionKey.connectionId; + } + + const { connections } = await this.graphQLService.sdk.getUserConnectionsOriginDetails({ + projectId, + connectionId, + projectIds, + }); + + if (connectionId && !connections.some(connection => connection.id === connectionId)) { + throw new Error(`Connection is not found (${connectionId})`); + } + + connectionsList.push(...connections); + }); + + runInAction(() => { + if (isResourceAlias(key)) { + removedConnections = ResourceKeyUtils.toList(this.aliases.transformToKey(key)).filter( + filterKey => !connectionsList.some(connection => isConnectionInfoParamEqual(filterKey, createConnectionParam(connection))), + ); + } + + this.delete(resourceKeyList(removedConnections)); + const keys = resourceKeyList(connectionsList.map(createConnectionParam)); + this.set(keys, connectionsList); + }); + + return this.data; + } + + override isKeyEqual(param: { projectId: string; connectionId: string }, second: { projectId: string; connectionId: string }): 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).toString(), { prefix: null })}`); + } + return parse.success; + } +} diff --git a/webapp/packages/core-connections/src/ConnectionInfoOriginResource.ts b/webapp/packages/core-connections/src/ConnectionInfoOriginResource.ts new file mode 100644 index 0000000000..bdc6dde9e7 --- /dev/null +++ b/webapp/packages/core-connections/src/ConnectionInfoOriginResource.ts @@ -0,0 +1,111 @@ +/* + * 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. + */ +import { runInAction, toJS } from 'mobx'; + +import { injectable } from '@cloudbeaver/core-di'; +import { ProjectsService } from '@cloudbeaver/core-projects'; +import { CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource'; +import { type DatabaseConnectionOriginFragment, GraphQLService } from '@cloudbeaver/core-sdk'; +import { schemaValidationError } from '@cloudbeaver/core-utils'; + +import { CONNECTION_INFO_PARAM_SCHEMA, type IConnectionInfoParams } from './CONNECTION_INFO_PARAM_SCHEMA.js'; +import { + ConnectionInfoActiveProjectKey, + ConnectionInfoProjectKey, + ConnectionInfoResource, + createConnectionParam, + isConnectionInfoParamEqual, +} from './ConnectionInfoResource.js'; +import { parseConnectionKey } from './parseConnectionKey.js'; + +export type ConnectionInfoOrigin = DatabaseConnectionOriginFragment; + +@injectable() +export class ConnectionInfoOriginResource extends CachedMapResource { + constructor( + private readonly projectsService: ProjectsService, + private readonly graphQLService: GraphQLService, + private readonly connectionInfoResource: ConnectionInfoResource, + ) { + super(); + + this.aliases.add(ConnectionInfoProjectKey, param => resourceKeyList(this.keys.filter(key => param.options.projectIds.includes(key.projectId)))); + + this.aliases.add(ConnectionInfoActiveProjectKey, () => + resourceKeyList(this.keys.filter(key => projectsService.activeProjects.some(({ id }) => id === key.projectId))), + ); + + this.sync(this.connectionInfoResource); + this.connectionInfoResource.onItemDelete.addHandler(this.delete.bind(this)); + } + + protected async loader( + originalKey: ResourceKey, + _: any, + refresh?: boolean, + ): Promise> { + const connectionsList: ConnectionInfoOrigin[] = []; + let removedConnections: IConnectionInfoParams[] = []; + const parsed = parseConnectionKey({ + originalKey, + aliases: this.aliases, + isOutdated: this.isOutdated.bind(this), + activeProjects: this.projectsService.activeProjects, + refresh, + }); + + let { projectId } = parsed; + const { projectIds, key } = parsed; + + await ResourceKeyUtils.forEachAsync(key, async connectionKey => { + let connectionId: string | undefined; + if (!isResourceAlias(connectionKey)) { + projectId = connectionKey.projectId; + connectionId = connectionKey.connectionId; + } + + const { connections } = await this.graphQLService.sdk.getUserConnectionsOrigin({ + projectId, + connectionId, + projectIds, + }); + + if (connectionId && !connections.some(connection => connection.id === connectionId)) { + throw new Error(`Connection is not found (${connectionId})`); + } + + connectionsList.push(...connections); + }); + + runInAction(() => { + if (isResourceAlias(key)) { + removedConnections = ResourceKeyUtils.toList(this.aliases.transformToKey(key)).filter( + filterKey => !connectionsList.some(connection => isConnectionInfoParamEqual(filterKey, createConnectionParam(connection))), + ); + } + + this.delete(resourceKeyList(removedConnections)); + const keys = resourceKeyList(connectionsList.map(createConnectionParam)); + this.set(keys, connectionsList); + }); + + return this.data; + } + + override 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).toString(), { prefix: null })}`); + } + return parse.success; + } +} diff --git a/webapp/packages/core-connections/src/ConnectionInfoResource.ts b/webapp/packages/core-connections/src/ConnectionInfoResource.ts index bf905e5431..6e6ec39cd0 100644 --- a/webapp/packages/core-connections/src/ConnectionInfoResource.ts +++ b/webapp/packages/core-connections/src/ConnectionInfoResource.ts @@ -41,14 +41,13 @@ import { CONNECTION_INFO_PARAM_SCHEMA, type IConnectionInfoParams } from './CONN import { ConnectionInfoEventHandler, type IConnectionInfoEvent } from './ConnectionInfoEventHandler.js'; import type { DatabaseConnection } from './DatabaseConnection.js'; import { DBDriverResource } from './DBDriverResource.js'; +import { parseConnectionKey } from './parseConnectionKey.js'; export type Connection = DatabaseConnection & { authProperties?: UserConnectionAuthPropertiesFragment[]; }; export type ConnectionInitConfig = Omit< InitConnectionMutationVariables, - | 'includeOrigin' - | 'customIncludeOriginDetails' | 'includeAuthProperties' | 'includeNetworkHandlersConfig' | 'includeAuthNeeded' @@ -492,33 +491,24 @@ export class ConnectionInfoResource extends CachedMapResource> { const connectionsList: Connection[] = []; - const projectKey = this.aliases.isAlias(originalKey, ConnectionInfoProjectKey); let removedConnections: IConnectionInfoParams[] = []; - let projectId: string | undefined; - let projectIds: string[] | undefined; - if (projectKey) { - projectIds = projectKey.options.projectIds; - } - - if (this.aliases.isAlias(originalKey, ConnectionInfoActiveProjectKey)) { - projectIds = this.projectsService.activeProjects.map(project => project.id); - } - - if (isResourceAlias(originalKey)) { - const key = this.aliases.transformToKey(originalKey); - const outdated = ResourceKeyUtils.filter(key, key => this.isOutdated(key, includes)); + const parsed = parseConnectionKey({ + originalKey, + aliases: this.aliases, + isOutdated: this.isOutdated.bind(this), + activeProjects: this.projectsService.activeProjects, + refresh, + }); - if (!refresh && outdated.length === 1) { - originalKey = outdated[0]!; // load only single connection - } - } + let { projectId } = parsed; + const { projectIds, key } = parsed; - await ResourceKeyUtils.forEachAsync(originalKey, async key => { + await ResourceKeyUtils.forEachAsync(key, async connectionKey => { let connectionId: string | undefined; - if (!isResourceAlias(key)) { - projectId = key.projectId; - connectionId = key.connectionId; + if (!isResourceAlias(connectionKey)) { + projectId = connectionKey.projectId; + connectionId = connectionKey.connectionId; } const { connections } = await this.graphQLService.sdk.getUserConnections({ @@ -526,7 +516,7 @@ export class ConnectionInfoResource extends CachedMapResource connection.id === connectionId)) { @@ -537,15 +527,15 @@ export class ConnectionInfoResource extends CachedMapResource { - if (isResourceAlias(originalKey)) { - removedConnections = ResourceKeyUtils.toList(this.aliases.transformToKey(originalKey)).filter( - key => !connectionsList.some(connection => isConnectionInfoParamEqual(key, createConnectionParam(connection))), + if (isResourceAlias(key)) { + removedConnections = ResourceKeyUtils.toList(this.aliases.transformToKey(key)).filter( + filterKey => !connectionsList.some(connection => isConnectionInfoParamEqual(filterKey, createConnectionParam(connection))), ); } this.delete(resourceKeyList(removedConnections)); - const key = resourceKeyList(connectionsList.map(createConnectionParam)); - this.set(key, connectionsList); + const keys = resourceKeyList(connectionsList.map(createConnectionParam)); + this.set(keys, connectionsList); }); this.sessionUpdate = false; @@ -587,9 +577,7 @@ export class ConnectionInfoResource extends CachedMapResource import('./ConnectionExecutionContext/ConnectionExecutionContextService.js').then(m => m.ConnectionExecutionContextService), () => import('./ConnectionsManagerService.js').then(m => m.ConnectionsManagerService), () => import('./ConnectionInfoResource.js').then(m => m.ConnectionInfoResource), + () => import('./ConnectionInfoOriginResource.js').then(m => m.ConnectionInfoOriginResource), + () => import('./ConnectionInfoOriginDetailsResource.js').then(m => m.ConnectionInfoOriginDetailsResource), () => import('./ConnectionToolsResource.js').then(m => m.ConnectionToolsResource), () => import('./ContainerResource.js').then(m => m.ContainerResource), () => import('./ConnectionsLocaleService.js').then(m => m.ConnectionsLocaleService), diff --git a/webapp/packages/core-connections/src/parseConnectionKey.ts b/webapp/packages/core-connections/src/parseConnectionKey.ts new file mode 100644 index 0000000000..1ab959187c --- /dev/null +++ b/webapp/packages/core-connections/src/parseConnectionKey.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ +import { isResourceAlias, ResourceAliases, type ResourceKey, ResourceKeyUtils } from '@cloudbeaver/core-resource'; +import { type ProjectInfo } from '@cloudbeaver/core-sdk'; + +import { type IConnectionInfoParams } from './CONNECTION_INFO_PARAM_SCHEMA.js'; +import { ConnectionInfoActiveProjectKey, ConnectionInfoProjectKey } from './ConnectionInfoResource.js'; + +type Args = { + originalKey: ResourceKey; + aliases: ResourceAliases; + isOutdated: (key: ResourceKey) => boolean; + activeProjects: ProjectInfo[]; + refresh?: boolean; +}; + +export function parseConnectionKey({ originalKey, aliases, isOutdated, activeProjects, refresh }: Args) { + const projectKey = aliases.isAlias(originalKey, ConnectionInfoProjectKey); + let projectId: string | undefined; + let projectIds: string[] | undefined; + + if (projectKey) { + projectIds = projectKey.options.projectIds; + } + + if (aliases.isAlias(originalKey, ConnectionInfoActiveProjectKey)) { + projectIds = activeProjects.map(project => project.id); + } + + if (isResourceAlias(originalKey)) { + const key = aliases.transformToKey(originalKey); + const outdated = ResourceKeyUtils.filter(key, key => isOutdated(key)); + + if (!refresh && outdated.length === 1 && outdated[0]) { + originalKey = outdated[0]; // load only single connection + } + } + + return { projectId, projectIds, key: originalKey }; +} diff --git a/webapp/packages/core-resource/src/index.ts b/webapp/packages/core-resource/src/index.ts index f261267d05..62137dbea1 100644 --- a/webapp/packages/core-resource/src/index.ts +++ b/webapp/packages/core-resource/src/index.ts @@ -25,6 +25,7 @@ export * from './Resource/ICachedResourceMetadata.js'; export * from './Resource/IResource.js'; export * from './Resource/Resource.js'; export * from './Resource/ResourceAlias.js'; +export * from './Resource/ResourceAliases.js'; export * from './Resource/ResourceError.js'; export * from './Resource/ResourceKey.js'; export * from './Resource/ResourceKeyAlias.js'; diff --git a/webapp/packages/core-sdk/src/queries/authentication/authLogin.gql b/webapp/packages/core-sdk/src/queries/authentication/authLogin.gql index cbb0ea8b7f..60678fe692 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/authLogin.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/authLogin.gql @@ -1,11 +1,4 @@ -query authLogin( - $provider: ID! - $configuration: ID - $credentials: Object - $linkUser: Boolean - $customIncludeOriginDetails: Boolean! - $forceSessionsLogout: Boolean -) { +query authLogin($provider: ID!, $configuration: ID, $credentials: Object, $linkUser: Boolean, $forceSessionsLogout: Boolean) { authInfo: authLogin( provider: $provider configuration: $configuration diff --git a/webapp/packages/core-sdk/src/queries/authentication/getActiveUser.gql b/webapp/packages/core-sdk/src/queries/authentication/getActiveUser.gql index 6e8bca4484..1419b31c6c 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/getActiveUser.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/getActiveUser.gql @@ -1,10 +1,9 @@ -query getActiveUser($includeMetaParameters: Boolean!, $includeConfigurationParameters: Boolean!, $customIncludeOriginDetails: Boolean!) { +query getActiveUser($includeConfigurationParameters: Boolean!) { user: activeUser { userId displayName authRole linkedAuthProviders - metaParameters @include(if: $includeMetaParameters) configurationParameters @include(if: $includeConfigurationParameters) teams { teamId diff --git a/webapp/packages/core-sdk/src/queries/authentication/getActiveUserMetaParameters.gql b/webapp/packages/core-sdk/src/queries/authentication/getActiveUserMetaParameters.gql new file mode 100644 index 0000000000..4476f11be2 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/getActiveUserMetaParameters.gql @@ -0,0 +1,5 @@ +query getActiveUserMetaParameters { + user: activeUser { + metaParameters + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/getAuthStatus.gql b/webapp/packages/core-sdk/src/queries/authentication/getAuthStatus.gql index 57f3446b30..add143143d 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/getAuthStatus.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/getAuthStatus.gql @@ -1,17 +1,10 @@ -query getAuthStatus( - $authId: ID! - $linkUser: Boolean - $customIncludeOriginDetails: Boolean! -) { - authInfo: authUpdateStatus( - authId: $authId, - linkUser: $linkUser - ) { - redirectLink - authId - authStatus - userTokens { - ...AuthToken - } +query getAuthStatus($authId: ID!, $linkUser: Boolean) { + authInfo: authUpdateStatus(authId: $authId, linkUser: $linkUser) { + redirectLink + authId + authStatus + userTokens { + ...AuthToken } + } } diff --git a/webapp/packages/core-sdk/src/queries/authentication/teams/createTeam.gql b/webapp/packages/core-sdk/src/queries/authentication/teams/createTeam.gql index 7654ea781e..27e14f972c 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/teams/createTeam.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/teams/createTeam.gql @@ -1,5 +1,5 @@ -query createTeam($teamId: ID!, $teamName: String, $description: String, $includeMetaParameters: Boolean!) { +query createTeam($teamId: ID!, $teamName: String, $description: String) { team: createTeam(teamId: $teamId, teamName: $teamName, description: $description) { ...AdminTeamInfo } -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsList.gql b/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsList.gql index fbbb425072..9286991546 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsList.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsList.gql @@ -1,5 +1,5 @@ -query getTeamsList($teamId: ID, $includeMetaParameters: Boolean!) { +query getTeamsList($teamId: ID) { teams: listTeams(teamId: $teamId) { ...AdminTeamInfo - } -} \ No newline at end of file + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsListMetaParameters.gql b/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsListMetaParameters.gql new file mode 100644 index 0000000000..ee62bb6314 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/teams/getTeamsListMetaParameters.gql @@ -0,0 +1,5 @@ +query getTeamsListMetaParameters($teamId: ID) { + teams: listTeams(teamId: $teamId) { + ...AdminTeamInfoMetaParameters + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/teams/updateTeam.gql b/webapp/packages/core-sdk/src/queries/authentication/teams/updateTeam.gql index 20bafa082b..a249d83c36 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/teams/updateTeam.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/teams/updateTeam.gql @@ -1,5 +1,5 @@ -query updateTeam($teamId: ID!, $teamName: String, $description: String, $includeMetaParameters: Boolean!) { +query updateTeam($teamId: ID!, $teamName: String, $description: String) { team: updateTeam(teamId: $teamId, teamName: $teamName, description: $description) { ...AdminTeamInfo } -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/updateUserPreferences.gql b/webapp/packages/core-sdk/src/queries/authentication/updateUserPreferences.gql index 51e93b791e..2a13182cb3 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/updateUserPreferences.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/updateUserPreferences.gql @@ -1,15 +1,9 @@ -mutation updateUserPreferences( - $preferences: Object! - $includeMetaParameters: Boolean! - $includeConfigurationParameters: Boolean! - $customIncludeOriginDetails: Boolean! -) { +mutation updateUserPreferences($preferences: Object!, $includeConfigurationParameters: Boolean!) { user: setUserPreferences(preferences: $preferences) { userId displayName authRole linkedAuthProviders - metaParameters @include(if: $includeMetaParameters) configurationParameters @include(if: $includeConfigurationParameters) teams { teamId diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/createUser.gql b/webapp/packages/core-sdk/src/queries/authentication/users/createUser.gql index d17b1a6f21..649a332167 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/users/createUser.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/users/createUser.gql @@ -1,15 +1,5 @@ -query createUser( - $userId: ID! - $enabled: Boolean! - $authRole: String - $includeMetaParameters: Boolean! - $customIncludeOriginDetails: Boolean! - ) { - user: createUser( - userId: $userId - enabled: $enabled - authRole: $authRole - ) { +query createUser($userId: ID!, $enabled: Boolean!, $authRole: String) { + user: createUser(userId: $userId, enabled: $enabled, authRole: $authRole) { ...AdminUserInfo } -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserMetaParameters.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserMetaParameters.gql new file mode 100644 index 0000000000..2078d1678d --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserMetaParameters.gql @@ -0,0 +1,5 @@ +query getAdminUserMetaParameters($userId: ID!) { + user: adminUserInfo(userId: $userId) { + metaParameters + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserOriginDetails.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserOriginDetails.gql new file mode 100644 index 0000000000..749ddb6308 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getAdminUserOriginDetails.gql @@ -0,0 +1,5 @@ +query getAdminUserOriginDetails($userId: ID!) { + user: adminUserInfo(userId: $userId) { + ...AdminOriginDetails + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getUserById.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getUserById.gql index b4ff8c390e..24cf53dec3 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/users/getUserById.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getUserById.gql @@ -1,4 +1,4 @@ -query getAdminUserInfo($userId: ID!, $includeMetaParameters: Boolean!, $customIncludeOriginDetails: Boolean!) { +query getAdminUserInfo($userId: ID!) { user: adminUserInfo(userId: $userId) { ...AdminUserInfo } diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getUsersList.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersList.gql index fd0f1c5eeb..9f7377b8c3 100644 --- a/webapp/packages/core-sdk/src/queries/authentication/users/getUsersList.gql +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersList.gql @@ -1,4 +1,4 @@ -query getUsersList($page: PageInput!, $filter: AdminUserFilterInput!, $includeMetaParameters: Boolean!, $customIncludeOriginDetails: Boolean!) { +query getUsersList($page: PageInput!, $filter: AdminUserFilterInput!) { users: listUsers(page: $page, filter: $filter) { ...AdminUserInfo } diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getUsersMetaParametersList.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersMetaParametersList.gql new file mode 100644 index 0000000000..9e1d01be5e --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersMetaParametersList.gql @@ -0,0 +1,6 @@ +query getUsersMetaParametersList($page: PageInput!, $filter: AdminUserFilterInput!) { + users: listUsers(page: $page, filter: $filter) { + userId + metaParameters + } +} diff --git a/webapp/packages/core-sdk/src/queries/authentication/users/getUsersOriginDetailsList.gql b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersOriginDetailsList.gql new file mode 100644 index 0000000000..0eae403825 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/authentication/users/getUsersOriginDetailsList.gql @@ -0,0 +1,6 @@ +query getUsersOriginDetailsList($page: PageInput!, $filter: AdminUserFilterInput!) { + users: listUsers(page: $page, filter: $filter) { + userId + ...AdminOriginDetails + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql index 7aee378640..41d1e5bee5 100644 --- a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql @@ -1,8 +1,6 @@ mutation closeConnection( $projectId: ID! $connectionId: ID! - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql index 9af020fc7a..26b5d67500 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql @@ -1,8 +1,6 @@ mutation createConnection( $projectId: ID! $config: ConnectionConfig! - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql index 9115537615..5dd8de0e1d 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromNode.gql @@ -2,8 +2,6 @@ mutation createConnectionFromNode( $projectId: ID! $nodePath: String! $config: ConnectionConfig - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql index 54dda8b0fa..93a68a8b9c 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnectionFromTemplate.gql @@ -2,8 +2,6 @@ mutation createConnectionFromTemplate( $projectId: ID! $templateId: ID! $connectionName: String! - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql b/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql index 7d28702d00..f25c011c8c 100644 --- a/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql +++ b/webapp/packages/core-sdk/src/queries/connections/getTemplateConnections.gql @@ -1,7 +1,5 @@ query getTemplateConnections( $projectId: ID - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql b/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql index a147612f7c..0e13f665dd 100644 --- a/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql +++ b/webapp/packages/core-sdk/src/queries/connections/getUserConnections.gql @@ -2,8 +2,6 @@ query getUserConnections( $projectId: ID $connectionId: ID $projectIds: [ID!] - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOrigin.gql b/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOrigin.gql new file mode 100644 index 0000000000..907b0a95bf --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOrigin.gql @@ -0,0 +1,5 @@ +query getUserConnectionsOrigin($projectId: ID, $connectionId: ID, $projectIds: [ID!]) { + connections: userConnections(projectId: $projectId, id: $connectionId, projectIds: $projectIds) { + ...DatabaseConnectionOrigin + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOriginDetails.gql b/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOriginDetails.gql new file mode 100644 index 0000000000..f419e38f02 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/getUserConnectionsOriginDetails.gql @@ -0,0 +1,5 @@ +query getUserConnectionsOriginDetails($projectId: ID, $connectionId: ID, $projectIds: [ID!]) { + connections: userConnections(projectId: $projectId, id: $connectionId, projectIds: $projectIds) { + ...DatabaseConnectionOriginDetails + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/initConnection.gql b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql index 98522e47a1..98d1a9e247 100644 --- a/webapp/packages/core-sdk/src/queries/connections/initConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql @@ -6,8 +6,6 @@ mutation initConnection( $saveCredentials: Boolean $sharedCredentials: Boolean $selectedSecretId: String - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql b/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql index c5cf9278ee..6dce7d6da0 100644 --- a/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql +++ b/webapp/packages/core-sdk/src/queries/connections/setConnectionNavigatorSettings.gql @@ -2,8 +2,6 @@ mutation setConnectionNavigatorSettings( $projectId: ID! $connectionId: ID! $settings: NavigatorSettingsInput! - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql b/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql index ebabddc440..f240f3d980 100644 --- a/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/updateConnection.gql @@ -1,8 +1,6 @@ mutation updateConnection( $projectId: ID! $config: ConnectionConfig! - $includeOrigin: Boolean! - $customIncludeOriginDetails: Boolean! $includeAuthProperties: Boolean! $includeNetworkHandlersConfig: Boolean! $includeCredentialsSaved: Boolean! diff --git a/webapp/packages/core-sdk/src/queries/fragments/AdminOriginDetails.gql b/webapp/packages/core-sdk/src/queries/fragments/AdminOriginDetails.gql new file mode 100644 index 0000000000..5a87159728 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/AdminOriginDetails.gql @@ -0,0 +1,5 @@ +fragment AdminOriginDetails on AdminUserInfo { + origins { + ...OriginDetails + } +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfo.gql b/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfo.gql index 29bfda19d0..35fa371b29 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfo.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfo.gql @@ -3,5 +3,4 @@ fragment AdminTeamInfo on AdminTeamInfo { teamName description teamPermissions - metaParameters @include(if: $includeMetaParameters) -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfoMetaParameters.gql b/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfoMetaParameters.gql new file mode 100644 index 0000000000..6c66ffa7d0 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/AdminTeamInfoMetaParameters.gql @@ -0,0 +1,3 @@ +fragment AdminTeamInfoMetaParameters on AdminTeamInfo { + metaParameters +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/AdminUserInfo.gql b/webapp/packages/core-sdk/src/queries/fragments/AdminUserInfo.gql index 11cf7871dc..ef1ced7fef 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/AdminUserInfo.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/AdminUserInfo.gql @@ -2,11 +2,10 @@ fragment AdminUserInfo on AdminUserInfo { userId grantedTeams linkedAuthProviders - metaParameters @include(if: $includeMetaParameters) - + origins { ...ObjectOriginInfo } enabled authRole -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql index bd0b84abee..1770c66c6a 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnection.gql @@ -36,10 +36,6 @@ fragment DatabaseConnection on ConnectionInfo { features supportedDataFormats - origin @include(if: $includeOrigin) { - ...ObjectOriginInfo - } - authNeeded @include(if: $includeAuthNeeded) authModel diff --git a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOrigin.gql b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOrigin.gql new file mode 100644 index 0000000000..be6631cd89 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOrigin.gql @@ -0,0 +1,7 @@ +fragment DatabaseConnectionOrigin on ConnectionInfo { + id + projectId + origin { + ...ObjectOriginInfo + } +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOriginDetails.gql b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOriginDetails.gql new file mode 100644 index 0000000000..4d2de9a430 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/DatabaseConnectionOriginDetails.gql @@ -0,0 +1,7 @@ +fragment DatabaseConnectionOriginDetails on ConnectionInfo { + id + projectId + origin { + ...OriginDetails + } +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/ObjectOriginInfo.gql b/webapp/packages/core-sdk/src/queries/fragments/ObjectOriginInfo.gql index f610576645..f42be2b125 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/ObjectOriginInfo.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/ObjectOriginInfo.gql @@ -3,19 +3,4 @@ fragment ObjectOriginInfo on ObjectOrigin { subType displayName icon - - details @include(if: $customIncludeOriginDetails) { - id - required - displayName - description - category - dataType - defaultValue - validValues - value - length - features - order - } -} \ No newline at end of file +} diff --git a/webapp/packages/core-sdk/src/queries/fragments/OriginDetails.gql b/webapp/packages/core-sdk/src/queries/fragments/OriginDetails.gql new file mode 100644 index 0000000000..bea3482c93 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/OriginDetails.gql @@ -0,0 +1,16 @@ +fragment OriginDetails on ObjectOrigin { + details { + id + required + displayName + description + category + dataType + defaultValue + validValues + value + length + features + order + } +} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Contexts/teamContext.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Contexts/teamContext.ts index f48293450b..d2fd97965a 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Contexts/teamContext.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Contexts/teamContext.ts @@ -5,9 +5,9 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { TeamInfo } from '@cloudbeaver/core-authentication'; +import type { TeamInfoConfig } from '../ITeamFormProps.js'; -export function teamContext(): TeamInfo { +export function teamContext(): TeamInfoConfig { return { teamId: '', teamPermissions: [], diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/CreateTeamService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/CreateTeamService.ts index fc6c6b1fce..38d261127b 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/CreateTeamService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/CreateTeamService.ts @@ -7,7 +7,7 @@ */ import { makeObservable, observable } from 'mobx'; -import { TeamsResource } from '@cloudbeaver/core-authentication'; +import { TeamInfoMetaParametersResource, TeamsResource } from '@cloudbeaver/core-authentication'; import { injectable } from '@cloudbeaver/core-di'; import type { ITeamFormState } from './ITeamFormProps.js'; @@ -24,6 +24,7 @@ export class CreateTeamService { private readonly teamsAdministrationNavService: TeamsAdministrationNavService, private readonly teamFormService: TeamFormService, private readonly teamsResource: TeamsResource, + private readonly teamInfoMetaParametersResource: TeamInfoMetaParametersResource, ) { this.data = null; @@ -41,7 +42,7 @@ export class CreateTeamService { } fillData(): void { - this.data = new TeamFormState(this.teamFormService, this.teamsResource); + this.data = new TeamFormState(this.teamFormService, this.teamsResource, this.teamInfoMetaParametersResource); } create(): void { diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/ConnectionList.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/ConnectionList.tsx index 3ff4d110b2..7c602d98d1 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/ConnectionList.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/ConnectionList.tsx @@ -24,7 +24,7 @@ import { useS, useTranslate, } from '@cloudbeaver/core-blocks'; -import { type Connection, DBDriverResource } from '@cloudbeaver/core-connections'; +import { type Connection, type ConnectionInfoOrigin, DBDriverResource } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import styles from './ConnectionList.module.css'; @@ -35,12 +35,13 @@ import { GrantedConnectionsTableItem } from './GrantedConnectionsTableItem.js'; interface Props { connectionList: Connection[]; + connectionsOrigins: ConnectionInfoOrigin[]; grantedSubjects: string[]; disabled: boolean; onGrant: (subjectIds: string[]) => void; } -export const ConnectionList = observer(function ConnectionList({ connectionList, grantedSubjects, disabled, onGrant }) { +export const ConnectionList = observer(function ConnectionList({ connectionList, connectionsOrigins, grantedSubjects, disabled, onGrant }) { const props = useObjectRef({ onGrant }); const style = useS(styles); const translate = useTranslate(); @@ -57,7 +58,7 @@ export const ConnectionList = observer(function ConnectionList({ connecti selectedSubjects.clear(); }, []); - const connections = getFilteredConnections(connectionList, filterState.filterValue); + const connections = getFilteredConnections(connectionList, connectionsOrigins, filterState.filterValue); const keys = connections.map(connection => connection.id); return ( diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx index 17e04edb8b..1c6efa9afa 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx @@ -22,6 +22,8 @@ import { } from '@cloudbeaver/core-blocks'; import { type Connection, + type ConnectionInfoOrigin, + ConnectionInfoOriginResource, ConnectionInfoProjectKey, ConnectionInfoResource, DBDriverResource, @@ -55,10 +57,12 @@ export const GrantedConnections: TabContainerPanelComponent = ob useResource(GrantedConnections, DBDriverResource, CachedMapAllKey, { active: selected }); const connectionsLoader = useResource(GrantedConnections, ConnectionInfoResource, globalConnectionsKey, { active: selected }); + const connectionsOriginLoader = useResource(GrantedConnections, ConnectionInfoOriginResource, globalConnectionsKey, { active: selected }); const connections = connectionsLoader.data as Connection[]; const grantedConnections = getComputed(() => connections.filter(connection => state.state.grantedSubjects.includes(connection.id))); + const connectionsOrigins = (connectionsOriginLoader.data ?? []) as ConnectionInfoOrigin[]; useAutoLoad(GrantedConnections, state, selected && !loaded); @@ -68,7 +72,7 @@ export const GrantedConnections: TabContainerPanelComponent = ob let info: TLocalizationToken | null = null; - const cloudExists = connections.some(isCloudConnection); + const cloudExists = connectionsOrigins.some(connectionOrigin => isCloudConnection(connectionOrigin.origin)); if (cloudExists) { info = 'cloud_connections_access_placeholder'; @@ -92,6 +96,7 @@ export const GrantedConnections: TabContainerPanelComponent = ob = ob {state.state.editing && ( void; onEdit: () => void; } -export const GrantedConnectionList = observer(function GrantedConnectionList({ grantedConnections, disabled, onRevoke, onEdit }) { +export const GrantedConnectionList = observer(function GrantedConnectionList({ + connectionsOrigins, + grantedConnections, + disabled, + onRevoke, + onEdit, +}) { const props = useObjectRef({ onRevoke, onEdit }); const styles = useS(style); const translate = useTranslate(); @@ -51,7 +58,7 @@ export const GrantedConnectionList = observer(function GrantedConnectionL const [selectedSubjects] = useState>(() => observable(new Map())); const [filterState] = useState(() => observable({ filterValue: '' })); - const connections = getFilteredConnections(grantedConnections, filterState.filterValue); + const connections = getFilteredConnections(grantedConnections, connectionsOrigins, filterState.filterValue); const keys = connections.map(connection => connection.id); const selected = getComputed(() => Array.from(selectedSubjects.values()).some(v => v)); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/getFilteredConnections.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/getFilteredConnections.ts index 41afb3cdcb..285e6b1121 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/getFilteredConnections.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/getFilteredConnections.ts @@ -5,15 +5,24 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import { isCloudConnection } from '@cloudbeaver/core-connections'; -import type { DatabaseConnectionFragment } from '@cloudbeaver/core-sdk'; +import { type Connection, type ConnectionInfoOrigin, isCloudConnection } from '@cloudbeaver/core-connections'; /** * @param {DatabaseConnectionFragment[]} connections * @param {string} filter */ -export function getFilteredConnections(connections: DatabaseConnectionFragment[], filter: string): DatabaseConnectionFragment[] { +export function getFilteredConnections(connections: Connection[], connectionsOrigin: ConnectionInfoOrigin[], filter: string): Connection[] { + const connectionsOriginsMap = new Map(); + + for (const connectionOrigin of connectionsOrigin) { + connectionsOriginsMap.set(connectionOrigin.id, connectionOrigin); + } + return connections - .filter(connection => connection.name.toLowerCase().includes(filter.toLowerCase()) && !isCloudConnection(connection)) + .filter(connection => { + const originDetails = connectionsOriginsMap.get(connection.id); + + return connection.name.toLowerCase().includes(filter.toLowerCase()) && originDetails && !isCloudConnection(originDetails.origin); + }) .sort((a, b) => a.name.localeCompare(b.name)); } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/ITeamFormProps.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/ITeamFormProps.ts index 4f186c39dd..46575e9df8 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/ITeamFormProps.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/ITeamFormProps.ts @@ -5,18 +5,22 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { TeamInfo, TeamsResource } from '@cloudbeaver/core-authentication'; +import type { TeamInfo, TeamMetaParameter, TeamsResource } from '@cloudbeaver/core-authentication'; import type { IExecutorHandlersCollection } from '@cloudbeaver/core-executor'; import type { MetadataMap } from '@cloudbeaver/core-utils'; export type TeamFormMode = 'edit' | 'create'; +export interface TeamInfoConfig extends TeamInfo { + metaParameters: Record; +} + export interface ITeamFormState { mode: TeamFormMode; - config: TeamInfo; + config: TeamInfoConfig; partsState: MetadataMap; - readonly info: TeamInfo | undefined; + readonly info: TeamInfoConfig | undefined; readonly statusMessage: string | null; readonly disabled: boolean; readonly readonly: boolean; diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptionsTabService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptionsTabService.ts index 4fa9273eca..3f8474095f 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptionsTabService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptionsTabService.ts @@ -7,7 +7,7 @@ */ import React from 'react'; -import { TeamsResource } from '@cloudbeaver/core-authentication'; +import { TeamInfoMetaParametersResource, TeamsResource } from '@cloudbeaver/core-authentication'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import type { IExecutionContextProvider } from '@cloudbeaver/core-executor'; import { LocalizationService } from '@cloudbeaver/core-localization'; @@ -27,6 +27,7 @@ export class TeamOptionsTabService extends Bootstrap { constructor( private readonly teamFormService: TeamFormService, private readonly teamResource: TeamsResource, + private readonly teamsMetaParametersResource: TeamInfoMetaParametersResource, private readonly localizationService: LocalizationService, ) { super(); @@ -72,7 +73,7 @@ export class TeamOptionsTabService extends Bootstrap { for (const key of Object.keys(config.metaParameters)) { if (typeof config.metaParameters[key] === 'string') { - config.metaParameters[key] = config.metaParameters[key].trim(); + config.metaParameters[key] = (config.metaParameters[key] as any).trim(); } } } @@ -100,17 +101,20 @@ export class TeamOptionsTabService extends Bootstrap { private async save({ state }: ITeamFormSubmitData, contexts: IExecutionContextProvider) { const status = contexts.getContext(this.teamFormService.configurationStatusContext); - const config = contexts.getContext(teamContext); + const { metaParameters, ...config } = contexts.getContext(teamContext); const create = state.mode === 'create'; try { if (create) { const team = await this.teamResource.createTeam(config); + await this.teamsMetaParametersResource.setMetaParameters(config.teamId, metaParameters); + status.info('administration_teams_team_info_created'); status.info(team.teamId); } else { const team = await this.teamResource.updateTeam(config); + await this.teamsMetaParametersResource.setMetaParameters(config.teamId, metaParameters); status.info('administration_teams_team_info_updated'); status.info(team.teamId); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamFormState.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamFormState.ts index c4a19c9d38..dedc898631 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamFormState.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamFormState.ts @@ -7,27 +7,33 @@ */ import { computed, makeObservable, observable } from 'mobx'; -import type { TeamInfo, TeamsResource } from '@cloudbeaver/core-authentication'; +import type { TeamInfo, TeamInfoMetaParametersResource, TeamsResource } from '@cloudbeaver/core-authentication'; import { Executor, type IExecutionContextProvider, type IExecutor } from '@cloudbeaver/core-executor'; import { MetadataMap } from '@cloudbeaver/core-utils'; import { teamFormConfigureContext } from './Contexts/teamFormConfigureContext.js'; import { type ITeamFormStateInfo, teamFormStateContext } from './Contexts/teamFormStateContext.js'; -import type { ITeamFormState, ITeamFormSubmitData, TeamFormMode } from './ITeamFormProps.js'; +import type { ITeamFormState, ITeamFormSubmitData, TeamFormMode, TeamInfoConfig } from './ITeamFormProps.js'; import type { TeamFormService } from './TeamFormService.js'; export class TeamFormState implements ITeamFormState { mode: TeamFormMode; - config: TeamInfo; + config: TeamInfoConfig; statusMessage: string | null; configured: boolean; partsState: MetadataMap; - get info(): TeamInfo | undefined { + get info(): TeamInfoConfig | undefined { if (!this.config.teamId) { return undefined; } - return this.resource.get(this.config.teamId); + const info = this.resource.get(this.config.teamId) ?? {}; + const meta = this.teamInfoMetaParametersResource.get(this.config.teamId) ?? {}; + + return { + ...info, + metaParameters: meta, + } as TeamInfoConfig; } get loading(): boolean { @@ -43,6 +49,7 @@ export class TeamFormState implements ITeamFormState { } readonly resource: TeamsResource; + readonly teamInfoMetaParametersResource: TeamInfoMetaParametersResource; readonly service: TeamFormService; readonly submittingTask: IExecutor; @@ -51,8 +58,9 @@ export class TeamFormState implements ITeamFormState { private readonly loadTeamTask: IExecutor; private readonly formStateTask: IExecutor; - constructor(service: TeamFormService, resource: TeamsResource) { + constructor(service: TeamFormService, resource: TeamsResource, teamInfoMetaParametersResource: TeamInfoMetaParametersResource) { this.resource = resource; + this.teamInfoMetaParametersResource = teamInfoMetaParametersResource; this.config = { teamId: '', teamPermissions: [], @@ -110,7 +118,7 @@ export class TeamFormState implements ITeamFormState { return this; } - setConfig(config: TeamInfo): this { + setConfig(config: TeamInfoConfig): this { this.config = config; return this; } @@ -142,6 +150,6 @@ export class TeamFormState implements ITeamFormState { return; } - await this.resource.load(data.config.teamId, ['includeMetaParameters']); + await Promise.all([this.resource.load(data.config.teamId), this.teamInfoMetaParametersResource.load(data.config.teamId)]); } } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/TeamEdit.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/TeamEdit.tsx index e5aff28a98..4f0ec3ef4b 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/TeamEdit.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/TeamEdit.tsx @@ -8,7 +8,7 @@ import { observer } from 'mobx-react-lite'; import { useCallback, useContext } from 'react'; -import { TeamsResource } from '@cloudbeaver/core-authentication'; +import { TeamInfoMetaParametersResource, TeamsResource } from '@cloudbeaver/core-authentication'; import { Container, s, TableContext, useS } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; @@ -23,13 +23,14 @@ interface Props { export const TeamEdit = observer(function TeamEdit({ item }) { const styles = useS(style); const resource = useService(TeamsResource); + const teamInfoMetaParametersResource = useService(TeamInfoMetaParametersResource); const tableContext = useContext(TableContext); const collapse = useCallback(() => { tableContext?.setItemExpand(item, false); }, [tableContext, item]); - const data = useTeamFormState(resource, state => state.setOptions('edit')); + const data = useTeamFormState(resource, teamInfoMetaParametersResource, state => state.setOptions('edit')); data.config.teamId = item; diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/useTeamFormState.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/useTeamFormState.ts index de2c4a5074..40fa40a3a1 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/useTeamFormState.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/useTeamFormState.ts @@ -7,17 +7,21 @@ */ import { useState } from 'react'; -import type { TeamsResource } from '@cloudbeaver/core-authentication'; +import type { TeamInfoMetaParametersResource, TeamsResource } from '@cloudbeaver/core-authentication'; import { useService } from '@cloudbeaver/core-di'; import type { ITeamFormState } from './ITeamFormProps.js'; import { TeamFormService } from './TeamFormService.js'; import { TeamFormState } from './TeamFormState.js'; -export function useTeamFormState(resource: TeamsResource, configure?: (state: ITeamFormState) => any): ITeamFormState { +export function useTeamFormState( + resource: TeamsResource, + teamInfoMetaParametersResource: TeamInfoMetaParametersResource, + configure?: (state: ITeamFormState) => any, +): ITeamFormState { const service = useService(TeamFormService); const [state] = useState(() => { - const state = new TeamFormState(service, resource); + const state = new TeamFormState(service, resource, teamInfoMetaParametersResource); configure?.(state); state.load(); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccess.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccess.tsx index 0ac6d7a39e..eed1f50953 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccess.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccess.tsx @@ -23,6 +23,7 @@ import { } from '@cloudbeaver/core-blocks'; import { compareConnectionsInfo, + ConnectionInfoOriginResource, ConnectionInfoProjectKey, ConnectionInfoResource, DBDriverResource, @@ -44,16 +45,17 @@ export const UserFormConnectionAccess: TabContainerPanelComponent const driversResource = useService(DBDriverResource); const tabState = useTabState(); const projectLoader = useResource(UserFormConnectionAccess, ProjectInfoResource, CachedMapAllKey, { active: tab.selected }); - const connectionsLoader = useResource( - UserFormConnectionAccess, - ConnectionInfoResource, - ConnectionInfoProjectKey(...projectLoader.data.filter(isGlobalProject).map(project => project.id)), - { active: tab.selected }, - ); + const key = ConnectionInfoProjectKey(...projectLoader.data.filter(isGlobalProject).map(project => project.id)); + const connectionsLoader = useResource(UserFormConnectionAccess, ConnectionInfoResource, key, { active: tab.selected }); + const connectionsOriginsLoader = useResource(UserFormConnectionAccess, ConnectionInfoOriginResource, key, { active: tab.selected }); const connections = connectionsLoader.data.filter(isDefined).sort(compareConnectionsInfo); - const cloudExists = connections.some(isCloudConnection); - const localConnections = connections.filter(connection => !isCloudConnection(connection)); + const connectionsOrigins = connectionsOriginsLoader.data.filter(isDefined); + const cloudExists = connectionsOrigins.some(connectionOrigin => isCloudConnection(connectionOrigin.origin)); + const localConnectionsIds = new Set( + connectionsOrigins.filter(connection => !isCloudConnection(connection.origin)).map(connection => connection.id), + ); + const localConnections = connections.filter(connection => localConnectionsIds.has(connection.id)); useResource( UserFormConnectionAccess, diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx index 7c72c6c0d8..029371d619 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoCredentials.tsx @@ -34,12 +34,7 @@ interface Props extends UserFormProps { export const UserFormInfoCredentials = observer(function UserFormInfoCredentials({ formState, tabState, tabSelected, disabled }) { const translate = useTranslate(); const editing = formState.mode === FormMode.Edit; - const userInfo = useResource( - UserFormInfoCredentials, - UsersResource, - { key: tabState.initialState.userId, includes: ['includeMetaParameters'] }, - { active: tabSelected && editing }, - ); + const userInfo = useResource(UserFormInfoCredentials, UsersResource, tabState.initialState.userId, { active: tabSelected && editing }); const authProvidersResource = useResource(UserFormInfoCredentials, AuthProvidersResource, null); const passwordValidationRef = usePasswordValidation(); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts index 2e90853826..0b21df2f5b 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Info/UserFormInfoPart.ts @@ -7,11 +7,9 @@ */ import { observable, toJS } from 'mobx'; -import type { AdminUser, AuthRolesResource, UserResourceIncludes, UsersResource } from '@cloudbeaver/core-authentication'; +import type { AdminUser, AuthRolesResource, UserMetaParameter, UsersMetaParametersResource, UsersResource } from '@cloudbeaver/core-authentication'; import type { IExecutionContextProvider } from '@cloudbeaver/core-executor'; -import { type CachedResourceIncludeArgs } from '@cloudbeaver/core-resource'; import type { ServerConfigResource } from '@cloudbeaver/core-root'; -import type { AdminUserInfoFragment } from '@cloudbeaver/core-sdk'; import { FormMode, FormPart, formValidationContext, type IFormState } from '@cloudbeaver/core-ui'; import { isArraysEqual, isDefined, isObjectsEqual, isValuesEqual } from '@cloudbeaver/core-utils'; @@ -21,12 +19,12 @@ import type { IUserFormInfoState } from './IUserFormInfoState.js'; const DEFAULT_ENABLED = true; export class UserFormInfoPart extends FormPart { - private baseIncludes: CachedResourceIncludeArgs; constructor( private readonly authRolesResource: AuthRolesResource, private readonly serverConfigResource: ServerConfigResource, formState: IFormState, private readonly usersResource: UsersResource, + private readonly usersMetaParametersResource: UsersMetaParametersResource, ) { super(formState, { userId: formState.state.userId || '', @@ -36,7 +34,6 @@ export class UserFormInfoPart extends FormPart, contexts: IExecutionContextProvider>): void | Promise { @@ -58,7 +55,7 @@ export class UserFormInfoPart extends FormPart): User const usersResource = di.getService(UsersResource); const serverConfigResource = di.getService(ServerConfigResource); const authRolesResource = di.getService(AuthRolesResource); + const usersMetaParametersResource = di.getService(UsersMetaParametersResource); - return new UserFormInfoPart(authRolesResource, serverConfigResource, formState, usersResource); + return new UserFormInfoPart(authRolesResource, serverConfigResource, formState, usersResource, usersMetaParametersResource); }); } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoPanel.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoPanel.tsx index e6944cbe72..353a370913 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoPanel.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/Origin/UserFormOriginInfoPanel.tsx @@ -8,7 +8,7 @@ import { observer } from 'mobx-react-lite'; import { Fragment } from 'react'; -import { type AdminUserOrigin, UsersResource } from '@cloudbeaver/core-authentication'; +import { type AdminUserOrigin, UsersOriginDetailsResource, UsersResource } from '@cloudbeaver/core-authentication'; import { Button, Combobox, @@ -42,18 +42,17 @@ export const UserFormOriginInfoPanel: TabContainerPanelComponent const localState = useTabState(() => ({ selectedOrigin: '0', })); - const userInfoLoader = useResource( - UserFormOriginInfoPanel, - UsersResource, - { key: state.userId, includes: ['customIncludeOriginDetails'] }, - { - active: editing, - }, - ); + const userInfoLoader = useResource(UserFormOriginInfoPanel, UsersResource, state.userId, { + active: editing, + }); const commonDialogService = useService(CommonDialogService); const notificationService = useService(NotificationService); const origins = userInfoLoader.data?.origins ?? []; const origin: AdminUserOrigin | undefined = origins[localState.selectedOrigin as any]; + const usersOriginDetailsResource = useResource(UserFormOriginInfoPanel, UsersOriginDetailsResource, state.userId, { + active: editing, + }); + const originDetails = usersOriginDetailsResource.data?.origins?.[localState.selectedOrigin as any]?.details ?? []; const { selected } = useTab(tabId); @@ -105,7 +104,7 @@ export const UserFormOriginInfoPanel: TabContainerPanelComponent { const { connections } = await this.graphQLService.sdk.getTemplateConnections({ includeNetworkHandlersConfig: true, - customIncludeOriginDetails: false, includeAuthProperties: true, - includeOrigin: false, includeAuthNeeded: true, includeCredentialsSaved: false, includeProperties: false, diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsAdministrationService.ts b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsAdministrationService.ts index fd2c756733..f1481c4082 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsAdministrationService.ts +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsAdministrationService.ts @@ -9,7 +9,7 @@ import React from 'react'; import { AdministrationItemService, AdministrationItemType } from '@cloudbeaver/core-administration'; import { ConfirmationDialog, PlaceholderContainer } from '@cloudbeaver/core-blocks'; -import { ConnectionInfoResource, type DatabaseConnection } from '@cloudbeaver/core-connections'; +import { type ConnectionInfoOrigin, ConnectionInfoResource, type DatabaseConnection } from '@cloudbeaver/core-connections'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs'; import { ServerConfigResource } from '@cloudbeaver/core-root'; @@ -18,6 +18,7 @@ import { CreateConnectionService } from './CreateConnectionService.js'; export interface IConnectionDetailsPlaceholderProps { connection: DatabaseConnection; + connectionOrigin?: ConnectionInfoOrigin; } const ConnectionsAdministration = React.lazy(async () => { diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx index e186a878c4..862122b688 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx @@ -19,7 +19,7 @@ import { useResource, useS, } from '@cloudbeaver/core-blocks'; -import { type DatabaseConnection, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; +import { type ConnectionInfoOrigin, type DatabaseConnection, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { ProjectInfoResource } from '@cloudbeaver/core-projects'; @@ -31,10 +31,11 @@ interface Props { connectionKey: IConnectionInfoParams; connection: DatabaseConnection; shouldDisplayProject: boolean; + connectionOrigin?: ConnectionInfoOrigin; icon?: string; } -export const Connection = observer(function Connection({ connectionKey, connection, shouldDisplayProject, icon }) { +export const Connection = observer(function Connection({ connectionKey, connectionOrigin, connection, shouldDisplayProject, icon }) { const style = useS(styles); const connectionsAdministrationService = useService(ConnectionsAdministrationService); const projectInfoResource = useResource(Connection, ProjectInfoResource, connectionKey.projectId, { active: shouldDisplayProject }); @@ -66,7 +67,11 @@ export const Connection = observer(function Connection({ connectionKey, c )} - + diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionDetailsInfo/Origin.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionDetailsInfo/Origin.tsx index 9a27111399..a87cb90c4a 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionDetailsInfo/Origin.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionDetailsInfo/Origin.tsx @@ -13,16 +13,16 @@ import { type PlaceholderComponent, s, StaticImage, useS } from '@cloudbeaver/co import type { IConnectionDetailsPlaceholderProps } from '../../ConnectionsAdministrationService.js'; import ConnectionDetailsStyles from './ConnectionDetailsStyles.module.css'; -export const Origin: PlaceholderComponent = observer(function Origin({ connection }) { - const isLocal = connection.origin?.type === AUTH_PROVIDER_LOCAL_ID; +export const Origin: PlaceholderComponent = observer(function Origin({ connectionOrigin }) { + const isLocal = connectionOrigin?.origin?.type === AUTH_PROVIDER_LOCAL_ID; const style = useS(ConnectionDetailsStyles); - if (!connection.origin || isLocal) { + if (!connectionOrigin?.origin || isLocal) { return null; } - const icon = connection.origin.icon; - const title = connection.origin.displayName; + const icon = connectionOrigin.origin.icon; + const title = connectionOrigin.origin.displayName; return ; }); diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx index c28882cfd9..71c9ed2a0d 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionEdit.tsx @@ -9,7 +9,7 @@ import { observer } from 'mobx-react-lite'; import { useMemo } from 'react'; import { Loader, s, useS } from '@cloudbeaver/core-blocks'; -import { ConnectionInfoResource, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; +import { ConnectionInfoOriginResource, ConnectionInfoResource, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { ConnectionFormLoader, useConnectionFormState } from '@cloudbeaver/plugin-connections'; @@ -21,10 +21,11 @@ interface Props { export const ConnectionEdit = observer(function ConnectionEditNew({ item }) { const connectionInfoResource = useService(ConnectionInfoResource); + const connectionInfoOriginResource = useService(ConnectionInfoOriginResource); // const tableContext = useContext(TableContext); // const collapse = useCallback(() => tableContext?.setItemExpand(item, false), [tableContext, item]); - const data = useConnectionFormState(connectionInfoResource, state => state.setOptions('edit', 'admin')); + const data = useConnectionFormState(connectionInfoResource, connectionInfoOriginResource, state => state.setOptions('edit', 'admin')); const style = useS(styles); const projectId = item.projectId; diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx index 4d7d60bad2..48a716e550 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/ConnectionsTable.tsx @@ -8,10 +8,11 @@ import { observer } from 'mobx-react-lite'; import { Table, TableBody, TableColumnHeader, TableHeader, TableSelect, useResource, useTranslate } from '@cloudbeaver/core-blocks'; -import { DBDriverResource, serializeConnectionParam } from '@cloudbeaver/core-connections'; +import { type ConnectionInfoOrigin, ConnectionInfoOriginResource, DBDriverResource, serializeConnectionParam } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { isGlobalProject, isSharedProject, ProjectsService } from '@cloudbeaver/core-projects'; import { CachedMapAllKey } from '@cloudbeaver/core-resource'; +import { isNotNullDefined } from '@cloudbeaver/core-utils'; import { Connection } from './Connection.js'; import { type IConnectionsTableState } from './useConnectionsTable.js'; @@ -20,11 +21,17 @@ interface Props { state: IConnectionsTableState; } +function getOriginsMap(origins: (ConnectionInfoOrigin | undefined)[]) { + return new Map(origins.filter(isNotNullDefined).map(origin => [origin.id, origin])); +} + export const ConnectionsTable = observer(function ConnectionsTable({ state }) { const translate = useTranslate(); const projectService = useService(ProjectsService); const dbDriverResource = useResource(ConnectionsTable, DBDriverResource, CachedMapAllKey); const shouldDisplayProjects = projectService.activeProjects.filter(project => isGlobalProject(project) || isSharedProject(project)).length > 1; + const connectionOriginResource = useResource(ConnectionsTable, ConnectionInfoOriginResource, CachedMapAllKey); + const connectionOriginsMap = getOriginsMap(connectionOriginResource.data); return ( @@ -45,6 +52,7 @@ export const ConnectionsTable = observer(function ConnectionsTable({ stat key={serializeConnectionParam(state.keys[i]!)} connectionKey={state.keys[i]!} connection={connection} + connectionOrigin={connectionOriginsMap.get(connection.id)} shouldDisplayProject={shouldDisplayProjects} icon={dbDriverResource.resource.get(connection.driverId)?.icon} /> diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnectionService.ts b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnectionService.ts index d94744121c..d2f80db241 100644 --- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnectionService.ts +++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/CreateConnectionService.ts @@ -8,7 +8,7 @@ import { action, makeObservable, observable } from 'mobx'; import { AdministrationScreenService } from '@cloudbeaver/core-administration'; -import { ConnectionInfoResource } from '@cloudbeaver/core-connections'; +import { ConnectionInfoOriginResource, ConnectionInfoResource } from '@cloudbeaver/core-connections'; import { injectable } from '@cloudbeaver/core-di'; import { ProjectInfoResource, ProjectsService } from '@cloudbeaver/core-projects'; import type { ConnectionConfig } from '@cloudbeaver/core-sdk'; @@ -38,6 +38,7 @@ export class CreateConnectionService { private readonly connectionInfoResource: ConnectionInfoResource, private readonly projectsService: ProjectsService, private readonly projectInfoResource: ProjectInfoResource, + private readonly connectionInfoOriginResource: ConnectionInfoOriginResource, ) { this.data = null; this.tabsContainer = new TabsContainer('Connection Creation mode'); @@ -109,7 +110,13 @@ export class CreateConnectionService { } setConnectionTemplate(projectId: string, config: ConnectionConfig, availableDrivers: string[]): void { - this.data = new ConnectionFormState(this.projectsService, this.projectInfoResource, this.connectionFormService, this.connectionInfoResource); + this.data = new ConnectionFormState( + this.projectsService, + this.projectInfoResource, + this.connectionFormService, + this.connectionInfoResource, + this.connectionInfoOriginResource, + ); this.data.closeTask.addHandler(this.cancelCreate.bind(this)); diff --git a/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccess.tsx b/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccess.tsx index 9faa6ddead..03677e20ac 100644 --- a/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccess.tsx +++ b/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccess.tsx @@ -63,7 +63,7 @@ export const ConnectionAccess: TabContainerPanelComponent } const loading = users.isLoading() || teams.isLoading() || state.state.loading; - const cloud = formState.info ? isCloudConnection(formState.info) : false; + const cloud = formState.info && formState.originInfo?.origin ? isCloudConnection(formState.originInfo.origin) : false; const disabled = loading || !state.state.loaded || formState.disabled || cloud; let info: TLocalizationToken | null = null; diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts index 9a84fb51b8..3e4b8af8db 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionFormState.ts @@ -7,7 +7,13 @@ */ import { action, computed, makeObservable, observable } from 'mobx'; -import { ConnectionInfoResource, createConnectionParam, type DatabaseConnection, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; +import { + ConnectionInfoOriginResource, + ConnectionInfoResource, + createConnectionParam, + type DatabaseConnection, + type IConnectionInfoParams, +} from '@cloudbeaver/core-connections'; import { Executor, type IExecutionContextProvider, type IExecutor } from '@cloudbeaver/core-executor'; import type { ProjectInfoResource, ProjectsService } from '@cloudbeaver/core-projects'; import type { ResourceKeySimple } from '@cloudbeaver/core-resource'; @@ -56,6 +62,14 @@ export class ConnectionFormState implements IConnectionFormState { return this.resource.get(createConnectionParam(this.projectId, this.config.connectionId)); } + get originInfo() { + if (!this.config.connectionId || this.projectId === null) { + return undefined; + } + + return this.originResource.get(createConnectionParam(this.projectId, this.config.connectionId)); + } + get readonly(): boolean { if (this.stateInfo?.readonly) { return true; @@ -81,6 +95,7 @@ export class ConnectionFormState implements IConnectionFormState { } readonly resource: ConnectionInfoResource; + readonly originResource: ConnectionInfoOriginResource; readonly service: ConnectionFormService; readonly submittingTask: IExecutor; readonly closeTask: IExecutor; @@ -96,11 +111,13 @@ export class ConnectionFormState implements IConnectionFormState { private readonly projectInfoResource: ProjectInfoResource, service: ConnectionFormService, resource: ConnectionInfoResource, + originResource: ConnectionInfoOriginResource, ) { this._id = uuid(); this.initError = null; this.resource = resource; + this.originResource = originResource; this.projectId = null; this.config = {}; this._availableDrivers = []; @@ -165,6 +182,7 @@ export class ConnectionFormState implements IConnectionFormState { availableDrivers: computed, _availableDrivers: observable, info: computed, + originInfo: computed, statusMessage: observable, configured: observable, readonly: computed, @@ -319,5 +337,6 @@ export class ConnectionFormState implements IConnectionFormState { } await data.resource.load(key, configuration.connectionIncludes); + await this.originResource.load(key); } } diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts b/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts index cb500aee50..95993cc023 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/IConnectionFormProps.ts @@ -5,7 +5,7 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { ConnectionInfoResource, DatabaseConnection } from '@cloudbeaver/core-connections'; +import type { ConnectionInfoOrigin, ConnectionInfoOriginResource, ConnectionInfoResource, DatabaseConnection } from '@cloudbeaver/core-connections'; import type { IExecutor, IExecutorHandlersCollection } from '@cloudbeaver/core-executor'; import type { ConnectionConfig } from '@cloudbeaver/core-sdk'; import type { IFormStateInfo } from '@cloudbeaver/core-ui'; @@ -32,7 +32,9 @@ export interface IConnectionFormState { readonly availableDrivers: string[]; readonly resource: ConnectionInfoResource; + readonly originResource: ConnectionInfoOriginResource; readonly info: DatabaseConnection | undefined; + readonly originInfo: ConnectionInfoOrigin | undefined; readonly readonly: boolean; readonly submittingTask: IExecutorHandlersCollection; readonly closeTask: IExecutor; diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts index 7084fc2ced..294fae54ad 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ConnectionOptionsTabService.ts @@ -242,7 +242,7 @@ export class ConnectionOptionsTabService extends Bootstrap { private configure(data: IConnectionFormState, contexts: IExecutionContextProvider) { const configuration = contexts.getContext(connectionFormConfigureContext); - configuration.include('includeOrigin', 'includeAuthProperties', 'includeCredentialsSaved', 'customIncludeOptions'); + configuration.include('includeAuthProperties', 'includeCredentialsSaved', 'customIncludeOptions'); } private async prepareConfig({ state }: IConnectionFormSubmitData, contexts: IExecutionContextProvider) { diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx index 2f980957bc..ae9c2f4be4 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx @@ -81,7 +81,7 @@ export const Options: TabContainerPanelComponent = observe const service = useService(ConnectionFormService); const formRef = useRef(null); const translate = useTranslate(); - const { info, config, availableDrivers, submittingTask: submittingHandlers, disabled } = state; + const { info, originInfo, config, availableDrivers, submittingTask: submittingHandlers, disabled } = state; const style = useS(styles); const tabsState = useContext(TabsContext); const isSharedProject = projectInfoResource.isProjectShared(state.projectId); @@ -149,7 +149,7 @@ export const Options: TabContainerPanelComponent = observe }); const edit = state.mode === 'edit'; - const originLocal = !info || isLocalConnection(info); + const originLocal = !info || (originInfo?.origin && isLocalConnection(originInfo.origin)); const drivers = driverMap.resource.enabledDrivers.filter(({ id }) => availableDrivers.includes(id)); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/ConnectionOriginInfoTabService.ts b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/ConnectionOriginInfoTabService.ts index e84f81ffc6..b30f900526 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/ConnectionOriginInfoTabService.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/ConnectionOriginInfoTabService.ts @@ -9,11 +9,8 @@ import React from 'react'; import { isLocalConnection } from '@cloudbeaver/core-connections'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; -import type { IExecutionContextProvider } from '@cloudbeaver/core-executor'; -import { connectionFormConfigureContext } from '../connectionFormConfigureContext.js'; import { ConnectionFormService } from '../ConnectionFormService.js'; -import type { IConnectionFormState } from '../IConnectionFormProps.js'; export const ConnectionFormAuthenticationAction = React.lazy(async () => { const { ConnectionFormAuthenticationAction } = await import('./ConnectionFormAuthenticationAction.js'); @@ -41,17 +38,9 @@ export class ConnectionOriginInfoTabService extends Bootstrap { tab: () => OriginInfoTab, panel: () => OriginInfo, stateGetter: () => () => ({}), - isHidden: (tabId, props) => (props?.state.info ? isLocalConnection(props.state.info) : true), + isHidden: (tabId, props) => (props?.state.originInfo ? isLocalConnection(props.state.originInfo.origin) : true), }); - this.connectionFormService.configureTask.addHandler(this.configure.bind(this)); - this.connectionFormService.actionsContainer.add(ConnectionFormAuthenticationAction, 0); } - - private configure(data: IConnectionFormState, contexts: IExecutionContextProvider) { - const configuration = contexts.getContext(connectionFormConfigureContext); - - configuration.include('includeOrigin'); - } } diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfo.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfo.tsx index d2b50cf785..190ea70392 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfo.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfo.tsx @@ -21,7 +21,12 @@ import { useS, useTranslate, } from '@cloudbeaver/core-blocks'; -import { createConnectionParam, DatabaseAuthModelsResource, DBDriverResource } from '@cloudbeaver/core-connections'; +import { + ConnectionInfoOriginDetailsResource, + createConnectionParam, + DatabaseAuthModelsResource, + DBDriverResource, +} from '@cloudbeaver/core-connections'; import { type TabContainerPanelComponent, useTab, useTabState } from '@cloudbeaver/core-ui'; import type { IConnectionFormProps } from '../IConnectionFormProps.js'; @@ -46,34 +51,30 @@ export const OriginInfo: TabContainerPanelComponent = obse const providerId = authModeLoader.data?.requiredAuth ?? info?.requiredAuth ?? AUTH_PROVIDER_LOCAL_ID; const isAuthenticated = userInfoLoader.resource.hasToken(providerId); const providerLoader = useResource(OriginInfo, AuthProvidersResource, providerId); + const connectionId = tab.selected && info ? createConnectionParam(info.projectId, info.id) : null; - const connection = useResource( - OriginInfo, - resource, - { - key: tab.selected && info ? createConnectionParam(info.projectId, info.id) : null, - includes: ['includeOrigin', 'customIncludeOriginDetails'] as const, - }, - { - active: isAuthenticated, - onData: connection => { - runInAction(() => { - if (!connection.origin.details) { - return; - } + const connectionOriginDetailsResource = useResource(OriginInfo, ConnectionInfoOriginDetailsResource, connectionId, { + active: isAuthenticated, + }); + const connection = useResource(OriginInfo, resource, connectionId, { + active: isAuthenticated, + onData: connection => { + runInAction(() => { + if (!connectionOriginDetailsResource.data?.origin.details) { + return; + } - for (const property of Object.keys(state)) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete state[property]; - } + for (const property of Object.keys(state)) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete state[property]; + } - for (const property of connection.origin.details) { - state[property.id!] = property.value; - } - }); - }, + for (const property of connectionOriginDetailsResource.data.origin.details) { + state[property.id!] = property.value; + } + }); }, - ); + }); if (connection.isLoading()) { return ( @@ -103,7 +104,7 @@ export const OriginInfo: TabContainerPanelComponent = obse ); } - if (!connection.data?.origin.details || connection.data.origin.details.length === 0) { + if (!connectionOriginDetailsResource.data?.origin.details || connectionOriginDetailsResource.data?.origin.details.length === 0) { return ( {translate('connections_administration_connection_no_information')} @@ -114,7 +115,7 @@ export const OriginInfo: TabContainerPanelComponent = obse return ( - + diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx index 32f08be4e5..aa82dbbf20 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/OriginInfo/OriginInfoTab.tsx @@ -12,11 +12,11 @@ import { Tab, type TabContainerTabComponent, TabTitle } from '@cloudbeaver/core- import type { IConnectionFormProps } from '../IConnectionFormProps.js'; -export const OriginInfoTab: TabContainerTabComponent = observer(function OriginInfoTab({ state: { info }, ...rest }) { +export const OriginInfoTab: TabContainerTabComponent = observer(function OriginInfoTab({ state: { originInfo }, ...rest }) { return ( - + ); diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/useConnectionFormState.ts b/webapp/packages/plugin-connections/src/ConnectionForm/useConnectionFormState.ts index 1acac4c2df..111e597d22 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/useConnectionFormState.ts +++ b/webapp/packages/plugin-connections/src/ConnectionForm/useConnectionFormState.ts @@ -7,7 +7,7 @@ */ import { useEffect, useState } from 'react'; -import type { ConnectionInfoResource } from '@cloudbeaver/core-connections'; +import { ConnectionInfoOriginResource, ConnectionInfoResource } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; import { ProjectInfoResource, ProjectsService } from '@cloudbeaver/core-projects'; @@ -15,13 +15,17 @@ import { ConnectionFormService } from './ConnectionFormService.js'; import { ConnectionFormState } from './ConnectionFormState.js'; import type { IConnectionFormState } from './IConnectionFormProps.js'; -export function useConnectionFormState(resource: ConnectionInfoResource, configure?: (state: IConnectionFormState) => any): IConnectionFormState { +export function useConnectionFormState( + resource: ConnectionInfoResource, + originResource: ConnectionInfoOriginResource, + configure?: (state: IConnectionFormState) => any, +): IConnectionFormState { const projectsService = useService(ProjectsService); const projectInfoResource = useService(ProjectInfoResource); const service = useService(ConnectionFormService); const [state] = useState(() => { - const state = new ConnectionFormState(projectsService, projectInfoResource, service, resource); + const state = new ConnectionFormState(projectsService, projectInfoResource, service, resource, originResource); configure?.(state); state.load(); diff --git a/webapp/packages/plugin-connections/src/PublicConnectionForm/PublicConnectionFormService.ts b/webapp/packages/plugin-connections/src/PublicConnectionForm/PublicConnectionFormService.ts index bff7ea0a33..c325cde384 100644 --- a/webapp/packages/plugin-connections/src/PublicConnectionForm/PublicConnectionFormService.ts +++ b/webapp/packages/plugin-connections/src/PublicConnectionForm/PublicConnectionFormService.ts @@ -9,7 +9,13 @@ import { action, makeObservable, observable } from 'mobx'; import { UserInfoResource } from '@cloudbeaver/core-authentication'; import { ConfirmationDialog, importLazyComponent } from '@cloudbeaver/core-blocks'; -import { ConnectionInfoResource, ConnectionsManagerService, createConnectionParam, type IConnectionInfoParams } from '@cloudbeaver/core-connections'; +import { + ConnectionInfoOriginResource, + ConnectionInfoResource, + ConnectionsManagerService, + createConnectionParam, + type IConnectionInfoParams, +} from '@cloudbeaver/core-connections'; import { injectable } from '@cloudbeaver/core-di'; import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs'; import { NotificationService } from '@cloudbeaver/core-events'; @@ -43,6 +49,7 @@ export class PublicConnectionFormService { private readonly authenticationService: AuthenticationService, private readonly projectsService: ProjectsService, private readonly projectInfoResource: ProjectInfoResource, + private readonly connectionInfoOriginResource: ConnectionInfoOriginResource, ) { this.formState = null; this.optionsPanelService.closeTask.addHandler(this.closeHandler); @@ -82,6 +89,7 @@ export class PublicConnectionFormService { this.projectInfoResource, this.connectionFormService, this.connectionInfoResource, + this.connectionInfoOriginResource, ); this.formState.closeTask.addHandler(this.close.bind(this, true)); diff --git a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserAuthenticationPart/UserProfileFormAuthenticationPart.ts b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserAuthenticationPart/UserProfileFormAuthenticationPart.ts index 7de55940df..7f4e6eddf4 100644 --- a/webapp/packages/plugin-user-profile/src/UserProfileForm/UserAuthenticationPart/UserProfileFormAuthenticationPart.ts +++ b/webapp/packages/plugin-user-profile/src/UserProfileForm/UserAuthenticationPart/UserProfileFormAuthenticationPart.ts @@ -5,10 +5,8 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import type { PasswordPolicyService, UserInfoResource, UserResourceIncludes } from '@cloudbeaver/core-authentication'; +import type { PasswordPolicyService, UserInfoMetaParametersResource, UserInfoResource } from '@cloudbeaver/core-authentication'; import type { IExecutionContextProvider } from '@cloudbeaver/core-executor'; -import type { CachedResourceIncludeArgs } from '@cloudbeaver/core-resource'; -import type { AdminUserInfoFragment } from '@cloudbeaver/core-sdk'; import { FormPart, formValidationContext, type IFormState } from '@cloudbeaver/core-ui'; import { isValuesEqual, schemaValidationError } from '@cloudbeaver/core-utils'; @@ -19,18 +17,17 @@ import { } from './IUserProfileFormAuthenticationState.js'; export class UserProfileFormAuthenticationPart extends FormPart { - private baseIncludes: CachedResourceIncludeArgs; constructor( formState: IFormState, private readonly userInfoResource: UserInfoResource, private readonly passwordPolicyService: PasswordPolicyService, + private readonly userInfoMetaParametersResource: UserInfoMetaParametersResource, ) { super(formState, { oldPassword: '', password: '', repeatedPassword: '', }); - this.baseIncludes = ['includeMetaParameters']; } protected override format(data: IFormState, contexts: IExecutionContextProvider>): void { @@ -40,11 +37,11 @@ export class UserProfileFormAuthenticationPart extends FormPart { - private baseIncludes: CachedResourceIncludeArgs; constructor( formState: IFormState, private readonly userInfoResource: UserInfoResource, + private readonly userInfoMetaParametersResource: UserInfoMetaParametersResource, ) { super(formState, { userId: userInfoResource.data?.userId || '', displayName: userInfoResource.data?.displayName || '', authRole: userInfoResource.data?.authRole || '', - metaParameters: toJS(userInfoResource.data?.metaParameters || {}), + metaParameters: toJS(userInfoMetaParametersResource.data || {}), }); - this.baseIncludes = ['includeMetaParameters']; } protected override format(data: IFormState, contexts: IExecutionContextProvider>): void { @@ -37,11 +34,11 @@ export class UserProfileFormInfoPart extends FormPart { const di = context.get(DATA_CONTEXT_DI_PROVIDER)!; const userInfoResource = di.getService(UserInfoResource); + const userInfoMetaParametersResource = di.getService(UserInfoMetaParametersResource); - return new UserProfileFormInfoPart(formState, userInfoResource); + return new UserProfileFormInfoPart(formState, userInfoResource, userInfoMetaParametersResource); }); }