KEYCLOAK: 8601: Evaluate REST/HTTP packages for React
This commit is contained in:
parent
c36b577566
commit
ec335629b4
6 changed files with 131 additions and 88 deletions
|
@ -122,7 +122,7 @@
|
||||||
if (loadListener) script.addEventListener("load", loadListener);
|
if (loadListener) script.addEventListener("load", loadListener);
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
};
|
};
|
||||||
keycloak.init({onLoad: 'check-sso'}).success(function(authenticated) {
|
keycloak.init({onLoad: 'login-required'}).success(function(authenticated) {
|
||||||
loadjs("/node_modules/react/umd/react.development.js", function() {
|
loadjs("/node_modules/react/umd/react.development.js", function() {
|
||||||
loadjs("/node_modules/react-dom/umd/react-dom.development.js", function() {
|
loadjs("/node_modules/react-dom/umd/react-dom.development.js", function() {
|
||||||
loadjs("/node_modules/systemjs/dist/system.src.js", function() {
|
loadjs("/node_modules/systemjs/dist/system.src.js", function() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2017 Red Hat Inc. and/or its affiliates and other contributors
|
* Copyright 2018 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
* as indicated by the @author tags. All rights reserved.
|
* as indicated by the @author tags. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
@ -15,98 +15,82 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*import {Injectable} from '@angular/core';
|
//import {KeycloakNotificationService} from '../notification/keycloak-notification.service';
|
||||||
import {Http, Response, RequestOptionsArgs} from '@angular/http';
|
|
||||||
|
|
||||||
import {KeycloakNotificationService} from '../notification/keycloak-notification.service';
|
|
||||||
import {KeycloakService} from '../keycloak-service/keycloak.service';
|
import {KeycloakService} from '../keycloak-service/keycloak.service';
|
||||||
|
import Axios, {AxiosRequestConfig, AxiosResponse, AxiosPromise} from 'axios';
|
||||||
|
|
||||||
import {NotificationType} from 'patternfly-ng/notification';*/
|
//import {NotificationType} from 'patternfly-ng/notification';*/
|
||||||
|
|
||||||
|
type AxiosResolve = (AxiosResponse) => void;
|
||||||
|
type ConfigResolve = (AxiosRequestConfig) => void;
|
||||||
|
type ErrorReject = (Error) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2017 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2018 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
//@Injectable()
|
|
||||||
export class AccountServiceClient {
|
export class AccountServiceClient {
|
||||||
|
private static instance: AccountServiceClient = new AccountServiceClient();
|
||||||
/* private accountUrl: string;
|
|
||||||
|
private kcSvc: KeycloakService = KeycloakService.Instance;
|
||||||
constructor(protected http: Http,
|
private accountUrl: string = this.kcSvc.authServerUrl() + 'realms/' + this.kcSvc.realm() + '/account';
|
||||||
protected kcSvc: KeycloakService,
|
|
||||||
protected kcNotifySvc: KeycloakNotificationService) {
|
private constructor() {}
|
||||||
this.accountUrl = kcSvc.authServerUrl() + 'realms/' + kcSvc.realm() + '/account';
|
|
||||||
|
public static get Instance(): AccountServiceClient {
|
||||||
|
return this.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public doGetRequest(endpoint: string,
|
public doGet(endpoint: string,
|
||||||
responseHandler: Function,
|
config?: AxiosRequestConfig): Promise<AxiosResponse> {
|
||||||
options?: RequestOptionsArgs) {
|
return this.doRequest(endpoint, {...config, method: 'get'});
|
||||||
this.http.get(this.accountUrl + endpoint, options)
|
|
||||||
.subscribe((res: Response) => responseHandler(res),
|
|
||||||
(error: Response) => this.handleServiceError(error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public doPostRequest(endpoint: string,
|
public doRequest(endpoint: string,
|
||||||
responseHandler: Function,
|
config?: AxiosRequestConfig): Promise<AxiosResponse> {
|
||||||
options?: RequestOptionsArgs,
|
|
||||||
successMessage?: string) {
|
|
||||||
this.http.post(this.accountUrl + endpoint, options)
|
|
||||||
.subscribe((res: Response) => this.handleAccountUpdated(responseHandler, res, successMessage),
|
|
||||||
(error: Response) => this.handleServiceError(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleAccountUpdated(responseHandler: Function, res: Response, successMessage?: string) {
|
|
||||||
let message: string = "Your account has been updated.";
|
|
||||||
if (successMessage) message = successMessage;
|
|
||||||
this.kcNotifySvc.notify(message, NotificationType.SUCCESS);
|
|
||||||
responseHandler(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public doDelete(endpoint: string,
|
|
||||||
responseHandler: Function,
|
|
||||||
options?: RequestOptionsArgs,
|
|
||||||
successMessage?: string) {
|
|
||||||
this.http.delete(this.accountUrl + endpoint, options)
|
|
||||||
.subscribe((res: Response) => this.handleAccountUpdated(responseHandler, res, successMessage),
|
|
||||||
(error: Response) => this.handleServiceError(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleServiceError(response: Response): void {
|
|
||||||
console.log('**** ERROR!!!! ***');
|
|
||||||
console.log(JSON.stringify(response));
|
|
||||||
console.log("response.status=" + response.status);
|
|
||||||
console.log('***************************************')
|
|
||||||
|
|
||||||
if ((response.status === undefined) || (response.status === 401)) {
|
return new Promise((resolve: AxiosResolve, reject: ErrorReject) => {
|
||||||
this.kcSvc.logout();
|
this.makeConfig(endpoint, config)
|
||||||
return;
|
.then((config: AxiosRequestConfig) => {
|
||||||
}
|
console.log({config});
|
||||||
|
this.axiosRequest(config, resolve, reject);
|
||||||
if (response.status === 403) {
|
}).catch( (error: Error) => {
|
||||||
// TODO: go to a forbidden page?
|
this.handleError(error);
|
||||||
}
|
reject(error);
|
||||||
|
});
|
||||||
if (response.status === 404) {
|
});
|
||||||
// TODO: route to PageNotFoundComponent
|
}
|
||||||
}
|
|
||||||
|
private axiosRequest(config: AxiosRequestConfig,
|
||||||
let message: string = response.status + " " + response.statusText;
|
resolve: AxiosResolve,
|
||||||
|
reject: ErrorReject): void {
|
||||||
const not500Error: boolean = response.status !== 500;
|
Axios.request(config)
|
||||||
console.log('not500Error=' + not500Error);
|
.then((response: AxiosResponse) => {
|
||||||
|
resolve(response);
|
||||||
// Unfortunately, errors can be sent back in the response body as
|
})
|
||||||
// 'errorMessage' or 'error_description'
|
.catch((error: Error) => {
|
||||||
if (not500Error && response.json().hasOwnProperty('errorMessage')) {
|
this.handleError(error);
|
||||||
message = response.json().errorMessage;
|
reject(error);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
if (not500Error && response.json().hasOwnProperty('error_description')) {
|
|
||||||
message = response.json().error_description;
|
private handleError(error: Error) {
|
||||||
}
|
console.log(error);
|
||||||
|
}
|
||||||
this.kcNotifySvc.notify(message, NotificationType.DANGER, response.json().params);
|
|
||||||
} */
|
private makeConfig(endpoint: string, config?: AxiosRequestConfig): Promise<AxiosRequestConfig> {
|
||||||
|
return new Promise( (resolve: ConfigResolve, reject: ErrorReject) => {
|
||||||
|
this.kcSvc.getToken()
|
||||||
|
.then( (token: string) => {
|
||||||
|
resolve( {
|
||||||
|
...config,
|
||||||
|
baseURL: this.accountUrl,
|
||||||
|
url: endpoint,
|
||||||
|
headers: {...config.headers, Authorization: 'Bearer ' + token}
|
||||||
|
});
|
||||||
|
}).catch((error: Error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,20 +15,42 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import {AxiosResponse} from 'axios';
|
||||||
|
import {AccountServiceClient} from '../../account-service/account.service';
|
||||||
|
|
||||||
export interface AccountPageProps {
|
interface AccountPageProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountPage extends React.Component<AccountPageProps> {
|
interface AccountPageState {
|
||||||
|
readonly username: string,
|
||||||
|
readonly firstName?: string,
|
||||||
|
readonly lastName?: string,
|
||||||
|
readonly email?: string,
|
||||||
|
readonly emailVerified?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2018 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
export class AccountPage extends React.Component<AccountPageProps, AccountPageState> {
|
||||||
|
readonly state: AccountPageState = {
|
||||||
|
username: ''
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props: AccountPageProps) {
|
constructor(props: AccountPageProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
AccountServiceClient.Instance.doGet("/")
|
||||||
|
.then((response: AxiosResponse<AccountPageState>) => {
|
||||||
|
this.setState(response.data);
|
||||||
|
console.log({response});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {username, firstName} = this.state;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Hello Account Page</h2>
|
<h2>Hello {username} {firstName}</h2>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,6 +294,15 @@
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.18.0",
|
||||||
|
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
|
||||||
|
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "^1.3.0",
|
||||||
|
"is-buffer": "^1.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
|
||||||
|
@ -411,6 +420,14 @@
|
||||||
"jquery": ">=1.7"
|
"jquery": ">=1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"drmonty-datatables-colvis": {
|
"drmonty-datatables-colvis": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/drmonty-datatables-colvis/-/drmonty-datatables-colvis-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/drmonty-datatables-colvis/-/drmonty-datatables-colvis-1.1.2.tgz",
|
||||||
|
@ -440,6 +457,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.5.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz",
|
||||||
|
"integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "=3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"font-awesome": {
|
"font-awesome": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
|
||||||
|
@ -492,6 +517,11 @@
|
||||||
"loose-envify": "^1.0.0"
|
"loose-envify": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||||
|
},
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
@ -535,6 +565,11 @@
|
||||||
"moment": ">= 2.6.0"
|
"moment": ">= 2.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"author": "Stan Silvert",
|
"author": "Stan Silvert",
|
||||||
"license": "Apache 2.0",
|
"license": "Apache 2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^0.18.0",
|
||||||
"bootstrap": "^4.1.0",
|
"bootstrap": "^4.1.0",
|
||||||
"patternfly": "^3.23.2",
|
"patternfly": "^3.23.2",
|
||||||
"react": "^16.5.2",
|
"react": "^16.5.2",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
'react-dom': 'npm:react-dom/umd/react-dom.development.js',
|
'react-dom': 'npm:react-dom/umd/react-dom.development.js',
|
||||||
'react-router-dom': 'npm:react-router-dom/umd/react-router-dom.js',
|
'react-router-dom': 'npm:react-router-dom/umd/react-router-dom.js',
|
||||||
|
|
||||||
|
'axios': 'npm:axios/dist/axios.min.js',
|
||||||
},
|
},
|
||||||
|
|
||||||
bundles: {
|
bundles: {
|
||||||
|
|
Loading…
Reference in a new issue