mirror of
https://gitlab.com/comunic/comunicconsole
synced 2024-11-27 15:59:23 +00:00
Can login using access reset token
This commit is contained in:
parent
b1929fc21f
commit
05117e71a3
@ -25,12 +25,13 @@ export async function serverRequest(uri: string, args?: any): Promise<any> {
|
|||||||
|
|
||||||
// TODO : add access token, once supported
|
// TODO : add access token, once supported
|
||||||
|
|
||||||
const result = await (
|
const result = await fetch((await ConfigHelper.apiURL()) + uri, {
|
||||||
await fetch((await ConfigHelper.apiURL()) + uri, {
|
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: fd,
|
body: fd,
|
||||||
})
|
});
|
||||||
).json();
|
|
||||||
|
|
||||||
return result;
|
if (result.status !== 200)
|
||||||
|
throw new Error("Request failed with status " + result.status);
|
||||||
|
|
||||||
|
return await result.json();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ export interface AuthOptions {
|
|||||||
reset_token: string;
|
reset_token: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SESSION_STORAGE_TOKEN = "auth_token";
|
||||||
|
|
||||||
export class AccountHelper {
|
export class AccountHelper {
|
||||||
/**
|
/**
|
||||||
* Check whether access token are available
|
* Check whether access token are available
|
||||||
@ -30,4 +32,19 @@ export class AccountHelper {
|
|||||||
mail: mail,
|
mail: mail,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to authenticate user using a reset token
|
||||||
|
*
|
||||||
|
* @param mail Email address of the admin
|
||||||
|
* @param token The reset token
|
||||||
|
*/
|
||||||
|
static async authWithResetToken(mail: string, token: string) {
|
||||||
|
const res = await serverRequest("accounts/auth_with_reset_token", {
|
||||||
|
mail: mail,
|
||||||
|
token: token,
|
||||||
|
});
|
||||||
|
|
||||||
|
sessionStorage.setItem(SESSION_STORAGE_TOKEN, res.token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,24 +5,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Typography,
|
Avatar,
|
||||||
Link,
|
Box,
|
||||||
makeStyles,
|
Button,
|
||||||
Container,
|
Container,
|
||||||
CssBaseline,
|
CssBaseline,
|
||||||
Avatar,
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemAvatar,
|
||||||
|
ListItemText,
|
||||||
|
Paper,
|
||||||
TextField,
|
TextField,
|
||||||
FormControlLabel,
|
Typography,
|
||||||
Checkbox,
|
|
||||||
Button,
|
|
||||||
Grid,
|
|
||||||
Box,
|
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
import { ErrorOutline, Lock, VpnKey } from "@material-ui/icons";
|
||||||
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
|
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { AccountHelper } from "../../helpers/AccountHelper";
|
import { AccountHelper, AuthOptions } from "../../helpers/AccountHelper";
|
||||||
import { matAlert } from "../widgets/DialogsProvider";
|
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() {
|
function Copyright() {
|
||||||
return (
|
return (
|
||||||
@ -37,6 +54,8 @@ function Copyright() {
|
|||||||
|
|
||||||
interface LoginRouteState {
|
interface LoginRouteState {
|
||||||
currEmail: string;
|
currEmail: string;
|
||||||
|
errorGettingAuthOptions: boolean;
|
||||||
|
authOptions?: AuthOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
||||||
@ -45,6 +64,8 @@ export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
currEmail: "",
|
currEmail: "",
|
||||||
|
errorGettingAuthOptions: false,
|
||||||
|
authOptions: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleChangedEmail = this.handleChangedEmail.bind(this);
|
this.handleChangedEmail = this.handleChangedEmail.bind(this);
|
||||||
@ -56,17 +77,31 @@ export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChangedEmail(e: React.ChangeEvent<HTMLInputElement>) {
|
handleChangedEmail(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
this.setState({ currEmail: e.target.value });
|
this.setState({
|
||||||
|
currEmail: e.target.value,
|
||||||
|
errorGettingAuthOptions: false,
|
||||||
|
authOptions: undefined,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmitEmail(e: React.ChangeEvent<any>) {
|
async handleSubmitEmail(e: React.ChangeEvent<any>) {
|
||||||
|
try {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (!this.canSubmit) return;
|
if (!this.canSubmit) return;
|
||||||
|
|
||||||
AccountHelper.getAuthOptions(this.state.currEmail).then((r) =>
|
const options = await AccountHelper.getAuthOptions(
|
||||||
matAlert("reset token => " + r.reset_token)
|
this.state.currEmail
|
||||||
);
|
);
|
||||||
|
this.setState({
|
||||||
|
errorGettingAuthOptions: false,
|
||||||
|
authOptions: options,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to get auth options!", e);
|
||||||
|
|
||||||
|
this.setState({ errorGettingAuthOptions: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -138,6 +173,23 @@ export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
|||||||
Sign In
|
Sign In
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</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>
|
</div>
|
||||||
<Box mt={8}>
|
<Box mt={8}>
|
||||||
<Copyright />
|
<Copyright />
|
||||||
@ -147,3 +199,75 @@ export class LoginRoute extends React.Component<{}, LoginRouteState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<VpnKey />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary="Work" secondary="Jan 7, 2014" />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user