From 4a1f24f5b44617ad869680815c7d62831a09ef91 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 21 Jan 2020 15:34:20 -0700 Subject: [PATCH 1/9] SHIBUI-1711 Added ability to use runtime context prop --- ui/package.json | 2 +- ui/proxy.conf.json | 28 +++++++++---- .../app/admin/service/admin.service.spec.ts | 7 ++-- ui/src/app/admin/service/admin.service.ts | 4 +- ui/src/app/app.brand.ts | 6 +-- ui/src/app/app.component.html | 4 +- ui/src/app/app.constant.ts | 2 + ui/src/app/app.module.ts | 21 +++++++++- ui/src/app/core/effect/version.effect.ts | 2 +- .../core/service/api-path.interceptor.spec.ts | 41 +++++++++++++++++++ .../app/core/service/api-path.interceptor.ts | 16 ++++++++ ui/src/app/core/service/user.service.ts | 4 +- ui/src/app/i18n/service/i18n.service.ts | 3 +- .../container/configuration.component.ts | 1 - .../container/metadata-options.component.ts | 3 ++ .../configuration/service/history.service.ts | 7 ++-- .../model/wizards/metadata-source-editor.ts | 3 +- .../model/wizards/metadata-source-wizard.ts | 3 +- .../domain/service/attributes.service.ts | 3 +- .../domain/service/entity-id.service.ts | 3 +- .../metadata/domain/service/filter.service.ts | 3 +- .../domain/service/provider.service.ts | 4 +- .../domain/service/resolver.service.spec.ts | 23 ++++++----- .../domain/service/resolver.service.ts | 4 +- .../filter/model/entity-attributes.filter.ts | 3 +- .../metadata/filter/model/nameid.filter.ts | 3 +- .../model/dynamic-http.provider.form.ts | 3 +- .../model/file-system.provider.form.ts | 3 +- .../model/local-dynamic.provider.form.ts | 4 +- .../provider/metadata-provider.schema.json | 2 +- ui/src/index.html | 2 +- ui/src/testing/attributes.stub.ts | 2 +- ui/src/testing/i18n.stub.ts | 2 +- ui/src/testing/mockMetadataWizard.ts | 2 +- 34 files changed, 166 insertions(+), 57 deletions(-) create mode 100644 ui/src/app/app.constant.ts create mode 100644 ui/src/app/core/service/api-path.interceptor.spec.ts create mode 100644 ui/src/app/core/service/api-path.interceptor.ts diff --git a/ui/package.json b/ui/package.json index f0fa2d460..d98b60f9a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json", + "start": "ng serve --proxy-config proxy.conf.json --base-href /shibui/", "build": "ng build", "test": "ng test --code-coverage --source-map=true", "lint": "ng lint", diff --git a/ui/proxy.conf.json b/ui/proxy.conf.json index be9b3e364..fea704271 100644 --- a/ui/proxy.conf.json +++ b/ui/proxy.conf.json @@ -1,22 +1,34 @@ { - "/api": { + "/shibui/api": { "target": "http://localhost:8080", "secure": false, - "logLevel": "debug" + "logLevel": "debug", + "pathRewrite": { + "^/shibui": "" + } }, - "/actuator": { + "/shibui/actuator": { "target": "http://localhost:8080", "secure": false, - "logLevel": "debug" + "logLevel": "debug", + "pathRewrite": { + "^/shibui": "" + } }, - "/login": { + "/shibui/login": { "target": "http://localhost:8080", "secure": false, - "logLevel": "debug" + "logLevel": "debug", + "pathRewrite": { + "^/shibui": "" + } }, - "/logout": { + "/shibui/logout": { "target": "http://localhost:8080", "secure": false, - "logLevel": "debug" + "logLevel": "debug", + "pathRewrite": { + "^/shibui": "" + } } } diff --git a/ui/src/app/admin/service/admin.service.spec.ts b/ui/src/app/admin/service/admin.service.spec.ts index de2a943a1..609c2d8bc 100644 --- a/ui/src/app/admin/service/admin.service.spec.ts +++ b/ui/src/app/admin/service/admin.service.spec.ts @@ -3,6 +3,7 @@ import { AdminService } from './admin.service'; import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpRequest, HttpClientModule } from '@angular/common/http'; import { Admin } from '../model/admin'; +import API_BASE_PATH from '../../app.constant'; let users = [ { @@ -43,7 +44,7 @@ describe('Admin Service', () => { service.query().subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === '/api/admin/users' + return req.url === `${API_BASE_PATH}/admin/users` && req.method === 'GET'; }, `GET admin collection`); } @@ -55,7 +56,7 @@ describe('Admin Service', () => { service.update({...users[0]}).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === '/api/admin/users/abc' + return req.url === `${API_BASE_PATH}/admin/users/abc` && req.method === 'PATCH'; }, `PATCH admin user`); } @@ -67,7 +68,7 @@ describe('Admin Service', () => { service.remove(users[0].username).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === '/api/admin/users/abc' + return req.url === `${API_BASE_PATH}/admin/users/abc` && req.method === 'DELETE'; }, `DELETE admin user`); } diff --git a/ui/src/app/admin/service/admin.service.ts b/ui/src/app/admin/service/admin.service.ts index 7604c7dd5..580616bc3 100644 --- a/ui/src/app/admin/service/admin.service.ts +++ b/ui/src/app/admin/service/admin.service.ts @@ -4,11 +4,13 @@ import { Admin } from '../model/admin'; import { HttpClient } from '@angular/common/http'; import { map, catchError } from 'rxjs/operators'; +import API_BASE_PATH from '../../app.constant'; + @Injectable() export class AdminService { private endpoint = '/admin/users'; - private base = '/api'; + private base = API_BASE_PATH; constructor( private http: HttpClient diff --git a/ui/src/app/app.brand.ts b/ui/src/app/app.brand.ts index bc0237204..eb828fc41 100644 --- a/ui/src/app/app.brand.ts +++ b/ui/src/app/app.brand.ts @@ -6,9 +6,9 @@ export const brand: Brand = { title: 'brand.header.title' }, logo: { - default: '/assets/shibboleth_logowordmark_color.png', - small: '/assets/shibboleth_icon_color_130x130.png', - large: '/assets/shibboleth_logowordmark_color.png', + default: 'assets/shibboleth_logowordmark_color.png', + small: 'assets/shibboleth_icon_color_130x130.png', + large: 'assets/shibboleth_logowordmark_color.png', alt: 'brand.logo-alt', link: { label: 'brand.logo-link-label', // shibboleth diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index 67ae33e22..fdeb258b9 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -84,11 +84,11 @@
In partnership with  - Unicon Logo + Unicon Logo  and  - Internet 2 Logo + Internet 2 Logo
diff --git a/ui/src/app/app.constant.ts b/ui/src/app/app.constant.ts new file mode 100644 index 000000000..206ee74c7 --- /dev/null +++ b/ui/src/app/app.constant.ts @@ -0,0 +1,2 @@ +export const API_BASE_PATH = 'api'; +export default API_BASE_PATH; diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index 99011223b..d8a1f0a7c 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -1,6 +1,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; -import { StoreModule, Store } from '@ngrx/store'; +import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { StoreRouterConnectingModule, RouterStateSerializer } from '@ngrx/router-store'; @@ -24,6 +24,8 @@ import { WizardModule } from './wizard/wizard.module'; import { FormModule } from './schema-form/schema-form.module'; import { environment } from '../environments/environment.prod'; import { I18nModule } from './i18n/i18n.module'; +import { ApiPathInterceptor } from './core/service/api-path.interceptor'; +import { APP_BASE_HREF } from '@angular/common'; @NgModule({ declarations: [ @@ -63,7 +65,17 @@ import { I18nModule } from './i18n/i18n.module'; AppRoutingModule ], providers: [ - { provide: RouterStateSerializer, useClass: CustomRouterStateSerializer }, + { + provide: APP_BASE_HREF, + useFactory: () => { + const url = new URL(document.getElementsByTagName('base')[0].href); + return url.pathname; + } + }, + { + provide: RouterStateSerializer, + useClass: CustomRouterStateSerializer + }, { provide: HTTP_INTERCEPTORS, useClass: AuthorizedInterceptor, @@ -73,6 +85,11 @@ import { I18nModule } from './i18n/i18n.module'; provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ApiPathInterceptor, + multi: true } ], bootstrap: [AppComponent] diff --git a/ui/src/app/core/effect/version.effect.ts b/ui/src/app/core/effect/version.effect.ts index e692e6b0d..b588a6011 100644 --- a/ui/src/app/core/effect/version.effect.ts +++ b/ui/src/app/core/effect/version.effect.ts @@ -13,7 +13,7 @@ import { VersionInfo } from '../model/version'; export class VersionEffects { private endpoint = '/info'; - private base = '/actuator'; + private base = 'actuator'; @Effect() loadVersionInfo$ = this.actions$ diff --git a/ui/src/app/core/service/api-path.interceptor.spec.ts b/ui/src/app/core/service/api-path.interceptor.spec.ts new file mode 100644 index 000000000..3f1b8fc66 --- /dev/null +++ b/ui/src/app/core/service/api-path.interceptor.spec.ts @@ -0,0 +1,41 @@ +import { TestBed, async, inject } from '@angular/core/testing'; +import { HTTP_INTERCEPTORS, HttpClientModule, HttpClient, HttpRequest } from '@angular/common/http'; +import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; + +import { ApiPathInterceptor } from './api-path.interceptor'; +import { APP_BASE_HREF } from '@angular/common'; + +describe('API Path Interceptor Service', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HttpClientModule, + HttpClientTestingModule + ], + providers: [ + { + provide: APP_BASE_HREF, + useValue: '/shibui/' + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ApiPathInterceptor, + multi: true + } + ] + }); + }); + + describe('query', () => { + it(`should send an expected query request`, async(inject([HttpClient, HttpTestingController], + (service: HttpClient, backend: HttpTestingController) => { + service.get('foo').subscribe(); + + backend.expectOne((req: HttpRequest) => { + return req.url === '/shibui/foo' + && req.method === 'GET'; + }, `GET collection`); + } + ))); + }); +}); diff --git a/ui/src/app/core/service/api-path.interceptor.ts b/ui/src/app/core/service/api-path.interceptor.ts new file mode 100644 index 000000000..9c3bfd360 --- /dev/null +++ b/ui/src/app/core/service/api-path.interceptor.ts @@ -0,0 +1,16 @@ +import { Injectable, Inject } from '@angular/core'; +import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { APP_BASE_HREF } from '@angular/common'; + +@Injectable() +export class ApiPathInterceptor implements HttpInterceptor { + constructor( + @Inject(APP_BASE_HREF) private baseHref: string + ) {} + intercept(req: HttpRequest, next: HttpHandler): Observable> { + const apiReq = req.clone({ url: `${this.baseHref}${req.url}` }); + console.log(req); + return next.handle(apiReq); + } +} diff --git a/ui/src/app/core/service/user.service.ts b/ui/src/app/core/service/user.service.ts index af8907160..d5ee80b53 100644 --- a/ui/src/app/core/service/user.service.ts +++ b/ui/src/app/core/service/user.service.ts @@ -2,12 +2,12 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { User } from '../model/user'; import { HttpClient } from '@angular/common/http'; -import { catchError, map } from 'rxjs/operators'; +import { API_BASE_PATH } from '../../app.constant'; @Injectable() export class UserService { - readonly base = `/api`; + readonly base = API_BASE_PATH; constructor( private http: HttpClient diff --git a/ui/src/app/i18n/service/i18n.service.ts b/ui/src/app/i18n/service/i18n.service.ts index 4d405c5b2..26f0ba4ff 100644 --- a/ui/src/app/i18n/service/i18n.service.ts +++ b/ui/src/app/i18n/service/i18n.service.ts @@ -4,12 +4,13 @@ import { HttpClient, HttpParams } from '@angular/common/http'; import { NavigatorService } from '../../core/service/navigator.service'; import { getCurrentLanguage, getCurrentLocale } from '../../shared/util'; import { Messages } from '../model/Messages'; +import API_BASE_PATH from '../../app.constant'; @Injectable() export class I18nService { readonly path = '/messages'; - readonly base = '/api'; + readonly base = API_BASE_PATH; constructor( private http: HttpClient, diff --git a/ui/src/app/metadata/configuration/container/configuration.component.ts b/ui/src/app/metadata/configuration/container/configuration.component.ts index c1e2daf35..1704bc6a6 100644 --- a/ui/src/app/metadata/configuration/container/configuration.component.ts +++ b/ui/src/app/metadata/configuration/container/configuration.component.ts @@ -25,7 +25,6 @@ export class ConfigurationComponent implements OnDestroy { private store: Store, private routerState: ActivatedRoute ) { - this.routerState.params.pipe( takeUntil(this.ngUnsubscribe), map(({ id, type, version }) => new SetMetadata({ diff --git a/ui/src/app/metadata/configuration/container/metadata-options.component.ts b/ui/src/app/metadata/configuration/container/metadata-options.component.ts index 411c6fb10..8205aa60a 100644 --- a/ui/src/app/metadata/configuration/container/metadata-options.component.ts +++ b/ui/src/app/metadata/configuration/container/metadata-options.component.ts @@ -57,6 +57,9 @@ export class MetadataOptionsComponent implements OnDestroy { protected router: Router, protected activatedRoute: ActivatedRoute ) { + + console.log('metadata options'); + this.model$ .pipe( takeUntil(this.ngUnsubscribe), diff --git a/ui/src/app/metadata/configuration/service/history.service.ts b/ui/src/app/metadata/configuration/service/history.service.ts index 9d3edc212..1027f82e2 100644 --- a/ui/src/app/metadata/configuration/service/history.service.ts +++ b/ui/src/app/metadata/configuration/service/history.service.ts @@ -7,11 +7,12 @@ import { PATHS } from '../../configuration/configuration.values'; import { MetadataVersion } from '../model/version'; import { map } from 'rxjs/operators'; import { Metadata } from '../../domain/domain.type'; +import API_BASE_PATH from '../../../app.constant'; @Injectable() export class MetadataHistoryService { - readonly base = `api`; + readonly base = API_BASE_PATH; readonly path = `Versions`; constructor( @@ -34,9 +35,9 @@ export class MetadataHistoryService { getVersion(resourceId: string, type: string, versionId: string = null): Observable { const api = versionId ? - `/${this.base}/${PATHS[type]}/${resourceId}/${this.path}/${versionId}` + `${this.base}/${PATHS[type]}/${resourceId}/${this.path}/${versionId}` : - `/${this.base}/${PATHS[type]}/${resourceId}`; + `${this.base}/${PATHS[type]}/${resourceId}`; return this.http.get(api); } diff --git a/ui/src/app/metadata/domain/model/wizards/metadata-source-editor.ts b/ui/src/app/metadata/domain/model/wizards/metadata-source-editor.ts index 13136ddfc..5fbfbd48a 100644 --- a/ui/src/app/metadata/domain/model/wizards/metadata-source-editor.ts +++ b/ui/src/app/metadata/domain/model/wizards/metadata-source-editor.ts @@ -1,9 +1,10 @@ import { Wizard, WizardStep } from '../../../../wizard/model'; import { MetadataResolver } from '../metadata-resolver'; import { MetadataSourceBase } from './metadata-source-base'; +import API_BASE_PATH from '../../../../app.constant'; export class MetadataSourceEditor extends MetadataSourceBase implements Wizard { - schema = '/api/ui/MetadataSources'; + schema = `${API_BASE_PATH}/ui/MetadataSources`; steps: WizardStep[] = [ { index: 1, diff --git a/ui/src/app/metadata/domain/model/wizards/metadata-source-wizard.ts b/ui/src/app/metadata/domain/model/wizards/metadata-source-wizard.ts index 10b7c4e79..b92ea5410 100644 --- a/ui/src/app/metadata/domain/model/wizards/metadata-source-wizard.ts +++ b/ui/src/app/metadata/domain/model/wizards/metadata-source-wizard.ts @@ -1,9 +1,10 @@ import { Wizard, WizardStep } from '../../../../wizard/model'; import { MetadataResolver } from '../metadata-resolver'; import { MetadataSourceBase } from './metadata-source-base'; +import API_BASE_PATH from '../../../../app.constant'; export class MetadataSourceWizard extends MetadataSourceBase implements Wizard { - schema = '/api/ui/MetadataSources'; + schema = `${API_BASE_PATH}/ui/MetadataSources`; steps: WizardStep[] = [ { index: 1, diff --git a/ui/src/app/metadata/domain/service/attributes.service.ts b/ui/src/app/metadata/domain/service/attributes.service.ts index c6b671e01..f07cd8e83 100644 --- a/ui/src/app/metadata/domain/service/attributes.service.ts +++ b/ui/src/app/metadata/domain/service/attributes.service.ts @@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError, shareReplay, map } from 'rxjs/operators'; import { ReleaseAttribute } from '../model/properties/release-attribute'; +import API_BASE_PATH from '../../../app.constant'; const CACHE_SIZE = 1; @@ -10,7 +11,7 @@ const CACHE_SIZE = 1; export class AttributesService { readonly endpoint = '/customAttributes'; - readonly base = '/api'; + readonly base = API_BASE_PATH; private cache$: Observable; diff --git a/ui/src/app/metadata/domain/service/entity-id.service.ts b/ui/src/app/metadata/domain/service/entity-id.service.ts index 07009e3d1..58845dd09 100644 --- a/ui/src/app/metadata/domain/service/entity-id.service.ts +++ b/ui/src/app/metadata/domain/service/entity-id.service.ts @@ -6,13 +6,14 @@ import { map, catchError } from 'rxjs/operators'; import { QueryParams } from '../../../core/model/query'; import { MDUI } from '../model'; +import API_BASE_PATH from '../../../app.constant'; @Injectable() export class EntityIdService { readonly searchEndpoint = '/EntityIds/search'; readonly entitiesEndpoint = '/entities'; - readonly base = '/api'; + readonly base = API_BASE_PATH; constructor( private http: HttpClient diff --git a/ui/src/app/metadata/domain/service/filter.service.ts b/ui/src/app/metadata/domain/service/filter.service.ts index bb610bf01..fed08adec 100644 --- a/ui/src/app/metadata/domain/service/filter.service.ts +++ b/ui/src/app/metadata/domain/service/filter.service.ts @@ -3,13 +3,14 @@ import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { MetadataFilter } from '../../domain/model'; +import API_BASE_PATH from '../../../app.constant'; @Injectable() export class MetadataFilterService { readonly endpoint = '/MetadataResolvers'; readonly order = 'FiltersPositionOrder'; - readonly base = '/api'; + readonly base = API_BASE_PATH; readonly path = 'Filters'; constructor( diff --git a/ui/src/app/metadata/domain/service/provider.service.ts b/ui/src/app/metadata/domain/service/provider.service.ts index f17557902..b93afee4e 100644 --- a/ui/src/app/metadata/domain/service/provider.service.ts +++ b/ui/src/app/metadata/domain/service/provider.service.ts @@ -4,6 +4,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { MetadataProvider } from '../../domain/model'; +import API_BASE_PATH from '../../../app.constant'; @Injectable() @@ -11,7 +12,7 @@ export class MetadataProviderService { readonly endpoint = '/MetadataResolvers'; readonly order = '/MetadataResolversPositionOrder'; - readonly base = '/api'; + readonly base = API_BASE_PATH; constructor( private http: HttpClient @@ -24,6 +25,7 @@ export class MetadataProviderService { } find(id: string): Observable { + console.log(id); return this.http.get(`${this.base}${this.endpoint}/${id}`); } diff --git a/ui/src/app/metadata/domain/service/resolver.service.spec.ts b/ui/src/app/metadata/domain/service/resolver.service.spec.ts index c11bb0dd5..69a00ccc0 100644 --- a/ui/src/app/metadata/domain/service/resolver.service.spec.ts +++ b/ui/src/app/metadata/domain/service/resolver.service.spec.ts @@ -2,6 +2,7 @@ import { TestBed, async, inject } from '@angular/core/testing'; import { HttpClientModule, HttpRequest } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { ResolverService } from './resolver.service'; +import API_BASE_PATH from '../../../app.constant'; describe(`Resolver Service`, () => { @@ -24,7 +25,7 @@ describe(`Resolver Service`, () => { service.query().subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === '/api/EntityDescriptors' + return req.url === `${API_BASE_PATH}/EntityDescriptors` && req.method === 'GET'; }, `GET EntityDescriptors collection`); } @@ -36,7 +37,7 @@ describe(`Resolver Service`, () => { expect(next).toBeTruthy(); }); - backend.expectOne('/api/EntityDescriptors').flush(['foo'], { status: 200, statusText: 'Ok' }); + backend.expectOne(`${API_BASE_PATH}/EntityDescriptors`).flush(['foo'], { status: 200, statusText: 'Ok' }); } ))); }); @@ -47,7 +48,7 @@ describe(`Resolver Service`, () => { service.queryForAdmin().subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === '/api/EntityDescriptor/disabledNonAdmin' + return req.url === `${API_BASE_PATH}/EntityDescriptor/disabledNonAdmin` && req.method === 'GET'; }, `GET EntityDescriptors collection for an admin`); } @@ -59,7 +60,7 @@ describe(`Resolver Service`, () => { expect(next).toBeTruthy(); }); - backend.expectOne('/api/EntityDescriptor/disabledNonAdmin').flush(['foo'], { status: 200, statusText: 'Ok' }); + backend.expectOne(`${API_BASE_PATH}/EntityDescriptor/disabledNonAdmin`).flush(['foo'], { status: 200, statusText: 'Ok' }); } ))); }); @@ -72,7 +73,7 @@ describe(`Resolver Service`, () => { service.find(id).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor/${id}` + return req.url === `${API_BASE_PATH}/EntityDescriptor/${id}` && req.method === 'GET'; }, `GET EntityDescriptor by id`); } @@ -89,7 +90,7 @@ describe(`Resolver Service`, () => { service.update({id, serviceProviderName, createdBy}).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor/${id}` + return req.url === `${ API_BASE_PATH }/EntityDescriptor/${id}` && req.method === 'PUT'; }, `PUT EntityDescriptor by id`); } @@ -106,7 +107,7 @@ describe(`Resolver Service`, () => { service.save({ id, serviceProviderName, createdBy }).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor` + return req.url === `api/EntityDescriptor` && req.method === 'POST'; }, `POST new EntityDescriptor`); } @@ -123,7 +124,7 @@ describe(`Resolver Service`, () => { service.remove({ id, serviceProviderName, createdBy }).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor/${id}` + return req.url === `api/EntityDescriptor/${id}` && req.method === 'DELETE'; }, `DELETE an EntityDescriptor`); } @@ -138,7 +139,7 @@ describe(`Resolver Service`, () => { service.preview(id).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor/${id}` + return req.url === `api/EntityDescriptor/${id}` && req.method === 'GET' && req.headers.get('Accept') === 'application/xml' && req.responseType === 'text'; @@ -154,7 +155,7 @@ describe(`Resolver Service`, () => { service.upload(name, xml).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor` + return req.url === `api/EntityDescriptor` && req.method === 'POST' && req.headers.get('Content-Type') === 'application/xml'; }, `POST new EntityDescriptor`); @@ -169,7 +170,7 @@ describe(`Resolver Service`, () => { service.createFromUrl(name, url).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/api/EntityDescriptor` + return req.url === `api/EntityDescriptor` && req.method === 'POST' && req.headers.get('Content-Type') === 'application/x-www-form-urlencoded' && req.body === `metadataUrl=${url}`; diff --git a/ui/src/app/metadata/domain/service/resolver.service.ts b/ui/src/app/metadata/domain/service/resolver.service.ts index cae3a5ed8..6d9fc0dae 100644 --- a/ui/src/app/metadata/domain/service/resolver.service.ts +++ b/ui/src/app/metadata/domain/service/resolver.service.ts @@ -3,12 +3,13 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Observable, throwError, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { MetadataResolver } from '../model'; +import API_BASE_PATH from '../../../app.constant'; @Injectable() export class ResolverService { private endpoint = '/EntityDescriptor'; - private base = '/api'; + private base = API_BASE_PATH; constructor( private http: HttpClient @@ -23,6 +24,7 @@ export class ResolverService { } find(id: string): Observable { + console.log(API_BASE_PATH); return this.http.get(`${ this.base }${ this.endpoint }/${ id }`); } diff --git a/ui/src/app/metadata/filter/model/entity-attributes.filter.ts b/ui/src/app/metadata/filter/model/entity-attributes.filter.ts index a4b18b67a..b310e6a85 100644 --- a/ui/src/app/metadata/filter/model/entity-attributes.filter.ts +++ b/ui/src/app/metadata/filter/model/entity-attributes.filter.ts @@ -5,13 +5,14 @@ import { EntityAttributesFilterEntity } from '../../domain/entity'; import { RegexValidator } from '../../../shared/validation/regex.validator'; import { getFilterNames } from '../reducer'; import { memoize } from '../../../shared/memo'; +import API_BASE_PATH from '../../../app.constant'; const checkRegex = memoize(RegexValidator.isValidRegex); export const EntityAttributesFilter: FormDefinition = { label: 'EntityAttributes', type: 'EntityAttributes', - schema: '/api/ui/EntityAttributesFilters', + schema: `${API_BASE_PATH}/ui/EntityAttributesFilters`, getEntity(filter: MetadataFilter): EntityAttributesFilterEntity { return new EntityAttributesFilterEntity(filter); }, diff --git a/ui/src/app/metadata/filter/model/nameid.filter.ts b/ui/src/app/metadata/filter/model/nameid.filter.ts index ee48f4f89..a095513ea 100644 --- a/ui/src/app/metadata/filter/model/nameid.filter.ts +++ b/ui/src/app/metadata/filter/model/nameid.filter.ts @@ -4,13 +4,14 @@ import { NameIDFormatFilterEntity } from '../../domain/entity/filter/nameid-form import { RegexValidator } from '../../../shared/validation/regex.validator'; import { getFilterNames } from '../reducer'; import { memoize } from '../../../shared/memo'; +import API_BASE_PATH from '../../../app.constant'; const checkRegex = memoize(RegexValidator.isValidRegex); export const NameIDFilter: FormDefinition = { label: 'NameIDFormat', type: 'NameIDFormat', - schema: '/api/ui/NameIdFormatFilter', + schema: `${API_BASE_PATH}/ui/NameIdFormatFilter`, getEntity(filter: MetadataFilter): NameIDFormatFilterEntity { return new NameIDFormatFilterEntity(filter); }, diff --git a/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts b/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts index 395bf56e1..ac09ed7ac 100644 --- a/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts +++ b/ui/src/app/metadata/provider/model/dynamic-http.provider.form.ts @@ -4,6 +4,7 @@ import { BaseMetadataProviderEditor } from './base.provider.form'; import { metadataFilterProcessor } from './utilities'; import RegexValidator from '../../../shared/validation/regex.validator'; import { memoize } from '../../../shared/memo'; +import API_BASE_PATH from '../../../app.constant'; const checkRegex = memoize(RegexValidator.isValidRegex); @@ -83,7 +84,7 @@ export const DynamicHttpMetadataProviderWizard: Wizard = { ...BaseMetadataProviderEditor, label: 'FilesystemMetadataProvider', type: 'FilesystemMetadataResolver', - schema: '/api/ui/MetadataResolver/FilesystemMetadataResolver', + schema: `${API_BASE_PATH}/ui/MetadataResolver/FilesystemMetadataResolver`, steps: [ { id: 'common', diff --git a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts index c79bc487d..6fdba5270 100644 --- a/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts +++ b/ui/src/app/metadata/provider/model/local-dynamic.provider.form.ts @@ -1,13 +1,13 @@ import { Wizard } from '../../../wizard/model'; import { LocalDynamicMetadataProvider } from '../../domain/model/providers/local-dynamic-metadata-provider'; import { BaseMetadataProviderEditor } from './base.provider.form'; -import { MetadataProvider } from '../../domain/model'; +import API_BASE_PATH from '../../../app.constant'; export const LocalDynamicMetadataProviderWizard: Wizard = { ...BaseMetadataProviderEditor, label: 'LocalDynamicMetadataProvider', type: 'LocalDynamicMetadataResolver', - schema: '/api/ui/MetadataResolver/LocalDynamicMetadataResolver', + schema: `${API_BASE_PATH}/ui/MetadataResolver/LocalDynamicMetadataResolver`, steps: [ { id: 'common', diff --git a/ui/src/assets/schema/provider/metadata-provider.schema.json b/ui/src/assets/schema/provider/metadata-provider.schema.json index a0242b633..5849ec8d8 100644 --- a/ui/src/assets/schema/provider/metadata-provider.schema.json +++ b/ui/src/assets/schema/provider/metadata-provider.schema.json @@ -21,7 +21,7 @@ "type": "string", "widget": { "id": "select", - "dataUrl": "/api/ui/MetadataResolver/types" + "dataUrl": "api/ui/MetadataResolver/types" } } }, diff --git a/ui/src/index.html b/ui/src/index.html index 705257e2b..55d6eee39 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -3,7 +3,7 @@ Shibboleth IDP UI - + diff --git a/ui/src/testing/attributes.stub.ts b/ui/src/testing/attributes.stub.ts index 200bf8ade..d2d6f9575 100644 --- a/ui/src/testing/attributes.stub.ts +++ b/ui/src/testing/attributes.stub.ts @@ -6,7 +6,7 @@ import { ReleaseAttribute } from '../app/metadata/domain/model/properties/releas export class MockAttributeService { readonly path = '/customAttributes'; - readonly base = '/api'; + readonly base = 'api'; constructor() { } diff --git a/ui/src/testing/i18n.stub.ts b/ui/src/testing/i18n.stub.ts index 3b38bef8c..4f0f012b3 100644 --- a/ui/src/testing/i18n.stub.ts +++ b/ui/src/testing/i18n.stub.ts @@ -49,7 +49,7 @@ export class MockTranslateComponent { export class MockI18nService { readonly path = '/messages'; - readonly base = '/api'; + readonly base = 'api'; constructor() { } diff --git a/ui/src/testing/mockMetadataWizard.ts b/ui/src/testing/mockMetadataWizard.ts index 6c0135e29..95844f8a0 100644 --- a/ui/src/testing/mockMetadataWizard.ts +++ b/ui/src/testing/mockMetadataWizard.ts @@ -23,7 +23,7 @@ export const MockMetadataWizard: Wizard = { getValidators(): { [key: string]: any } { return {}; }, - schema: '/api/ui/MetadataSources', + schema: 'api/ui/MetadataSources', steps: [ { index: 1, From 59f11ab7a1e7d1ed587f7b28f58afd2f58e2c694 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 22 Jan 2020 07:12:31 -0700 Subject: [PATCH 2/9] SHIBUI-1711 reverted build to not use context by default --- ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/package.json b/ui/package.json index d98b60f9a..f0fa2d460 100644 --- a/ui/package.json +++ b/ui/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json --base-href /shibui/", + "start": "ng serve --proxy-config proxy.conf.json", "build": "ng build", "test": "ng test --code-coverage --source-map=true", "lint": "ng lint", From 634a943d35bac23be4b94c48c0db77db5b556155 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 22 Jan 2020 08:26:30 -0700 Subject: [PATCH 3/9] SHIBUI-1711 Fixed path issue --- ui/proxy.conf.json | 4 ++-- .../metadata/configuration/service/history.service.spec.ts | 6 +++--- .../app/metadata/configuration/service/history.service.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/proxy.conf.json b/ui/proxy.conf.json index fea704271..89fcfdf90 100644 --- a/ui/proxy.conf.json +++ b/ui/proxy.conf.json @@ -15,7 +15,7 @@ "^/shibui": "" } }, - "/shibui/login": { + "/login": { "target": "http://localhost:8080", "secure": false, "logLevel": "debug", @@ -23,7 +23,7 @@ "^/shibui": "" } }, - "/shibui/logout": { + "/logout": { "target": "http://localhost:8080", "secure": false, "logLevel": "debug", diff --git a/ui/src/app/metadata/configuration/service/history.service.spec.ts b/ui/src/app/metadata/configuration/service/history.service.spec.ts index e4fa72dac..8edb179a3 100644 --- a/ui/src/app/metadata/configuration/service/history.service.spec.ts +++ b/ui/src/app/metadata/configuration/service/history.service.spec.ts @@ -47,7 +47,7 @@ describe(`Attributes Service`, () => { const type = 'resource'; service.getVersion(resourceId, type).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/${service.base}/${PATHS[type]}/${resourceId}` + return req.url === `${service.base}/${PATHS[type]}/${resourceId}` && req.method === 'GET'; }, `GET schema by path`); } @@ -59,7 +59,7 @@ describe(`Attributes Service`, () => { const versionId = '1'; service.getVersion(resourceId, type, versionId).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/${service.base}/${PATHS[type]}/${resourceId}/${service.path}/${versionId}` + return req.url === `${service.base}/${PATHS[type]}/${resourceId}/${service.path}/${versionId}` && req.method === 'GET'; }, `GET schema by path`); } @@ -74,7 +74,7 @@ describe(`Attributes Service`, () => { const versionId = '1'; service.updateVersion(resourceId, type, {} as Metadata).subscribe(); backend.expectOne((req: HttpRequest) => { - return req.url === `/${service.base}/${PATHS[type]}/${resourceId}` + return req.url === `${service.base}/${PATHS[type]}/${resourceId}` && req.method === 'PUT'; }, `PUT schema by path`); } diff --git a/ui/src/app/metadata/configuration/service/history.service.ts b/ui/src/app/metadata/configuration/service/history.service.ts index 1027f82e2..9e6a3d3f3 100644 --- a/ui/src/app/metadata/configuration/service/history.service.ts +++ b/ui/src/app/metadata/configuration/service/history.service.ts @@ -20,7 +20,7 @@ export class MetadataHistoryService { ) { } query(resourceId: string, type: string): Observable { - return this.http.get(`/${this.base}/${PATHS[type]}/${resourceId}/${this.path}`).pipe( + return this.http.get(`${this.base}/${PATHS[type]}/${resourceId}/${this.path}`).pipe( map(resp => ({ versions: resp })) @@ -42,6 +42,6 @@ export class MetadataHistoryService { } updateVersion(resourceId: string, type: string, model: Metadata): Observable { - return this.http.put(`/${this.base}/${PATHS[type]}/${resourceId}`, model); + return this.http.put(`${this.base}/${PATHS[type]}/${resourceId}`, model); } } From 38859ea162c1d95af9f1775d8c3dd31e23135fbc Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 22 Jan 2020 16:52:28 -0500 Subject: [PATCH 4/9] Dynamic app context --- backend/build.gradle | 6 ++---- ui/src/index.html | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 423d9c450..3c3cacec0 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -90,8 +90,7 @@ bootWar { ) } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { - // into '/' - into '/public' + into 'WEB-INF/classes/resources' } archiveName = "${baseName}-${version}.war" } @@ -107,8 +106,7 @@ bootJar { ) } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { - // into '/' - into '/public' + into 'WEB-INF/classes/resources' } archiveName = "${baseName}-${version}.jar" } diff --git a/ui/src/index.html b/ui/src/index.html index 55d6eee39..d1bacd083 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -3,7 +3,8 @@ Shibboleth IDP UI - + + From d19f5c4847bbde87cba699b93cef3b2dd75cb10d Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 23 Jan 2020 12:08:19 -0500 Subject: [PATCH 5/9] WIP1 --- backend/build.gradle | 5 +++++ .../shibboleth/admin/ui/controller/RootUiViewController.java | 2 +- ui/src/index.html | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 3c3cacec0..b800d20ef 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -89,8 +89,13 @@ bootWar { "Implementation-Version" : "${project.version}" ) } + from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { + into 'WEB-INF/classes/templates' + include 'index.html' + } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { into 'WEB-INF/classes/resources' + //include 'index.html' } archiveName = "${baseName}-${version}.war" } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java index b0ef4984c..b5968a7e5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java @@ -8,6 +8,6 @@ public class RootUiViewController { @RequestMapping("/") public String index() { - return "redirect:/index.html"; + return "index"; } } diff --git a/ui/src/index.html b/ui/src/index.html index d1bacd083..4a7de4520 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -4,7 +4,7 @@ Shibboleth IDP UI - + From bb61c9b020390f5bcae39bacd3511845f0db31b8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 23 Jan 2020 17:21:04 -0500 Subject: [PATCH 6/9] wip --- backend/build.gradle | 5 ---- .../ui/controller/RootUiViewController.java | 24 +++++++++++++++++-- ui/src/index.html | 3 +-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index b800d20ef..3c3cacec0 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -89,13 +89,8 @@ bootWar { "Implementation-Version" : "${project.version}" ) } - from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { - into 'WEB-INF/classes/templates' - include 'index.html' - } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { into 'WEB-INF/classes/resources' - //include 'index.html' } archiveName = "${baseName}-${version}.war" } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java index b5968a7e5..35c06653d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java @@ -1,13 +1,33 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; +import com.google.common.io.ByteStreams; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.OutputStream; @Controller public class RootUiViewController { + @Value("classpath:/resources/index.html") + Resource resourceFile; + @RequestMapping("/") - public String index() { - return "index"; + @ResponseBody + public void index(HttpServletRequest request, OutputStream os) throws IOException { + final String ctxPath = request.getContextPath(); + try { + byte[] indexHtmlBytes = ByteStreams.toByteArray(resourceFile.getInputStream()); + os.write(indexHtmlBytes, 0, indexHtmlBytes.length); + //os.write(ctxPath.getBytes(), 0, ctxPath.length()); + } + finally { + os.close(); + } } } diff --git a/ui/src/index.html b/ui/src/index.html index 4a7de4520..705257e2b 100644 --- a/ui/src/index.html +++ b/ui/src/index.html @@ -3,8 +3,7 @@ Shibboleth IDP UI - - + From bd910bc5727248eedab7dbd0c562b503a5a4659d Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 23 Jan 2020 17:47:45 -0500 Subject: [PATCH 7/9] wip --- .../ui/controller/RootUiViewController.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java index 35c06653d..dabb03e55 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java @@ -4,30 +4,34 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.stereotype.Controller; +import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.Charset; @Controller public class RootUiViewController { @Value("classpath:/resources/index.html") - Resource resourceFile; + Resource indexHtmlResource; @RequestMapping("/") - @ResponseBody - public void index(HttpServletRequest request, OutputStream os) throws IOException { + //@ResponseBody + public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { + //TODO: Use Jsoup lib to inject context path into DOM before writing to response buffer + final String ctxPath = request.getContextPath(); - try { - byte[] indexHtmlBytes = ByteStreams.toByteArray(resourceFile.getInputStream()); - os.write(indexHtmlBytes, 0, indexHtmlBytes.length); - //os.write(ctxPath.getBytes(), 0, ctxPath.length()); - } - finally { - os.close(); - } + + //This does not work! In order form Angular to kick in we need to redirect to index.html + String indexHtmlAsString = StreamUtils.copyToString(indexHtmlResource.getInputStream(), Charset.defaultCharset()); + //byte[] indexHtmlBytes = ByteStreams.toByteArray(indexHtmlResource.getInputStream()); + response.setHeader("Content-Type", "text/html"); + response.getWriter().print(indexHtmlAsString); + //os.write(ctxPath.getBytes(), 0, ctxPath.length()); } } From 0fab57f6f28625d45e4fc456f9d5818b0c25cde6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 27 Jan 2020 12:05:32 -0500 Subject: [PATCH 8/9] Working solution --- backend/build.gradle | 7 +++- .../ui/controller/RootUiViewController.java | 33 +++++++++++-------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 3c3cacec0..334c907ea 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -90,6 +90,9 @@ bootWar { ) } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { + //Copying into this particular classpath location due too + //deployment to external Tomcat would not work with /public location + //This way, it works with both embedded and extarnal Tomcat into 'WEB-INF/classes/resources' } archiveName = "${baseName}-${version}.war" @@ -106,6 +109,9 @@ bootJar { ) } from(tasks.findByPath(':ui:npm_run_buildProd').outputs) { + //Copying into this particular classpath location due too + //deployment to external Tomcat would not work with /public location + //This way, it works with both embedded and external Tomcat into 'WEB-INF/classes/resources' } archiveName = "${baseName}-${version}.jar" @@ -164,7 +170,6 @@ dependencies { //So it works on Java 9 without explicitly requiring to load that module (needed by Hibernate) runtimeOnly 'javax.xml.bind:jaxb-api:2.3.0' - // TODO: these will likely only be runtimeOnly or test scope, unless we want to ship the libraries with the final product compile "com.h2database:h2" runtimeOnly "org.postgresql:postgresql" runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.2.0' diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java index dabb03e55..fe9e4b246 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java @@ -10,28 +10,35 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.net.URISyntaxException; import java.nio.charset.Charset; +import java.util.stream.Collectors; @Controller public class RootUiViewController { - @Value("classpath:/resources/index.html") - Resource indexHtmlResource; - @RequestMapping("/") - //@ResponseBody - public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { - //TODO: Use Jsoup lib to inject context path into DOM before writing to response buffer + public String index() { + return "redirect:/index.html"; + } - final String ctxPath = request.getContextPath(); + @RequestMapping(value = {"**/index.html", "/dashboard/**", "/metadata/**"}) + public void indexHtml(HttpServletRequest request, HttpServletResponse response) throws IOException, URISyntaxException { + //This method is necessary in order for Angular framework to honor dynamic ServletContext + //under which shib ui application is deployed, both during initial index.html load and subsequest page refreshes + String content = new BufferedReader(new InputStreamReader(request.getServletContext() + .getResourceAsStream("/WEB-INF/classes/resources/index.html"))) + .lines() + .collect(Collectors.joining("\n")); - //This does not work! In order form Angular to kick in we need to redirect to index.html - String indexHtmlAsString = StreamUtils.copyToString(indexHtmlResource.getInputStream(), Charset.defaultCharset()); - //byte[] indexHtmlBytes = ByteStreams.toByteArray(indexHtmlResource.getInputStream()); - response.setHeader("Content-Type", "text/html"); - response.getWriter().print(indexHtmlAsString); - //os.write(ctxPath.getBytes(), 0, ctxPath.length()); + content = content.replaceFirst("", ""); + response.setContentType("text/html"); + try (OutputStream writer = response.getOutputStream()) { + writer.write(content.getBytes()); + } } } From e8224f4598d8cf57b9d19f5938f6ba9451a03cc6 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 28 Jan 2020 07:18:51 -0700 Subject: [PATCH 9/9] Removed console logs --- ui/src/app/core/service/api-path.interceptor.ts | 1 - .../configuration/container/metadata-options.component.ts | 3 --- ui/src/app/metadata/domain/service/provider.service.ts | 1 - ui/src/app/metadata/domain/service/resolver.service.ts | 1 - ui/src/app/metadata/provider/effect/collection.effect.ts | 1 - 5 files changed, 7 deletions(-) diff --git a/ui/src/app/core/service/api-path.interceptor.ts b/ui/src/app/core/service/api-path.interceptor.ts index 9c3bfd360..5417e5a7f 100644 --- a/ui/src/app/core/service/api-path.interceptor.ts +++ b/ui/src/app/core/service/api-path.interceptor.ts @@ -10,7 +10,6 @@ export class ApiPathInterceptor implements HttpInterceptor { ) {} intercept(req: HttpRequest, next: HttpHandler): Observable> { const apiReq = req.clone({ url: `${this.baseHref}${req.url}` }); - console.log(req); return next.handle(apiReq); } } diff --git a/ui/src/app/metadata/configuration/container/metadata-options.component.ts b/ui/src/app/metadata/configuration/container/metadata-options.component.ts index 8205aa60a..411c6fb10 100644 --- a/ui/src/app/metadata/configuration/container/metadata-options.component.ts +++ b/ui/src/app/metadata/configuration/container/metadata-options.component.ts @@ -57,9 +57,6 @@ export class MetadataOptionsComponent implements OnDestroy { protected router: Router, protected activatedRoute: ActivatedRoute ) { - - console.log('metadata options'); - this.model$ .pipe( takeUntil(this.ngUnsubscribe), diff --git a/ui/src/app/metadata/domain/service/provider.service.ts b/ui/src/app/metadata/domain/service/provider.service.ts index b93afee4e..b48e8876f 100644 --- a/ui/src/app/metadata/domain/service/provider.service.ts +++ b/ui/src/app/metadata/domain/service/provider.service.ts @@ -25,7 +25,6 @@ export class MetadataProviderService { } find(id: string): Observable { - console.log(id); return this.http.get(`${this.base}${this.endpoint}/${id}`); } diff --git a/ui/src/app/metadata/domain/service/resolver.service.ts b/ui/src/app/metadata/domain/service/resolver.service.ts index 6d9fc0dae..4db8ab41f 100644 --- a/ui/src/app/metadata/domain/service/resolver.service.ts +++ b/ui/src/app/metadata/domain/service/resolver.service.ts @@ -24,7 +24,6 @@ export class ResolverService { } find(id: string): Observable { - console.log(API_BASE_PATH); return this.http.get(`${ this.base }${ this.endpoint }/${ id }`); } diff --git a/ui/src/app/metadata/provider/effect/collection.effect.ts b/ui/src/app/metadata/provider/effect/collection.effect.ts index 70aff3257..1eb9e5093 100644 --- a/ui/src/app/metadata/provider/effect/collection.effect.ts +++ b/ui/src/app/metadata/provider/effect/collection.effect.ts @@ -115,7 +115,6 @@ export class CollectionEffects { map(action => action.payload), withLatestFrom(this.store.select(fromI18n.getMessages)), map(([error, messages]) => { - console.log(error); let message = `${error.errorCode}: ${this.i18nService.translate(error.errorMessage, null, messages)}`; message = error.cause ? `${message} - ${error.cause}` : message; return new AddNotification(