KNOX-1333 - Admin UI needs to handle SSO cookie expiration
Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/08cf0cbc Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/08cf0cbc Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/08cf0cbc Branch: refs/heads/master Commit: 08cf0cbcaf5b7ede13515dd3d975ed62ade2dc7c Parents: 1b053c5 Author: Phil Zampino <[email protected]> Authored: Fri May 25 10:26:55 2018 -0400 Committer: Phil Zampino <[email protected]> Committed: Fri May 25 10:26:55 2018 -0400 ---------------------------------------------------------------------- gateway-admin-ui/src/app/app.module.ts | 5 +- .../src/app/resource/resource.service.ts | 55 ++++++++++--- gateway-admin-ui/src/app/topology.service.ts | 82 ++++++++++++++------ .../applications/admin-ui/app/index.html | 2 +- .../app/inline.01ff628f1583dc5f05a5.bundle.js | 1 + .../app/inline.0c680e32597e9a9b9b80.bundle.js | 1 - .../app/main.127a9848c632a6cae3a9.bundle.js | 1 - .../app/main.d090da84954158b29e34.bundle.js | 1 + 8 files changed, 108 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-admin-ui/src/app/app.module.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/app.module.ts b/gateway-admin-ui/src/app/app.module.ts index 0810786..f15d49c 100644 --- a/gateway-admin-ui/src/app/app.module.ts +++ b/gateway-admin-ui/src/app/app.module.ts @@ -19,6 +19,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HttpClientXsrfModule } from "@angular/common/http"; import { FormsModule } from '@angular/forms'; import { CustomFormsModule } from 'ng2-validation'; +import { APP_BASE_HREF } from '@angular/common'; import { AppComponent } from './app.component'; import { TopologyService } from './topology.service'; @@ -43,6 +44,7 @@ import { ProviderConfigSelectorComponent } from './provider-config-selector/prov import { NewDescWizardComponent } from './new-desc-wizard/new-desc-wizard.component'; import { ProviderConfigWizardComponent } from './provider-config-wizard/provider-config-wizard.component' + @NgModule({ imports: [ BrowserModule, HttpClientModule, @@ -72,7 +74,8 @@ import { ProviderConfigWizardComponent } from './provider-config-wizard/provider GatewayVersionService, ResourceComponent, ResourceTypesService, - ResourceService + ResourceService, + { provide: APP_BASE_HREF, useValue : '/' } ], bootstrap: [ AppComponent, GatewayVersionComponent http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-admin-ui/src/app/resource/resource.service.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/resource/resource.service.ts b/gateway-admin-ui/src/app/resource/resource.service.ts index 618f80e..9bbfea1 100644 --- a/gateway-admin-ui/src/app/resource/resource.service.ts +++ b/gateway-admin-ui/src/app/resource/resource.service.ts @@ -65,8 +65,12 @@ export class ResourceService { .toPromise() .then(response => response['items'] as Resource[]) .catch((err: HttpErrorResponse) => { - console.debug('ResourceService --> getProviderConfigResources() --> error: ' + err.message); - return this.handleError(err); + console.debug('ResourceService --> getProviderConfigResources() --> error: HTTP ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -76,8 +80,12 @@ export class ResourceService { .toPromise() .then(response => response['items'] as Resource[]) .catch((err: HttpErrorResponse) => { - console.debug('ResourceService --> getDescriptorResources() --> error: ' + err.message); - return this.handleError(err); + console.debug('ResourceService --> getDescriptorResources() --> error: HTTP ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -87,8 +95,12 @@ export class ResourceService { .toPromise() .then(response => response['topologies'].topology as Resource[]) .catch((err: HttpErrorResponse) => { - console.debug('ResourceService --> getTopologyResources() --> error: ' + err.message); - return this.handleError(err); + console.debug('ResourceService --> getTopologyResources() --> error: HTTP ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -96,7 +108,6 @@ export class ResourceService { if (res) { let headers = new HttpHeaders(); headers = (resType === 'Topologies') ? this.addXmlHeaders(headers) : this.addHeaders(headers, res.name); - return this.http.get(res.href, {headers: headers, responseType: 'text'}) .toPromise() .then(response => { @@ -104,8 +115,12 @@ export class ResourceService { return response; }) .catch((err: HttpErrorResponse) => { - console.debug('ResourceService --> getResource() ' + res.name + '\n error: ' + err.message); + console.debug('ResourceService --> getResource() ' + res.name + '\n error: ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { return this.handleError(err); + } }); } else { return Promise.resolve(null); @@ -122,7 +137,11 @@ export class ResourceService { .then(() => content) .catch((err: HttpErrorResponse) => { console.debug('ResourceService --> saveResource() ' + resource.name + '\n error: ' + err.message); - return this.handleError(err); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -135,7 +154,11 @@ export class ResourceService { .then(() => content) .catch((err: HttpErrorResponse) => { console.debug('ResourceService --> createResource() --> ' + resource.name + '\n error: ' + err.message); - return this.handleError(err); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -147,7 +170,11 @@ export class ResourceService { .then(response => response) .catch((err: HttpErrorResponse) => { console.debug('ResourceService --> deleteResource() --> ' + href + '\n error: ' + err.message); - return this.handleError(err); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } }); } @@ -264,7 +291,11 @@ export class ResourceService { } addCsrfHeaders(headers: HttpHeaders): HttpHeaders { - return headers.append('X-XSRF-Header', 'admin-ui'); + return this.addXHRHeaders(headers.append('X-XSRF-Header', 'admin-ui')); + } + + addXHRHeaders(headers: HttpHeaders): HttpHeaders { + return headers.append('X-Requested-With', 'XMLHttpRequest'); } selectedResourceType(value: string) { http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-admin-ui/src/app/topology.service.ts ---------------------------------------------------------------------- diff --git a/gateway-admin-ui/src/app/topology.service.ts b/gateway-admin-ui/src/app/topology.service.ts index c71225b..28d1e70 100644 --- a/gateway-admin-ui/src/app/topology.service.ts +++ b/gateway-admin-ui/src/app/topology.service.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import { Injectable } from '@angular/core'; -import { HttpHeaders, HttpClient } from '@angular/common/http'; +import {HttpHeaders, HttpClient, HttpErrorResponse} from '@angular/common/http'; import 'rxjs/add/operator/toPromise'; import { Subject } from 'rxjs/Subject'; @@ -39,9 +39,16 @@ export class TopologyService { return this.http.get(this.topologiesUrl, { headers: headers } ) - .toPromise() - .then(response => response['topologies'].topology as Topology[]) - .catch(this.handleError); + .toPromise() + .then(response => response['topologies'].topology as Topology[]) + .catch((err: HttpErrorResponse) => { + console.debug('TopologyService --> getTopologies() --> ' + '\n error: ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } + }); } getTopology(href : string): Promise<string> { @@ -50,32 +57,49 @@ export class TopologyService { return this.http.get(href, { headers: headers, responseType: 'text' } ) - .toPromise() - .then(response => response) - .catch(this.handleError); - + .toPromise() + .then(response => response) + .catch((err: HttpErrorResponse) => { + console.debug('TopologyService --> getTopology() --> ' + href + '\n error: ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } + }); } saveTopology(url: string, xml : string): Promise<string> { let xheaders = new HttpHeaders(); xheaders = this.addXmlHeaders(xheaders); - return this.http - .put(url, xml, { headers: xheaders, responseType: 'text' }) - .toPromise() - .then(() => xml) - .catch(this.handleError); - + return this.http.put(url, xml, { headers: xheaders, responseType: 'text' }) + .toPromise() + .then(() => xml) + .catch((err: HttpErrorResponse) => { + console.debug('TopologyService --> getTopology() --> \n error: ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } + }); } createTopology(name: string, xml : string): Promise<string> { let xheaders = new HttpHeaders(); xheaders = this.addXmlHeaders(xheaders); let url = this.topologiesUrl + "/" + name; - return this.http - .put(url, xml, { headers: xheaders, responseType: 'text' }) - .toPromise() - .then(() => xml) - .catch(this.handleError); + return this.http.put(url, xml, { headers: xheaders, responseType: 'text' }) + .toPromise() + .then(() => xml) + .catch((err: HttpErrorResponse) => { + console.debug('TopologyService --> getTopology() --> \n error: ' + err.status + ' ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } + }); } deleteTopology(href: string): Promise<string> { @@ -84,9 +108,16 @@ export class TopologyService { return this.http.delete(href, { headers: headers, responseType: 'text' } ) - .toPromise() - .then(response => response) - .catch(this.handleError); + .toPromise() + .then(response => response) + .catch((err: HttpErrorResponse) => { + console.debug('TopologyService --> getTopology() --> ' + href + '\n error: ' + err.message); + if (err.status === 401) { + window.location.assign(document.location.pathname); + } else { + return this.handleError(err); + } + }); } addJsonHeaders(headers: HttpHeaders): HttpHeaders { @@ -100,7 +131,11 @@ export class TopologyService { } addCsrfHeaders(headers: HttpHeaders): HttpHeaders { - return headers.append('X-XSRF-Header', 'admin-ui'); + return this.addXHRHeaders(headers.append('X-XSRF-Header', 'admin-ui')); + } + + addXHRHeaders(headers: HttpHeaders): HttpHeaders { + return headers.append('X-Requested-With', 'XMLHttpRequest'); } selectedTopology(value: Topology) { @@ -111,7 +146,6 @@ export class TopologyService { this.changedTopologySource.next(value); } - private handleError(error: any): Promise<any> { console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-applications/src/main/resources/applications/admin-ui/app/index.html ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html index 359e486..e9a45db 100644 --- a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html +++ b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html @@ -11,4 +11,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 1.0.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.0c680e32597e9a9b9b80.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.127a9848c632a6cae3a9.bundle.js"></script></div></body></html> \ No newline at end of file +--><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res ource-management><footer class="footer"><div class="container-fluid"><div>Knox Manager Version 1.0.0</div><gateway-version></gateway-version></div></footer><script type="text/javascript" src="inline.01ff628f1583dc5f05a5.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.d090da84954158b29e34.bundle.js"></script></div></body></html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01ff628f1583dc5f05a5.bundle.js ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01ff628f1583dc5f05a5.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01ff628f1583dc5f05a5.bundle.js new file mode 100644 index 0000000..bc8c767 --- /dev/null +++ b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01ff628f1583dc5f05a5.bundle.js @@ -0,0 +1 @@ +!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"d090da84954158b29e34",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/08cf0cbc/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c680e32597e9a9b9b80.bundle.js ---------------------------------------------------------------------- diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c680e32597e9a9b9b80.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c680e32597e9a9b9b80.bundle.js deleted file mode 100644 index 9489b77..0000000 --- a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.0c680e32597e9a9b9b80.bundle.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,c){for(var u,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(u in a)Object.prototype.hasOwnProperty.call(a,u)&&(e[u]=a[u]);for(n&&n(r,a,c);s.length;)s.shift()();if(c)for(l=0;l<c.length;l++)f=o(o.s=c[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var a=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.timeout=12e4,o.nc&&c.setAttribute("nonce",o.nc),c.src=o.p+""+e+"."+{0:"127a9848c632a6cae3a9",1:"aed76669724804835353"}[e]+".chunk.js";var u=setTimeout(i,12e4);function i(){c.onerror=c.onload=null,clearTimeout(u);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu nk "+e+" failed.")),t[e]=void 0)}return c.onerror=c.onload=i,a.appendChild(c),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]); \ No newline at end of file
