From f390ab0e549a2620fcf61e95de17ee420f9b5e01 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Tue, 19 Jun 2018 18:09:11 +0100 Subject: [PATCH] Update the connected user roles section of store on roles change - includes renaming of role change actions from 'permissions' to 'roles' --- .../manage-users-confirm.component.ts | 6 +- .../cf-org-permission-cell.component.ts | 15 ++-- .../list-types/cf-users/cf-permission-cell.ts | 17 +++-- .../cf-space-permission-cell.component.ts | 15 ++-- .../app/store/actions/users.actions.ts | 37 +++++----- .../app/store/effects/users-roles.effects.ts | 38 ++++++---- .../app/store/reducers/auth.reducer.ts | 3 +- .../current-user-roles-changed.reducers.ts | 72 +++++++++++++++++++ .../current-user-roles.reducer.ts | 6 ++ .../app/store/reducers/users.reducer.ts | 34 ++++----- 10 files changed, 173 insertions(+), 70 deletions(-) create mode 100644 src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles-changed.reducers.ts diff --git a/src/frontend/app/features/cloud-foundry/users/manage-users/manage-users-confirm/manage-users-confirm.component.ts b/src/frontend/app/features/cloud-foundry/users/manage-users/manage-users-confirm/manage-users-confirm.component.ts index ffde9930a2..d99bab8ecd 100644 --- a/src/frontend/app/features/cloud-foundry/users/manage-users/manage-users-confirm/manage-users-confirm.component.ts +++ b/src/frontend/app/features/cloud-foundry/users/manage-users/manage-users-confirm/manage-users-confirm.component.ts @@ -1,5 +1,5 @@ -import {combineLatest as observableCombineLatest, BehaviorSubject , Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, BehaviorSubject, Observable } from 'rxjs'; import { AfterContentInit, Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { distinctUntilChanged, filter, first, map, mergeMap, withLatestFrom } from 'rxjs/operators'; @@ -22,7 +22,7 @@ import { } from '../../../../../shared/components/list/list-types/cf-confirm-roles/table-cell-confirm-role-add-rem/table-cell-confirm-role-add-rem.component'; import { CfUserService } from '../../../../../shared/data-services/cf-user.service'; import { UsersRolesClearUpdateState } from '../../../../../store/actions/users-roles.actions'; -import { ChangeUserPermission } from '../../../../../store/actions/users.actions'; +import { ChangeUserRole } from '../../../../../store/actions/users.actions'; import { AppState } from '../../../../../store/app-state'; import { cfUserSchemaKey, @@ -100,7 +100,7 @@ export class UsersRolesConfirmComponent implements OnInit, AfterContentInit { entityKey: schema.key, schema: schema, monitorState: AppMonitorComponentTypes.UPDATE, - updateKey: ChangeUserPermission.generateUpdatingKey(row.role, row.userGuid), + updateKey: ChangeUserRole.generateUpdatingKey(row.role, row.userGuid), getId: () => guid }; } diff --git a/src/frontend/app/shared/components/list/list-types/cf-users/cf-org-permission-cell/cf-org-permission-cell.component.ts b/src/frontend/app/shared/components/list/list-types/cf-users/cf-org-permission-cell/cf-org-permission-cell.component.ts index ed635b8f70..4d55e4cb77 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-users/cf-org-permission-cell/cf-org-permission-cell.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-users/cf-org-permission-cell/cf-org-permission-cell.component.ts @@ -6,7 +6,7 @@ import { CurrentUserPermissions } from '../../../../../../core/current-user-perm import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; import { arrayHelper } from '../../../../../../core/helper-classes/array.helper'; import { getOrgRoles } from '../../../../../../features/cloud-foundry/cf.helpers'; -import { RemoveUserPermission } from '../../../../../../store/actions/users.actions'; +import { RemoveUserRole } from '../../../../../../store/actions/users.actions'; import { AppState } from '../../../../../../store/app-state'; import { entityFactory, organizationSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; @@ -24,12 +24,12 @@ import { CfPermissionCell, ICellPermissionList } from '../cf-permission-cell'; }) export class CfOrgPermissionCellComponent extends CfPermissionCell { constructor( - public store: Store, + store: Store, public cfUserService: CfUserService, private userPerms: CurrentUserPermissionsService, confirmDialog: ConfirmationDialogService ) { - super(confirmDialog); + super(store, confirmDialog); } protected setChipConfig(row: APIResource) { @@ -42,7 +42,7 @@ export class CfOrgPermissionCellComponent extends CfPermissionCell): ICellPermissionList[] { return getOrgRoles(orgPerms.permissions).map(perm => { - const updatingKey = RemoveUserPermission.generateUpdatingKey( + const updatingKey = RemoveUserRole.generateUpdatingKey( perm.key, row.metadata.guid ); @@ -66,13 +66,14 @@ export class CfOrgPermissionCellComponent extends CfPermissionCell) { - this.store.dispatch(new RemoveUserPermission( + public removePermission(cellPermission: ICellPermissionList, updateConnectedUser: boolean) { + this.store.dispatch(new RemoveUserRole( this.cfUserService.activeRouteCfOrgSpace.cfGuid, cellPermission.userGuid, cellPermission.guid, cellPermission.key, - false + false, + updateConnectedUser )); } diff --git a/src/frontend/app/shared/components/list/list-types/cf-users/cf-permission-cell.ts b/src/frontend/app/shared/components/list/list-types/cf-users/cf-permission-cell.ts index 3171bbce16..087b36331d 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-users/cf-permission-cell.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-users/cf-permission-cell.ts @@ -1,6 +1,6 @@ import { Input } from '@angular/core'; import { Observable, of as observableOf } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { map, first } from 'rxjs/operators'; import { IUserRole } from '../../../../../features/cloud-foundry/cf.helpers'; import { APIResource } from '../../../../../store/types/api.types'; @@ -9,6 +9,9 @@ import { AppChip } from '../../../chips/chips.component'; import { TableCellCustom } from '../../list.types'; import { ConfirmationDialogService } from '../../../confirmation-dialog.service'; import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config'; +import { Store } from '@ngrx/store'; +import { AppState } from '../../../../../store/app-state'; +import { selectSessionData } from '../../../../../store/reducers/auth.reducer'; export interface ICellPermissionList extends IUserRole { @@ -36,7 +39,7 @@ export abstract class CfPermissionCell extends TableCellCustom, private confirmDialog: ConfirmationDialogService) { super(); } @@ -70,11 +73,17 @@ export abstract class CfPermissionCell extends TableCellCustom { - this.removePermission(cellPermission); + this.store.select(selectSessionData()).pipe( + first() + ).subscribe(sessionData => { + const cfSession = sessionData.endpoints.cf[cellPermission.cfGuid]; + const updateConnectedUser = !cfSession.user.admin && cellPermission.userGuid === cfSession.user.guid; + this.removePermission(cellPermission, updateConnectedUser); + }); }); } - protected removePermission(cellPermission: ICellPermissionList) { + protected removePermission(cellPermission: ICellPermissionList, updateConnectedUser: boolean) { } diff --git a/src/frontend/app/shared/components/list/list-types/cf-users/cf-space-permission-cell/cf-space-permission-cell.component.ts b/src/frontend/app/shared/components/list/list-types/cf-users/cf-space-permission-cell/cf-space-permission-cell.component.ts index 90c222f941..2ebbc06cc4 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-users/cf-space-permission-cell/cf-space-permission-cell.component.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-users/cf-space-permission-cell/cf-space-permission-cell.component.ts @@ -6,7 +6,7 @@ import { CurrentUserPermissions } from '../../../../../../core/current-user-perm import { CurrentUserPermissionsService } from '../../../../../../core/current-user-permissions.service'; import { arrayHelper } from '../../../../../../core/helper-classes/array.helper'; import { getSpaceRoles } from '../../../../../../features/cloud-foundry/cf.helpers'; -import { RemoveUserPermission } from '../../../../../../store/actions/users.actions'; +import { RemoveUserRole } from '../../../../../../store/actions/users.actions'; import { AppState } from '../../../../../../store/app-state'; import { entityFactory, spaceSchemaKey } from '../../../../../../store/helpers/entity-factory'; import { APIResource } from '../../../../../../store/types/api.types'; @@ -25,12 +25,12 @@ import { CfPermissionCell, ICellPermissionList } from '../cf-permission-cell'; export class CfSpacePermissionCellComponent extends CfPermissionCell { constructor( - public store: Store, + store: Store, public cfUserService: CfUserService, private userPerms: CurrentUserPermissionsService, confirmDialog: ConfirmationDialogService ) { - super(confirmDialog); + super(store, confirmDialog); } protected setChipConfig(row: APIResource) { @@ -43,7 +43,7 @@ export class CfSpacePermissionCellComponent extends CfPermissionCell) { return getSpaceRoles(spacePerms.permissions).map(perm => { - const updatingKey = RemoveUserPermission.generateUpdatingKey( + const updatingKey = RemoveUserRole.generateUpdatingKey( perm.key, row.metadata.guid ); @@ -68,13 +68,14 @@ export class CfSpacePermissionCellComponent extends CfPermissionCell) { - this.store.dispatch(new RemoveUserPermission( + public removePermission(cellPermission: ICellPermissionList, updateConnectedUser: boolean) { + this.store.dispatch(new RemoveUserRole( this.cfUserService.activeRouteCfOrgSpace.cfGuid, cellPermission.userGuid, cellPermission.guid, cellPermission.key, - true + true, + updateConnectedUser )); } diff --git a/src/frontend/app/store/actions/users.actions.ts b/src/frontend/app/store/actions/users.actions.ts index ae9b3b68c9..ae5bdfebdb 100644 --- a/src/frontend/app/store/actions/users.actions.ts +++ b/src/frontend/app/store/actions/users.actions.ts @@ -19,13 +19,13 @@ export const GET_ALL = '[Users] Get all'; export const GET_ALL_SUCCESS = '[Users] Get all success'; export const GET_ALL_FAILED = '[Users] Get all failed'; -export const REMOVE_PERMISSION = '[Users] Remove Permission'; -export const REMOVE_PERMISSION_SUCCESS = '[Users] Remove Permission success'; -export const REMOVE_PERMISSION_FAILED = '[Users] Remove Permission failed'; +export const REMOVE_ROLE = '[Users] Remove role'; +export const REMOVE_ROLE_SUCCESS = '[Users] Remove role success'; +export const REMOVE_ROLE_FAILED = '[Users] Remove role failed'; -export const ADD_PERMISSION = '[Users] Add Permission'; -export const ADD_PERMISSION_SUCCESS = '[Users] Add Permission success'; -export const ADD_PERMISSION_FAILED = '[Users] Add Permission failed'; +export const ADD_ROLE = '[Users] Add role'; +export const ADD_ROLE_SUCCESS = '[Users] Add role success'; +export const ADD_ROLE_FAILED = '[Users] Add role failed'; const defaultUserRelations = [ createEntityRelationKey(cfUserSchemaKey, organizationSchemaKey), @@ -101,7 +101,7 @@ export class GetCFUser extends CFStartAction implements IRequestAction { options: RequestOptions; } -export class ChangeUserPermission extends CFStartAction implements IRequestAction { +export class ChangeUserRole extends CFStartAction implements IRequestAction { constructor( public endpointGuid: string, public userGuid: string, @@ -110,10 +110,11 @@ export class ChangeUserPermission extends CFStartAction implements IRequestActio public permissionTypeKey: OrgUserRoleNames | SpaceUserRoleNames, public entityGuid: string, public isSpace = false, + public updateConnectedUser = false ) { super(); this.guid = entityGuid; - this.updatingKey = ChangeUserPermission.generateUpdatingKey(permissionTypeKey, userGuid); + this.updatingKey = ChangeUserRole.generateUpdatingKey(permissionTypeKey, userGuid); this.options = new RequestOptions(); this.options.url = `${isSpace ? 'spaces' : 'organizations'}/${this.guid}/${this.updatingKey}`; this.options.method = method; @@ -132,42 +133,46 @@ export class ChangeUserPermission extends CFStartAction implements IRequestActio } } -export class AddUserPermission extends ChangeUserPermission { +export class AddUserRole extends ChangeUserRole { constructor( endpointGuid: string, userGuid: string, entityGuid: string, permissionTypeKey: OrgUserRoleNames | SpaceUserRoleNames, - isSpace = false + isSpace = false, + updateConnectedUser = false ) { super( endpointGuid, userGuid, 'put', - [ADD_PERMISSION, ADD_PERMISSION_SUCCESS, ADD_PERMISSION_FAILED], + [ADD_ROLE, ADD_ROLE_SUCCESS, ADD_ROLE_FAILED], permissionTypeKey, entityGuid, - isSpace + isSpace, + updateConnectedUser, ); } } -export class RemoveUserPermission extends ChangeUserPermission { +export class RemoveUserRole extends ChangeUserRole { constructor( endpointGuid: string, userGuid: string, entityGuid: string, permissionTypeKey: OrgUserRoleNames | SpaceUserRoleNames, - isSpace = false + isSpace = false, + updateConnectedUser = false ) { super( endpointGuid, userGuid, 'delete', - [REMOVE_PERMISSION, REMOVE_PERMISSION_SUCCESS, REMOVE_PERMISSION_FAILED], + [REMOVE_ROLE, REMOVE_ROLE_SUCCESS, REMOVE_ROLE_FAILED], permissionTypeKey, entityGuid, - isSpace + isSpace, + updateConnectedUser ); } } diff --git a/src/frontend/app/store/effects/users-roles.effects.ts b/src/frontend/app/store/effects/users-roles.effects.ts index b1841fdd7e..d4b7814d5a 100644 --- a/src/frontend/app/store/effects/users-roles.effects.ts +++ b/src/frontend/app/store/effects/users-roles.effects.ts @@ -6,10 +6,12 @@ import { filter, first, map, mergeMap, pairwise, withLatestFrom } from 'rxjs/ope import { EntityMonitor } from '../../shared/monitors/entity-monitor'; import { UsersRolesActions, UsersRolesClearUpdateState, UsersRolesExecuteChanges } from '../actions/users-roles.actions'; -import { AddUserPermission, ChangeUserPermission, RemoveUserPermission } from '../actions/users.actions'; +import { AddUserRole, ChangeUserRole, RemoveUserRole } from '../actions/users.actions'; import { AppState } from '../app-state'; import { entityFactory, organizationSchemaKey, spaceSchemaKey } from '../helpers/entity-factory'; +import { selectSessionData } from '../reducers/auth.reducer'; import { selectUsersRoles } from '../selectors/users-roles.selector'; +import { SessionDataEndpoint } from '../types/auth.types'; import { ICFAction, UpdateCfAction } from '../types/request.types'; import { OrgUserRoleNames } from '../types/user.types'; import { CfRoleChange } from '../types/users-roles.types'; @@ -30,7 +32,7 @@ export class UsersRolesEffects { const apiAction = { guid: change.spaceGuid ? change.spaceGuid : change.orgGuid, entityKey: change.spaceGuid ? spaceSchemaKey : organizationSchemaKey, - updatingKey: ChangeUserPermission.generateUpdatingKey(change.role, change.userGuid), + updatingKey: ChangeUserRole.generateUpdatingKey(change.role, change.userGuid), options: null, actions: [] } as ICFAction; @@ -42,14 +44,18 @@ export class UsersRolesEffects { ); @Effect() executeUsersRolesChange$ = this.actions$.ofType(UsersRolesActions.ExecuteChanges).pipe( - withLatestFrom(this.store.select(selectUsersRoles)), - mergeMap(([action, usersRoles]) => { + withLatestFrom( + this.store.select(selectUsersRoles), + this.store.select(selectSessionData()) + ), + mergeMap(([action, usersRoles, sessionData]) => { // If the user is adding the org user role then that needs to execute and succeed first, otherwise the other changes will fail // Conversely if the org user role is being removed all other changes need to execute first // Note - we should never be in the state where a user is adding space/org roles and removing org user. We could safeguard against // this here, however the UX should have already ensured this const cfGuid = usersRoles.cfGuid; + const cfSession = sessionData.endpoints.cf[cfGuid]; const changes = [...usersRoles.changedRoles]; // Split changes into `org user` and `other` @@ -69,30 +75,32 @@ export class UsersRolesEffects { if (orgUserChanges.length) { // Are we adding the org user role (can never add to one user and remove from another) if (orgUserChanges[0].add) { + // Do org user changes first - return this.executeChanges(cfGuid, orgUserChanges).pipe( + return this.executeChanges(cfGuid, cfSession, orgUserChanges).pipe( // Then do all other changes - mergeMap(() => this.executeChanges(cfGuid, nonOrgUserChanges)) + mergeMap(() => this.executeChanges(cfGuid, cfSession, nonOrgUserChanges)) ); } else { // Do all other changes first - return this.executeChanges(cfGuid, nonOrgUserChanges).pipe( + return this.executeChanges(cfGuid, cfSession, nonOrgUserChanges).pipe( // Then do org user change - mergeMap(() => this.executeChanges(cfGuid, orgUserChanges)) + mergeMap(() => this.executeChanges(cfGuid, cfSession, orgUserChanges)) ); } } else { - return this.executeChanges(cfGuid, nonOrgUserChanges); + return this.executeChanges(cfGuid, cfSession, nonOrgUserChanges); } }), mergeMap(() => []) ); - private executeChanges(cfGuid: string, changes: CfRoleChange[]): Observable { + private executeChanges(cfGuid: string, cfSession: SessionDataEndpoint, changes: CfRoleChange[]): Observable { const observables: Observable[] = []; changes.forEach(change => { - const action = this.createAction(cfGuid, change); + const updateConnectedUser = !cfSession.user.admin && change.userGuid === cfSession.user.guid; + const action = this.createAction(cfGuid, updateConnectedUser, change); this.store.dispatch(action); observables.push(this.createActionObs(action)); }); @@ -102,15 +110,15 @@ export class UsersRolesEffects { ); } - private createAction(cfGuid: string, change: CfRoleChange): ChangeUserPermission { + private createAction(cfGuid: string, updateConnectedUser: boolean, change: CfRoleChange): ChangeUserRole { const isSpace = !!change.spaceGuid; const entityGuid = isSpace ? change.spaceGuid : change.orgGuid; return change.add ? - new AddUserPermission(cfGuid, change.userGuid, entityGuid, change.role, isSpace) : - new RemoveUserPermission(cfGuid, change.userGuid, entityGuid, change.role, isSpace); + new AddUserRole(cfGuid, change.userGuid, entityGuid, change.role, isSpace, updateConnectedUser) : + new RemoveUserRole(cfGuid, change.userGuid, entityGuid, change.role, isSpace, updateConnectedUser); } - private createActionObs(action: ChangeUserPermission): Observable { + private createActionObs(action: ChangeUserRole): Observable { return new EntityMonitor( this.store, action.guid, diff --git a/src/frontend/app/store/reducers/auth.reducer.ts b/src/frontend/app/store/reducers/auth.reducer.ts index 77a8a6e61e..91a5d58f18 100644 --- a/src/frontend/app/store/reducers/auth.reducer.ts +++ b/src/frontend/app/store/reducers/auth.reducer.ts @@ -12,6 +12,7 @@ import { VERIFY_SESSION, } from './../actions/auth.actions'; import { RouterRedirect } from './routing.reducer'; +import { AppState } from '../app-state'; export interface AuthUser { guid: string; @@ -86,5 +87,5 @@ export function authReducer(state: AuthState = defaultState, action): AuthState } export function selectSessionData() { - return (state) => state.auth.sessionData; + return (state: AppState) => state.auth.sessionData; } diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles-changed.reducers.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles-changed.reducers.ts new file mode 100644 index 0000000000..faea279f40 --- /dev/null +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles-changed.reducers.ts @@ -0,0 +1,72 @@ +import { PermissionStrings } from '../../../core/current-user-permissions.config'; +import { ChangeUserRole } from '../../actions/users.actions'; +import { ICfRolesState, ICurrentUserRolesState } from '../../types/current-user-roles.types'; +import { APISuccessOrFailedAction } from '../../types/request.types'; +import { OrgUserRoleNames, SpaceUserRoleNames } from '../../types/user.types'; + +export function updateAfterRoleChange( + state: ICurrentUserRolesState, + isAdd: boolean, + action: APISuccessOrFailedAction): ICurrentUserRolesState { + const changePerm = action.apiAction as ChangeUserRole; + if (!changePerm.updateConnectedUser) { + // We haven't changed the user connected to this cf or the connected user is an admin. No need to update the permission roles + return state; + } + + const entityType = changePerm.isSpace ? 'spaces' : 'organizations'; + + const cf = state.cf[changePerm.endpointGuid]; + const entity = cf[entityType][changePerm.entityGuid]; + + const permissionType = userRoleNameToPermissionName(changePerm.permissionTypeKey); + const currentValue = entity[permissionType]; + + if (currentValue === isAdd) { + // No change, just return the state. Unlikely to happen + return state; + } + + const newCf = { + ...cf, + [entityType]: { + ...cf[entityType], + [changePerm.entityGuid]: { + ...entity, + [permissionType]: isAdd + } + } + }; + return spreadState(state, changePerm.endpointGuid, newCf); +} + +function userRoleNameToPermissionName(roleName: OrgUserRoleNames | SpaceUserRoleNames): PermissionStrings { + switch (roleName) { + case OrgUserRoleNames.AUDITOR: + return PermissionStrings.ORG_AUDITOR; + case OrgUserRoleNames.BILLING_MANAGERS: + return PermissionStrings.ORG_BILLING_MANAGER; + case OrgUserRoleNames.MANAGER: + return PermissionStrings.ORG_MANAGER; + case OrgUserRoleNames.USER: + return PermissionStrings.ORG_USER; + case SpaceUserRoleNames.AUDITOR: + return PermissionStrings.SPACE_AUDITOR; + case SpaceUserRoleNames.DEVELOPER: + return PermissionStrings.SPACE_DEVELOPER; + case SpaceUserRoleNames.MANAGER: + return PermissionStrings.SPACE_MANAGER; + } +} + +function spreadState(state: ICurrentUserRolesState, cfGuid: string, cf: ICfRolesState): ICurrentUserRolesState { + return { + ...state, + cf: { + ...state.cf, + [cfGuid]: { + ...cf + } + } + }; +} diff --git a/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles.reducer.ts b/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles.reducer.ts index 9ec951094a..687551e335 100644 --- a/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles.reducer.ts +++ b/src/frontend/app/store/reducers/current-user-roles-reducer/current-user-roles.reducer.ts @@ -21,6 +21,7 @@ import { GetUserCfRelations, } from '../../actions/permissions.actions'; import { DELETE_SPACE_SUCCESS } from '../../actions/space.actions'; +import { ADD_ROLE_SUCCESS, REMOVE_ROLE_SUCCESS } from '../../actions/users.actions'; import { getDefaultRolesRequestState, ICurrentUserRolesState } from '../../types/current-user-roles.types'; import { APISuccessOrFailedAction } from '../../types/request.types'; import { currentUserBaseCFRolesReducer } from './current-user-base-cf-role.reducer'; @@ -29,6 +30,7 @@ import { currentUserRolesRequestStateReducer, } from './current-user-request-state.reducers'; import { roleInfoFromSessionReducer, updateNewlyConnectedEndpoint } from './current-user-role-session.reducer'; +import { updateAfterRoleChange } from './current-user-roles-changed.reducers'; import { addEndpoint, removeEndpointRoles, removeOrgRoles, removeSpaceRoles } from './current-user-roles-clear.reducers'; const getDefaultState = () => ({ @@ -60,6 +62,10 @@ export function currentUserRolesReducer(state: ICurrentUserRolesState = getDefau return removeOrgRoles(state, action as APISuccessOrFailedAction); case DELETE_SPACE_SUCCESS: return removeSpaceRoles(state, action as APISuccessOrFailedAction); + case ADD_ROLE_SUCCESS: + return updateAfterRoleChange(state, true, action as APISuccessOrFailedAction); + case REMOVE_ROLE_SUCCESS: + return updateAfterRoleChange(state, false, action as APISuccessOrFailedAction); case GET_CURRENT_USER_RELATIONS: case GET_CURRENT_USER_RELATIONS_SUCCESS: case GET_CURRENT_USER_RELATIONS_FAILED: diff --git a/src/frontend/app/store/reducers/users.reducer.ts b/src/frontend/app/store/reducers/users.reducer.ts index 1f83d6dc3a..53b28f7635 100644 --- a/src/frontend/app/store/reducers/users.reducer.ts +++ b/src/frontend/app/store/reducers/users.reducer.ts @@ -1,5 +1,5 @@ import { IOrganization, ISpace } from '../../core/cf-api.types'; -import { ADD_PERMISSION_SUCCESS, ChangeUserPermission, REMOVE_PERMISSION_SUCCESS } from '../actions/users.actions'; +import { ADD_ROLE_SUCCESS, ChangeUserRole, REMOVE_ROLE_SUCCESS } from '../actions/users.actions'; import { IRequestEntityTypeState } from '../app-state'; import { APIResource } from '../types/api.types'; import { APISuccessOrFailedAction } from '../types/request.types'; @@ -22,16 +22,16 @@ const properties = { export function userReducer(state: IRequestEntityTypeState>, action: APISuccessOrFailedAction) { switch (action.type) { - case ADD_PERMISSION_SUCCESS: - case REMOVE_PERMISSION_SUCCESS: + case ADD_ROLE_SUCCESS: + case REMOVE_ROLE_SUCCESS: // Ensure that a user's roles collections are updated when we call add/remove - const permAction = action.apiAction as ChangeUserPermission; + const permAction = action.apiAction as ChangeUserRole; const { entityGuid, isSpace, permissionTypeKey, userGuid } = permAction; return { ...state, [userGuid]: { ...state[userGuid], - entity: updatePermission(state[userGuid].entity, entityGuid, isSpace, permissionTypeKey, action.type === ADD_PERMISSION_SUCCESS), + entity: updatePermission(state[userGuid].entity, entityGuid, isSpace, permissionTypeKey, action.type === ADD_ROLE_SUCCESS), } }; } @@ -41,13 +41,13 @@ export function endpointDisconnectUserReducer(state: IRequestEntityTypeState u.entity.cfGuid !== cfGuid) - .forEach(u => newUsers[u.metadata.guid] = u); - return newUsers; + const cfGuid = action.guid; + // remove users that belong to this CF + const newUsers = {}; + Object.values(state) + .filter(u => u.entity.cfGuid !== cfGuid) + .forEach(u => newUsers[u.metadata.guid] = u); + return newUsers; } } return state; @@ -76,18 +76,18 @@ interface StateEntities { [guid: string]: APIResource; } export function userSpaceOrgReducer(isSpace: boolean) { return function (state: StateEntities, action: APISuccessOrFailedAction) { switch (action.type) { - case ADD_PERMISSION_SUCCESS: - case REMOVE_PERMISSION_SUCCESS: + case ADD_ROLE_SUCCESS: + case REMOVE_ROLE_SUCCESS: // Ensure that an org or space's roles lists are updated when we call add/remove - const permAction = action.apiAction as ChangeUserPermission; - const isAdd = action.type === ADD_PERMISSION_SUCCESS ? true : false; + const permAction = action.apiAction as ChangeUserRole; + const isAdd = action.type === ADD_ROLE_SUCCESS ? true : false; return (isSpace && !!permAction.isSpace) || (!isSpace && !permAction.isSpace) ? newEntityState(state, permAction, isAdd) : state; } return state; }; } -function newEntityState(state: StateEntities, action: ChangeUserPermission, add: boolean): StateEntities { +function newEntityState(state: StateEntities, action: ChangeUserRole, add: boolean): StateEntities { const apiResource: APIResource = state[action.guid]; if (!apiResource) { return state;