Skip to content

Commit

Permalink
Change following review #1
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-cox committed Jun 4, 2020
1 parent df2a958 commit 619e9b3
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import {
ListViewTypes,
} from '../../../../../../../core/src/shared/components/list/list.component.types';
import { ListView } from '../../../../../../../store/src/actions/list.actions';
import { connectedEndpointsOfTypesSelector } from '../../../../../../../store/src/selectors/endpoint.selectors';
import { APIResource } from '../../../../../../../store/src/types/api.types';
import { CF_ENDPOINT_TYPE } from '../../../../../cf-types';
import { ActiveRouteCfOrgSpace } from '../../../../../features/cloud-foundry/cf-page.types';
import { haveMultiConnectedCfs } from '../../../../../features/cloud-foundry/cf.helpers';
import { endpointsCfEntitiesConnectedSelector } from '../../../../../store/selectors/cloud-foundry.selector';
import { CfOrgSpaceItem, createCfOrgSpaceFilterConfig } from '../../../../data-services/cf-org-space-service.service';
import { CfServiceCardComponent } from './cf-service-card/cf-service-card.component';
import { CfServicesDataSource } from './cf-services-data-source';
Expand All @@ -38,7 +39,7 @@ export class CfServicesListConfigService implements IListConfig<APIResource> {
) {
this.dataSource = new CfServicesDataSource(this.store, activeRouteCfOrgSpace.cfGuid, this);
this.cf = {
list$: this.store.select(endpointsCfEntitiesConnectedSelector).pipe(
list$: this.store.select(connectedEndpointsOfTypesSelector(CF_ENDPOINT_TYPE)).pipe(
first(),
map(endpoints => Object.values(endpoints))
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ import { ResetPagination, SetParams } from '../../../../store/src/actions/pagina
import { PaginationMonitorFactory } from '../../../../store/src/monitors/pagination-monitor.factory';
import { getPaginationObservables } from '../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper';
import { getCurrentPageRequestInfo } from '../../../../store/src/reducers/pagination-reducer/pagination-reducer.types';
import { connectedEndpointsOfTypesSelector } from '../../../../store/src/selectors/endpoint.selectors';
import { selectPaginationState } from '../../../../store/src/selectors/pagination.selectors';
import { APIResource } from '../../../../store/src/types/api.types';
import { EndpointModel } from '../../../../store/src/types/endpoint.types';
import { PaginatedAction, PaginationParam } from '../../../../store/src/types/pagination.types';
import { IOrganization, ISpace } from '../../cf-api.types';
import { cfEntityCatalog } from '../../cf-entity-catalog';
import { cfEntityFactory } from '../../cf-entity-factory';
import { endpointsCfEntitiesConnectedSelector } from '../../store/selectors/cloud-foundry.selector';
import { CF_ENDPOINT_TYPE } from '../../cf-types';
import { QParam, QParamJoiners } from '../q-param';

export function spreadPaginationParams(params: PaginationParam): PaginationParam {
Expand Down Expand Up @@ -221,7 +222,7 @@ export class CfOrgSpaceDataService implements OnDestroy {
}

private createCf() {
const list$ = this.store.select(endpointsCfEntitiesConnectedSelector).pipe(
const list$ = this.store.select(connectedEndpointsOfTypesSelector(CF_ENDPOINT_TYPE)).pipe(
// Ensure we have endpoints
filter(endpoints => endpoints && !!Object.keys(endpoints).length),
publishReplay(1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { CreateAppPageEffects } from './effects/create-app-effects';
import { DeployAppEffects } from './effects/deploy-app.effects';
import { GithubEffects } from './effects/github.effects';
import { CfValidateEffects } from './effects/request.effects';
import { PermissionEffects } from './effects/roles.effects';
import { RouteEffect } from './effects/route.effects';
import { ServiceInstanceEffects } from './effects/service-instance.effects';
import { UpdateAppEffects } from './effects/update-app-effects';
Expand All @@ -26,7 +25,6 @@ import { UsersRolesEffects } from './effects/users-roles.effects';
GithubEffects,
CloudFoundryEffects,
RouteEffect,
PermissionEffects,
ServiceInstanceEffects,
AppEffects,
UpdateAppEffects,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
Expand All @@ -14,12 +15,14 @@ import { selectSessionData } from '../../../../store/src/reducers/auth.reducer';
import { SessionDataEndpoint } from '../../../../store/src/types/auth.types';
import { PaginatedAction } from '../../../../store/src/types/pagination.types';
import { ICFAction, UpdateCfAction } from '../../../../store/src/types/request.types';
import { GET_CURRENT_CF_USER_RELATION, GetCurrentCfUserRelations } from '../../actions/permissions.actions';
import { UsersRolesActions, UsersRolesClearUpdateState, UsersRolesExecuteChanges } from '../../actions/users-roles.actions';
import { AddCfUserRole, ChangeCfUserRole, RemoveCfUserRole } from '../../actions/users.actions';
import { CFAppState } from '../../cf-app-state';
import { organizationEntityType, spaceEntityType } from '../../cf-entity-types';
import { CF_ENDPOINT_TYPE } from '../../cf-types';
import { CfUserService } from '../../shared/data-services/cf-user.service';
import { fetchCfUserRole } from '../../user-permissions/cf-user-roles-fetch';
import { selectCfUsersRoles } from '../selectors/cf-users-roles.selector';
import { OrgUserRoleNames } from '../types/cf-user.types';
import { CfRoleChange, UsersRolesState } from '../types/users-roles.types';
Expand All @@ -29,11 +32,22 @@ import { CfRoleChange, UsersRolesState } from '../types/users-roles.types';
export class UsersRolesEffects {

constructor(
private httpClient: HttpClient,
private actions$: Actions,
private store: Store<CFAppState>,
private cfUserService: CfUserService,
) { }

@Effect() getCurrentUsersPermissions$ = this.actions$.pipe(
ofType<GetCurrentCfUserRelations>(GET_CURRENT_CF_USER_RELATION),
map(action => {
return fetchCfUserRole(this.store, action, this.httpClient).pipe(
map(() => ({ type: action.actions[1] })),
catchError(() => [{ type: action.actions[2] }])
);
})
);

@Effect() clearEntityUpdates$ = this.actions$.pipe(
ofType<UsersRolesClearUpdateState>(UsersRolesActions.ClearUpdateState),
mergeMap(action => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
IConfigGroups,
ICurrentUserPermissionsChecker,
IPermissionCheckCombiner,
} from '../../../core/src/core/permissions/stratos-user-permissions.checker';
} from '../../../core/src/core/permissions/current-user-permissions.types';
import { GeneralEntityAppState } from '../../../store/src/app-state';
import { connectedEndpointsSelector } from '../../../store/src/selectors/endpoint.selectors';
import { CFFeatureFlagTypes, IFeatureFlag } from '../cf-api.types';
Expand Down Expand Up @@ -397,7 +397,7 @@ export class CfUserPermissionsChecker extends BaseCurrentUserPermissionsChecker

private getAllEndpointGuids() {
return this.store.select(connectedEndpointsSelector).pipe(
map(endpoints => Object.values(endpoints).filter(e => e.cnsi_type === 'cf').map(endpoint => endpoint.guid))
map(endpoints => Object.values(endpoints).filter(e => e.cnsi_type === CF_ENDPOINT_TYPE).map(endpoint => endpoint.guid))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
PaginationFlattener,
} from '../../../store/src/helpers/paginated-request-helpers';
import { ActionState } from '../../../store/src/reducers/api-request-reducer/types';
import { connectedEndpointsOfTypesSelector } from '../../../store/src/selectors/endpoint.selectors';
import { selectPaginationState } from '../../../store/src/selectors/pagination.selectors';
import { BasePaginatedAction, PaginationEntityState } from '../../../store/src/types/pagination.types';
import {
Expand All @@ -28,14 +29,14 @@ import {
GetCurrentCfUserRelationsComplete,
} from '../actions/permissions.actions';
import { cfEntityCatalog } from '../cf-entity-catalog';
import { endpointsCfEntitiesConnectedSelector } from '../store/selectors/cloud-foundry.selector';
import { CF_ENDPOINT_TYPE } from '../cf-types';
import { CFResponse } from '../store/types/cf-api.types';

const createEndpointArray = (store: Store<AppState>, endpoints: string[] | EntityUserRolesEndpoint[]): Observable<EntityUserRolesEndpoint[]> => {
// If there's no endpoints get all from store. Alternatively fetch specific endpoint id's from store
if (!endpoints || !endpoints.length || typeof (endpoints[0]) === 'string') {
const endpointIds = endpoints as string[];
return store.select(endpointsCfEntitiesConnectedSelector).pipe(
return store.select(connectedEndpointsOfTypesSelector(CF_ENDPOINT_TYPE)).pipe(
first(),
map(cfEndpoints => endpointIds.length === 0 ?
Object.values(cfEndpoints) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {
BaseCurrentUserPermissionsChecker,
ICurrentUserPermissionsChecker,
IPermissionCheckCombiner,
StratosUserPermissionsChecker,
} from './stratos-user-permissions.checker';
} from './current-user-permissions.types';
import { StratosUserPermissionsChecker } from './stratos-user-permissions.checker';


export const CUSTOM_USER_PERMISSION_CHECKERS = 'custom_user_perm_checkers'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { combineLatest, Observable, of } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';

import { PermissionConfig, PermissionConfigType, PermissionTypes } from './current-user-permissions.config';

export interface IConfigGroups {
[permissionType: string]: IConfigGroup;
}

export type IConfigGroup = PermissionConfig[];

export type IPermissionCheckCombineTypes = '||' | '&&';

export interface IPermissionCheckCombiner {
checks: Observable<boolean>[];
combineType?: IPermissionCheckCombineTypes;
}
export interface ICurrentUserPermissionsChecker {
/**
* For the given permission action find the checker configuration that will determine if the user can or cannot do the action
* If this is not supported by the the checker null is returned. If another checker also lays claim to the same string the check will
* always return denied
*/
getPermissionConfig: (action: string) => PermissionConfigType
/**
* Simple checks are used when the permission config contains a single thing to check
*/
getSimpleCheck: (
permissionConfig: PermissionConfig,
endpointGuid?: string,
...args: any[]
) => Observable<boolean>;
/**
* Used when the permission config contains multiple things to check
*/
getComplexCheck: (
permissionConfig: PermissionConfig[],
permission: PermissionTypes,
...args: any[]
) => IPermissionCheckCombiner[];
/**
* If no checker provides simple
*/
getFallbackCheck: (
endpointGuid: string,
endpointType: string
) => Observable<boolean>;
}

export abstract class BaseCurrentUserPermissionsChecker {
public static reduceChecks(checks: Observable<boolean>[], type: IPermissionCheckCombineTypes = '||') {
const func = type === '||' ? 'some' : 'every';
if (!checks || !checks.length) {
return of(true);
}
return combineLatest(checks).pipe(
map(flags => flags[func](flag => flag)),
distinctUntilChanged()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,78 +1,20 @@
import { Store } from '@ngrx/store';
import { combineLatest, Observable, of as observableOf } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';
import { Observable } from 'rxjs';

import { GeneralEntityAppState } from '../../../../store/src/app-state';
import {
getCurrentUserStratosHasScope,
getCurrentUserStratosRole,
} from '../../../../store/src/selectors/current-user-role.selectors';
import { IPermissionConfigs, PermissionConfig, PermissionTypes, PermissionValues } from './current-user-permissions.config';
import {
IPermissionConfigs,
PermissionConfig,
PermissionConfigType,
PermissionTypes,
PermissionValues,
} from './current-user-permissions.config';
BaseCurrentUserPermissionsChecker,
IConfigGroups,
ICurrentUserPermissionsChecker,
IPermissionCheckCombiner,
} from './current-user-permissions.types';


export interface IConfigGroups {
[permissionType: string]: IConfigGroup;
}

export type IConfigGroup = PermissionConfig[];

export type IPermissionCheckCombineTypes = '||' | '&&';

export interface IPermissionCheckCombiner {
checks: Observable<boolean>[];
combineType?: IPermissionCheckCombineTypes;
}
export interface ICurrentUserPermissionsChecker {
/**
* For the given permission action find the checker configuration that will determine if the user can or cannot do the action
* If this is not supported by the the checker null is returned. If another checker also lays claim to the same string the check will
* always return denied
*/
getPermissionConfig: (action: string) => PermissionConfigType
/**
* Simple checks are used when the permission config contains a single thing to check
*/
getSimpleCheck: (
permissionConfig: PermissionConfig,
endpointGuid?: string,
...args: any[]
) => Observable<boolean>;
/**
* Used when the permission config contains multiple things to check
*/
getComplexCheck: (
permissionConfig: PermissionConfig[],
permission: PermissionTypes,
...args: any[]
) => IPermissionCheckCombiner[];
/**
* If no checker provides simple
*/
getFallbackCheck: (
endpointGuid: string,
endpointType: string
) => Observable<boolean>;
}

export abstract class BaseCurrentUserPermissionsChecker {
public static reduceChecks(checks: Observable<boolean>[], type: IPermissionCheckCombineTypes = '||') {
const func = type === '||' ? 'some' : 'every';
if (!checks || !checks.length) {
return observableOf(true);
}
return combineLatest(checks).pipe(
map(flags => flags[func](flag => flag)),
distinctUntilChanged()
);
}
}

export enum StratosCurrentUserPermissions {
ENDPOINT_REGISTER = 'register.endpoint',
PASSWORD_CHANGE = 'change-password',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const getDefaultState = () => ({
});

export function currentUserRolesReducer(state: ICurrentUserRolesState = getDefaultState(), action: Action): ICurrentUserRolesState {
const stateAfterStratosChanges = coreCurrentUserRolesReducer(state, action);
return entityCatalog.getAllCurrentUserReducers(stateAfterStratosChanges, action);
const stateAfterCoreChanges = coreCurrentUserRolesReducer(state, action);
return entityCatalog.getAllCurrentUserReducers(stateAfterCoreChanges, action);
}

function coreCurrentUserRolesReducer(state: ICurrentUserRolesState, action: Action): ICurrentUserRolesState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ export interface IStratosRolesState {
scopes: UserScopeStrings[];
}

export interface ICurrentUserRolesState<T = any> {
export interface ICurrentUserRolesState {
internal: IStratosRolesState;
endpoints: {
// T could be different in each endpoint type, however supplying a type makes it nicer to use when looking at a specific type
[endpointType: string]: T
[endpointType: string]: any
}
state: RolesRequestState;
}

0 comments on commit 619e9b3

Please sign in to comment.