From 2ef92590e0d74d33d0b7cc9fc722afedd8fe8476 Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Tue, 27 Nov 2018 15:08:47 +0000 Subject: [PATCH 1/3] Hide app vars tab if user is not a space developer --- secrets.yaml.sys | 57 +++++++++++++++++++ .../applications/application.service.ts | 11 ++++ .../application-tabs-base.component.ts | 34 +++++++---- .../page-subheader.component.html | 8 ++- .../page-subheader.component.scss | 3 - 5 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 secrets.yaml.sys diff --git a/secrets.yaml.sys b/secrets.yaml.sys new file mode 100644 index 0000000000..96d030b504 --- /dev/null +++ b/secrets.yaml.sys @@ -0,0 +1,57 @@ +# E2E Configuration file + +consoleUsers: + admin: + username: admin + password: changeme + nonAdmin: + username: user + password: changeme + +endpoints: + cf: + - name: cf + url: https://api.10.86.2.89.xip.io + skipSSLValidation: true + testOrg: e2e + testSpace: e2e + testService: app-autoscaler + services: + bindApp: go-env + publicService: + name: public-service + privateService: + name: private-service + invalidOrgName: test-e2e + invalidSpaceName: test-e2e + spaceScopedService: + name: space-scoped-service + invalidOrgName: test-e2e + invalidSpaceName: test-e2e + creds: + admin: + username: admin + password: changeme + nonAdmin: + username: user + password: changeme + - name: regonlycf + url: https://cfinfo.capbristol.com + skipSSLValidation: true + testOrg: e2e + testSpace: e2e + creds: + admin: + username: admin + password: changeme + nonAdmin: + username: e2e + password: changeme + +# Skip SSL validation when talking to the backend API for test setup +skipSSLValidation: true + +#headless: true +#stratosGitHubApiUrl: https://github.capbristol.com:37070 + + diff --git a/src/frontend/app/features/applications/application.service.ts b/src/frontend/app/features/applications/application.service.ts index 73c1f41af0..bd3ed96e56 100644 --- a/src/frontend/app/features/applications/application.service.ts +++ b/src/frontend/app/features/applications/application.service.ts @@ -29,6 +29,7 @@ import { spaceSchemaKey, spaceWithOrgKey, stackSchemaKey, + appEnvVarsSchemaKey, } from '../../store/helpers/entity-factory'; import { createEntityRelationKey } from '../../store/helpers/entity-relations/entity-relations.types'; import { ActionState, rootUpdatingKey } from '../../store/reducers/api-request-reducer/types'; @@ -47,6 +48,7 @@ import { EnvVarStratosProject, } from './application/application-tabs-base/tabs/build-tab/application-env-vars.service'; import { getRoute, isTCPRoute } from './routes/routes.helper'; +import { EntityMonitorFactory } from '../../shared/monitors/entity-monitor.factory.service'; export function createGetApplicationAction(guid: string, endpointGuid: string) { @@ -213,6 +215,15 @@ export class ApplicationService { this.appEnvVars = this.appEnvVarsService.createEnvVarsObs(this.appGuid, this.cfGuid); } + public getApplicationEnvVarsMonitor() { + const factory = new EntityMonitorFactory(this.store); + return factory.create>( + this.appGuid, + appEnvVarsSchemaKey, + entityFactory(appEnvVarsSchemaKey) + ); + } + private constructAmalgamatedObservables() { // Assign/Amalgamate them to public properties (with mangling if required) const action = new GetAppStatsAction(this.appGuid, this.cfGuid); diff --git a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts index 15453be49b..d146d47cb2 100644 --- a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts +++ b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts @@ -1,11 +1,11 @@ +import { CfUserService } from './../../../../shared/data-services/cf-user.service'; import { Component, Inject, NgZone, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Store } from '@ngrx/store'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; -import { delay, filter, first, map, mergeMap, tap, withLatestFrom, startWith } from 'rxjs/operators'; +import { delay, filter, first, map, mergeMap, tap, withLatestFrom, startWith, switchMap } from 'rxjs/operators'; import { IApp, IOrganization, ISpace } from '../../../../core/cf-api.types'; -import { CurrentUserPermissions } from '../../../../core/current-user-permissions.config'; import { EntityService } from '../../../../core/entity-service'; import { ConfirmationDialogConfig } from '../../../../shared/components/confirmation-dialog.config'; import { ConfirmationDialogService } from '../../../../shared/components/confirmation-dialog.service'; @@ -32,6 +32,7 @@ import { getActionsFromExtensions, StratosActionType } from '../../../../core/extension/extension-service'; +import { CurrentUserPermissions } from '../../../../core/current-user-permissions.config'; // Confirmation dialogs const appStopConfirmation = new ConfirmationDialogConfig( @@ -110,9 +111,28 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { } }); + // Listen for the response to the env vars API call - if it errors then we hide the variables tab + // This is simpler than the code to check permissions since we make the env vars request anyway + const appDoesNotHaveEnvVars$ = this.applicationService.getApplicationEnvVarsMonitor().entityRequest$.pipe( + filter(resp => resp.error || resp.response), + first(), + map(resp => resp.error) + ); + + this.tabLinks = [ + { link: 'summary', label: 'Summary' }, + { link: 'instances', label: 'Instances' }, + { link: 'routes', label: 'Routes' }, + { link: 'log-stream', label: 'Log Stream' }, + { link: 'services', label: 'Services' }, + { link: 'variables', label: 'Variables', hidden: appDoesNotHaveEnvVars$ }, + { link: 'events', label: 'Events' } + ]; + // Add any tabs from extensions this.tabLinks = this.tabLinks.concat(getTabsFromExtensions(StratosTabType.Application)); } + public breadcrumbs$: Observable; isFetching$: Observable; applicationActions$: Observable; @@ -125,15 +145,7 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { update => update[this.autoRefreshString] || { busy: false } )); - tabLinks: ISubHeaderTabs[] = [ - { link: 'summary', label: 'Summary' }, - { link: 'instances', label: 'Instances' }, - { link: 'routes', label: 'Routes' }, - { link: 'log-stream', label: 'Log Stream' }, - { link: 'services', label: 'Services' }, - { link: 'variables', label: 'Variables' }, - { link: 'events', label: 'Events' } - ]; + tabLinks: ISubHeaderTabs[]; private getBreadcrumbs( application: IApp, diff --git a/src/frontend/app/shared/components/page-subheader/page-subheader.component.html b/src/frontend/app/shared/components/page-subheader/page-subheader.component.html index 285fa6adf6..96c214e3ca 100644 --- a/src/frontend/app/shared/components/page-subheader/page-subheader.component.html +++ b/src/frontend/app/shared/components/page-subheader/page-subheader.component.html @@ -5,9 +5,11 @@ diff --git a/src/frontend/app/shared/components/page-subheader/page-subheader.component.scss b/src/frontend/app/shared/components/page-subheader/page-subheader.component.scss index 0bf0ce22ce..52913ff0cd 100644 --- a/src/frontend/app/shared/components/page-subheader/page-subheader.component.scss +++ b/src/frontend/app/shared/components/page-subheader/page-subheader.component.scss @@ -9,9 +9,6 @@ position: relative; height: 46px; } - &__tab-hidden { - display: none; - } } .tab-nav { From ac74017bf796431281a4bc9d4474c8b85d148fff Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Thu, 6 Dec 2018 14:10:53 +0000 Subject: [PATCH 2/3] Delete secrets.yaml.sys --- secrets.yaml.sys | 57 ------------------------------------------------ 1 file changed, 57 deletions(-) delete mode 100644 secrets.yaml.sys diff --git a/secrets.yaml.sys b/secrets.yaml.sys deleted file mode 100644 index 96d030b504..0000000000 --- a/secrets.yaml.sys +++ /dev/null @@ -1,57 +0,0 @@ -# E2E Configuration file - -consoleUsers: - admin: - username: admin - password: changeme - nonAdmin: - username: user - password: changeme - -endpoints: - cf: - - name: cf - url: https://api.10.86.2.89.xip.io - skipSSLValidation: true - testOrg: e2e - testSpace: e2e - testService: app-autoscaler - services: - bindApp: go-env - publicService: - name: public-service - privateService: - name: private-service - invalidOrgName: test-e2e - invalidSpaceName: test-e2e - spaceScopedService: - name: space-scoped-service - invalidOrgName: test-e2e - invalidSpaceName: test-e2e - creds: - admin: - username: admin - password: changeme - nonAdmin: - username: user - password: changeme - - name: regonlycf - url: https://cfinfo.capbristol.com - skipSSLValidation: true - testOrg: e2e - testSpace: e2e - creds: - admin: - username: admin - password: changeme - nonAdmin: - username: e2e - password: changeme - -# Skip SSL validation when talking to the backend API for test setup -skipSSLValidation: true - -#headless: true -#stratosGitHubApiUrl: https://github.capbristol.com:37070 - - From 1e3bfe5020cb44f0422e763ef54fb4a1320a5274 Mon Sep 17 00:00:00 2001 From: Neil MacDougall Date: Wed, 12 Dec 2018 11:33:30 +0000 Subject: [PATCH 3/3] Address review feedback --- .../app/core/current-user-permissions.config.ts | 2 ++ .../application-tabs-base.component.ts | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/frontend/app/core/current-user-permissions.config.ts b/src/frontend/app/core/current-user-permissions.config.ts index eeff264185..b0f1541dc4 100644 --- a/src/frontend/app/core/current-user-permissions.config.ts +++ b/src/frontend/app/core/current-user-permissions.config.ts @@ -5,6 +5,7 @@ export enum CurrentUserPermissions { APPLICATION_EDIT = 'edit.application', APPLICATION_CREATE = 'create.application', APPLICATION_MANAGE = 'manage.application', + APPLICATION_VIEW_ENV_VARS = 'env-vars.view.application', SPACE_VIEW = 'view.space', SPACE_CREATE = 'create.space', SPACE_DELETE = 'delete.space', @@ -88,6 +89,7 @@ export const permissionConfigs: IPermissionConfigs = { [CurrentUserPermissions.APPLICATION_CREATE]: new PermissionConfig(PermissionTypes.SPACE, PermissionStrings.SPACE_DEVELOPER), [CurrentUserPermissions.APPLICATION_MANAGE]: new PermissionConfig(PermissionTypes.SPACE, PermissionStrings.SPACE_DEVELOPER), [CurrentUserPermissions.APPLICATION_EDIT]: new PermissionConfig(PermissionTypes.SPACE, PermissionStrings.SPACE_DEVELOPER), + [CurrentUserPermissions.APPLICATION_VIEW_ENV_VARS]: new PermissionConfig(PermissionTypes.SPACE, PermissionStrings.SPACE_DEVELOPER), [CurrentUserPermissions.SPACE_VIEW]: [ // See #2186 new PermissionConfig(PermissionTypes.ENDPOINT_SCOPE, ScopeStrings.CF_READ_ONLY_ADMIN_GROUP), diff --git a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts index d146d47cb2..b7f4a56425 100644 --- a/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts +++ b/src/frontend/app/features/applications/application/application-tabs-base/application-tabs-base.component.ts @@ -33,6 +33,7 @@ import { StratosActionType } from '../../../../core/extension/extension-service'; import { CurrentUserPermissions } from '../../../../core/current-user-permissions.config'; +import { CurrentUserPermissionsService } from '../../../../core/current-user-permissions.service'; // Confirmation dialogs const appStopConfirmation = new ConfirmationDialogConfig( @@ -72,7 +73,8 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { private store: Store, private confirmDialog: ConfirmationDialogService, private endpointsService: EndpointsService, - private ngZone: NgZone + private ngZone: NgZone, + private currentUserPermissionsService: CurrentUserPermissionsService ) { const endpoints$ = store.select(endpointEntitiesSelector); this.breadcrumbs$ = applicationService.waitForAppEntity$.pipe( @@ -111,12 +113,11 @@ export class ApplicationTabsBaseComponent implements OnInit, OnDestroy { } }); - // Listen for the response to the env vars API call - if it errors then we hide the variables tab - // This is simpler than the code to check permissions since we make the env vars request anyway - const appDoesNotHaveEnvVars$ = this.applicationService.getApplicationEnvVarsMonitor().entityRequest$.pipe( - filter(resp => resp.error || resp.response), - first(), - map(resp => resp.error) + const appDoesNotHaveEnvVars$ = this.applicationService.appSpace$.pipe( + switchMap(space => this.currentUserPermissionsService.can(CurrentUserPermissions.APPLICATION_VIEW_ENV_VARS, + this.applicationService.cfGuid, space.metadata.guid) + ), + map(can => !can) ); this.tabLinks = [