From 8515052e1a6de2de56effbc61c73d3aa80169a93 Mon Sep 17 00:00:00 2001 From: Aijana Schumann Date: Mon, 15 Feb 2021 18:22:28 +0100 Subject: Add OAuth support to odlux Extend odlux to support oauth, support external login provider for sign-in Issue-ID: CCSDK-3167 Signed-off-by: Aijana Schumann Change-Id: Id5772e0026fa7ebda22c41c2620a7868598f41aa --- sdnr/wt/odlux/framework/src/views/login.tsx | 92 +++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 12 deletions(-) (limited to 'sdnr/wt/odlux/framework/src/views/login.tsx') diff --git a/sdnr/wt/odlux/framework/src/views/login.tsx b/sdnr/wt/odlux/framework/src/views/login.tsx index b06cf7631..be1fb801f 100644 --- a/sdnr/wt/odlux/framework/src/views/login.tsx +++ b/sdnr/wt/odlux/framework/src/views/login.tsx @@ -32,10 +32,16 @@ import Paper from '@material-ui/core/Paper'; import Typography from '@material-ui/core/Typography'; import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; -import connect, { Connect } from '../flux/connect'; +import connect, { Connect, IDispatcher } from '../flux/connect'; import authenticationService from '../services/authenticationService'; -import { UpdateAuthentication } from '../actions/authentication'; +import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider'; +import { UpdatePolicies, UpdateUser } from '../actions/authentication'; + +import { IApplicationStoreState } from '../store/applicationStore'; +import { AuthPolicy, AuthToken, User } from '../models/authentication'; +import Menu from '@material-ui/core/Menu'; +import { MenuItem } from '@material-ui/core'; const styles = (theme: Theme) => createStyles({ layout: { @@ -69,14 +75,37 @@ const styles = (theme: Theme) => createStyles({ }, }); -type LoginProps = RouteComponentProps<{}> & WithStyles & Connect; +const mapProps = (state: IApplicationStoreState) => ({ + search: state.framework.navigationState.search, + authentication: state.framework.applicationState.authentication, + externalLoginProviders: state.framework.applicationState.externalLoginProviders , +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + updateExternalProviders: () => dispatcher.dispatch(updateExternalLoginProviderAsyncActionCreator()), + updateAuthentication: (token: AuthToken | null) => { + const user = token && new User(token) || undefined; + dispatcher.dispatch(new UpdateUser(user)); + }, + updatePolicies: (policies?: AuthPolicy[]) => { + return dispatcher.dispatch(new UpdatePolicies(policies)); + }, +}); + +type LoginProps = RouteComponentProps<{}> & WithStyles & Connect; interface ILoginState { + externalProviderAnchor: HTMLElement | null; busy: boolean; username: string; password: string; scope: string; message: string; + providers: { + id: string; + title: string; + loginUrl: string; + }[] | null; } @@ -87,14 +116,26 @@ class LoginComponent extends React.Component { super(props); this.state = { + externalProviderAnchor: null, busy: false, username: '', password: '', scope: 'sdn', - message: '' + message: '', + providers: null, }; } + async componentDidMount(){ + if (this.props.authentication === "oauth" && (this.props.externalLoginProviders == null || this.props.externalLoginProviders.length === 0)){ + this.props.updateExternalProviders(); + } + } + + private setExternalProviderAnchor = (el: HTMLElement | null) => { + this.setState({externalProviderAnchor: el }) + } + render(): JSX.Element { const { classes } = this.props; return ( @@ -153,6 +194,33 @@ class LoginComponent extends React.Component { > Sign in + { this.props.externalLoginProviders && this.props.externalLoginProviders.length > 0 + ? + [ + , + { this.setExternalProviderAnchor(null); }} + > + { + this.props.externalLoginProviders.map((provider) => ( + { window.location = provider.loginUrl as any; } }>{ provider.title} + )) + } + + ] + : null + } {this.state.message && {this.state.message}} @@ -165,16 +233,16 @@ class LoginComponent extends React.Component { event.preventDefault(); this.setState({ busy: true }); - // const token = await authenticationService.authenticateUserOAuth(this.state.username, this.state.password, this.state.scope); - const token = await authenticationService.authenticateUserBasicAuth(this.state.username, this.state.password, this.state.scope); - this.props.dispatch(new UpdateAuthentication(token)); + + const token = this.props.authentication === "oauth" + ? await authenticationService.authenticateUserOAuth(this.state.username, this.state.password, this.state.scope) + : await authenticationService.authenticateUserBasicAuth(this.state.username, this.state.password, this.state.scope); + + this.props.updateAuthentication(token); this.setState({ busy: false }); if (token) { - const query = - this.props.state.framework.navigationState.search && - this.props.state.framework.navigationState.search.replace(/^\?/, "") - .split('&').map(e => e.split("=")); + const query = this.props.search && this.props.search.replace(/^\?/, "").split('&').map(e => e.split("=")); const returnTo = query && query.find(e => e[0] === "returnTo"); this.props.history.replace(returnTo && returnTo[1] || "/"); } @@ -187,5 +255,5 @@ class LoginComponent extends React.Component { } } -export const Login = withStyles(styles)(withRouter(connect()(LoginComponent))); +export const Login = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(LoginComponent))); export default Login; \ No newline at end of file -- cgit 1.2.3-korg