From f1538ad17746807964dec7acb108deb2c24899a9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipov Date: Mon, 2 Oct 2023 03:19:46 +0200 Subject: [PATCH] refactor: subject connection permissions --- .../core-authentication/src/UsersResource.ts | 16 ++++++++-- .../addProjectsPermissions.graphql | 3 ++ .../deleteProjectsPermissions.graphql | 3 ++ .../GrantedConnectionsTabService.ts | 32 ++++++++++++++++--- .../UserFormConnectionAccessPart.ts | 24 +++++++++++++- .../ConnectionAccessTabService.ts | 31 ++++++++++++------ 6 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 webapp/packages/core-sdk/src/queries/resource-manager/addProjectsPermissions.graphql create mode 100644 webapp/packages/core-sdk/src/queries/resource-manager/deleteProjectsPermissions.graphql diff --git a/webapp/packages/core-authentication/src/UsersResource.ts b/webapp/packages/core-authentication/src/UsersResource.ts index b1c79004030..e8d95f74384 100644 --- a/webapp/packages/core-authentication/src/UsersResource.ts +++ b/webapp/packages/core-authentication/src/UsersResource.ts @@ -115,8 +115,20 @@ export class UsersResource extends CachedMapResource { - await this.graphQLService.sdk.setConnections({ userId, connections }); + async addConnectionsAccess(userId: string, connectionIds: string[]): Promise { + await this.graphQLService.sdk.addConnectionsAccess({ + projectId: 'g_GlobalConfiguration', + connectionIds, + subjects: [userId], + }); + } + + async deleteConnectionsAccess(userId: string, connectionIds: string[]): Promise { + await this.graphQLService.sdk.deleteConnectionsAccess({ + projectId: 'g_GlobalConfiguration', + connectionIds, + subjects: [userId], + }); } async setMetaParameters(userId: string, parameters: Record): Promise { diff --git a/webapp/packages/core-sdk/src/queries/resource-manager/addProjectsPermissions.graphql b/webapp/packages/core-sdk/src/queries/resource-manager/addProjectsPermissions.graphql new file mode 100644 index 00000000000..153c1d1cc97 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/resource-manager/addProjectsPermissions.graphql @@ -0,0 +1,3 @@ +mutation addProjectsPermissions($projectIds: [ID!]!, $subjectIds: [ID!]!, $permissions: [String!]!) { + rmAddProjectsPermissions(projectIds: $projectIds, subjectIds: $subjectIds, permissions: $permissions) +} diff --git a/webapp/packages/core-sdk/src/queries/resource-manager/deleteProjectsPermissions.graphql b/webapp/packages/core-sdk/src/queries/resource-manager/deleteProjectsPermissions.graphql new file mode 100644 index 00000000000..a16a9eb9ef7 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/resource-manager/deleteProjectsPermissions.graphql @@ -0,0 +1,3 @@ +mutation deleteProjectsPermissions($projectIds: [ID!]!, $subjectIds: [ID!]!, $permissions: [String!]!) { + rmDeleteProjectsPermissions(projectIds: $projectIds, subjectIds: $subjectIds, permissions: $permissions) +} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnectionsTabService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnectionsTabService.ts index 2f8894c3d85..869b15a0bf0 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnectionsTabService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnectionsTabService.ts @@ -95,15 +95,39 @@ export class GrantedConnectionsTabService extends Bootstrap { return; } + const { connectionsToRevoke, connectionsToGrant } = this.getSubjectDifferences(state); + try { - await this.graphQLService.sdk.setSubjectConnectionAccess({ - subjectId: config.teamId, - connections: state.grantedSubjects, - }); + if (connectionsToRevoke.length > 0) { + await this.graphQLService.sdk.deleteConnectionsAccess({ + projectId: 'g_GlobalConfiguration', + subjects: [config.teamId], + connectionIds: connectionsToRevoke, + }); + } + + if (connectionsToGrant.length > 0) { + await this.graphQLService.sdk.addConnectionsAccess({ + projectId: 'g_GlobalConfiguration', + subjects: [config.teamId], + connectionIds: connectionsToGrant, + }); + } state.loaded = false; } catch (exception: any) { this.notificationService.logException(exception); } } + + private getSubjectDifferences(state: IGrantedConnectionsTabState): { connectionsToRevoke: string[]; connectionsToGrant: string[] } { + const current = state.initialGrantedSubjects; + const next = state.grantedSubjects; + + const connectionsToRevoke = current.filter(value => !next.some(subjectId => subjectId === value)); + + const connectionsToGrant = next.filter(subjectId => !current.some(value => value === subjectId)); + + return { connectionsToRevoke, connectionsToGrant }; + } } diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccessPart.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccessPart.ts index c1e59f6e084..560cf4828b7 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccessPart.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UserForm/ConnectionAccess/UserFormConnectionAccessPart.ts @@ -55,14 +55,36 @@ export class UserFormConnectionAccessPart extends FormPart 0) { + await this.usersResource.deleteConnectionsAccess(userFormInfoPart.state.userId, connectionsToRevoke); + } + + if (connectionsToGrant.length > 0) { + await this.usersResource.addConnectionsAccess(userFormInfoPart.state.userId, connectionsToGrant); + } } private getGrantedConnections(state: AdminConnectionGrantInfo[]): string[] { return state.filter(connection => connection.subjectType !== AdminSubjectType.Team).map(connection => connection.dataSourceId); } + private async getConnectionsDifferences( + current: string[], + next: string[], + ): Promise<{ connectionsToRevoke: string[]; connectionsToGrant: string[] }> { + const connectionsToRevoke = current.filter(subjectId => !next.includes(subjectId)); + const connectionsToGrant = next.filter(subjectId => !current.includes(subjectId)); + + return { connectionsToRevoke, connectionsToGrant }; + } + protected override async loader() { const userFormInfoPart = this.formState.dataContext.get(DATA_CONTEXT_USER_FORM_INFO_PART); let grantedConnections: AdminConnectionGrantInfo[] = []; diff --git a/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccessTabService.ts b/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccessTabService.ts index 56810ba0a87..81de02c7c12 100644 --- a/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccessTabService.ts +++ b/webapp/packages/plugin-connections-administration/src/ConnectionForm/ConnectionAccess/ConnectionAccessTabService.ts @@ -104,20 +104,24 @@ export class ConnectionAccessTabService extends Bootstrap { const key = createConnectionParam(data.state.projectId, config.connectionId); - const changed = await this.isChanged(key, state.grantedSubjects); + const currentGrantedSubjects = await this.connectionInfoResource.loadAccessSubjects(key); + const currentGrantedSubjectIds = currentGrantedSubjects.map(subject => subject.subjectId); - if (changed) { - if (state.initialGrantedSubjects.length > state.grantedSubjects.length) { + const { subjectsToRevoke, subjectsToGrant } = await this.getSubjectDifferences(currentGrantedSubjectIds, state.grantedSubjects); + + if (subjectsToRevoke.length === 0 && subjectsToGrant.length === 0) { + return; + } - const subjectsToRemove = state.initialGrantedSubjects.filter(subject => !state.grantedSubjects.includes(subject)); - await this.connectionInfoResource.deleteConnectionsAccess(key, subjectsToRemove); - } else if (state.initialGrantedSubjects.length < state.grantedSubjects.length) { + if (subjectsToRevoke.length > 0) { + await this.connectionInfoResource.deleteConnectionsAccess(key, subjectsToRevoke); + } - const subjectsToAdd = state.grantedSubjects.filter(subject => !state.initialGrantedSubjects.includes(subject)); - await this.connectionInfoResource.addConnectionsAccess(key, subjectsToAdd); - } - state.initialGrantedSubjects = state.grantedSubjects.slice(); + if (subjectsToGrant.length > 0) { + await this.connectionInfoResource.addConnectionsAccess(key, subjectsToGrant); } + + state.initialGrantedSubjects = state.grantedSubjects.slice(); } private async formState(data: IConnectionFormState, contexts: IExecutionContextProvider) { @@ -146,4 +150,11 @@ export class ConnectionAccessTabService extends Bootstrap { return current.some(value => !next.some(subjectId => subjectId === value.subjectId)); } + + private async getSubjectDifferences(current: string[], next: string[]): Promise<{ subjectsToRevoke: string[]; subjectsToGrant: string[] }> { + const subjectsToRevoke = current.filter(subjectId => !next.includes(subjectId)); + const subjectsToGrant = next.filter(subjectId => !current.includes(subjectId)); + + return { subjectsToRevoke, subjectsToGrant }; + } }