KEYCLOAK-8421: POC for account management extension

This commit is contained in:
Stan Silvert 2018-10-15 07:46:05 -04:00
parent ab8789739f
commit 68ab08aa56
8 changed files with 293 additions and 8 deletions

View file

@ -77,7 +77,24 @@
<script src="${resourceUrl}/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="${resourceUrl}/node_modules/patternfly/dist/js/patternfly.min.js"></script>
<script src="${authUrl}/js/keycloak.js"></script>
<#if properties.developmentMode?has_content && properties.developmentMode == "true">
<!-- Don't use this in production: -->
<script src="${resourceUrl}/node_modules/react/umd/react.development.js" crossorigin></script>
<script src="${resourceUrl}/node_modules/react-dom/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</#if>
<#if properties.extensions?has_content>
<#list properties.extensions?split(' ') as script>
<#if properties.developmentMode?has_content && properties.developmentMode == "true">
<script type="text/babel" src="${resourceUrl}/${script}"></script>
<#else>
<script type="text/javascript" src="${resourceUrl}/${script}"></script>
</#if>
</#list>
</#if>
<!-- TODO: We should save these css and js into variables and then load in
main.ts for better performance. These might be loaded twice.
-->
@ -107,7 +124,7 @@
};
keycloak.init({onLoad: 'check-sso'}).success(function(authenticated) {
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("/systemjs.config.js", function() {
System.import('${resourceUrl}/Main.js').catch(function (err) {

View file

@ -0,0 +1,49 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {HashRouter} from 'react-router-dom';
import {App} from './app/App';
const e = React.createElement;
export interface MainProps {
}
//declare function loadjs(url,loadListener?);
//loadjs('/js/MyExtension.js');
export class Main extends React.Component<MainProps> {
constructor(props: MainProps) {
super(props);
}
render() {
return (
<HashRouter>
<App/>
</HashRouter>
);
}
};
const domContainer = document.querySelector('#main_react_container');
ReactDOM.render(e(Main), domContainer);

View file

@ -0,0 +1,67 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
import {Route, Link} from 'react-router-dom';
import {KeycloakService} from './keycloak-service/keycloak.service';
import {Logout} from './widgets/Logout';
import {AccountPage} from './content/account-page/AccountPage';
import {ApplicationsPage} from './content/applications-page/ApplicationsPage';
import {PasswordPage} from './content/password-page/PasswordPage';
import {ExtensionPages} from './content/extensions/ExtensionPages';
declare function toggleReact():void;
declare function isWelcomePage(): boolean;
export interface AppProps {};
export class App extends React.Component<AppProps> {
private kcSvc: KeycloakService = KeycloakService.Instance;
constructor(props:AppProps) {
super(props);
console.log('Called into App constructor');
toggleReact();
}
render() {
toggleReact();
// check login
if (!this.kcSvc.authenticated() && !isWelcomePage()) {
this.kcSvc.login();
}
return (
<span>
<nav>
<Link to="/app/account" className="btn btn-primary btn-lg btn-sign" type="button">Account</Link>
<Link to="/app/applications" className="btn btn-primary btn-lg btn-sign" type="button">Applications</Link>
<Link to="/app/password" className="btn btn-primary btn-lg btn-sign" type="button">Password</Link>
{ExtensionPages.Links}
<Logout/>
<Route path='/app/account' component={AccountPage}/>
<Route path='/app/applications' component={ApplicationsPage}/>
<Route path='/app/password' component={PasswordPage}/>
{ExtensionPages.Routes}
</nav>
</span>
);
}
};

View file

@ -0,0 +1,35 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
export interface AccountPageProps {
}
export class AccountPage extends React.Component<AccountPageProps> {
constructor(props: AccountPageProps) {
super(props);
}
render() {
return (
<div>
<h2>Hello Account Page</h2>
</div>
);
}
};

View file

@ -0,0 +1,35 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
export interface ApplicationsPageProps {
}
export class ApplicationsPage extends React.Component<ApplicationsPageProps> {
constructor(props: ApplicationsPageProps) {
super(props);
}
render() {
return (
<div>
<h2>Hello Applications Page</h2>
</div>
);
}
};

View file

@ -0,0 +1,48 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
import {Route, Link} from 'react-router-dom';
export interface PageDef {
path: string,
label: string,
component: React.ComponentType<any>,
}
declare const extensionPages: PageDef[];
export class ExtensionPages { // extends React.Component<ExtensionPagesProps> {
public static get Links(): React.ReactElement<any> {
if (typeof extensionPages === 'undefined') return (<span/>);
const links: React.ReactElement<Link>[] = extensionPages.map((page: PageDef) =>
<Link key={page.path} to={'/app/' + page.path} className="btn btn-primary btn-lg btn-sign" type="button">{page.label}</Link>
);
return (<span>{links}</span>);
}
public static get Routes(): React.ReactElement<any> {
if (typeof extensionPages === 'undefined') return (<span/>);
const routes: React.ReactElement<Route>[] = extensionPages.map((page) =>
<Route key={page.path} path={'/app/' + page.path} component={page.component}/>
);
return (<span>{routes}</span>);
}
};

View file

@ -0,0 +1,35 @@
/*
* Copyright 2018 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/
import * as React from 'react';
export interface PasswordPageProps {
}
export class PasswordPage extends React.Component<PasswordPageProps> {
constructor(props: PasswordPageProps) {
super(props);
}
render() {
return (
<div>
<h2>Hello Password Page</h2>
</div>
);
}
};

View file

@ -18,6 +18,8 @@ import * as React from 'react';
import {Link} from 'react-router-dom';
import {KeycloakService} from '../keycloak-service/keycloak.service';
declare const baseUrl;
export interface LogoutProps {
}
@ -27,16 +29,13 @@ export class Logout extends React.Component<LogoutProps> {
super(props);
}
handleLogout = () => {
KeycloakService.Instance.logout();
private handleLogout() {
KeycloakService.Instance.logout(baseUrl);
}
render() {
return (
<div>
<Link to="/" type="button" onClick={this.handleLogout}>Logout</Link>
</div>
<Link to="/" className="btn btn-primary btn-lg btn-sign" type="button" onClick={this.handleLogout}>Logout</Link>
);
}
}