1
0
mirror of https://github.com/0rangebananaspy/authelia.git synced 2024-09-14 22:47:21 +07:00
authelia/client/src/components/SecondFactorForm/SecondFactorForm.tsx
2019-03-03 11:39:40 +01:00

160 lines
4.7 KiB
TypeScript

import React, { Component, KeyboardEvent, ChangeEvent } from 'react';
import { WithStyles, withStyles, Button, TextField } from '@material-ui/core';
import styles from '../../assets/jss/components/SecondFactorForm/SecondFactorForm';
import CircleLoader, { Status } from '../../components/CircleLoader/CircleLoader';
import FormNotification from '../FormNotification/FormNotification';
export interface OwnProps {
username: string;
redirection: string | null;
}
export interface StateProps {
securityKeySupported: boolean;
securityKeyVerified: boolean;
securityKeyError: string | null;
oneTimePasswordVerificationInProgress: boolean,
oneTimePasswordVerificationError: string | null;
}
export interface DispatchProps {
onInit: () => void;
onLogoutClicked: () => void;
onRegisterSecurityKeyClicked: () => void;
onRegisterOneTimePasswordClicked: () => void;
onOneTimePasswordValidationRequested: (token: string) => void;
}
export type Props = OwnProps & StateProps & DispatchProps & WithStyles;
interface State {
oneTimePassword: string;
}
class SecondFactorView extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
oneTimePassword: '',
}
}
componentWillMount() {
this.props.onInit();
}
private renderU2f(n: number) {
const { classes } = this.props;
let u2fStatus = Status.LOADING;
if (this.props.securityKeyVerified) {
u2fStatus = Status.SUCCESSFUL;
} else if (this.props.securityKeyError) {
u2fStatus = Status.FAILURE;
}
return (
<div className={classes.methodU2f} key='u2f-method'>
<div className={classes.methodName}>Option {n} - Security Key</div>
<div>Insert your security key into a USB port and touch the gold disk.</div>
<div className={classes.imageContainer}>
<CircleLoader status={u2fStatus}></CircleLoader>
</div>
<div className={classes.registerDeviceContainer}>
<a className={classes.registerDevice} href="#"
onClick={this.props.onRegisterSecurityKeyClicked}>
Register device
</a>
</div>
</div>
)
}
private onOneTimePasswordChanged = (e: ChangeEvent<HTMLInputElement>) => {
this.setState({oneTimePassword: e.target.value});
}
private onTotpKeyPressed = (e: KeyboardEvent) => {
if (e.key === 'Enter') {
this.onOneTimePasswordValidationRequested();
}
}
private onOneTimePasswordValidationRequested = () => {
if (this.props.oneTimePasswordVerificationInProgress) return;
this.props.onOneTimePasswordValidationRequested(this.state.oneTimePassword);
}
private renderTotp(n: number) {
const { classes } = this.props;
return (
<div className={classes.methodTotp} key='totp-method'>
<div className={classes.methodName}>Option {n} - One-Time Password</div>
<FormNotification show={this.props.oneTimePasswordVerificationError !== null}>
{this.props.oneTimePasswordVerificationError}
</FormNotification>
<TextField
className={classes.totpField}
name="totp-token"
id="totp-token"
variant="outlined"
label="One-Time Password"
onChange={this.onOneTimePasswordChanged}
onKeyPress={this.onTotpKeyPressed}>
</TextField>
<div className={classes.registerDeviceContainer}>
<a className={classes.registerDevice} href="#"
onClick={this.props.onRegisterOneTimePasswordClicked}>
Register device
</a>
</div>
<Button
className={classes.totpButton}
variant="contained"
color="primary"
onClick={this.onOneTimePasswordValidationRequested}
disabled={this.props.oneTimePasswordVerificationInProgress}>
OK
</Button>
</div>
)
}
private renderMode() {
const { classes } = this.props;
const methods = [];
let n = 1;
if (this.props.securityKeySupported) {
methods.push(this.renderU2f(n));
n++;
}
methods.push(this.renderTotp(n));
return (
<div className={classes.methodsContainer}>
{methods}
</div>
);
}
render() {
const { classes } = this.props;
return (
<div className={classes.container}>
<div className={classes.header}>
<div className={classes.hello}>Hello <b>{this.props.username}</b></div>
<div className={classes.logout}>
<a onClick={this.props.onLogoutClicked} href="#">Logout</a>
</div>
</div>
<div className={classes.body}>
{this.renderMode()}
</div>
</div>
)
}
}
export default withStyles(styles)(SecondFactorView);