mirror of
https://gitlab.com/comunic/comunicconsole
synced 2025-04-20 03:30:54 +00:00
288 lines
5.8 KiB
TypeScript
288 lines
5.8 KiB
TypeScript
/**
|
|
* Login route
|
|
*
|
|
* @author Pierre Hubert
|
|
*/
|
|
|
|
import {
|
|
Avatar,
|
|
Box,
|
|
Button,
|
|
Container,
|
|
CssBaseline,
|
|
List,
|
|
ListItem,
|
|
ListItemAvatar,
|
|
ListItemText,
|
|
Paper,
|
|
TextField,
|
|
Typography,
|
|
} from "@material-ui/core";
|
|
import { ErrorOutline, Lock, VpnKey } from "@material-ui/icons";
|
|
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
|
|
import React from "react";
|
|
import { AccountHelper, AuthOptions } from "../../helpers/AccountHelper";
|
|
import { input, matAlert } from "../widgets/DialogsProvider";
|
|
|
|
function ErrorGettingOptions() {
|
|
return (
|
|
<Paper
|
|
style={{
|
|
width: "100%",
|
|
padding: "10px",
|
|
marginTop: "10px",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<ErrorOutline></ErrorOutline>
|
|
Could not get your auth options!
|
|
</Paper>
|
|
);
|
|
}
|
|
|
|
function Copyright() {
|
|
return (
|
|
<Typography variant="body2" color="textSecondary" align="center">
|
|
{"Copyright © "}
|
|
Comunic
|
|
{new Date().getFullYear()}
|
|
{"."}
|
|
</Typography>
|
|
);
|
|
}
|
|
|
|
interface LoginRouteState {
|
|
currEmail: string;
|
|
errorGettingAuthOptions: boolean;
|
|
authOptions?: AuthOptions;
|
|
}
|
|
|
|
export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
|
constructor(props: any) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
currEmail: "",
|
|
errorGettingAuthOptions: false,
|
|
authOptions: undefined,
|
|
};
|
|
|
|
this.handleChangedEmail = this.handleChangedEmail.bind(this);
|
|
this.handleSubmitEmail = this.handleSubmitEmail.bind(this);
|
|
}
|
|
|
|
get canSubmit(): boolean {
|
|
return this.state.currEmail.length > 4;
|
|
}
|
|
|
|
handleChangedEmail(e: React.ChangeEvent<HTMLInputElement>) {
|
|
this.setState({
|
|
currEmail: e.target.value,
|
|
errorGettingAuthOptions: false,
|
|
authOptions: undefined,
|
|
});
|
|
}
|
|
|
|
async handleSubmitEmail(e: React.ChangeEvent<any>) {
|
|
try {
|
|
e.preventDefault();
|
|
|
|
if (!this.canSubmit) return;
|
|
|
|
const options = await AccountHelper.getAuthOptions(
|
|
this.state.currEmail
|
|
);
|
|
this.setState({
|
|
errorGettingAuthOptions: false,
|
|
authOptions: options,
|
|
});
|
|
} catch (e) {
|
|
console.error("Failed to get auth options!", e);
|
|
|
|
this.setState({ errorGettingAuthOptions: true });
|
|
}
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "100%",
|
|
}}
|
|
>
|
|
<Container component="main" maxWidth="xs">
|
|
<CssBaseline />
|
|
<div
|
|
style={{
|
|
marginTop: "8px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<Avatar
|
|
style={{
|
|
margin: "1px",
|
|
backgroundColor: "pink",
|
|
}}
|
|
>
|
|
<LockOutlinedIcon />
|
|
</Avatar>
|
|
<Typography
|
|
component="h1"
|
|
variant="h5"
|
|
style={{ margin: "10px", marginBottom: "50px" }}
|
|
>
|
|
Comunic Console
|
|
</Typography>
|
|
<form
|
|
style={{
|
|
width: "100%", // Fix IE 11 issue.
|
|
marginTop: "1px",
|
|
}}
|
|
noValidate
|
|
onSubmit={this.handleSubmitEmail}
|
|
>
|
|
<TextField
|
|
variant="outlined"
|
|
margin="normal"
|
|
required
|
|
fullWidth
|
|
id="email"
|
|
label="Email Address"
|
|
value={this.state.currEmail}
|
|
autoComplete="email"
|
|
onChange={this.handleChangedEmail}
|
|
autoFocus
|
|
/>
|
|
|
|
<Button
|
|
onClick={this.handleSubmitEmail}
|
|
fullWidth
|
|
variant="contained"
|
|
color="primary"
|
|
style={{
|
|
margin: "10px 0px 2px 0px",
|
|
}}
|
|
disabled={!this.canSubmit}
|
|
>
|
|
Sign In
|
|
</Button>
|
|
</form>
|
|
|
|
{/* Login error (if any) */}
|
|
{this.state.errorGettingAuthOptions ? (
|
|
ErrorGettingOptions()
|
|
) : (
|
|
<div></div>
|
|
)}
|
|
|
|
{/* Auth options */}
|
|
{this.state.authOptions ? (
|
|
<AuthOptionsWidget
|
|
email={this.state.currEmail}
|
|
options={this.state.authOptions}
|
|
></AuthOptionsWidget>
|
|
) : (
|
|
<div></div>
|
|
)}
|
|
</div>
|
|
<Box mt={8}>
|
|
<Copyright />
|
|
</Box>
|
|
</Container>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
interface AuthOptionsWidgetProps {
|
|
email: string;
|
|
options: AuthOptions;
|
|
}
|
|
|
|
interface AuthOptionsWidgetState {}
|
|
|
|
class AuthOptionsWidget extends React.Component<
|
|
AuthOptionsWidgetProps,
|
|
AuthOptionsWidgetState
|
|
> {
|
|
constructor(props: Readonly<AuthOptionsWidgetProps>) {
|
|
super(props);
|
|
|
|
this.state = {};
|
|
|
|
this.loginWithResetToken = this.loginWithResetToken.bind(this);
|
|
this.loginWithSecurityKey = this.loginWithSecurityKey.bind(this);
|
|
}
|
|
|
|
async loginWithResetToken() {
|
|
try {
|
|
const token = await input({
|
|
label: "Reset token",
|
|
message: "Please specify here your token:",
|
|
minLength: 2,
|
|
title: "Login using access token",
|
|
});
|
|
|
|
await AccountHelper.authWithResetToken(this.props.email, token);
|
|
|
|
document.location.href = document.location.href + "";
|
|
} catch (e) {
|
|
console.error(e);
|
|
matAlert("Authentication failed!");
|
|
}
|
|
}
|
|
|
|
async loginWithSecurityKey(id: number) {
|
|
console.info(id);
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<Paper style={{ width: "100%", marginTop: "10px" }}>
|
|
<List style={{ width: "100%" }}>
|
|
{/* Password reset token */}
|
|
{this.props.options.reset_token ? (
|
|
<ListItem button onClick={this.loginWithResetToken}>
|
|
<ListItemAvatar>
|
|
<Avatar>
|
|
<Lock />
|
|
</Avatar>
|
|
</ListItemAvatar>
|
|
<ListItemText
|
|
primary="Reset token"
|
|
secondary="Sign in using a reset token"
|
|
/>
|
|
</ListItem>
|
|
) : (
|
|
<span></span>
|
|
)}
|
|
|
|
{this.props.options.keys.map((key) => (
|
|
<ListItem
|
|
button
|
|
onClick={() => this.loginWithSecurityKey(key.id)}
|
|
key={key.id}
|
|
>
|
|
<ListItemAvatar>
|
|
<Avatar>
|
|
<VpnKey />
|
|
</Avatar>
|
|
</ListItemAvatar>
|
|
<ListItemText
|
|
primary={key.name}
|
|
secondary="Sign in using this security key"
|
|
/>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</Paper>
|
|
);
|
|
}
|
|
}
|